mirror of
https://github.com/frida/frida-core.git
synced 2026-11-08 17:12:49 -10:00
Compare commits
1
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
e0ada4a9ff |
No files matched your search
@@ -1,4 +0,0 @@
|
||||
set(VCPKG_TARGET_ARCHITECTURE arm64)
|
||||
set(VCPKG_CRT_LINKAGE dynamic)
|
||||
set(VCPKG_LIBRARY_LINKAGE dynamic)
|
||||
set(VCPKG_BUILD_TYPE release)
|
||||
@@ -1,4 +0,0 @@
|
||||
set(VCPKG_TARGET_ARCHITECTURE x64)
|
||||
set(VCPKG_CRT_LINKAGE dynamic)
|
||||
set(VCPKG_LIBRARY_LINKAGE dynamic)
|
||||
set(VCPKG_BUILD_TYPE release)
|
||||
+32
-153
@@ -20,8 +20,8 @@ jobs:
|
||||
strategy:
|
||||
matrix:
|
||||
include:
|
||||
- { id: windows-arm64, runner: '"windows-11-arm"', sys: CLANGARM64, pkg: 'mingw-w64-clang-aarch64-clang', opts: "'-Dfrida-gum:v8=disabled'" }
|
||||
- { id: windows-x86_64, runner: '"windows-latest"', sys: UCRT64, pkg: 'mingw-w64-ucrt-x86_64-gcc' }
|
||||
- { id: windows-arm64, runner: '"windows-11-arm"', sys: CLANGARM64, pkg: 'mingw-w64-clang-aarch64-clang' }
|
||||
- { id: windows-x86_64, runner: '"windows-latest"', sys: MINGW64, pkg: 'mingw-w64-x86_64-gcc' }
|
||||
- { id: windows-x86, runner: '"windows-latest"', sys: MINGW32, pkg: 'mingw-w64-i686-gcc' }
|
||||
- { id: macos-x86_64, runner: '"macos-latest"' }
|
||||
- { id: macos-arm64, runner: '"macos-latest"' }
|
||||
@@ -31,7 +31,7 @@ jobs:
|
||||
runs-on: ${{ fromJSON(matrix.runner) }}
|
||||
steps:
|
||||
- name: Check out repo
|
||||
uses: actions/checkout@v6
|
||||
uses: actions/checkout@v4
|
||||
with:
|
||||
submodules: recursive
|
||||
- name: Install MinGW toolchain for cgo support
|
||||
@@ -42,7 +42,7 @@ jobs:
|
||||
msystem: ${{ matrix.sys }}
|
||||
install: ${{ matrix.pkg }}
|
||||
- name: Install Go toolchain
|
||||
uses: actions/setup-go@v6
|
||||
uses: actions/setup-go@v5
|
||||
with:
|
||||
go-version-file: 'src/compiler/go.mod'
|
||||
cache-dependency-path: 'src/compiler/go.mod'
|
||||
@@ -61,17 +61,13 @@ jobs:
|
||||
run: |
|
||||
sudo apt-get update
|
||||
sudo apt-get install gcc-multilib lib32stdc++-13-dev
|
||||
- name: Install setuptools for distutils shim
|
||||
if: ${{ startsWith(matrix.id, 'windows-') }}
|
||||
run: pip install setuptools
|
||||
- name: Build
|
||||
if: ${{ startsWith(matrix.id, 'windows-') }}
|
||||
run: |
|
||||
.\configure `
|
||||
--host=${{ matrix.id }} `
|
||||
--enable-compiler-backend `
|
||||
${{ env.FRIDA_CORE_OPTIONS }} `
|
||||
-- --force-fallback-for=openssl ${{ matrix.opts }}
|
||||
${{ env.FRIDA_CORE_OPTIONS }}
|
||||
.\make
|
||||
env:
|
||||
MSYS2_LOCATION: ${{ steps.msys2.outputs.msys2-location }}
|
||||
@@ -95,40 +91,14 @@ jobs:
|
||||
make
|
||||
- name: Upload devkit
|
||||
if: ${{ !startsWith(matrix.id, 'linux-') }}
|
||||
uses: actions/upload-artifact@v7
|
||||
uses: actions/upload-artifact@v4
|
||||
with:
|
||||
name: core-devkit-${{ matrix.id }}
|
||||
path: build/src/devkit/
|
||||
- name: Upload GObject introspection data
|
||||
if: ${{ matrix.id == 'linux-x86_64' }}
|
||||
uses: actions/upload-artifact@v7
|
||||
with:
|
||||
name: core-gir
|
||||
path: build/src/api/Frida-1.0.gir
|
||||
- name: Test
|
||||
if: ${{ matrix.id != 'windows-arm64' && !startsWith(matrix.id, 'macos-') }}
|
||||
run: make test
|
||||
|
||||
publish-gir:
|
||||
if: ${{ !cancelled() && github.ref_type == 'tag' && needs.native.result == 'success' }}
|
||||
needs:
|
||||
- native
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Download GObject introspection data
|
||||
uses: actions/download-artifact@v8
|
||||
with:
|
||||
name: core-gir
|
||||
path: gir
|
||||
- name: Attach to GitHub release
|
||||
uses: softprops/action-gh-release@v3
|
||||
with:
|
||||
files: |
|
||||
gir/Frida-1.0.gir
|
||||
prerelease: ${{ contains(github.ref_name, 'snapshot') }}
|
||||
env:
|
||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
|
||||
cross:
|
||||
strategy:
|
||||
matrix:
|
||||
@@ -143,7 +113,7 @@ jobs:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Check out repo
|
||||
uses: actions/checkout@v6
|
||||
uses: actions/checkout@v4
|
||||
with:
|
||||
submodules: recursive
|
||||
- name: Install toolchain
|
||||
@@ -151,7 +121,7 @@ jobs:
|
||||
sudo apt-get update
|
||||
sudo apt-get install ${{ matrix.pkg }}
|
||||
- name: Install Go toolchain
|
||||
uses: actions/setup-go@v6
|
||||
uses: actions/setup-go@v5
|
||||
with:
|
||||
go-version-file: 'src/compiler/go.mod'
|
||||
cache-dependency-path: 'src/compiler/go.mod'
|
||||
@@ -164,7 +134,7 @@ jobs:
|
||||
make
|
||||
- name: Upload devkit
|
||||
if: ${{ !startsWith(matrix.id, 'linux-') }}
|
||||
uses: actions/upload-artifact@v7
|
||||
uses: actions/upload-artifact@v4
|
||||
with:
|
||||
name: core-devkit-${{ matrix.id }}
|
||||
path: build/src/devkit/
|
||||
@@ -178,11 +148,11 @@ jobs:
|
||||
container: ghcr.io/frida/x-tools-linux-${{ matrix.arch }}:latest
|
||||
steps:
|
||||
- name: Check out repo
|
||||
uses: actions/checkout@v6
|
||||
uses: actions/checkout@v4
|
||||
with:
|
||||
submodules: recursive
|
||||
- name: Install Go toolchain
|
||||
uses: actions/setup-go@v6
|
||||
uses: actions/setup-go@v5
|
||||
with:
|
||||
go-version-file: 'src/compiler/go.mod'
|
||||
cache-dependency-path: 'src/compiler/go.mod'
|
||||
@@ -194,7 +164,7 @@ jobs:
|
||||
${{ env.FRIDA_CORE_OPTIONS }}
|
||||
make
|
||||
- name: Upload devkit
|
||||
uses: actions/upload-artifact@v7
|
||||
uses: actions/upload-artifact@v4
|
||||
with:
|
||||
name: core-devkit-linux-${{ matrix.arch }}
|
||||
path: build/src/devkit/
|
||||
@@ -211,7 +181,7 @@ jobs:
|
||||
container: ghcr.io/frida/x-tools-linux-${{ matrix.arch }}:latest
|
||||
steps:
|
||||
- name: Check out repo
|
||||
uses: actions/checkout@v6
|
||||
uses: actions/checkout@v4
|
||||
with:
|
||||
submodules: recursive
|
||||
- name: Build
|
||||
@@ -342,11 +312,11 @@ jobs:
|
||||
runs-on: ${{ startsWith(matrix.id, 'ios-') && 'macos-latest' || 'ubuntu-latest' }}
|
||||
steps:
|
||||
- name: Check out repo
|
||||
uses: actions/checkout@v6
|
||||
uses: actions/checkout@v4
|
||||
with:
|
||||
submodules: recursive
|
||||
- name: Install Go toolchain
|
||||
uses: actions/setup-go@v6
|
||||
uses: actions/setup-go@v5
|
||||
with:
|
||||
go-version-file: 'src/compiler/go.mod'
|
||||
cache-dependency-path: 'src/compiler/go.mod'
|
||||
@@ -361,7 +331,7 @@ jobs:
|
||||
if: startsWith(matrix.id, 'android-')
|
||||
id: setup-ndk
|
||||
with:
|
||||
ndk-version: r29
|
||||
ndk-version: r25c
|
||||
- name: Add NDK to env
|
||||
if: startsWith(matrix.id, 'android-')
|
||||
run: echo ANDROID_NDK_ROOT=${{ steps.setup-ndk.outputs.ndk-path }} >> $GITHUB_ENV
|
||||
@@ -373,7 +343,7 @@ jobs:
|
||||
${{ env.FRIDA_CORE_OPTIONS }}
|
||||
make
|
||||
- name: Upload devkit
|
||||
uses: actions/upload-artifact@v7
|
||||
uses: actions/upload-artifact@v4
|
||||
with:
|
||||
name: core-devkit-${{ matrix.id }}
|
||||
path: build/src/devkit/
|
||||
@@ -432,7 +402,7 @@ jobs:
|
||||
container: ghcr.io/frida/qnx-tools:latest
|
||||
steps:
|
||||
- name: Check out repo
|
||||
uses: actions/checkout@v6
|
||||
uses: actions/checkout@v4
|
||||
with:
|
||||
submodules: recursive
|
||||
- name: Build
|
||||
@@ -441,7 +411,7 @@ jobs:
|
||||
./configure --host=arm-unknown-nto-qnx6.5.0eabi ${{ env.FRIDA_CORE_OPTIONS }}
|
||||
make
|
||||
- name: Upload devkit
|
||||
uses: actions/upload-artifact@v7
|
||||
uses: actions/upload-artifact@v4
|
||||
with:
|
||||
name: core-devkit-qnx-armeabi
|
||||
path: build/src/devkit/
|
||||
@@ -458,7 +428,6 @@ jobs:
|
||||
# in, and we want to ensure that they are up-to-date with respect to the source
|
||||
# for all architectures.
|
||||
check-linux-helpers:
|
||||
if: false
|
||||
strategy:
|
||||
matrix:
|
||||
arch: [x86, x86_64, arm, armbe8, arm64, arm64be, arm64beilp32, mips, mipsel, mips64, mips64el]
|
||||
@@ -467,7 +436,7 @@ jobs:
|
||||
container: ghcr.io/frida/core-linux-helpers-${{ matrix.arch }}:latest
|
||||
steps:
|
||||
- name: Check out repo
|
||||
uses: actions/checkout@v6
|
||||
uses: actions/checkout@v4
|
||||
with:
|
||||
submodules: recursive
|
||||
- name: Build
|
||||
@@ -476,7 +445,7 @@ jobs:
|
||||
- name: Check for unexpected changes
|
||||
run: |
|
||||
git config --global --add safe.directory "$(realpath .)"
|
||||
status_output=$(git status --porcelain src/linux/helpers/artifacts)
|
||||
status_output=$(git status --porcelain tests/labrats/{resident-agent,simple-agent}-linux-${{ matrix.arch }}.so tests/labrats/{forker,sleeper,spawner}-linux-${{ matrix.arch }})
|
||||
if [ -n "$status_output" ]; then
|
||||
echo "Unexpected changes detected:"
|
||||
echo "$status_output"
|
||||
@@ -492,7 +461,6 @@ jobs:
|
||||
# in, and we want to ensure that they are up-to-date with respect to the source
|
||||
# for all architectures.
|
||||
check-labrats:
|
||||
if: false
|
||||
strategy:
|
||||
matrix:
|
||||
arch: [x86, x86_64, arm, armbe8, arm64, arm64be, arm64beilp32, mips, mipsel, mips64, mips64el]
|
||||
@@ -501,7 +469,7 @@ jobs:
|
||||
container: ghcr.io/frida/core-linux-helpers-${{ matrix.arch }}:latest
|
||||
steps:
|
||||
- name: Check out repo
|
||||
uses: actions/checkout@v6
|
||||
uses: actions/checkout@v4
|
||||
with:
|
||||
submodules: recursive
|
||||
- name: Build
|
||||
@@ -510,7 +478,7 @@ jobs:
|
||||
- name: Check for unexpected changes
|
||||
run: |
|
||||
git config --global --add safe.directory "$(realpath .)"
|
||||
status_output=$(git status --porcelain tests/labrats/{resident-agent,simple-agent}-linux-${{ matrix.arch }}.so tests/labrats/{forker,sleeper,spawner}-linux-${{ matrix.arch }})
|
||||
status_output=$(git status --porcelain src/linux/helpers/{bootstrapper,loader}-${{ matrix.arch }}.bin)
|
||||
if [ -n "$status_output" ]; then
|
||||
echo "Unexpected changes detected:"
|
||||
echo "$status_output"
|
||||
@@ -523,31 +491,30 @@ jobs:
|
||||
|
||||
xcframework:
|
||||
name: Build FridaCore.xcframework
|
||||
if: ${{ !cancelled() }}
|
||||
runs-on: macos-latest
|
||||
needs:
|
||||
- native
|
||||
- mobile
|
||||
steps:
|
||||
- name: Check out repo
|
||||
uses: actions/checkout@v6
|
||||
uses: actions/checkout@v4
|
||||
- name: Download macOS/x86_64 devkit
|
||||
uses: actions/download-artifact@v8
|
||||
uses: actions/download-artifact@v4
|
||||
with:
|
||||
name: core-devkit-macos-x86_64
|
||||
path: devkits/macos-x86_64
|
||||
- name: Download macOS/arm64 devkit
|
||||
uses: actions/download-artifact@v8
|
||||
uses: actions/download-artifact@v4
|
||||
with:
|
||||
name: core-devkit-macos-arm64
|
||||
path: devkits/macos-arm64
|
||||
- name: Download iOS/arm64 devkit
|
||||
uses: actions/download-artifact@v8
|
||||
uses: actions/download-artifact@v4
|
||||
with:
|
||||
name: core-devkit-ios-arm64
|
||||
path: devkits/ios-arm64
|
||||
- name: Download iOS/arm64-simulator devkit
|
||||
uses: actions/download-artifact@v8
|
||||
uses: actions/download-artifact@v4
|
||||
with:
|
||||
name: core-devkit-ios-arm64-simulator
|
||||
path: devkits/ios-arm64-simulator
|
||||
@@ -610,19 +577,19 @@ jobs:
|
||||
-headers xcframework_headers/ios-arm64-simulator \
|
||||
-output FridaCore.xcframework
|
||||
- name: Upload FridaCore.xcframework
|
||||
uses: actions/upload-artifact@v7
|
||||
uses: actions/upload-artifact@v4
|
||||
with:
|
||||
name: FridaCore.xcframework
|
||||
path: FridaCore.xcframework
|
||||
|
||||
publish-xcframework:
|
||||
if: ${{ !cancelled() && github.ref_type == 'tag' && needs.xcframework.result == 'success' }}
|
||||
if: github.ref_type == 'tag'
|
||||
runs-on: macos-latest
|
||||
needs:
|
||||
- xcframework
|
||||
steps:
|
||||
- name: Download FridaCore.xcframework artifact
|
||||
uses: actions/download-artifact@v8
|
||||
uses: actions/download-artifact@v4
|
||||
with:
|
||||
name: FridaCore.xcframework
|
||||
path: dist
|
||||
@@ -645,98 +612,10 @@ jobs:
|
||||
cd dist
|
||||
zip -r FridaCore.xcframework.zip FridaCore.xcframework
|
||||
- name: Create GitHub release
|
||||
uses: softprops/action-gh-release@v3
|
||||
uses: softprops/action-gh-release@v2
|
||||
with:
|
||||
files: |
|
||||
dist/FridaCore.xcframework.zip
|
||||
prerelease: ${{ contains(github.ref_name, 'snapshot') }}
|
||||
env:
|
||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
|
||||
windows-shared:
|
||||
strategy:
|
||||
matrix:
|
||||
include:
|
||||
- { arch: x86_64, runner: windows-latest, msvc-arch: amd64, vcpkg-triplet: x64-windows-release }
|
||||
- { arch: arm64, runner: windows-11-arm, msvc-arch: arm64, vcpkg-triplet: arm64-windows-release, opts: "'-Dfrida-gum:v8=disabled'" }
|
||||
fail-fast: false
|
||||
runs-on: ${{ matrix.runner }}
|
||||
timeout-minutes: 120
|
||||
steps:
|
||||
- name: Check out repo
|
||||
uses: actions/checkout@v6
|
||||
with:
|
||||
submodules: recursive
|
||||
|
||||
- name: Set up MSVC environment
|
||||
run: |
|
||||
$vs = & "${env:ProgramFiles(x86)}\Microsoft Visual Studio\Installer\vswhere.exe" -products * -latest -property installationPath
|
||||
$before = @{}
|
||||
Get-ChildItem env: | ForEach-Object { $before[$_.Name] = $_.Value }
|
||||
cmd /c "`"$vs\VC\Auxiliary\Build\vcvarsall.bat`" ${{ matrix.msvc-arch }} >nul && set" | ForEach-Object {
|
||||
$name, $value = $_ -split '=', 2
|
||||
if ($before[$name] -ne $value) {
|
||||
"$name=$value" >> $env:GITHUB_ENV
|
||||
}
|
||||
}
|
||||
|
||||
- uses: actions/setup-python@v6
|
||||
with:
|
||||
python-version: "3.12"
|
||||
|
||||
- name: Install build tools
|
||||
run: |
|
||||
pip install meson ninja setuptools
|
||||
choco install pkgconfiglite -y
|
||||
|
||||
- name: Restore vcpkg cache
|
||||
id: vcpkg-cache
|
||||
uses: actions/cache/restore@v5
|
||||
with:
|
||||
path: C:\vcpkg\installed
|
||||
key: vcpkg-${{ matrix.vcpkg-triplet }}-v5
|
||||
|
||||
- name: Install dependencies via vcpkg
|
||||
if: steps.vcpkg-cache.outputs.cache-hit != 'true'
|
||||
run: >-
|
||||
vcpkg install
|
||||
--overlay-triplets=${{ github.workspace }}/.github/vcpkg-triplets
|
||||
--triplet ${{ matrix.vcpkg-triplet }}
|
||||
glib json-glib libsoup
|
||||
|
||||
- name: Save vcpkg cache
|
||||
if: steps.vcpkg-cache.outputs.cache-hit != 'true'
|
||||
uses: actions/cache/save@v5
|
||||
with:
|
||||
path: C:\vcpkg\installed
|
||||
key: vcpkg-${{ matrix.vcpkg-triplet }}-v5
|
||||
|
||||
- name: Set up vcpkg environment
|
||||
shell: bash
|
||||
run: |
|
||||
TRIPLET="${{ matrix.vcpkg-triplet }}"
|
||||
VCPKG_PREFIX="C:/vcpkg/installed/$TRIPLET"
|
||||
echo "$VCPKG_PREFIX/tools/pkgconf" >> $GITHUB_PATH
|
||||
echo "$VCPKG_PREFIX/bin" >> $GITHUB_PATH
|
||||
echo "$VCPKG_PREFIX/tools" >> $GITHUB_PATH
|
||||
echo "PKG_CONFIG_PATH=$VCPKG_PREFIX/lib/pkgconfig" >> $GITHUB_ENV
|
||||
|
||||
- name: Configure
|
||||
run: |
|
||||
python -c "import sys; sys.path.insert(0, '.'); from releng.meson_configure import main; main()" `
|
||||
. `
|
||||
--host=windows-${{ matrix.arch }} `
|
||||
--enable-shared `
|
||||
--without-prebuilds=sdk `
|
||||
"--prefix=$env:RUNNER_TEMP\frida-prefix" `
|
||||
-- --force-fallback-for=openssl,libnghttp2 -Dcompiler_backend=disabled -Dtests=disabled ${{ matrix.opts }}
|
||||
|
||||
- name: Compile
|
||||
run: python releng/meson/meson.py compile -C build
|
||||
|
||||
- name: Install
|
||||
run: python releng/meson/meson.py install -C build --no-rebuild --skip-subprojects
|
||||
|
||||
- name: List installed files
|
||||
shell: bash
|
||||
run: find "$RUNNER_TEMP/frida-prefix" -type f | sort
|
||||
+1
-10
@@ -1,16 +1,7 @@
|
||||
/.cache/
|
||||
/build/
|
||||
/deps/
|
||||
/src/android-helper/build/
|
||||
/src/barebone/agent/linux/*.ko
|
||||
/src/barebone/agent/linux/*.mod
|
||||
/src/barebone/agent/linux/*.mod.c
|
||||
/src/barebone/agent/linux/*.o
|
||||
/src/barebone/agent/linux/*.o.bin
|
||||
/src/barebone/agent/linux/.*.cmd
|
||||
/src/barebone/agent/linux/Module.symvers
|
||||
/src/barebone/agent/linux/modules.order
|
||||
/src/barebone/agent/target*/
|
||||
/src/barebone/agent/target/
|
||||
/src/barebone/agent/xpacks/
|
||||
/src/barebone/helpers/memory-scanner/target/
|
||||
/src/barebone/helpers/target/
|
||||
|
||||
@@ -1,153 +0,0 @@
|
||||
# CLAUDE.md
|
||||
|
||||
This file provides guidance to Claude Code (claude.ai/code)
|
||||
when working with code in this repository.
|
||||
|
||||
## What This Is
|
||||
|
||||
frida-core is the core library of the Frida dynamic
|
||||
instrumentation toolkit. It packages GumJS into a shared
|
||||
library, injects JavaScript instrumentation into target
|
||||
processes, provides bidirectional RPC communication with
|
||||
injected scripts, and enumerates apps/processes/devices.
|
||||
Written primarily in Vala with OS-specific glue in
|
||||
C/Objective-C/asm.
|
||||
|
||||
## Build Commands
|
||||
|
||||
```bash
|
||||
# First-time setup (fetches git submodules, configures build):
|
||||
./configure \
|
||||
--enable-compiler-backend \
|
||||
--with-devkits=core \
|
||||
--enable-tests
|
||||
|
||||
# Build:
|
||||
make
|
||||
|
||||
# Run tests:
|
||||
make test
|
||||
|
||||
# Rebuild after code changes
|
||||
make
|
||||
```
|
||||
|
||||
The `configure` script and `Makefile` are thin wrappers
|
||||
around `releng/meson_configure.py` and
|
||||
`releng/meson_make.py`. The actual build system is Meson
|
||||
(>=1.1.0).
|
||||
|
||||
Build artifacts go into `build/`. The triplet is
|
||||
platform-dependent (e.g. `linux-x86_64`).
|
||||
|
||||
## Build Requirements
|
||||
|
||||
- **Vala compiler**: Must be the Frida-optimized fork from
|
||||
https://github.com/frida/vala (checks for `-frida` suffix
|
||||
in version)
|
||||
- **C/C++ standards**: gnu99/c99 for C, c++17 for C++
|
||||
- **Go >= 1.24**: Required for compiler backend
|
||||
- **Python 3**: Build scripts
|
||||
|
||||
## Architecture
|
||||
|
||||
### Backend System
|
||||
|
||||
The core abstraction is a pluggable backend system. Each
|
||||
backend implements `HostSessionBackend` and provides a
|
||||
`HostSessionProvider` to create sessions with target
|
||||
processes:
|
||||
|
||||
- **local** — Injects into processes on the local system
|
||||
(Linux, macOS, Windows, FreeBSD, QNX)
|
||||
- **fruity** — iOS/tvOS/xrOS devices via USB/network
|
||||
(QUIC, lockdown protocols)
|
||||
- **droidy** — Android devices via ADB/JDWP
|
||||
- **socket** — Remote devices via TCP (connects to
|
||||
frida-server, frida-gadget, frida-portal)
|
||||
- **barebone** — Minimal backend using QuickJS
|
||||
- **simmy** — macOS Simulator
|
||||
- **compiler** — TypeScript/ESBuild compilation backend
|
||||
(Go + TypeScript in `src/compiler/`)
|
||||
|
||||
Backends are selected at build time via meson options
|
||||
(e.g. `-Dlocal_backend=enabled`).
|
||||
|
||||
### Key Source Layout
|
||||
|
||||
- **`src/frida.vala`** — Public API: `DeviceManager`,
|
||||
`Device`, `Session`, `Script`
|
||||
- **`src/host-session-service.vala`** — Backend
|
||||
orchestration, provider registration
|
||||
- **`src/control-service.vala`** — the guts of frida-server
|
||||
- **`src/portal-service.vala`** — the guts of frida-portal,
|
||||
which looks like a frida-server that surfaces any joined
|
||||
processes (think aggregator/reverse proxy)
|
||||
- **`lib/base/`** — Core primitives: Session, RPC, streams,
|
||||
sockets, P2P, buffers
|
||||
- **`lib/agent/`** — In-process JavaScript agent runtime
|
||||
- **`lib/payload/`** — Payload compilation and embedding
|
||||
- **`lib/gadget/`** — Gadget (preloaded library)
|
||||
implementation
|
||||
- **`src/<platform>/`** — Platform-specific injectors and
|
||||
helpers (`linux/`, `darwin/`, `windows/`, `freebsd/`,
|
||||
`qnx/`)
|
||||
- **`src/fruity/`** — iOS device protocol stack (USB, QUIC,
|
||||
plist, XPC, LLDB)
|
||||
- **`src/droidy/`** — Android device protocol stack
|
||||
- **`src/compiler/`** — Go/TypeScript compiler backend
|
||||
|
||||
### Injection Flow
|
||||
|
||||
Each platform has its own injector (e.g. `Linjector` on
|
||||
Linux, `Fruitjector` on Darwin, `Winjector` on Windows). A
|
||||
helper process (`frida-helper`) performs privileged injection
|
||||
operations out-of-process. Helpers and agents can be embedded
|
||||
into the library or installed as separate files (controlled
|
||||
by the `assets` meson option).
|
||||
|
||||
### Deliverables
|
||||
|
||||
- **frida-server** (`server/`) — Standalone daemon exposing
|
||||
the full API over the network
|
||||
- **frida-portal** (`portal/`) — Cluster node for
|
||||
distributed instrumentation
|
||||
- **frida-inject** (`inject/`) — CLI tool for one-shot
|
||||
script injection
|
||||
- **frida-gadget** (`lib/gadget/`) — Shared library for
|
||||
preload-based instrumentation
|
||||
|
||||
### Resource Embedding
|
||||
|
||||
Build artifacts (frida-helper, frida-agent) are compiled
|
||||
into resource blobs via `tools/resource-compiler.vala` and
|
||||
embedding scripts (`src/embed-helper.py`,
|
||||
`src/embed-agent.py`). On non-MSVC toolchains these become
|
||||
`.S` assembly files; on MSVC they become `.obj` files.
|
||||
|
||||
## Tests
|
||||
|
||||
Tests are in `tests/` as Vala files using a custom async
|
||||
test harness (`tests/async-harness.vala`). Test binary is
|
||||
`tests/frida-tests`. Platform-specific runner scripts exist
|
||||
(e.g. `tests/run-linux-x86_64.sh`).
|
||||
|
||||
Test modules: `test-system`, `test-injector`, `test-agent`,
|
||||
`test-host-session`, `test-gadget`, `test-compiler`. Test
|
||||
helper programs ("labrats") are in `tests/labrats/`.
|
||||
|
||||
## Code Style
|
||||
|
||||
### Function Order
|
||||
|
||||
Use newspaper/stepdown order: high-level entry points
|
||||
first, low-level helpers and constants last. In C,
|
||||
`main()` is always first. When ordering siblings at the
|
||||
same level, use the chronological order of first use
|
||||
within their caller.
|
||||
|
||||
## Commit Style
|
||||
|
||||
- Subject line: max 50 characters
|
||||
- Body lines: wrap at 72 characters (use the full width, or
|
||||
slightly less if it avoids making the next line awkward)
|
||||
@@ -1,18 +1,15 @@
|
||||
# frida-core
|
||||
|
||||
Frida core library.
|
||||
Frida core library intended for static linking into bindings.
|
||||
|
||||
- Lets you inject your own JavaScript instrumentation code
|
||||
into other processes, optionally with your own [C code][]
|
||||
for performance-sensitive bits.
|
||||
- Acts as a logistics layer that packages up [GumJS][] into
|
||||
a shared library.
|
||||
- Provides a two-way communication channel for talking to
|
||||
your scripts, if needed, and later unload them.
|
||||
- Also lets you enumerate installed apps, running processes,
|
||||
and connected devices.
|
||||
- Written in [Vala][], with OS-specific glue code in
|
||||
C/Objective-C/asm.
|
||||
- Lets you inject your own JavaScript instrumentation code into other processes,
|
||||
optionally with your own [C code][] for performance-sensitive bits.
|
||||
- Acts as a logistics layer that packages up [GumJS][] into a shared library.
|
||||
- Provides a two-way communication channel for talking to your scripts,
|
||||
if needed, and later unload them.
|
||||
- Also lets you enumerate installed apps, running processes, and connected
|
||||
devices.
|
||||
- Written in [Vala][], with OS-specific glue code in C/Objective-C/asm.
|
||||
|
||||
## Binaries
|
||||
|
||||
@@ -32,43 +29,8 @@ $ pip install frida # Python bindings
|
||||
$ npm install frida # Node.js bindings
|
||||
```
|
||||
|
||||
Or, for static linking into your own project written in a
|
||||
C-compatible language, download a devkit from the Frida
|
||||
[releases][] page.
|
||||
|
||||
## Distro Packaging
|
||||
|
||||
For building a shared library suitable for distro packaging:
|
||||
|
||||
```console
|
||||
$ ./configure --enable-shared --without-prebuilds=sdk && make
|
||||
```
|
||||
|
||||
This builds `libfrida-core-1.0.so` against system dependencies,
|
||||
while `frida-agent.so` is built using Frida's SDK (with its GLib
|
||||
fork, needed for the agent's inject/unload lifecycle).
|
||||
|
||||
Prerequisites on Fedora:
|
||||
|
||||
```console
|
||||
$ sudo dnf install libgee-devel json-glib-devel \
|
||||
libsoup3-devel libunwind-devel libdwarf-devel \
|
||||
libnice-devel ngtcp2-crypto-ossl-devel
|
||||
```
|
||||
|
||||
Prerequisites on Ubuntu:
|
||||
|
||||
```console
|
||||
$ sudo apt install libgee-0.8-dev libjson-glib-dev \
|
||||
libsoup-3.0-dev libunwind-dev libdwarf-dev \
|
||||
libnice-dev libngtcp2-crypto-ossl-dev
|
||||
```
|
||||
|
||||
Prerequisites on macOS:
|
||||
|
||||
```console
|
||||
$ brew install libgee json-glib libsoup libnice capstone
|
||||
```
|
||||
Or, for static linking into your own project written in a C-compatible language,
|
||||
download a devkit from the Frida [releases][] page.
|
||||
|
||||
## Internals
|
||||
|
||||
|
||||
+62
-234
@@ -9,7 +9,6 @@ import os
|
||||
from pathlib import Path
|
||||
import pickle
|
||||
import platform
|
||||
import re
|
||||
import shlex
|
||||
import shutil
|
||||
import subprocess
|
||||
@@ -36,7 +35,6 @@ def main(argv):
|
||||
command.add_argument("top_builddir", help="top build directory", type=Path)
|
||||
command.add_argument("frida_version", help="the Frida version")
|
||||
command.add_argument("host_os", help="operating system binaries are being built for")
|
||||
command.add_argument("host_os_family", help="operating system family, e.g. darwin")
|
||||
command.add_argument("host_arch", help="architecture binaries are being built for")
|
||||
command.add_argument("host_config", help="configuration binaries are being built for")
|
||||
command.add_argument("compat", help="support for targets with a different architecture",
|
||||
@@ -44,23 +42,17 @@ def main(argv):
|
||||
command.add_argument("assets", help="whether assets are embedded vs installed and loaded at runtime")
|
||||
command.add_argument("components", help="which components will be built",
|
||||
type=parse_array_option_value)
|
||||
command.add_argument("glib_flavor", help="upstream or frida", choices=["upstream", "frida"])
|
||||
command.add_argument("apple_tls", help="whether the parent build is using the Apple TLS backend",
|
||||
choices=["enabled", "disabled"])
|
||||
command.add_argument("compilers", help="compiler command arrays", nargs="+")
|
||||
command.set_defaults(func=lambda args: setup(args.role,
|
||||
args.builddir,
|
||||
args.top_builddir,
|
||||
args.frida_version,
|
||||
args.host_os,
|
||||
args.host_os_family,
|
||||
args.host_arch,
|
||||
args.host_config if args.host_config else None,
|
||||
args.compat,
|
||||
args.assets,
|
||||
args.components,
|
||||
args.glib_flavor,
|
||||
args.apple_tls,
|
||||
parse_compilers(args.compilers)))
|
||||
|
||||
command = subparsers.add_parser("compile", help="compile compatibility assets")
|
||||
@@ -121,14 +113,11 @@ def setup(role: Role,
|
||||
top_builddir: Path,
|
||||
frida_version: str,
|
||||
host_os: str,
|
||||
host_os_family: str,
|
||||
host_arch: str,
|
||||
host_config: Optional[str],
|
||||
compat: set[str],
|
||||
assets: str,
|
||||
components: set[str],
|
||||
glib_flavor: str,
|
||||
apple_tls: str,
|
||||
compilers: Compilers):
|
||||
try:
|
||||
outputs: Mapping[str, Sequence[Output]] = OrderedDict()
|
||||
@@ -160,20 +149,9 @@ def setup(role: Role,
|
||||
other_triplet: Optional[str] = None
|
||||
extra_environ: dict[str, str] = {}
|
||||
|
||||
if host_os == "windows" and host_arch in {"x86_64", "x86"}:
|
||||
if host_arch == "x86_64":
|
||||
other_label = "x86"
|
||||
other_kind = "legacy"
|
||||
else:
|
||||
other_label = "x86_64"
|
||||
other_kind = "modern"
|
||||
|
||||
if host_config == "mingw":
|
||||
have_toolchain, other_triplet = detect_mingw_toolchain_for(other_label)
|
||||
else:
|
||||
have_toolchain = True
|
||||
other_triplet = None
|
||||
|
||||
if host_os == "windows" and host_arch == "x86_64" and host_config == "mingw":
|
||||
other_label = "x86"
|
||||
have_toolchain, other_triplet = detect_mingw_toolchain_for("x86")
|
||||
elif host_os == "linux" and host_arch == "x86_64" and host_config is None:
|
||||
other_label = "x86"
|
||||
other_triplet = "i686-linux-gnu"
|
||||
@@ -201,26 +179,21 @@ def setup(role: Role,
|
||||
raise ToolchainNotFoundError(f"unable to locate toolchain for {other_triplet}")
|
||||
missing.append(MissingFeature(other_label, other_triplet))
|
||||
|
||||
if host_os == "windows" and host_arch in {"x86_64", "x86"} and have_toolchain:
|
||||
group = OutputGroup(other_label, other_triplet, extra_environ)
|
||||
outputs[group] = []
|
||||
if "helper" in components:
|
||||
outputs[group] += [
|
||||
Output(identifier=f"helper_{other_kind}",
|
||||
name=HELPER_FILE_WINDOWS.name,
|
||||
file=HELPER_FILE_WINDOWS,
|
||||
target=HELPER_TARGET),
|
||||
]
|
||||
if "agent" in components:
|
||||
outputs[group] += [
|
||||
Output(identifier=f"agent_{other_kind}",
|
||||
name=AGENT_FILE_WINDOWS.name,
|
||||
file=AGENT_FILE_WINDOWS,
|
||||
target=AGENT_TARGET),
|
||||
]
|
||||
if host_os == "windows" and host_arch == "x86_64" and have_toolchain:
|
||||
group = OutputGroup("x86", other_triplet, extra_environ)
|
||||
outputs[group] = [
|
||||
Output(identifier="helper_legacy",
|
||||
name=HELPER_FILE_WINDOWS.name,
|
||||
file=HELPER_FILE_WINDOWS,
|
||||
target=HELPER_TARGET),
|
||||
Output(identifier="agent_legacy",
|
||||
name=AGENT_FILE_WINDOWS.name,
|
||||
file=AGENT_FILE_WINDOWS,
|
||||
target=AGENT_TARGET),
|
||||
]
|
||||
if "gadget" in components:
|
||||
outputs[group] += [
|
||||
Output(identifier=f"gadget_{other_kind}",
|
||||
Output(identifier="gadget_legacy",
|
||||
name=GADGET_FILE_WINDOWS.name,
|
||||
file=GADGET_FILE_WINDOWS,
|
||||
target=GADGET_TARGET),
|
||||
@@ -234,21 +207,16 @@ def setup(role: Role,
|
||||
other_arch = "arm64e"
|
||||
kind = "modern"
|
||||
group = OutputGroup(other_arch)
|
||||
outputs[group] = []
|
||||
if "helper" in components:
|
||||
outputs[group] += [
|
||||
Output(identifier=f"helper_{kind}",
|
||||
name=f"frida-helper-{other_arch}",
|
||||
file=HELPER_FILE_UNIX,
|
||||
target=HELPER_TARGET),
|
||||
]
|
||||
if "agent" in components:
|
||||
outputs[group] += [
|
||||
Output(identifier=f"agent_{kind}",
|
||||
name=f"frida-agent-{other_arch}.dylib",
|
||||
file=AGENT_FILE_DARWIN,
|
||||
target=AGENT_TARGET),
|
||||
]
|
||||
outputs[group] = [
|
||||
Output(identifier=f"helper_{kind}",
|
||||
name=f"frida-helper-{other_arch}",
|
||||
file=HELPER_FILE_UNIX,
|
||||
target=HELPER_TARGET),
|
||||
Output(identifier=f"agent_{kind}",
|
||||
name=f"frida-agent-{other_arch}.dylib",
|
||||
file=AGENT_FILE_DARWIN,
|
||||
target=AGENT_TARGET),
|
||||
]
|
||||
if "gadget" in components:
|
||||
outputs[group] += [
|
||||
Output(identifier=f"gadget_{kind}",
|
||||
@@ -266,21 +234,16 @@ def setup(role: Role,
|
||||
|
||||
if host_os == "linux" and host_arch == "x86_64" and have_toolchain:
|
||||
group = OutputGroup("x86", other_triplet, extra_environ)
|
||||
outputs[group] = []
|
||||
if "helper" in components:
|
||||
outputs[group] += [
|
||||
Output(identifier="helper_legacy",
|
||||
name=HELPER_FILE_UNIX.name,
|
||||
file=HELPER_FILE_UNIX,
|
||||
target=HELPER_TARGET),
|
||||
]
|
||||
if "agent" in components:
|
||||
outputs[group] += [
|
||||
Output(identifier="agent_legacy",
|
||||
name=AGENT_FILE_ELF.name,
|
||||
file=AGENT_FILE_ELF,
|
||||
target=AGENT_TARGET),
|
||||
]
|
||||
outputs[group] = [
|
||||
Output(identifier="helper_legacy",
|
||||
name=HELPER_FILE_UNIX.name,
|
||||
file=HELPER_FILE_UNIX,
|
||||
target=HELPER_TARGET),
|
||||
Output(identifier="agent_legacy",
|
||||
name=AGENT_FILE_ELF.name,
|
||||
file=AGENT_FILE_ELF,
|
||||
target=AGENT_TARGET),
|
||||
]
|
||||
if "gadget" in components:
|
||||
outputs[group] += [
|
||||
Output(identifier="gadget_legacy",
|
||||
@@ -291,21 +254,16 @@ def setup(role: Role,
|
||||
|
||||
if host_os == "android" and host_arch in {"arm64", "x86_64"}:
|
||||
group = OutputGroup("arm" if host_arch == "arm64" else "x86")
|
||||
outputs[group] = []
|
||||
if "helper" in components:
|
||||
outputs[group] += [
|
||||
Output(identifier="helper_legacy",
|
||||
name=HELPER_FILE_UNIX.name,
|
||||
file=HELPER_FILE_UNIX,
|
||||
target=HELPER_TARGET),
|
||||
]
|
||||
if "agent" in components:
|
||||
outputs[group] += [
|
||||
Output(identifier="agent_legacy",
|
||||
name=AGENT_FILE_ELF.name,
|
||||
file=AGENT_FILE_ELF,
|
||||
target=AGENT_TARGET),
|
||||
]
|
||||
outputs[group] = [
|
||||
Output(identifier="helper_legacy",
|
||||
name=HELPER_FILE_UNIX.name,
|
||||
file=HELPER_FILE_UNIX,
|
||||
target=HELPER_TARGET),
|
||||
Output(identifier="agent_legacy",
|
||||
name=AGENT_FILE_ELF.name,
|
||||
file=AGENT_FILE_ELF,
|
||||
target=AGENT_TARGET),
|
||||
]
|
||||
if "gadget" in components:
|
||||
outputs[group] += [
|
||||
Output(identifier="gadget_legacy",
|
||||
@@ -326,24 +284,18 @@ def setup(role: Role,
|
||||
continue
|
||||
else:
|
||||
emulated_triplet = None
|
||||
group = OutputGroup(emulated_arch, emulated_triplet, extra_environ)
|
||||
outputs[group] = []
|
||||
if "helper" in components:
|
||||
outputs[group] += [
|
||||
Output(identifier=f"helper_emulated_{kind}",
|
||||
name=HELPER_FILE_WINDOWS.name.replace(".exe", f"-{emulated_arch}.exe"),
|
||||
file=HELPER_FILE_WINDOWS,
|
||||
target=HELPER_TARGET),
|
||||
]
|
||||
if "agent" in components:
|
||||
outputs[group] += [
|
||||
Output(identifier=f"agent_emulated_{kind}",
|
||||
name=AGENT_FILE_WINDOWS.name.replace(".dll", f"-{emulated_arch}.dll"),
|
||||
file=AGENT_FILE_WINDOWS,
|
||||
target=AGENT_TARGET),
|
||||
]
|
||||
outputs[OutputGroup(emulated_arch, emulated_triplet, extra_environ)] = [
|
||||
Output(identifier=f"helper_emulated_{kind}",
|
||||
name=HELPER_FILE_WINDOWS.name.replace(".exe", f"-{emulated_arch}.exe"),
|
||||
file=HELPER_FILE_WINDOWS,
|
||||
target=HELPER_TARGET),
|
||||
Output(identifier=f"agent_emulated_{kind}",
|
||||
name=AGENT_FILE_WINDOWS.name.replace(".dll", f"-{emulated_arch}.dll"),
|
||||
file=AGENT_FILE_WINDOWS,
|
||||
target=AGENT_TARGET),
|
||||
]
|
||||
|
||||
if host_os == "android" and host_arch in {"x86_64", "x86"} and "agent" in components:
|
||||
if host_os == "android" and host_arch in {"x86_64", "x86"}:
|
||||
outputs[OutputGroup("arm")] = [
|
||||
Output(identifier="agent_emulated_legacy",
|
||||
name="frida-agent-arm.so",
|
||||
@@ -358,46 +310,10 @@ def setup(role: Role,
|
||||
target=AGENT_TARGET),
|
||||
]
|
||||
|
||||
if glib_flavor == "upstream":
|
||||
kind = "modern" if arch_is_modern(host_os, host_arch) else "legacy"
|
||||
_, agent_file, gadget_file = native_file_paths(host_os)
|
||||
group = OutputGroup(host_arch)
|
||||
outputs[group] = []
|
||||
if "agent" in components:
|
||||
outputs[group] += [
|
||||
Output(identifier=f"agent_{kind}",
|
||||
name=arch_suffixed_name(agent_file.name, host_arch),
|
||||
file=agent_file,
|
||||
target=AGENT_TARGET),
|
||||
]
|
||||
if "gadget" in components:
|
||||
outputs[group] += [
|
||||
Output(identifier=f"gadget_{kind}",
|
||||
name=arch_suffixed_name(gadget_file.name, host_arch),
|
||||
file=gadget_file,
|
||||
target=GADGET_TARGET),
|
||||
]
|
||||
elif apple_tls == "enabled" and "agent" in components:
|
||||
kind = "modern" if arch_is_modern(host_os, host_arch) else "legacy"
|
||||
_, agent_file, _ = native_file_paths(host_os)
|
||||
group = OutputGroup(host_arch)
|
||||
outputs.setdefault(group, [])
|
||||
outputs[group] += [
|
||||
Output(identifier=f"agent_{kind}",
|
||||
name=arch_suffixed_name(agent_file.name, host_arch),
|
||||
file=agent_file,
|
||||
target=AGENT_TARGET),
|
||||
]
|
||||
|
||||
outputs = OrderedDict((g, items) for g, items in outputs.items() if items)
|
||||
|
||||
raw_allowed_prebuilds = os.environ.get("FRIDA_ALLOWED_PREBUILDS")
|
||||
if raw_allowed_prebuilds is not None:
|
||||
allowed_prebuilds = set(filter(None, raw_allowed_prebuilds.split(",")))
|
||||
else:
|
||||
allowed_prebuilds = None
|
||||
allowed_prebuilds = set(raw_allowed_prebuilds.split(",")) if raw_allowed_prebuilds is not None else None
|
||||
|
||||
state = State(role, builddir, top_builddir, frida_version, host_os, host_os_family, host_config, glib_flavor, apple_tls, allowed_prebuilds, outputs)
|
||||
state = State(role, builddir, top_builddir, frida_version, host_os, host_config, allowed_prebuilds, outputs)
|
||||
serialized_state = base64.b64encode(pickle.dumps(state)).decode('ascii')
|
||||
|
||||
if missing:
|
||||
@@ -433,10 +349,7 @@ class State:
|
||||
top_builddir: Path
|
||||
frida_version: str
|
||||
host_os: str
|
||||
host_os_family: str
|
||||
host_config: Optional[str]
|
||||
glib_flavor: str
|
||||
apple_tls: str
|
||||
allowed_prebuilds: Optional[set[str]]
|
||||
outputs: Mapping[OutputGroup, Sequence[Output]]
|
||||
|
||||
@@ -516,35 +429,20 @@ def compile(privdir: Path, state: State):
|
||||
|
||||
host_machine = MachineSpec(state.host_os, group.arch, state.host_config, group.triplet)
|
||||
|
||||
if state.glib_flavor == "upstream":
|
||||
allowed = None
|
||||
else:
|
||||
allowed = state.allowed_prebuilds
|
||||
|
||||
if state.glib_flavor == "upstream":
|
||||
forwarded_options = [o for o in options if not is_stripped_compat_option(o)]
|
||||
forwarded_options += ["-Ddefault_library=static"]
|
||||
else:
|
||||
forwarded_options = [o for o in options if not is_overridden_compat_option(o)]
|
||||
if state.apple_tls == "enabled":
|
||||
forwarded_options += ["-Dapple_tls=disabled"]
|
||||
|
||||
configure(sourcedir=REPO_ROOT,
|
||||
builddir=workdir,
|
||||
host_machine=host_machine,
|
||||
environ={**build_env, **group.extra_environ},
|
||||
allowed_prebuilds=allowed,
|
||||
apple_min_os=detect_parent_apple_min_os(top_builddir, state.host_os, state.host_os_family),
|
||||
allowed_prebuilds=state.allowed_prebuilds,
|
||||
extra_meson_options=[
|
||||
"-Dcompiler_backend=disabled",
|
||||
"-Dassets=installed",
|
||||
"-Dhelper_modern=",
|
||||
"-Dhelper_legacy=",
|
||||
"-Dagent_modern=",
|
||||
"-Dagent_legacy=",
|
||||
"-Dagent_emulated_modern=",
|
||||
"-Dagent_emulated_legacy=",
|
||||
*forwarded_options,
|
||||
*options,
|
||||
],
|
||||
call_meson=call_internal_meson,
|
||||
on_progress=lambda progress: None)
|
||||
@@ -575,18 +473,6 @@ def compile(privdir: Path, state: State):
|
||||
(state.builddir / DEPFILE_FILENAME).write_text("\n".join(depfile_lines), encoding="utf-8")
|
||||
|
||||
|
||||
def is_stripped_compat_option(o: str) -> bool:
|
||||
if is_overridden_compat_option(o):
|
||||
return True
|
||||
name = o.split("=", 1)[0].removeprefix("-D")
|
||||
return name in STRIPPED_COMPAT_OPTIONS or name.endswith(":default_library")
|
||||
|
||||
|
||||
def is_overridden_compat_option(o: str) -> bool:
|
||||
name = o.split("=", 1)[0].removeprefix("-D")
|
||||
return name in OVERRIDDEN_COMPAT_OPTIONS
|
||||
|
||||
|
||||
def load_meson_options(top_builddir: Path,
|
||||
role: Role,
|
||||
subprojects: set[str]) -> Sequence[str]:
|
||||
@@ -624,11 +510,7 @@ def option_should_be_forwarded(k: "OptionKey",
|
||||
return is_for_us or is_for_child
|
||||
|
||||
if coredata.CoreData.is_per_machine_option(k):
|
||||
# The compat build generates its own machine files, so forwarding the
|
||||
# parent's build-machine options would inject a foreign toolchain. In a
|
||||
# native compat build that conjures a compiler-less build machine and
|
||||
# breaks any native: true target.
|
||||
return False
|
||||
return k.machine is coredata.MachineChoice.BUILD
|
||||
|
||||
if k.is_builtin():
|
||||
if k.name in {"buildtype", "genvslite"}:
|
||||
@@ -700,19 +582,6 @@ def ensure_submodules_checked_out(releng_location: Path):
|
||||
check=True)
|
||||
|
||||
|
||||
def detect_parent_apple_min_os(top_builddir: Path,
|
||||
host_os: str,
|
||||
host_os_family: str) -> Optional[Mapping[str, str]]:
|
||||
if host_os_family != "darwin":
|
||||
return None
|
||||
pattern = re.compile(r"-target['\"],\s*['\"][^-]+-apple-" + re.escape(host_os) + r"([0-9.]+)")
|
||||
for native_file in top_builddir.glob(f"frida-{host_os}-*.txt"):
|
||||
match = pattern.search(native_file.read_text(encoding="utf-8"))
|
||||
if match is not None:
|
||||
return {host_os: match.group(1)}
|
||||
return None
|
||||
|
||||
|
||||
def detect_relevant_subprojects(releng_location: Path) -> dict[str, Path]:
|
||||
subprojects = detect_relevant_subprojects_in(REPO_ROOT, releng_location)
|
||||
gum_location = subprojects.get("frida-gum")
|
||||
@@ -763,48 +632,9 @@ def detect_mingw_toolchain_for(arch: str) -> Tuple[bool, Optional[str]]:
|
||||
return (found, triplet)
|
||||
|
||||
|
||||
def arch_is_modern(host_os: str, host_arch: str) -> bool:
|
||||
if host_os in {"macos", "ios", "tvos"} and host_arch == "arm64":
|
||||
return host_arch == "arm64e"
|
||||
return host_arch in MODERN_ARCHS
|
||||
|
||||
|
||||
def native_file_paths(host_os: str) -> Tuple[Path, Path, Path]:
|
||||
if host_os == "windows":
|
||||
return (HELPER_FILE_WINDOWS, AGENT_FILE_WINDOWS, GADGET_FILE_WINDOWS)
|
||||
elif host_os in {"macos", "ios", "tvos"}:
|
||||
return (HELPER_FILE_UNIX, AGENT_FILE_DARWIN, GADGET_FILE_DARWIN)
|
||||
else:
|
||||
return (HELPER_FILE_UNIX, AGENT_FILE_ELF, GADGET_FILE_ELF)
|
||||
|
||||
|
||||
def arch_suffixed_name(name: str, arch: str) -> str:
|
||||
stem, _, ext = name.partition(".")
|
||||
if ext:
|
||||
return f"{stem}-{arch}.{ext}"
|
||||
return f"{stem}-{arch}"
|
||||
|
||||
|
||||
STATE_FILENAME = "state.dat"
|
||||
DEPFILE_FILENAME = "compat.deps"
|
||||
|
||||
STRIPPED_COMPAT_OPTIONS = {
|
||||
"default_library",
|
||||
"frida-gum:gumjs",
|
||||
"frida-gum:inspector",
|
||||
}
|
||||
|
||||
OVERRIDDEN_COMPAT_OPTIONS = {
|
||||
"compiler_backend",
|
||||
"assets",
|
||||
"helper_modern",
|
||||
"helper_legacy",
|
||||
"agent_modern",
|
||||
"agent_legacy",
|
||||
"agent_emulated_modern",
|
||||
"agent_emulated_legacy",
|
||||
}
|
||||
|
||||
HELPER_TARGET = "frida-helper"
|
||||
HELPER_FILE_WINDOWS = Path("src") / "frida-helper.exe"
|
||||
HELPER_FILE_UNIX = Path("src") / "frida-helper"
|
||||
@@ -829,8 +659,6 @@ MSVS_ENVVARS = {
|
||||
"LIB",
|
||||
}
|
||||
|
||||
MODERN_ARCHS = {"x86_64", "arm64", "arm64e", "mips64", "riscv64"}
|
||||
|
||||
MINGW_ARCHS = {
|
||||
"x86": "i686",
|
||||
"arm64": "aarch64",
|
||||
|
||||
@@ -1,15 +0,0 @@
|
||||
import os
|
||||
import shutil
|
||||
import sys
|
||||
|
||||
src = sys.argv[1]
|
||||
install_subdir = sys.argv[2]
|
||||
install_name = sys.argv[3]
|
||||
|
||||
destdir_prefix = os.environ["MESON_INSTALL_DESTDIR_PREFIX"]
|
||||
dst_dir = os.path.join(destdir_prefix, install_subdir)
|
||||
dst = os.path.join(dst_dir, install_name)
|
||||
|
||||
os.makedirs(dst_dir, exist_ok=True)
|
||||
shutil.copy2(src, dst)
|
||||
print(f"Installing {os.path.basename(src)} to {dst_dir}/{install_name}")
|
||||
+3
-47
@@ -8,7 +8,6 @@ helper_depends = []
|
||||
agent_modern = get_option('agent_modern')
|
||||
agent_legacy = get_option('agent_legacy')
|
||||
agent_compat = ''
|
||||
agent_host_compat = ''
|
||||
agent_emulated_modern = get_option('agent_emulated_modern')
|
||||
agent_emulated_legacy = get_option('agent_emulated_legacy')
|
||||
agent_depends = []
|
||||
@@ -29,9 +28,6 @@ if no_overridden_compat_bits
|
||||
build_py = [python, files('build.py')]
|
||||
|
||||
components = []
|
||||
if have_local_backend
|
||||
components += ['helper', 'agent']
|
||||
endif
|
||||
if build_gadget
|
||||
components += 'gadget'
|
||||
endif
|
||||
@@ -46,14 +42,11 @@ if no_overridden_compat_bits
|
||||
meson.global_build_root(),
|
||||
frida_version,
|
||||
host_os,
|
||||
host_os_family,
|
||||
host_abi,
|
||||
host_config,
|
||||
','.join(get_option('compat')),
|
||||
assets_mode,
|
||||
get_option('assets'),
|
||||
','.join(components),
|
||||
have_shared_glib ? 'upstream' : 'frida',
|
||||
use_apple_tls ? 'enabled' : 'disabled',
|
||||
'--',
|
||||
'>>>', cc.cmd_array(), '<<<',
|
||||
'>>>', cpp.cmd_array(), '<<<',
|
||||
@@ -71,27 +64,18 @@ if no_overridden_compat_bits
|
||||
depfile = lines[4]
|
||||
state = lines[5]
|
||||
|
||||
native_arch_suffix = '-' + host_abi
|
||||
|
||||
if host_os_family == 'darwin'
|
||||
install = false
|
||||
install_dir = asset_dir
|
||||
else
|
||||
install = true
|
||||
install_dir = []
|
||||
i = 0
|
||||
foreach varname : varnames
|
||||
output_name = outputs[i]
|
||||
needs_rename = output_name.contains(native_arch_suffix) or varname.contains('_emulated_')
|
||||
should_install = varname != 'arch_support_bundle' \
|
||||
and not needs_rename \
|
||||
and (assets_mode == 'installed' or varname.startswith('gadget_'))
|
||||
if should_install
|
||||
if varname != 'arch_support_bundle' and (get_option('assets') == 'installed' or varname.startswith('gadget_'))
|
||||
install_dir += varname.endswith('_modern') ? asset_dir_modern : asset_dir_legacy
|
||||
else
|
||||
install_dir += false
|
||||
endif
|
||||
i += 1
|
||||
endforeach
|
||||
endif
|
||||
|
||||
@@ -112,7 +96,6 @@ if no_overridden_compat_bits
|
||||
foreach output : arch_support.to_list()
|
||||
outpath = output.full_path()
|
||||
varname = varnames[i]
|
||||
output_name = outputs[i]
|
||||
|
||||
set_variable(varname, outpath)
|
||||
|
||||
@@ -120,11 +103,7 @@ if no_overridden_compat_bits
|
||||
helper_compat = outpath
|
||||
helper_depends += arch_support
|
||||
elif varname.startswith('agent_')
|
||||
if output_name.contains('-' + host_abi + '.')
|
||||
agent_host_compat = outpath
|
||||
else
|
||||
agent_compat = outpath
|
||||
endif
|
||||
agent_compat = outpath
|
||||
agent_depends += arch_support
|
||||
elif varname.startswith('gadget_')
|
||||
gadget_compat = outpath
|
||||
@@ -136,29 +115,6 @@ if no_overridden_compat_bits
|
||||
assert(false, f'unexpected variable name: @varname@')
|
||||
endif
|
||||
|
||||
if host_os_family != 'darwin'
|
||||
rename_target_dir = ''
|
||||
if output_name.contains(native_arch_suffix)
|
||||
rename_target_dir = asset_dir
|
||||
elif varname.contains('_emulated_')
|
||||
emulated_arch = output_name.split('-')[-1].split('.')[0]
|
||||
rename_target_dir = root_asset_dir / emulated_arch
|
||||
endif
|
||||
if rename_target_dir != ''
|
||||
install_name = output_name.replace(native_arch_suffix, '')
|
||||
foreach arch_suffix : ['-x86_64', '-x86', '-arm64', '-arm']
|
||||
install_name = install_name.replace(arch_suffix, '')
|
||||
endforeach
|
||||
if assets_mode == 'installed' or varname.startswith('gadget_')
|
||||
meson.add_install_script(python, files('install-renamed.py'),
|
||||
outpath,
|
||||
rename_target_dir,
|
||||
install_name,
|
||||
)
|
||||
endif
|
||||
endif
|
||||
endif
|
||||
|
||||
i += 1
|
||||
endforeach
|
||||
else
|
||||
|
||||
File renamed without changes.
File renamed without changes.
+15
-2
@@ -4,14 +4,27 @@ inject_sources = [
|
||||
]
|
||||
|
||||
system_vala_args = []
|
||||
|
||||
if host_os_family != 'windows'
|
||||
system_vala_args += ['--pkg=posix']
|
||||
endif
|
||||
|
||||
extra_link_args = []
|
||||
extra_link_depends = []
|
||||
if host_os_family == 'darwin'
|
||||
symlist = 'frida-inject.symbols'
|
||||
extra_link_args += ['-Wl,-exported_symbols_list,' + meson.current_source_dir() / symlist]
|
||||
extra_link_depends += [symlist]
|
||||
elif host_os_family != 'windows'
|
||||
symscript = 'frida-inject.version'
|
||||
extra_link_args += ['-Wl,--version-script,' + meson.current_source_dir() / symscript]
|
||||
extra_link_depends += [symscript]
|
||||
endif
|
||||
|
||||
raw_inject = executable('frida-inject-raw', inject_sources,
|
||||
vala_args: [core_vala_args, system_vala_args],
|
||||
link_args: executable_no_exports_link_args,
|
||||
link_depends: executable_no_exports_link_depends,
|
||||
link_args: extra_link_args,
|
||||
link_depends: extra_link_depends,
|
||||
dependencies: [json_glib_dep, core_dep],
|
||||
)
|
||||
|
||||
|
||||
+2
-46
@@ -9,48 +9,8 @@
|
||||
# include <signal.h>
|
||||
# endif
|
||||
#endif
|
||||
#if defined (HAVE_GIOAPPLE)
|
||||
# include <gioapple.h>
|
||||
#elif defined (HAVE_GIOOPENSSL)
|
||||
#ifdef HAVE_GIOOPENSSL
|
||||
# include <gioopenssl.h>
|
||||
#endif
|
||||
#ifdef HAVE_PROSPERO
|
||||
# include "frida-prospero.h"
|
||||
# include <unistd.h>
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_PROSPERO
|
||||
|
||||
FridaProsperoAgentArgs frida_prospero_agent_args = { .fifo_fd = -1 };
|
||||
|
||||
int
|
||||
main (int argc, char * argv[], char * envp[])
|
||||
{
|
||||
FridaProsperoAgentArgs * args = &frida_prospero_agent_args;
|
||||
FridaProsperoInjectorState injector_state;
|
||||
guint8 hello_byte = FRIDA_PROSPERO_HELLO_BYTE;
|
||||
FridaUnloadPolicy unload_policy = FRIDA_UNLOAD_POLICY_IMMEDIATE;
|
||||
guint8 policy_byte;
|
||||
guint32 worker_id;
|
||||
|
||||
injector_state.fifo_fd = args->fifo_fd;
|
||||
injector_state.agent_ctrlfd = args->agent_ctrlfd;
|
||||
injector_state.mapped_range = &args->mapped_range;
|
||||
|
||||
write (injector_state.fifo_fd, &hello_byte, sizeof (hello_byte));
|
||||
|
||||
frida_agent_main (GSIZE_TO_POINTER (args->agent_parameters), &unload_policy, &injector_state);
|
||||
|
||||
policy_byte = unload_policy;
|
||||
worker_id = gum_process_get_current_thread_id ();
|
||||
|
||||
write (injector_state.fifo_fd, &policy_byte, sizeof (policy_byte));
|
||||
write (injector_state.fifo_fd, &worker_id, sizeof (worker_id));
|
||||
close (injector_state.fifo_fd);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
void
|
||||
@@ -71,9 +31,7 @@ _frida_agent_environment_init (void)
|
||||
|
||||
g_thread_set_garbage_handler (_frida_agent_on_pending_thread_garbage, NULL);
|
||||
|
||||
#if defined (HAVE_GIOAPPLE)
|
||||
g_io_module_apple_register ();
|
||||
#elif defined (HAVE_GIOOPENSSL)
|
||||
#ifdef HAVE_GIOOPENSSL
|
||||
g_io_module_openssl_register ();
|
||||
#endif
|
||||
|
||||
@@ -93,8 +51,6 @@ void
|
||||
_frida_agent_environment_deinit (void)
|
||||
{
|
||||
#ifndef HAVE_MUSL
|
||||
frida_libc_shim_prepare_to_deinit ();
|
||||
|
||||
gum_shutdown ();
|
||||
gio_shutdown ();
|
||||
glib_shutdown ();
|
||||
|
||||
+11
-50
@@ -117,8 +117,6 @@ namespace Frida.Agent {
|
||||
void * opaque_injector_state) {
|
||||
Environment._init ();
|
||||
|
||||
apply_linker_notifier_offsets (agent_parameters);
|
||||
|
||||
{
|
||||
Gum.MemoryRange? mapped_range = null;
|
||||
|
||||
@@ -128,12 +126,6 @@ namespace Frida.Agent {
|
||||
mapped_range = injector_state.mapped_range;
|
||||
#endif
|
||||
|
||||
#if PROSPERO
|
||||
var prospero_state = (ProsperoInjectorState *) opaque_injector_state;
|
||||
if (prospero_state != null)
|
||||
mapped_range = prospero_state.mapped_range;
|
||||
#endif
|
||||
|
||||
if (cached_agent_path == null) {
|
||||
cached_agent_range = detect_own_range_and_path (mapped_range, out cached_agent_path);
|
||||
Gum.Cloak.add_range (cached_agent_range);
|
||||
@@ -163,19 +155,6 @@ namespace Frida.Agent {
|
||||
}
|
||||
#endif
|
||||
|
||||
#if PROSPERO
|
||||
string? agent_parameters_with_transport_uri = null;
|
||||
if (prospero_state != null) {
|
||||
int agent_ctrlfd = prospero_state.agent_ctrlfd;
|
||||
prospero_state.agent_ctrlfd = -1;
|
||||
|
||||
fdt_padder.move_descriptor_if_needed (ref agent_ctrlfd);
|
||||
|
||||
agent_parameters_with_transport_uri = "socket:%d%s".printf (agent_ctrlfd, agent_parameters);
|
||||
agent_parameters = agent_parameters_with_transport_uri;
|
||||
}
|
||||
#endif
|
||||
|
||||
var ignore_scope = new ThreadIgnoreScope (FRIDA_THREAD);
|
||||
|
||||
shared_instance = new Runner (agent_parameters, cached_agent_path, cached_agent_range);
|
||||
@@ -207,25 +186,6 @@ namespace Frida.Agent {
|
||||
Environment._deinit ();
|
||||
}
|
||||
|
||||
private static void apply_linker_notifier_offsets (string agent_parameters) {
|
||||
foreach (unowned string token in agent_parameters.split ("|")) {
|
||||
if (!token.has_prefix ("linker-notifier-offsets:"))
|
||||
continue;
|
||||
|
||||
uint[] offsets = {};
|
||||
foreach (unowned string entry in token[24:].split (",")) {
|
||||
uint offset;
|
||||
if (uint.try_parse (entry, out offset))
|
||||
offsets += offset;
|
||||
}
|
||||
|
||||
if (offsets.length != 0)
|
||||
Gum.ModuleRegistry.set_rtld_notifier_offsets (offsets);
|
||||
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
public static void resume_after_transition (ref Frida.UnloadPolicy unload_policy, void * opaque_injector_state) {
|
||||
{
|
||||
#if LINUX || FREEBSD
|
||||
@@ -322,29 +282,30 @@ namespace Frida.Agent {
|
||||
private async void start (owned FileDescriptorTablePadder padder) {
|
||||
string[] tokens = agent_parameters.split ("|");
|
||||
unowned string transport_uri = tokens[0];
|
||||
var exceptor_mode = Gum.ExceptorMode.FULL;
|
||||
bool enable_unwind_broker = true;
|
||||
bool enable_exceptor = true;
|
||||
#if DARWIN
|
||||
enable_exceptor = !Gum.Darwin.query_hardened ();
|
||||
#endif
|
||||
bool enable_exit_monitor = true;
|
||||
bool enable_thread_suspend_monitor = true;
|
||||
bool enable_unwind_sitter = true;
|
||||
foreach (unowned string option in tokens[1:]) {
|
||||
if (option == "eternal")
|
||||
ensure_eternalized ();
|
||||
else if (option == "sticky")
|
||||
stop_thread_on_unload = false;
|
||||
else if (option == "exceptor:off")
|
||||
exceptor_mode = OFF;
|
||||
else if (option == "exceptor:handler-only")
|
||||
exceptor_mode = HANDLER_ONLY;
|
||||
else if (option == "unwind-broker:off")
|
||||
enable_unwind_broker = false;
|
||||
enable_exceptor = false;
|
||||
else if (option == "exit-monitor:off")
|
||||
enable_exit_monitor = false;
|
||||
else if (option == "thread-suspend-monitor:off")
|
||||
enable_thread_suspend_monitor = false;
|
||||
else if (option == "unwind-sitter:off")
|
||||
enable_unwind_sitter = false;
|
||||
}
|
||||
|
||||
if (exceptor_mode != FULL)
|
||||
Gum.Exceptor.set_mode (exceptor_mode);
|
||||
if (!enable_exceptor)
|
||||
Gum.Exceptor.disable ();
|
||||
|
||||
{
|
||||
var interceptor = Gum.Interceptor.obtain ();
|
||||
@@ -356,7 +317,7 @@ namespace Frida.Agent {
|
||||
if (enable_thread_suspend_monitor)
|
||||
thread_suspend_monitor = new ThreadSuspendMonitor (this);
|
||||
|
||||
if (enable_unwind_broker)
|
||||
if (enable_unwind_sitter)
|
||||
unwind_sitter = new UnwindSitter (this);
|
||||
|
||||
this.interceptor = interceptor;
|
||||
|
||||
@@ -1,14 +0,0 @@
|
||||
FRIDA_1.0 {
|
||||
global:
|
||||
frida_agent_main;
|
||||
|
||||
local:
|
||||
*;
|
||||
};
|
||||
|
||||
GLIBC_2.2.5 {
|
||||
local:
|
||||
fopen*;
|
||||
fseeko*;
|
||||
ftello*;
|
||||
} FRIDA_1.0;
|
||||
@@ -1,8 +0,0 @@
|
||||
{
|
||||
global:
|
||||
frida_agent_main;
|
||||
frida_prospero_agent_args;
|
||||
|
||||
local:
|
||||
*;
|
||||
};
|
||||
+91
-124
@@ -1,131 +1,98 @@
|
||||
agent_sources = [
|
||||
'agent.vala',
|
||||
'agent-glue.c',
|
||||
]
|
||||
|
||||
force_cpp_linking = have_v8
|
||||
if force_cpp_linking
|
||||
agent_sources += ['dummy.cpp']
|
||||
endif
|
||||
|
||||
extra_vala_args = []
|
||||
extra_link_args = []
|
||||
extra_link_depends = []
|
||||
|
||||
if host_os_family != 'windows'
|
||||
extra_vala_args += '--pkg=posix'
|
||||
endif
|
||||
if host_os_family == 'darwin'
|
||||
extra_vala_args += '--pkg=frida-gum-darwin-1.0'
|
||||
endif
|
||||
|
||||
if host_os_family == 'windows'
|
||||
if host_toolchain != 'microsoft'
|
||||
symfile = (host_arch == 'x86') ? 'frida-agent-x86.symbols' : 'frida-agent.symbols'
|
||||
extra_link_args += '-Wl,--retain-symbols-file,' + meson.current_source_dir() / symfile
|
||||
extra_link_depends += symfile
|
||||
endif
|
||||
elif host_os_family == 'darwin'
|
||||
extra_link_args += '-Wl,-exported_symbol,_frida_agent_main'
|
||||
else
|
||||
symscript = (host_os == 'android') ? 'frida-agent-android.version' : 'frida-agent.version'
|
||||
extra_link_args += '-Wl,--version-script,' + meson.current_source_dir() / symscript
|
||||
extra_link_depends += symscript
|
||||
endif
|
||||
|
||||
if host_os_family in ['linux', 'qnx']
|
||||
# For our libc shim to be effective.
|
||||
extra_link_args += '-Wl,-Bsymbolic'
|
||||
endif
|
||||
|
||||
raw_agent = shared_library('frida-agent-raw', agent_sources,
|
||||
name_prefix: 'lib',
|
||||
c_args: frida_component_cflags,
|
||||
vala_header: 'frida-agent.h',
|
||||
vala_args: [base_vala_args, payload_vala_args, extra_vala_args],
|
||||
link_args: extra_link_args,
|
||||
link_depends: extra_link_depends,
|
||||
vs_module_defs: 'frida-agent.def',
|
||||
override_options: ['b_asneeded=true'],
|
||||
dependencies: [gio_dep, gee_dep, gum_dep, gumjs_dep, base_dep, pipe_dep, tls_provider_dep, payload_dep],
|
||||
)
|
||||
|
||||
operations = ['--move', 'constructor', 'frida_libc_shim_init', 'first']
|
||||
if host_os_family != 'darwin'
|
||||
operations += ['--move', 'destructor', 'frida_libc_shim_deinit', 'first']
|
||||
endif
|
||||
modulated_agent = custom_target('frida-agent-modulated',
|
||||
input: raw_agent,
|
||||
output: 'libfrida-agent-modulated' + shlib_suffix,
|
||||
command: modulate + operations,
|
||||
)
|
||||
|
||||
need_universal_agent = host_os_family == 'darwin' \
|
||||
and assets_mode == 'installed' \
|
||||
and get_option('assets') == 'installed' \
|
||||
and agent_compat != ''
|
||||
|
||||
# When compat provides the host-arch agent (e.g. when use_apple_tls is on, so
|
||||
# the agent has to be built separately to avoid pulling in Apple frameworks),
|
||||
# skip building it here.
|
||||
build_agent = agent_host_compat == ''
|
||||
|
||||
if build_agent
|
||||
agent_sources = [
|
||||
'agent.vala',
|
||||
'agent-glue.c',
|
||||
]
|
||||
|
||||
force_cpp_linking = have_v8
|
||||
if force_cpp_linking
|
||||
agent_sources += ['dummy.cpp']
|
||||
endif
|
||||
|
||||
extra_vala_args = []
|
||||
extra_link_args = []
|
||||
extra_link_depends = []
|
||||
|
||||
if host_os_family != 'windows'
|
||||
extra_vala_args += '--pkg=posix'
|
||||
endif
|
||||
if host_os_family == 'darwin'
|
||||
extra_vala_args += '--pkg=frida-gum-darwin-1.0'
|
||||
endif
|
||||
|
||||
if host_os_family == 'windows'
|
||||
if host_toolchain != 'microsoft'
|
||||
symfile = (host_arch == 'x86') ? 'frida-agent-x86.symbols' : 'frida-agent.symbols'
|
||||
extra_link_args += '-Wl,--retain-symbols-file,' + meson.current_source_dir() / symfile
|
||||
extra_link_depends += symfile
|
||||
endif
|
||||
elif host_os_family == 'darwin'
|
||||
extra_link_args += '-Wl,-exported_symbol,_frida_agent_main'
|
||||
else
|
||||
if libc == 'glibc'
|
||||
symscript = 'frida-agent-glibc.version'
|
||||
elif host_os == 'android'
|
||||
symscript = 'frida-agent-android.version'
|
||||
elif host_is_prospero
|
||||
symscript = 'frida-agent-prospero.version'
|
||||
else
|
||||
symscript = 'frida-agent.version'
|
||||
endif
|
||||
extra_link_args += '-Wl,--version-script,' + meson.current_source_dir() / symscript
|
||||
extra_link_depends += symscript
|
||||
endif
|
||||
|
||||
if host_os_family in ['linux', 'qnx']
|
||||
# For our libc shim to be effective.
|
||||
extra_link_args += '-Wl,-Bsymbolic'
|
||||
endif
|
||||
|
||||
extra_link_args += prospero_crt_link_args
|
||||
|
||||
raw_agent = shared_library('frida-agent-raw', agent_sources,
|
||||
name_prefix: 'lib',
|
||||
c_args: frida_component_cflags,
|
||||
vala_header: 'frida-agent.h',
|
||||
vala_args: [base_vala_args, payload_vala_args, extra_vala_args],
|
||||
link_args: extra_link_args,
|
||||
link_depends: extra_link_depends,
|
||||
vs_module_defs: 'frida-agent.def',
|
||||
override_options: ['b_asneeded=true'],
|
||||
dependencies: [gio_dep, gee_dep, gum_dep, gumjs_dep, base_dep, pipe_dep, tls_provider_dep, payload_dep],
|
||||
)
|
||||
|
||||
operations = ['--move', 'constructor', 'frida_libc_shim_init', 'first']
|
||||
if host_os_family != 'darwin'
|
||||
operations += ['--move', 'destructor', 'frida_libc_shim_deinit', 'first']
|
||||
endif
|
||||
modulated_agent = custom_target('frida-agent-modulated',
|
||||
input: raw_agent,
|
||||
output: 'libfrida-agent-modulated' + shlib_suffix,
|
||||
command: modulate + operations,
|
||||
)
|
||||
|
||||
if host_os_family == 'darwin'
|
||||
identity = 'FridaAgent'
|
||||
else
|
||||
identity = agent_name
|
||||
endif
|
||||
agent = custom_target('frida-agent',
|
||||
input: modulated_agent,
|
||||
output: need_universal_agent ? f'@agent_name@-@host_abi@' : agent_name,
|
||||
command: post_process + ['shared-library', identity],
|
||||
build_by_default: true,
|
||||
install: assets_mode == 'installed' and not need_universal_agent,
|
||||
install_dir: asset_dir,
|
||||
)
|
||||
|
||||
agent_dep = declare_dependency(link_with: agent)
|
||||
if host_os_family == 'darwin'
|
||||
identity = 'FridaAgent'
|
||||
else
|
||||
identity = agent_name
|
||||
endif
|
||||
agent = custom_target('frida-agent',
|
||||
input: modulated_agent,
|
||||
output: need_universal_agent ? f'@agent_name@-@host_abi@' : agent_name,
|
||||
command: post_process + ['shared-library', identity],
|
||||
build_by_default: true,
|
||||
install: get_option('assets') == 'installed' and not need_universal_agent,
|
||||
install_dir: asset_dir,
|
||||
)
|
||||
|
||||
agent_dep = declare_dependency(link_with: agent)
|
||||
|
||||
if need_universal_agent
|
||||
if build_agent
|
||||
custom_target('frida-agent-universal',
|
||||
input: agent,
|
||||
output: agent_name,
|
||||
command: [
|
||||
lipo,
|
||||
'@INPUT@',
|
||||
agent_compat,
|
||||
'-create',
|
||||
'-output', meson.current_build_dir() / agent_name,
|
||||
],
|
||||
depends: agent_depends,
|
||||
install: true,
|
||||
install_dir: asset_dir,
|
||||
)
|
||||
else
|
||||
custom_target('frida-agent-universal',
|
||||
output: agent_name,
|
||||
command: [
|
||||
lipo,
|
||||
agent_host_compat,
|
||||
agent_compat,
|
||||
'-create',
|
||||
'-output', meson.current_build_dir() / agent_name,
|
||||
],
|
||||
depends: agent_depends,
|
||||
install: true,
|
||||
install_dir: asset_dir,
|
||||
)
|
||||
endif
|
||||
custom_target('frida-agent-universal',
|
||||
input: agent,
|
||||
output: agent_name,
|
||||
command: [
|
||||
lipo,
|
||||
'@INPUT@',
|
||||
agent_compat,
|
||||
'-create',
|
||||
'-output', meson.current_build_dir() / agent_name,
|
||||
],
|
||||
depends: agent_depends,
|
||||
install: true,
|
||||
install_dir: asset_dir,
|
||||
)
|
||||
endif
|
||||
@@ -1,53 +0,0 @@
|
||||
namespace Frida {
|
||||
public class AssetLocation : Object {
|
||||
public string libdir {
|
||||
get;
|
||||
construct;
|
||||
}
|
||||
|
||||
public static AssetLocation detect () {
|
||||
string? module_path = null;
|
||||
Gum.Address our_address = Gum.Address.from_pointer (Gum.strip_code_pointer ((void *) detect));
|
||||
|
||||
Gum.Process.enumerate_modules ((details) => {
|
||||
var range = details.range;
|
||||
if (our_address >= range.base_address && our_address < range.base_address + range.size) {
|
||||
module_path = details.path;
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
});
|
||||
assert (module_path != null);
|
||||
|
||||
string libdir = Path.get_dirname (module_path);
|
||||
string basename = Path.get_basename (libdir).down ();
|
||||
if (basename == "bin" || basename == "sbin") {
|
||||
string parent = Path.get_dirname (libdir);
|
||||
string candidate = Path.build_filename (parent, Config.FRIDA_LIBDIR);
|
||||
if (FileUtils.test (candidate, IS_DIR))
|
||||
libdir = candidate;
|
||||
}
|
||||
|
||||
return new AssetLocation (libdir);
|
||||
}
|
||||
|
||||
private AssetLocation (string libdir) {
|
||||
Object (libdir: libdir);
|
||||
}
|
||||
|
||||
public string derive_asset_path (string arch, string filename) {
|
||||
string root = Path.build_filename (libdir, Config.FRIDA_LIBDIR_NAME);
|
||||
if (FileUtils.test (root, IS_DIR))
|
||||
#if DARWIN
|
||||
return Path.build_filename (root, filename);
|
||||
#else
|
||||
return Path.build_filename (root, arch, filename);
|
||||
#endif
|
||||
return Path.build_filename (libdir, filename);
|
||||
}
|
||||
|
||||
public string derive_plugin_path (string filename) {
|
||||
return Path.build_filename (libdir, Config.FRIDA_LIBDIR_NAME, "plugins", filename);
|
||||
}
|
||||
}
|
||||
}
|
||||
+127
-262
@@ -309,17 +309,8 @@ namespace Frida {
|
||||
|
||||
public sealed class Buffer : Object {
|
||||
public Bytes bytes {
|
||||
get {
|
||||
if (_bytes == null)
|
||||
_bytes = new Bytes.static (_data);
|
||||
return _bytes;
|
||||
}
|
||||
}
|
||||
|
||||
public size_t size {
|
||||
get {
|
||||
return _data.length;
|
||||
}
|
||||
get;
|
||||
construct;
|
||||
}
|
||||
|
||||
public ByteOrder byte_order {
|
||||
@@ -332,39 +323,20 @@ namespace Frida {
|
||||
construct;
|
||||
}
|
||||
|
||||
private Bytes? _bytes;
|
||||
private unowned uint8[] _data;
|
||||
private unowned uint8 * data;
|
||||
private size_t size;
|
||||
|
||||
public Buffer (Bytes bytes, ByteOrder byte_order = HOST, uint pointer_size = (uint) sizeof (size_t)) {
|
||||
Object (
|
||||
bytes: bytes,
|
||||
byte_order: byte_order,
|
||||
pointer_size: pointer_size
|
||||
);
|
||||
|
||||
reset_bytes (bytes);
|
||||
}
|
||||
|
||||
public Buffer.from_data (uint8[] data, ByteOrder byte_order = HOST, uint pointer_size = (uint) sizeof (size_t)) {
|
||||
Object (
|
||||
byte_order: byte_order,
|
||||
pointer_size: pointer_size
|
||||
);
|
||||
|
||||
reset_data (data);
|
||||
}
|
||||
|
||||
public void reset_bytes (Bytes bytes) {
|
||||
_bytes = bytes;
|
||||
_data = bytes.get_data ();
|
||||
}
|
||||
|
||||
public void reset_data (uint8[] data) {
|
||||
_bytes = null;
|
||||
_data = data;
|
||||
}
|
||||
|
||||
public unowned uint8[] peek_data () {
|
||||
return _data;
|
||||
construct {
|
||||
data = bytes.get_data ();
|
||||
size = bytes.get_size ();
|
||||
}
|
||||
|
||||
public uint64 read_pointer (size_t offset) {
|
||||
@@ -498,13 +470,17 @@ namespace Frida {
|
||||
return *((double *) &bits);
|
||||
}
|
||||
|
||||
public unowned string read_string (size_t offset) throws Error {
|
||||
public string read_string (size_t offset) throws Error {
|
||||
string * start = (string *) get_pointer (offset, sizeof (char));
|
||||
size_t max_length = _data.length - offset;
|
||||
size_t max_length = size - offset;
|
||||
string * end = memchr (start, 0, max_length);
|
||||
if (end == null)
|
||||
throw new Error.PROTOCOL ("Missing null character");
|
||||
return start;
|
||||
size_t size = end - start;
|
||||
string val = start->substring (0, (long) size);
|
||||
if (!val.validate ())
|
||||
throw new Error.PROTOCOL ("Invalid UTF-8 string");
|
||||
return val;
|
||||
}
|
||||
|
||||
[CCode (cname = "memchr", cheader_filename = "string.h")]
|
||||
@@ -512,14 +488,17 @@ namespace Frida {
|
||||
|
||||
public string read_fixed_string (size_t offset, size_t size) throws Error {
|
||||
string * start = (string *) get_pointer (offset, size);
|
||||
size_t max_length = size_t.min (size, _data.length - offset);
|
||||
size_t max_length = size_t.min (size, this.size - offset);
|
||||
string * end = memchr (start, 0, max_length);
|
||||
size_t n;
|
||||
if (end != null)
|
||||
n = end - start;
|
||||
else
|
||||
n = size;
|
||||
return start->substring (0, (long) n);
|
||||
string val = start->substring (0, (long) n);
|
||||
if (!val.validate ())
|
||||
throw new Error.PROTOCOL ("Invalid UTF-8 string");
|
||||
return val;
|
||||
}
|
||||
|
||||
public unowned Buffer write_string (size_t offset, string val) {
|
||||
@@ -529,14 +508,9 @@ namespace Frida {
|
||||
}
|
||||
|
||||
public Bytes read_bytes (size_t offset, size_t size) {
|
||||
if (_bytes == null)
|
||||
return make_bytes_with_owner ((uint8 *) _data + offset, _data.length - size, this);
|
||||
return _bytes[offset:offset + size];
|
||||
}
|
||||
|
||||
public unowned uint8[] read_data (size_t offset, size_t size) {
|
||||
unowned uint8 * ptr = get_pointer (offset, size);
|
||||
return ((uint8[]) ptr)[:size];
|
||||
var data = new uint8[size + 1];
|
||||
Memory.copy (data, get_pointer (offset, size), size);
|
||||
return new Bytes.take ((owned) data);
|
||||
}
|
||||
|
||||
public unowned Buffer write_bytes (size_t offset, Bytes bytes) {
|
||||
@@ -547,49 +521,129 @@ namespace Frida {
|
||||
|
||||
private uint8 * get_pointer (size_t offset, size_t n) {
|
||||
size_t minimum_size = offset + n;
|
||||
assert (_data.length >= minimum_size);
|
||||
return (uint8 *) _data + offset;
|
||||
assert (size >= minimum_size);
|
||||
|
||||
return data + offset;
|
||||
}
|
||||
}
|
||||
|
||||
public sealed class BufferReader {
|
||||
public Buffer buffer {
|
||||
get;
|
||||
}
|
||||
|
||||
public size_t offset {
|
||||
get;
|
||||
get {
|
||||
return _offset;
|
||||
}
|
||||
}
|
||||
|
||||
public size_t available {
|
||||
get {
|
||||
return _size - _offset;
|
||||
return buffer.bytes.get_size () - _offset;
|
||||
}
|
||||
}
|
||||
|
||||
private size_t _size;
|
||||
private Buffer buffer;
|
||||
private size_t _offset = 0;
|
||||
|
||||
public BufferReader (Buffer buffer) {
|
||||
reset (buffer);
|
||||
public BufferReader (Buffer buf) {
|
||||
buffer = buf;
|
||||
}
|
||||
|
||||
public void reset (Buffer buffer) {
|
||||
_buffer = buffer;
|
||||
_size = buffer.size;
|
||||
_offset = 0;
|
||||
public uint64 read_pointer () throws Error {
|
||||
var pointer_size = buffer.pointer_size;
|
||||
check_available (pointer_size);
|
||||
var ptr = buffer.read_pointer (_offset);
|
||||
_offset += pointer_size;
|
||||
return ptr;
|
||||
}
|
||||
|
||||
public void reset_at (Buffer buffer, size_t offset) throws Error {
|
||||
_buffer = buffer;
|
||||
_size = buffer.size;
|
||||
seek (offset);
|
||||
public int8 read_int8 () throws Error {
|
||||
check_available (sizeof (int8));
|
||||
var val = buffer.read_int8 (_offset);
|
||||
_offset += sizeof (int8);
|
||||
return val;
|
||||
}
|
||||
|
||||
public unowned BufferReader seek (size_t offset) throws Error {
|
||||
if (offset > _size)
|
||||
throw new Error.PROTOCOL ("Malformed buffer: truncated");
|
||||
_offset = offset;
|
||||
return this;
|
||||
public uint8 read_uint8 () throws Error {
|
||||
check_available (sizeof (uint8));
|
||||
var val = buffer.read_uint8 (_offset);
|
||||
_offset += sizeof (uint8);
|
||||
return val;
|
||||
}
|
||||
|
||||
public int16 read_int16 () throws Error {
|
||||
check_available (sizeof (int16));
|
||||
var val = buffer.read_int16 (_offset);
|
||||
_offset += sizeof (int16);
|
||||
return val;
|
||||
}
|
||||
|
||||
public uint16 read_uint16 () throws Error {
|
||||
check_available (sizeof (uint16));
|
||||
var val = buffer.read_uint16 (_offset);
|
||||
_offset += sizeof (uint16);
|
||||
return val;
|
||||
}
|
||||
|
||||
public int32 read_int32 () throws Error {
|
||||
check_available (sizeof (int32));
|
||||
var val = buffer.read_int32 (_offset);
|
||||
_offset += sizeof (int32);
|
||||
return val;
|
||||
}
|
||||
|
||||
public uint32 read_uint32 () throws Error {
|
||||
check_available (sizeof (uint32));
|
||||
var val = buffer.read_uint32 (_offset);
|
||||
_offset += sizeof (uint32);
|
||||
return val;
|
||||
}
|
||||
|
||||
public int64 read_int64 () throws Error {
|
||||
check_available (sizeof (int64));
|
||||
var val = buffer.read_int64 (_offset);
|
||||
_offset += sizeof (int64);
|
||||
return val;
|
||||
}
|
||||
|
||||
public uint64 read_uint64 () throws Error {
|
||||
check_available (sizeof (uint64));
|
||||
var val = buffer.read_uint64 (_offset);
|
||||
_offset += sizeof (uint64);
|
||||
return val;
|
||||
}
|
||||
|
||||
public float read_float () throws Error {
|
||||
check_available (sizeof (float));
|
||||
var val = buffer.read_float (_offset);
|
||||
_offset += sizeof (float);
|
||||
return val;
|
||||
}
|
||||
|
||||
public double read_double () throws Error {
|
||||
check_available (sizeof (double));
|
||||
var val = buffer.read_double (_offset);
|
||||
_offset += sizeof (double);
|
||||
return val;
|
||||
}
|
||||
|
||||
public string read_string () throws Error {
|
||||
check_available (1);
|
||||
var val = buffer.read_string (_offset);
|
||||
_offset += val.length + 1;
|
||||
return val;
|
||||
}
|
||||
|
||||
public string read_fixed_string (size_t size) throws Error {
|
||||
check_available (size);
|
||||
var val = buffer.read_fixed_string (_offset, size);
|
||||
_offset += size;
|
||||
return val;
|
||||
}
|
||||
|
||||
public Bytes read_bytes (size_t size) throws Error {
|
||||
check_available (size);
|
||||
var val = buffer.bytes[_offset:_offset + size];
|
||||
_offset += size;
|
||||
return val;
|
||||
}
|
||||
|
||||
public unowned BufferReader skip (size_t n) throws Error {
|
||||
@@ -598,195 +652,6 @@ namespace Frida {
|
||||
return this;
|
||||
}
|
||||
|
||||
public unowned BufferReader align (size_t alignment) throws Error {
|
||||
size_t mask = alignment - 1;
|
||||
size_t rem = _offset & mask;
|
||||
if (rem != 0)
|
||||
skip (alignment - rem);
|
||||
return this;
|
||||
}
|
||||
|
||||
public uint64 peek_pointer () throws Error {
|
||||
var pointer_size = _buffer.pointer_size;
|
||||
check_available (pointer_size);
|
||||
return _buffer.read_pointer (_offset);
|
||||
}
|
||||
|
||||
public uint64 read_pointer () throws Error {
|
||||
var pointer_size = _buffer.pointer_size;
|
||||
check_available (pointer_size);
|
||||
var ptr = _buffer.read_pointer (_offset);
|
||||
_offset += pointer_size;
|
||||
return ptr;
|
||||
}
|
||||
|
||||
public int8 peek_int8 () throws Error {
|
||||
check_available (sizeof (int8));
|
||||
return _buffer.read_int8 (_offset);
|
||||
}
|
||||
|
||||
public int8 read_int8 () throws Error {
|
||||
check_available (sizeof (int8));
|
||||
var val = _buffer.read_int8 (_offset);
|
||||
_offset += sizeof (int8);
|
||||
return val;
|
||||
}
|
||||
|
||||
public uint8 peek_uint8 () throws Error {
|
||||
check_available (sizeof (uint8));
|
||||
return _buffer.read_uint8 (_offset);
|
||||
}
|
||||
|
||||
public uint8 read_uint8 () throws Error {
|
||||
check_available (sizeof (uint8));
|
||||
var val = _buffer.read_uint8 (_offset);
|
||||
_offset += sizeof (uint8);
|
||||
return val;
|
||||
}
|
||||
|
||||
public int16 peek_int16 () throws Error {
|
||||
check_available (sizeof (int16));
|
||||
return _buffer.read_int16 (_offset);
|
||||
}
|
||||
|
||||
public int16 read_int16 () throws Error {
|
||||
check_available (sizeof (int16));
|
||||
var val = _buffer.read_int16 (_offset);
|
||||
_offset += sizeof (int16);
|
||||
return val;
|
||||
}
|
||||
|
||||
public uint16 peek_uint16 () throws Error {
|
||||
check_available (sizeof (uint16));
|
||||
return _buffer.read_uint16 (_offset);
|
||||
}
|
||||
|
||||
public uint16 read_uint16 () throws Error {
|
||||
check_available (sizeof (uint16));
|
||||
var val = _buffer.read_uint16 (_offset);
|
||||
_offset += sizeof (uint16);
|
||||
return val;
|
||||
}
|
||||
|
||||
public int32 peek_int32 () throws Error {
|
||||
check_available (sizeof (int32));
|
||||
return _buffer.read_int32 (_offset);
|
||||
}
|
||||
|
||||
public int32 read_int32 () throws Error {
|
||||
check_available (sizeof (int32));
|
||||
var val = _buffer.read_int32 (_offset);
|
||||
_offset += sizeof (int32);
|
||||
return val;
|
||||
}
|
||||
|
||||
public uint32 peek_uint32 () throws Error {
|
||||
check_available (sizeof (uint32));
|
||||
return _buffer.read_uint32 (_offset);
|
||||
}
|
||||
|
||||
public uint32 read_uint32 () throws Error {
|
||||
check_available (sizeof (uint32));
|
||||
var val = _buffer.read_uint32 (_offset);
|
||||
_offset += sizeof (uint32);
|
||||
return val;
|
||||
}
|
||||
|
||||
public int64 peek_int64 () throws Error {
|
||||
check_available (sizeof (int64));
|
||||
return _buffer.read_int64 (_offset);
|
||||
}
|
||||
|
||||
public int64 read_int64 () throws Error {
|
||||
check_available (sizeof (int64));
|
||||
var val = _buffer.read_int64 (_offset);
|
||||
_offset += sizeof (int64);
|
||||
return val;
|
||||
}
|
||||
|
||||
public uint64 peek_uint64 () throws Error {
|
||||
check_available (sizeof (uint64));
|
||||
return _buffer.read_uint64 (_offset);
|
||||
}
|
||||
|
||||
public uint64 read_uint64 () throws Error {
|
||||
check_available (sizeof (uint64));
|
||||
var val = _buffer.read_uint64 (_offset);
|
||||
_offset += sizeof (uint64);
|
||||
return val;
|
||||
}
|
||||
|
||||
public float peek_float () throws Error {
|
||||
check_available (sizeof (float));
|
||||
return _buffer.read_float (_offset);
|
||||
}
|
||||
|
||||
public float read_float () throws Error {
|
||||
check_available (sizeof (float));
|
||||
var val = _buffer.read_float (_offset);
|
||||
_offset += sizeof (float);
|
||||
return val;
|
||||
}
|
||||
|
||||
public double peek_double () throws Error {
|
||||
check_available (sizeof (double));
|
||||
return _buffer.read_double (_offset);
|
||||
}
|
||||
|
||||
public double read_double () throws Error {
|
||||
check_available (sizeof (double));
|
||||
var val = _buffer.read_double (_offset);
|
||||
_offset += sizeof (double);
|
||||
return val;
|
||||
}
|
||||
|
||||
public unowned string peek_string () throws Error {
|
||||
check_available (1);
|
||||
return _buffer.read_string (_offset);
|
||||
}
|
||||
|
||||
public unowned string read_string () throws Error {
|
||||
check_available (1);
|
||||
unowned string val = _buffer.read_string (_offset);
|
||||
_offset += val.length + 1;
|
||||
return val;
|
||||
}
|
||||
|
||||
public string peek_fixed_string (size_t size) throws Error {
|
||||
check_available (size);
|
||||
return _buffer.read_fixed_string (_offset, size);
|
||||
}
|
||||
|
||||
public string read_fixed_string (size_t size) throws Error {
|
||||
check_available (size);
|
||||
var val = _buffer.read_fixed_string (_offset, size);
|
||||
_offset += size;
|
||||
return val;
|
||||
}
|
||||
|
||||
public unowned uint8[] peek_data (size_t size) throws Error {
|
||||
check_available (size);
|
||||
return _buffer.read_data (_offset, size);
|
||||
}
|
||||
|
||||
public unowned uint8[] read_data (size_t size) throws Error {
|
||||
check_available (size);
|
||||
unowned uint8[] slice = _buffer.read_data (_offset, size);
|
||||
_offset += size;
|
||||
return slice;
|
||||
}
|
||||
|
||||
public Bytes read_bytes (size_t size) throws Error {
|
||||
check_available (size);
|
||||
var val = _buffer.read_bytes (_offset, size);
|
||||
_offset += size;
|
||||
return val;
|
||||
}
|
||||
|
||||
public unowned uint8[] read_remaining_data () throws Error {
|
||||
return read_data (available);
|
||||
}
|
||||
|
||||
private void check_available (size_t n) throws Error {
|
||||
if (available < n)
|
||||
throw new Error.PROTOCOL ("Malformed buffer: truncated");
|
||||
|
||||
@@ -1,26 +1,18 @@
|
||||
#ifndef __FRIDA_ATOMICS_H__
|
||||
#define __FRIDA_ATOMICS_H__
|
||||
|
||||
#include <glib.h>
|
||||
|
||||
G_BEGIN_DECLS
|
||||
|
||||
#ifdef _MSC_VER
|
||||
|
||||
/* TODO: Add once needed. */
|
||||
|
||||
#else
|
||||
|
||||
typedef guint64 FridaAtomicU64 __attribute__ ((aligned (8)));
|
||||
|
||||
static inline guint64
|
||||
frida_atomics_load_u64_acquire (volatile FridaAtomicU64 * p)
|
||||
static inline guint64 frida_atomics_load_u64_acquire (volatile guint64 * p)
|
||||
{
|
||||
return __atomic_load_n (p, __ATOMIC_ACQUIRE);
|
||||
}
|
||||
|
||||
static inline void
|
||||
frida_atomics_store_u64_release (volatile FridaAtomicU64 * p, guint64 v)
|
||||
static inline void frida_atomics_store_u64_release (volatile guint64 * p, guint64 v)
|
||||
{
|
||||
__atomic_store_n (p, v, __ATOMIC_RELEASE);
|
||||
}
|
||||
@@ -32,6 +24,4 @@ static inline guint32 frida_atomics_load_u32_acquire (volatile guint32 * p)
|
||||
|
||||
#endif
|
||||
|
||||
G_END_DECLS
|
||||
|
||||
#endif
|
||||
@@ -1,6 +1,6 @@
|
||||
[CCode (cheader_filename = "frida-atomics.h")]
|
||||
namespace Frida.Atomics {
|
||||
public static uint64 load_u64_acquire (uint64 * p);
|
||||
public static void store_u64_release (uint64 * p, uint64 v);
|
||||
public static uint32 load_u32_acquire (uint32 * p);
|
||||
public static uint64 load_u64_acquire (void * p);
|
||||
public static void store_u64_release (void * p, uint64 v);
|
||||
public static uint32 load_u32_acquire (void * p);
|
||||
}
|
||||
@@ -6,8 +6,6 @@
|
||||
#include <glib.h>
|
||||
#include <xpc/xpc.h>
|
||||
|
||||
G_BEGIN_DECLS
|
||||
|
||||
typedef void (* FridaXpcHandler) (xpc_object_t object, gpointer user_data);
|
||||
typedef gboolean (* FridaXpcDictionaryApplier) (const gchar * key, xpc_object_t val, gpointer user_data);
|
||||
|
||||
@@ -19,8 +17,6 @@ void _frida_xpc_connection_send_message_with_reply (xpc_connection_t connection,
|
||||
gchar * _frida_xpc_object_to_string (xpc_object_t object);
|
||||
gboolean _frida_xpc_dictionary_apply (xpc_object_t dict, FridaXpcDictionaryApplier applier, gpointer user_data);
|
||||
|
||||
G_END_DECLS
|
||||
|
||||
#endif
|
||||
|
||||
#endif
|
||||
@@ -1,41 +0,0 @@
|
||||
#ifndef __FRIDA_JNI_H__
|
||||
#define __FRIDA_JNI_H__
|
||||
|
||||
#include <jni.h>
|
||||
|
||||
G_BEGIN_DECLS
|
||||
|
||||
typedef jint (* JNIDestroyJavaVMFunc) (JavaVM *);
|
||||
typedef jint (* JNIAttachCurrentThreadFunc) (JavaVM *, JNIEnv **, void *);
|
||||
typedef jint (* JNIDetachCurrentThreadFunc) (JavaVM *);
|
||||
typedef jint (* JNIGetEnvFunc) (JavaVM *, JNIEnv **, jint);
|
||||
|
||||
typedef jclass (* JNIFindClassFunc) (JNIEnv *, const char *);
|
||||
|
||||
typedef jthrowable (* JNIExceptionOccurredFunc) (JNIEnv *);
|
||||
typedef void (* JNIExceptionDescribeFunc) (JNIEnv *);
|
||||
typedef void (* JNIExceptionClearFunc) (JNIEnv *);
|
||||
|
||||
typedef jint (* JNIPushLocalFrameFunc) (JNIEnv *, jint);
|
||||
typedef jobject (* JNIPopLocalFrameFunc) (JNIEnv *, jobject);
|
||||
|
||||
typedef jobject (* JNINewGlobalRefFunc) (JNIEnv *, jobject);
|
||||
typedef void (* JNIDeleteGlobalRefFunc) (JNIEnv *, jobject);
|
||||
typedef void (* JNIDeleteLocalRefFunc) (JNIEnv *, jobject);
|
||||
|
||||
typedef jobject (* JNINewObjectFunc) (JNIEnv *, jclass, jmethodID, ...);
|
||||
|
||||
typedef jclass (* JNIGetObjectClassFunc) (JNIEnv *, jobject);
|
||||
typedef jmethodID (* JNIGetMethodIDFunc) (JNIEnv *, jclass, const char *, const char *);
|
||||
|
||||
typedef jobject (* JNICallObjectMethodFunc) (JNIEnv *, jobject, jmethodID, ...);
|
||||
|
||||
typedef jstring (* JNINewStringUTFFunc) (JNIEnv *, const char *);
|
||||
typedef const char * (* JNIGetStringUTFCharsFunc) (JNIEnv *, jstring, jboolean *);
|
||||
typedef void (* JNIReleaseStringUTFCharsFunc) (JNIEnv *, jstring, const char *);
|
||||
|
||||
typedef jboolean (* JNIExceptionCheckFunc) (JNIEnv *);
|
||||
|
||||
G_END_DECLS
|
||||
|
||||
#endif
|
||||
@@ -1,42 +0,0 @@
|
||||
#ifndef __FRIDA_PROSPERO_H__
|
||||
#define __FRIDA_PROSPERO_H__
|
||||
|
||||
#ifdef HAVE_PROSPERO
|
||||
|
||||
#include <gum/gum.h>
|
||||
|
||||
G_BEGIN_DECLS
|
||||
|
||||
#define FRIDA_PROSPERO_AGENT_ARGS_SYMBOL "frida_prospero_agent_args"
|
||||
#define FRIDA_PROSPERO_HELLO_BYTE 0xff
|
||||
|
||||
typedef struct _FridaProsperoAgentArgs FridaProsperoAgentArgs;
|
||||
|
||||
struct _FridaProsperoAgentArgs
|
||||
{
|
||||
GumAddress agent_parameters;
|
||||
gint fifo_fd;
|
||||
gint agent_ctrlfd;
|
||||
GumMemoryRange mapped_range;
|
||||
};
|
||||
|
||||
typedef struct _FridaProsperoAppLaunchContext FridaProsperoAppLaunchContext;
|
||||
|
||||
struct _FridaProsperoAppLaunchContext
|
||||
{
|
||||
guint32 size;
|
||||
guint32 user_id;
|
||||
guint32 app_opt;
|
||||
guint64 crash_report;
|
||||
guint32 check_flag;
|
||||
};
|
||||
|
||||
extern int sceUserServiceInitialize (void * params);
|
||||
extern int sceUserServiceGetForegroundUser (guint32 * user_id);
|
||||
extern int sceSystemServiceLaunchApp (const gchar * title_id, gchar ** argv, FridaProsperoAppLaunchContext * ctx);
|
||||
|
||||
G_END_DECLS
|
||||
|
||||
#endif
|
||||
|
||||
#endif
|
||||
@@ -90,18 +90,6 @@ namespace Frida.FS {
|
||||
yield write_all_bytes (f, new Bytes (t.data), cancellable);
|
||||
}
|
||||
|
||||
public Bytes read_all_bytes_sync (File f) throws Error {
|
||||
try {
|
||||
uint8[] contents;
|
||||
f.load_contents (null, out contents, null);
|
||||
return new Bytes.take ((owned) contents);
|
||||
} catch (GLib.Error e) {
|
||||
if (e is IOError.NOT_FOUND)
|
||||
throw new Error.INVALID_ARGUMENT ("%s", e.message);
|
||||
throw new Error.PERMISSION_DENIED ("%s", e.message);
|
||||
}
|
||||
}
|
||||
|
||||
public async Bytes read_all_bytes (File f, Cancellable? cancellable) throws Error, IOError {
|
||||
try {
|
||||
return yield f.load_bytes_async (cancellable, null);
|
||||
|
||||
+11
-49
@@ -46,7 +46,7 @@ namespace Frida {
|
||||
public extern unowned LinuxSyscallSignature[]? get_compat32_syscall_signatures ();
|
||||
|
||||
public struct LinuxSyscallSignature {
|
||||
public int nr;
|
||||
public uint nr;
|
||||
public string name;
|
||||
public uint8 nargs;
|
||||
public LinuxSyscallArg args[6];
|
||||
@@ -128,7 +128,6 @@ namespace Frida {
|
||||
}
|
||||
}
|
||||
|
||||
#if HAVE_LOCAL_BACKEND
|
||||
public sealed class BpfObject {
|
||||
public Programs programs {
|
||||
get;
|
||||
@@ -139,35 +138,37 @@ namespace Frida {
|
||||
}
|
||||
|
||||
internal Libbpf.Object handle;
|
||||
private char[] kernel_log_buf;
|
||||
|
||||
public static BpfObject open (string name, uint8[] blob) throws Error {
|
||||
var log_buf = new char[64 * 1024];
|
||||
|
||||
var opts = Libbpf.Object.OpenOpts ();
|
||||
opts.sz = sizeof (Libbpf.Object.OpenOpts);
|
||||
opts.object_name = name;
|
||||
opts.kernel_log_buf = log_buf;
|
||||
|
||||
var log = new LibbpfLogScope ();
|
||||
var handle = Libbpf.Object.open_mem (blob, opts);
|
||||
if (handle == null)
|
||||
throw_libbpf_error (errno, log.take ());
|
||||
throw_libbpf_error (errno);
|
||||
|
||||
return new BpfObject ((owned) handle);
|
||||
return new BpfObject ((owned) handle, (owned) log_buf);
|
||||
}
|
||||
|
||||
private BpfObject (owned Libbpf.Object handle) {
|
||||
private BpfObject (owned Libbpf.Object handle, owned char[] kernel_log_buf) {
|
||||
this.handle = (owned) handle;
|
||||
this.kernel_log_buf = (owned) kernel_log_buf;
|
||||
|
||||
_programs = new Programs (this);
|
||||
_maps = new Maps (this);
|
||||
}
|
||||
|
||||
public void prepare () throws Error {
|
||||
var log = new LibbpfLogScope ();
|
||||
check_libbpf_result (handle.prepare (), log.take ());
|
||||
check_libbpf_result (handle.prepare ());
|
||||
}
|
||||
|
||||
public void load () throws Error {
|
||||
var log = new LibbpfLogScope ();
|
||||
check_libbpf_result (handle.load (), log.take ());
|
||||
check_libbpf_result (handle.load (), (string) kernel_log_buf);
|
||||
}
|
||||
|
||||
public sealed class Programs {
|
||||
@@ -347,18 +348,6 @@ namespace Frida {
|
||||
remove_raw ((uint8[]) &key);
|
||||
}
|
||||
|
||||
public void update_u64_u8 (uint64 key, uint8 val) throws Error {
|
||||
update_raw ((uint8[]) &key, (uint8[]) &val);
|
||||
}
|
||||
|
||||
public void update_u64_u32 (uint64 key, uint32 val) throws Error {
|
||||
update_raw ((uint8[]) &key, (uint8[]) &val);
|
||||
}
|
||||
|
||||
public void remove_u64 (uint64 key) throws Error {
|
||||
remove_raw ((uint8[]) &key);
|
||||
}
|
||||
|
||||
public void foreach_percpu_value<T> (uint8[] key, PercpuValueFunc<T> func) throws Error {
|
||||
var ncpus = check_libbpf_result (Libbpf.num_possible_cpus ());
|
||||
var percpu_stride = round_up_8 (value_size);
|
||||
@@ -395,30 +384,6 @@ namespace Frida {
|
||||
}
|
||||
}
|
||||
|
||||
private sealed class LibbpfLogScope {
|
||||
private static StringBuilder buffer;
|
||||
|
||||
public LibbpfLogScope () {
|
||||
if (buffer == null)
|
||||
buffer = new StringBuilder ();
|
||||
buffer.truncate ();
|
||||
Libbpf.set_print (on_message);
|
||||
}
|
||||
|
||||
~LibbpfLogScope () {
|
||||
Libbpf.set_print (null);
|
||||
}
|
||||
|
||||
public string take () {
|
||||
return buffer.str.chomp ();
|
||||
}
|
||||
|
||||
private static int on_message (Libbpf.PrintLevel level, string format, va_list args) {
|
||||
buffer.append_vprintf (format, args);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
private int check_libbpf_result (int result, string details = "") throws Error {
|
||||
if (result < 0)
|
||||
throw_libbpf_error (result, details);
|
||||
@@ -545,7 +510,6 @@ namespace Frida {
|
||||
STOP,
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
namespace PerfEvent {
|
||||
public FileDescriptor open (PerfEventAttr * attr, int pid, int cpu, int group_fd, uint flags) throws Error {
|
||||
@@ -560,9 +524,7 @@ namespace Frida {
|
||||
throw new Error.NOT_SUPPORTED ("%s (errno=%d: %s)".printf (message, Posix.errno, Posix.strerror (Posix.errno)));
|
||||
}
|
||||
|
||||
#if HAVE_LOCAL_BACKEND
|
||||
private size_t round_up_8 (size_t x) {
|
||||
return (x + 7) & ~((size_t) 7);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
+11
-18
@@ -1,5 +1,4 @@
|
||||
base_sources = [
|
||||
'asset-location.vala',
|
||||
'session.vala',
|
||||
'session-glue.c',
|
||||
'channel.vala',
|
||||
@@ -16,14 +15,12 @@ base_sources = [
|
||||
'buffer.vala',
|
||||
'buffer-glue.c',
|
||||
'value.vala',
|
||||
'xnu-syscalls' / 'xnu-syscalls.vala',
|
||||
'xnu-syscalls' / 'xnu-syscalls-glue.c',
|
||||
]
|
||||
|
||||
extra_vala_args = []
|
||||
|
||||
if host_os == 'windows'
|
||||
base_sources += ['windows.vala', 'windows-glue.c']
|
||||
base_sources += 'windows.vala'
|
||||
else
|
||||
base_sources += 'posix.vala'
|
||||
extra_vala_args += '--pkg=posix'
|
||||
@@ -48,10 +45,8 @@ if host_os_family == 'linux'
|
||||
extra_vala_args += [
|
||||
'--pkg=linux',
|
||||
'--pkg=frida-atomics',
|
||||
'--pkg=libbpf',
|
||||
]
|
||||
if have_local_backend
|
||||
extra_vala_args += '--pkg=libbpf'
|
||||
endif
|
||||
|
||||
syscall_arch_from_abi = {
|
||||
'armbe': 'arm',
|
||||
@@ -78,7 +73,7 @@ extra_deps = []
|
||||
if host_os_family != 'windows'
|
||||
extra_deps += gio_unix_dep
|
||||
endif
|
||||
if host_os_family == 'linux' and have_local_backend
|
||||
if host_os_family == 'linux'
|
||||
extra_deps += libbpf_dep
|
||||
endif
|
||||
|
||||
@@ -115,7 +110,7 @@ base = static_library('frida-base-' + api_version, base_sources,
|
||||
vala_gir: base_gir_name,
|
||||
vala_vapi: f'frida-base-@[email protected]',
|
||||
dependencies: [glib_dep, gobject_dep, gio_dep, libsoup_dep, nice_dep, usrsctp_dep, gee_dep, json_glib_dep, gum_dep, openssl_dep] + extra_deps,
|
||||
install: have_in_tree_payloads,
|
||||
install: true,
|
||||
install_dir: [true, header_install_dir, true, false],
|
||||
)
|
||||
|
||||
@@ -127,12 +122,10 @@ base_dep = declare_dependency(
|
||||
|
||||
base_build_dir = meson.current_build_dir()
|
||||
|
||||
if have_in_tree_payloads
|
||||
pkg = import('pkgconfig')
|
||||
pkg.generate(base,
|
||||
filebase: f'frida-base-@api_version@',
|
||||
name: 'Frida Base Library',
|
||||
version: frida_version,
|
||||
description: 'Basic building blocks',
|
||||
)
|
||||
endif
|
||||
pkg = import('pkgconfig')
|
||||
pkg.generate(base,
|
||||
filebase: f'frida-base-@api_version@',
|
||||
name: 'Frida Base Library',
|
||||
version: frida_version,
|
||||
description: 'Basic building blocks',
|
||||
)
|
||||
+9
-417
@@ -1,432 +1,26 @@
|
||||
#ifdef HAVE_NICE
|
||||
|
||||
#define OPENSSL_SUPPRESS_DEPRECATED
|
||||
|
||||
#include "frida-base.h"
|
||||
|
||||
#include <errno.h>
|
||||
#include <openssl/asn1.h>
|
||||
#include <openssl/bio.h>
|
||||
#include <openssl/bn.h>
|
||||
#include <openssl/evp.h>
|
||||
#include <openssl/pem.h>
|
||||
#include <openssl/rsa.h>
|
||||
#include <openssl/x509.h>
|
||||
#include <usrsctp.h>
|
||||
|
||||
#ifdef HAVE_GIOAPPLE
|
||||
# include <CoreFoundation/CoreFoundation.h>
|
||||
# include <Security/Security.h>
|
||||
#else
|
||||
# define OPENSSL_SUPPRESS_DEPRECATED
|
||||
# include <openssl/asn1.h>
|
||||
# include <openssl/bio.h>
|
||||
# include <openssl/bn.h>
|
||||
# include <openssl/evp.h>
|
||||
# include <openssl/pem.h>
|
||||
# include <openssl/rsa.h>
|
||||
# include <openssl/x509.h>
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_GIOAPPLE
|
||||
static SecKeyRef frida_rsa_keypair_generate (void);
|
||||
static void frida_rsa_export_public_key (SecKeyRef private_key, GByteArray * out);
|
||||
static void frida_rsa_export_private_key (SecKeyRef private_key, GByteArray * out);
|
||||
static void frida_rsa_sign_sha256 (SecKeyRef private_key, const guint8 * message, gsize message_length, GByteArray * out);
|
||||
|
||||
static void frida_build_tbs_certificate (GByteArray * out, const GByteArray * subject_public_key);
|
||||
static void frida_build_name (GByteArray * out);
|
||||
static void frida_build_rdn (GByteArray * out, const guint8 * oid, gsize oid_length, guint8 value_tag, const gchar * value);
|
||||
static void frida_build_validity (GByteArray * out);
|
||||
static void frida_build_subject_public_key_info (GByteArray * out, const GByteArray * rsa_public_key);
|
||||
static void frida_build_signed_certificate (GByteArray * out, const GByteArray * tbs, const GByteArray * signature);
|
||||
static void frida_build_algorithm_identifier (GByteArray * out, const guint8 * oid, gsize oid_length);
|
||||
static void frida_build_pkcs8_private_key_info (GByteArray * out, const GByteArray * rsa_private_key);
|
||||
static gchar * frida_pem_encode (const gchar * type, const guint8 * der, gsize der_length);
|
||||
|
||||
static void frida_der_append_tlv (GByteArray * out, guint8 tag, const guint8 * value, gsize length);
|
||||
static void frida_der_append_length (GByteArray * out, gsize length);
|
||||
static void frida_der_append_integer_uint (GByteArray * out, guint64 value);
|
||||
static void frida_der_append_null (GByteArray * out);
|
||||
static void frida_der_append_oid (GByteArray * out, const guint8 * oid, gsize length);
|
||||
static void frida_der_append_utctime (GByteArray * out, time_t t);
|
||||
static void frida_der_append_bit_string (GByteArray * out, const guint8 * bytes, gsize length);
|
||||
|
||||
static const guint8 frida_oid_country[] = { 0x55, 0x04, 0x06 };
|
||||
static const guint8 frida_oid_organization[] = { 0x55, 0x04, 0x0a };
|
||||
static const guint8 frida_oid_common_name[] = { 0x55, 0x04, 0x03 };
|
||||
static const guint8 frida_oid_rsa_encryption[] = { 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x01 };
|
||||
static const guint8 frida_oid_sha256_with_rsa[] = { 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x0b };
|
||||
#else
|
||||
static gchar * frida_steal_bio_to_string (BIO ** bio);
|
||||
#endif
|
||||
|
||||
static int frida_on_connection_output (void * addr, void * buffer, size_t length, uint8_t tos, uint8_t set_df);
|
||||
static void frida_on_debug_printf (const char * format, ...);
|
||||
|
||||
static void frida_on_upcall (struct socket * sock, void * user_data, int flags);
|
||||
|
||||
#ifdef HAVE_GIOAPPLE
|
||||
|
||||
void
|
||||
_frida_generate_certificate (guint8 ** cert_der, gint * cert_der_length, gchar ** cert_pem, gchar ** key_pem)
|
||||
{
|
||||
SecKeyRef private_key;
|
||||
GByteArray * rsa_public_key, * rsa_private_key, * subject_public_key, * tbs, * signature, * certificate, * pkcs8;
|
||||
|
||||
*cert_der = NULL;
|
||||
*cert_der_length = 0;
|
||||
*cert_pem = NULL;
|
||||
*key_pem = NULL;
|
||||
|
||||
private_key = frida_rsa_keypair_generate ();
|
||||
|
||||
rsa_public_key = g_byte_array_new ();
|
||||
frida_rsa_export_public_key (private_key, rsa_public_key);
|
||||
|
||||
rsa_private_key = g_byte_array_new ();
|
||||
frida_rsa_export_private_key (private_key, rsa_private_key);
|
||||
|
||||
subject_public_key = g_byte_array_new ();
|
||||
frida_build_subject_public_key_info (subject_public_key, rsa_public_key);
|
||||
|
||||
tbs = g_byte_array_new ();
|
||||
frida_build_tbs_certificate (tbs, subject_public_key);
|
||||
|
||||
signature = g_byte_array_new ();
|
||||
frida_rsa_sign_sha256 (private_key, tbs->data, tbs->len, signature);
|
||||
|
||||
certificate = g_byte_array_new ();
|
||||
frida_build_signed_certificate (certificate, tbs, signature);
|
||||
|
||||
pkcs8 = g_byte_array_new ();
|
||||
frida_build_pkcs8_private_key_info (pkcs8, rsa_private_key);
|
||||
|
||||
*cert_der = g_memdup2 (certificate->data, certificate->len);
|
||||
*cert_der_length = certificate->len;
|
||||
*cert_pem = frida_pem_encode ("CERTIFICATE", certificate->data, certificate->len);
|
||||
*key_pem = frida_pem_encode ("PRIVATE KEY", pkcs8->data, pkcs8->len);
|
||||
|
||||
g_byte_array_unref (pkcs8);
|
||||
g_byte_array_unref (certificate);
|
||||
g_byte_array_unref (signature);
|
||||
g_byte_array_unref (tbs);
|
||||
g_byte_array_unref (subject_public_key);
|
||||
g_byte_array_unref (rsa_private_key);
|
||||
g_byte_array_unref (rsa_public_key);
|
||||
CFRelease (private_key);
|
||||
}
|
||||
|
||||
static SecKeyRef
|
||||
frida_rsa_keypair_generate (void)
|
||||
{
|
||||
SecKeyRef private_key;
|
||||
CFMutableDictionaryRef attrs;
|
||||
const int key_size_bits = 2048;
|
||||
CFNumberRef key_size;
|
||||
|
||||
attrs = CFDictionaryCreateMutable (kCFAllocatorDefault, 0, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks);
|
||||
|
||||
key_size = CFNumberCreate (kCFAllocatorDefault, kCFNumberIntType, &key_size_bits);
|
||||
CFDictionarySetValue (attrs, kSecAttrKeyType, kSecAttrKeyTypeRSA);
|
||||
CFDictionarySetValue (attrs, kSecAttrKeySizeInBits, key_size);
|
||||
CFRelease (key_size);
|
||||
|
||||
private_key = SecKeyCreateRandomKey (attrs, NULL);
|
||||
g_assert (private_key != NULL);
|
||||
|
||||
CFRelease (attrs);
|
||||
|
||||
return private_key;
|
||||
}
|
||||
|
||||
static void
|
||||
frida_rsa_export_public_key (SecKeyRef private_key, GByteArray * out)
|
||||
{
|
||||
SecKeyRef public_key;
|
||||
CFDataRef data;
|
||||
|
||||
public_key = SecKeyCopyPublicKey (private_key);
|
||||
g_assert (public_key != NULL);
|
||||
|
||||
data = SecKeyCopyExternalRepresentation (public_key, NULL);
|
||||
g_assert (data != NULL);
|
||||
|
||||
g_byte_array_append (out, CFDataGetBytePtr (data), CFDataGetLength (data));
|
||||
|
||||
CFRelease (data);
|
||||
CFRelease (public_key);
|
||||
}
|
||||
|
||||
static void
|
||||
frida_rsa_export_private_key (SecKeyRef private_key, GByteArray * out)
|
||||
{
|
||||
CFDataRef data;
|
||||
|
||||
data = SecKeyCopyExternalRepresentation (private_key, NULL);
|
||||
g_assert (data != NULL);
|
||||
|
||||
g_byte_array_append (out, CFDataGetBytePtr (data), (guint) CFDataGetLength (data));
|
||||
|
||||
CFRelease (data);
|
||||
}
|
||||
|
||||
static void
|
||||
frida_rsa_sign_sha256 (SecKeyRef private_key, const guint8 * message, gsize message_length, GByteArray * out)
|
||||
{
|
||||
CFDataRef to_sign, signature;
|
||||
|
||||
to_sign = CFDataCreate (kCFAllocatorDefault, message, (CFIndex) message_length);
|
||||
|
||||
signature = SecKeyCreateSignature (private_key, kSecKeyAlgorithmRSASignatureMessagePKCS1v15SHA256, to_sign, NULL);
|
||||
g_assert (signature != NULL);
|
||||
|
||||
g_byte_array_append (out, CFDataGetBytePtr (signature), (guint) CFDataGetLength (signature));
|
||||
|
||||
CFRelease (signature);
|
||||
CFRelease (to_sign);
|
||||
}
|
||||
|
||||
static void
|
||||
frida_build_tbs_certificate (GByteArray * out, const GByteArray * subject_public_key)
|
||||
{
|
||||
GByteArray * inner = g_byte_array_new ();
|
||||
|
||||
frida_der_append_integer_uint (inner, 1);
|
||||
frida_build_algorithm_identifier (inner, frida_oid_sha256_with_rsa, sizeof (frida_oid_sha256_with_rsa));
|
||||
frida_build_name (inner);
|
||||
frida_build_validity (inner);
|
||||
frida_build_name (inner);
|
||||
g_byte_array_append (inner, subject_public_key->data, subject_public_key->len);
|
||||
|
||||
frida_der_append_tlv (out, 0x30, inner->data, inner->len);
|
||||
|
||||
g_byte_array_unref (inner);
|
||||
}
|
||||
|
||||
static void
|
||||
frida_build_name (GByteArray * out)
|
||||
{
|
||||
GByteArray * inner = g_byte_array_new ();
|
||||
|
||||
frida_build_rdn (inner, frida_oid_country, sizeof (frida_oid_country), 0x13, "CA");
|
||||
frida_build_rdn (inner, frida_oid_organization, sizeof (frida_oid_organization), 0x0c, "Frida");
|
||||
frida_build_rdn (inner, frida_oid_common_name, sizeof (frida_oid_common_name), 0x0c, "lolcathost");
|
||||
|
||||
frida_der_append_tlv (out, 0x30, inner->data, inner->len);
|
||||
|
||||
g_byte_array_unref (inner);
|
||||
}
|
||||
|
||||
static void
|
||||
frida_build_rdn (GByteArray * out, const guint8 * oid, gsize oid_length, guint8 value_tag, const gchar * value)
|
||||
{
|
||||
GByteArray * atv, * rdn;
|
||||
|
||||
atv = g_byte_array_new ();
|
||||
rdn = g_byte_array_new ();
|
||||
|
||||
frida_der_append_oid (atv, oid, oid_length);
|
||||
frida_der_append_tlv (atv, value_tag, (const guint8 *) value, strlen (value));
|
||||
frida_der_append_tlv (rdn, 0x30, atv->data, atv->len);
|
||||
frida_der_append_tlv (out, 0x31, rdn->data, rdn->len);
|
||||
|
||||
g_byte_array_unref (rdn);
|
||||
g_byte_array_unref (atv);
|
||||
}
|
||||
|
||||
static void
|
||||
frida_build_validity (GByteArray * out)
|
||||
{
|
||||
const time_t lifetime_seconds = 15780000;
|
||||
GByteArray * inner;
|
||||
time_t not_before, not_after;
|
||||
|
||||
inner = g_byte_array_new ();
|
||||
|
||||
not_before = time (NULL);
|
||||
not_after = not_before + lifetime_seconds;
|
||||
|
||||
frida_der_append_utctime (inner, not_before);
|
||||
frida_der_append_utctime (inner, not_after);
|
||||
|
||||
frida_der_append_tlv (out, 0x30, inner->data, inner->len);
|
||||
|
||||
g_byte_array_unref (inner);
|
||||
}
|
||||
|
||||
static void
|
||||
frida_build_subject_public_key_info (GByteArray * out, const GByteArray * rsa_public_key)
|
||||
{
|
||||
GByteArray * inner = g_byte_array_new ();
|
||||
|
||||
frida_build_algorithm_identifier (inner, frida_oid_rsa_encryption, sizeof (frida_oid_rsa_encryption));
|
||||
frida_der_append_bit_string (inner, rsa_public_key->data, rsa_public_key->len);
|
||||
|
||||
frida_der_append_tlv (out, 0x30, inner->data, inner->len);
|
||||
|
||||
g_byte_array_unref (inner);
|
||||
}
|
||||
|
||||
static void
|
||||
frida_build_signed_certificate (GByteArray * out, const GByteArray * tbs, const GByteArray * signature)
|
||||
{
|
||||
GByteArray * inner = g_byte_array_new ();
|
||||
|
||||
g_byte_array_append (inner, tbs->data, tbs->len);
|
||||
frida_build_algorithm_identifier (inner, frida_oid_sha256_with_rsa, sizeof (frida_oid_sha256_with_rsa));
|
||||
frida_der_append_bit_string (inner, signature->data, signature->len);
|
||||
|
||||
frida_der_append_tlv (out, 0x30, inner->data, inner->len);
|
||||
|
||||
g_byte_array_unref (inner);
|
||||
}
|
||||
|
||||
static void
|
||||
frida_build_algorithm_identifier (GByteArray * out, const guint8 * oid, gsize oid_length)
|
||||
{
|
||||
GByteArray * inner = g_byte_array_new ();
|
||||
|
||||
frida_der_append_oid (inner, oid, oid_length);
|
||||
frida_der_append_null (inner);
|
||||
|
||||
frida_der_append_tlv (out, 0x30, inner->data, inner->len);
|
||||
|
||||
g_byte_array_unref (inner);
|
||||
}
|
||||
|
||||
static void
|
||||
frida_build_pkcs8_private_key_info (GByteArray * out, const GByteArray * rsa_private_key)
|
||||
{
|
||||
GByteArray * inner = g_byte_array_new ();
|
||||
|
||||
frida_der_append_integer_uint (inner, 0);
|
||||
frida_build_algorithm_identifier (inner, frida_oid_rsa_encryption, sizeof (frida_oid_rsa_encryption));
|
||||
frida_der_append_tlv (inner, 0x04, rsa_private_key->data, rsa_private_key->len);
|
||||
|
||||
frida_der_append_tlv (out, 0x30, inner->data, inner->len);
|
||||
|
||||
g_byte_array_unref (inner);
|
||||
}
|
||||
|
||||
static gchar *
|
||||
frida_pem_encode (const gchar * type, const guint8 * der, gsize der_length)
|
||||
{
|
||||
GString * pem;
|
||||
gchar * base64;
|
||||
gsize length, i;
|
||||
|
||||
base64 = g_base64_encode (der, der_length);
|
||||
length = strlen (base64);
|
||||
|
||||
pem = g_string_sized_new (length + 128);
|
||||
|
||||
g_string_append_printf (pem, "-----BEGIN %s-----\n", type);
|
||||
|
||||
for (i = 0; i < length; i += 64)
|
||||
{
|
||||
gsize chunk = MIN (64, length - i);
|
||||
g_string_append_len (pem, base64 + i, chunk);
|
||||
g_string_append_c (pem, '\n');
|
||||
}
|
||||
|
||||
g_string_append_printf (pem, "-----END %s-----\n", type);
|
||||
|
||||
g_free (base64);
|
||||
|
||||
return g_string_free (pem, FALSE);
|
||||
}
|
||||
|
||||
static void
|
||||
frida_der_append_tlv (GByteArray * out, guint8 tag, const guint8 * value, gsize length)
|
||||
{
|
||||
g_byte_array_append (out, &tag, 1);
|
||||
frida_der_append_length (out, length);
|
||||
if (length > 0)
|
||||
g_byte_array_append (out, value, length);
|
||||
}
|
||||
|
||||
static void
|
||||
frida_der_append_length (GByteArray * out, gsize length)
|
||||
{
|
||||
gint i;
|
||||
guint8 buf[9], header;
|
||||
|
||||
if (length < 0x80)
|
||||
{
|
||||
guint8 b = (guint8) length;
|
||||
g_byte_array_append (out, &b, 1);
|
||||
return;
|
||||
}
|
||||
|
||||
i = 0;
|
||||
while (length > 0)
|
||||
{
|
||||
buf[++i] = (guint8) (length & 0xff);
|
||||
length >>= 8;
|
||||
}
|
||||
header = (guint8) (0x80 | i);
|
||||
g_byte_array_append (out, &header, 1);
|
||||
while (i > 0)
|
||||
{
|
||||
g_byte_array_append (out, &buf[i], 1);
|
||||
i--;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
frida_der_append_integer_uint (GByteArray * out, guint64 value)
|
||||
{
|
||||
gint i;
|
||||
guint8 buf[9];
|
||||
gint start;
|
||||
|
||||
for (i = 7; i >= 0; i--)
|
||||
{
|
||||
buf[i + 1] = (guint8) (value & 0xff);
|
||||
value >>= 8;
|
||||
}
|
||||
buf[0] = 0;
|
||||
|
||||
start = 0;
|
||||
while (start < 8 && buf[start] == 0 && (buf[start + 1] & 0x80) == 0)
|
||||
start++;
|
||||
|
||||
frida_der_append_tlv (out, 0x02, buf + start, (gsize) (9 - start));
|
||||
}
|
||||
|
||||
static void
|
||||
frida_der_append_null (GByteArray * out)
|
||||
{
|
||||
frida_der_append_tlv (out, 0x05, NULL, 0);
|
||||
}
|
||||
|
||||
static void
|
||||
frida_der_append_oid (GByteArray * out, const guint8 * oid, gsize length)
|
||||
{
|
||||
frida_der_append_tlv (out, 0x06, oid, length);
|
||||
}
|
||||
|
||||
static void
|
||||
frida_der_append_utctime (GByteArray * out, time_t t)
|
||||
{
|
||||
struct tm tm;
|
||||
gchar buf[16];
|
||||
|
||||
gmtime_r (&t, &tm);
|
||||
g_snprintf (buf, sizeof (buf), "%02d%02d%02d%02d%02d%02dZ",
|
||||
tm.tm_year % 100, tm.tm_mon + 1, tm.tm_mday,
|
||||
tm.tm_hour, tm.tm_min, tm.tm_sec);
|
||||
|
||||
frida_der_append_tlv (out, 0x17, (const guint8 *) buf, strlen (buf));
|
||||
}
|
||||
|
||||
static void
|
||||
frida_der_append_bit_string (GByteArray * out, const guint8 * bytes, gsize length)
|
||||
{
|
||||
guint8 tag = 0x03;
|
||||
guint8 unused_bits = 0;
|
||||
|
||||
g_byte_array_append (out, &tag, 1);
|
||||
frida_der_append_length (out, length + 1);
|
||||
g_byte_array_append (out, &unused_bits, 1);
|
||||
if (length > 0)
|
||||
g_byte_array_append (out, bytes, length);
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
void
|
||||
_frida_generate_certificate (guint8 ** cert_der, gint * cert_der_length, gchar ** cert_pem, gchar ** key_pem)
|
||||
{
|
||||
@@ -496,8 +90,6 @@ frida_steal_bio_to_string (BIO ** bio)
|
||||
return result;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
void
|
||||
_frida_sctp_connection_initialize_sctp_backend (void)
|
||||
{
|
||||
|
||||
@@ -220,128 +220,4 @@ namespace Frida {
|
||||
Posix.tcsetattr (fd, 0, tios);
|
||||
}
|
||||
#endif
|
||||
|
||||
namespace ChildProcess {
|
||||
public async WaitResult wait_for_next_stop (uint pid, Cancellable? cancellable) throws Error, IOError {
|
||||
var main_context = MainContext.get_thread_default ();
|
||||
|
||||
bool timed_out = false;
|
||||
var timeout_source = new TimeoutSource.seconds (5);
|
||||
timeout_source.set_callback (() => {
|
||||
timed_out = true;
|
||||
return Source.REMOVE;
|
||||
});
|
||||
timeout_source.attach (main_context);
|
||||
|
||||
int status = 0;
|
||||
uint[] delays = { 0, 1, 2, 5, 10, 20, 50, 250 };
|
||||
|
||||
try {
|
||||
for (uint i = 0; !timed_out && !cancellable.set_error_if_cancelled (); i++) {
|
||||
int res = Posix.waitpid ((Posix.pid_t) pid, out status, Posix.WNOHANG);
|
||||
if (res == -1)
|
||||
throw new Error.NOT_SUPPORTED ("Unable to wait for next stop: %s", strerror (errno));
|
||||
if (res != 0)
|
||||
break;
|
||||
|
||||
uint delay_ms = (i < delays.length) ? delays[i] : delays[delays.length - 1];
|
||||
|
||||
var delay_source = new TimeoutSource (delay_ms);
|
||||
delay_source.set_callback (wait_for_next_stop.callback);
|
||||
delay_source.attach (main_context);
|
||||
|
||||
var cancel_source = new CancellableSource (cancellable);
|
||||
cancel_source.set_callback (wait_for_next_stop.callback);
|
||||
cancel_source.attach (main_context);
|
||||
|
||||
yield;
|
||||
|
||||
cancel_source.destroy ();
|
||||
delay_source.destroy ();
|
||||
}
|
||||
} finally {
|
||||
timeout_source.destroy ();
|
||||
}
|
||||
|
||||
if (timed_out)
|
||||
throw new Error.TIMED_OUT ("Unexpectedly timed out while waiting for stop from process with PID %u", pid);
|
||||
|
||||
return WaitResult (pid, status);
|
||||
}
|
||||
}
|
||||
|
||||
public struct WaitResult {
|
||||
public uint pid;
|
||||
public int status;
|
||||
|
||||
public WaitKind kind;
|
||||
|
||||
public uint exit_status;
|
||||
|
||||
public int term_signal;
|
||||
|
||||
public int stop_signal;
|
||||
|
||||
public WaitResult (uint pid, int status) {
|
||||
this.pid = pid;
|
||||
this.status = status;
|
||||
|
||||
kind = WaitKind.OTHER;
|
||||
exit_status = 0;
|
||||
term_signal = 0;
|
||||
stop_signal = 0;
|
||||
|
||||
if (PosixStatus.is_exit (status)) {
|
||||
kind = WaitKind.EXITED;
|
||||
exit_status = PosixStatus.parse_exit_status (status);
|
||||
} else if (PosixStatus.is_signaled (status)) {
|
||||
kind = WaitKind.SIGNALED;
|
||||
term_signal = PosixStatus.parse_termination_signal (status);
|
||||
} else if (PosixStatus.is_stopped (status)) {
|
||||
kind = WaitKind.STOPPED;
|
||||
|
||||
stop_signal = PosixStatus.parse_stop_signal (status);
|
||||
}
|
||||
}
|
||||
|
||||
public void check_stopped () throws Error {
|
||||
switch (kind) {
|
||||
case WaitKind.EXITED:
|
||||
throw new Error.NOT_SUPPORTED ("Target exited with status %u", exit_status);
|
||||
case WaitKind.SIGNALED:
|
||||
throw new Error.NOT_SUPPORTED ("Target terminated with signal %u", term_signal);
|
||||
case WaitKind.STOPPED:
|
||||
return;
|
||||
default:
|
||||
throw new Error.NOT_SUPPORTED ("Unexpected status: 0x%08x", status);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public enum WaitKind {
|
||||
EXITED,
|
||||
SIGNALED,
|
||||
STOPPED,
|
||||
OTHER
|
||||
}
|
||||
|
||||
namespace PosixStatus {
|
||||
[CCode (cname = "WIFEXITED", cheader_filename = "sys/wait.h")]
|
||||
private extern bool is_exit (int status);
|
||||
|
||||
[CCode (cname = "WIFSIGNALED", cheader_filename = "sys/wait.h")]
|
||||
private extern bool is_signaled (int status);
|
||||
|
||||
[CCode (cname = "WIFSTOPPED", cheader_filename = "sys/wait.h")]
|
||||
private extern bool is_stopped (int status);
|
||||
|
||||
[CCode (cname = "WEXITSTATUS", cheader_filename = "sys/wait.h")]
|
||||
private extern uint parse_exit_status (int status);
|
||||
|
||||
[CCode (cname = "WTERMSIG", cheader_filename = "sys/wait.h")]
|
||||
private extern Posix.Signal parse_termination_signal (int status);
|
||||
|
||||
[CCode (cname = "WSTOPSIG", cheader_filename = "sys/wait.h")]
|
||||
private extern Posix.Signal parse_stop_signal (int status);
|
||||
}
|
||||
}
|
||||
@@ -1,11 +1,5 @@
|
||||
namespace Frida {
|
||||
/**
|
||||
* Issues RPC calls over a {@link RpcPeer}, matching responses to requests.
|
||||
*/
|
||||
public sealed class RpcClient : Object {
|
||||
/**
|
||||
* The peer used to send and receive RPC messages.
|
||||
*/
|
||||
public weak RpcPeer peer {
|
||||
get;
|
||||
construct;
|
||||
@@ -13,23 +7,10 @@ namespace Frida {
|
||||
|
||||
private Gee.HashMap<string, PendingResponse> pending_responses = new Gee.HashMap<string, PendingResponse> ();
|
||||
|
||||
/**
|
||||
* Creates an RPC client that talks over @peer.
|
||||
*
|
||||
* @param peer the peer to send and receive messages through
|
||||
*/
|
||||
public RpcClient (RpcPeer peer) {
|
||||
Object (peer: peer);
|
||||
}
|
||||
|
||||
/**
|
||||
* Calls a remote method and waits for its result.
|
||||
*
|
||||
* @param method the method name to invoke
|
||||
* @param args the JSON arguments
|
||||
* @param data binary data to accompany the call, if any
|
||||
* @return the method's JSON result
|
||||
*/
|
||||
public async Json.Node call (string method, Json.Node[] args, Bytes? data, Cancellable? cancellable) throws Error, IOError {
|
||||
string request_id = Uuid.string_random ();
|
||||
|
||||
@@ -88,13 +69,6 @@ namespace Frida {
|
||||
return pending.result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Feeds an incoming message to the client, matching it against pending
|
||||
* calls if it is an RPC response.
|
||||
*
|
||||
* @param json the incoming message as a JSON string
|
||||
* @return true if the message was an RPC message and was handled
|
||||
*/
|
||||
public bool try_handle_message (string json) {
|
||||
if (json.index_of ("\"frida:rpc\"") == -1)
|
||||
return false;
|
||||
@@ -183,17 +157,7 @@ namespace Frida {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* A transport over which an {@link RpcClient} sends and receives RPC
|
||||
* messages.
|
||||
*/
|
||||
public interface RpcPeer : Object {
|
||||
/**
|
||||
* Posts an RPC message to the peer.
|
||||
*
|
||||
* @param json the message as a JSON string
|
||||
* @param data binary data to accompany the message, if any
|
||||
*/
|
||||
public abstract async void post_rpc_message (string json, Bytes? data, Cancellable? cancellable) throws Error, IOError;
|
||||
}
|
||||
}
|
||||
+1
-622
@@ -12,8 +12,6 @@ namespace Frida {
|
||||
Cancellable? cancellable) throws GLib.Error;
|
||||
|
||||
public abstract async void enable_spawn_gating (Cancellable? cancellable) throws GLib.Error;
|
||||
public abstract async void enable_spawn_gating_with_options (HashTable<string, Variant> options,
|
||||
Cancellable? cancellable) throws GLib.Error;
|
||||
public abstract async void disable_spawn_gating (Cancellable? cancellable) throws GLib.Error;
|
||||
public abstract async HostSpawnInfo[] enumerate_pending_spawn (Cancellable? cancellable) throws GLib.Error;
|
||||
public abstract async HostChildInfo[] enumerate_pending_children (Cancellable? cancellable) throws GLib.Error;
|
||||
@@ -33,7 +31,6 @@ namespace Frida {
|
||||
|
||||
public abstract async ServiceSessionId open_service (string address, Cancellable? cancellable) throws GLib.Error;
|
||||
|
||||
public signal void spawn_gating_disabled (SpawnGatingDisabledReason reason);
|
||||
public signal void spawn_added (HostSpawnInfo info);
|
||||
public signal void spawn_removed (HostSpawnInfo info);
|
||||
public signal void child_added (HostChildInfo info);
|
||||
@@ -81,8 +78,6 @@ namespace Frida {
|
||||
Cancellable? cancellable) throws GLib.Error;
|
||||
public abstract async void destroy_script (AgentScriptId script_id, Cancellable? cancellable) throws GLib.Error;
|
||||
public abstract async void load_script (AgentScriptId script_id, Cancellable? cancellable) throws GLib.Error;
|
||||
public abstract async void interrupt_script (AgentScriptId script_id, Cancellable? cancellable) throws GLib.Error;
|
||||
public abstract async void terminate_script (AgentScriptId script_id, Cancellable? cancellable) throws GLib.Error;
|
||||
public abstract async void eternalize_script (AgentScriptId script_id, Cancellable? cancellable) throws GLib.Error;
|
||||
|
||||
public abstract async void enable_debugger (AgentScriptId script_id, Cancellable? cancellable) throws GLib.Error;
|
||||
@@ -760,25 +755,10 @@ namespace Frida {
|
||||
public abstract async void break_and_detach (Cancellable? cancellable) throws GLib.Error;
|
||||
}
|
||||
|
||||
/**
|
||||
* What the Gadget should do when a configured breakpoint is hit.
|
||||
*/
|
||||
public enum GadgetBreakpointAction {
|
||||
/**
|
||||
* Invoke the function and return immediately.
|
||||
*/
|
||||
INVOKE_RETURN,
|
||||
/**
|
||||
* Resume execution.
|
||||
*/
|
||||
RESUME,
|
||||
/**
|
||||
* Detach the Gadget.
|
||||
*/
|
||||
DETACH,
|
||||
/**
|
||||
* Apply the page plan.
|
||||
*/
|
||||
PAGE_PLAN,
|
||||
}
|
||||
|
||||
@@ -822,37 +802,16 @@ namespace Frida {
|
||||
}
|
||||
|
||||
[DBus (name = "re.frida.AuthenticationService17")]
|
||||
/**
|
||||
* Authenticates clients connecting to a {@link PortalService} or
|
||||
* {@link ControlService}.
|
||||
*/
|
||||
public interface AuthenticationService : Object {
|
||||
/**
|
||||
* Authenticates a client by its token.
|
||||
*
|
||||
* @param token the token presented by the client
|
||||
* @return a JSON string describing the authenticated session
|
||||
*/
|
||||
public abstract async string authenticate (string token, Cancellable? cancellable) throws GLib.Error;
|
||||
}
|
||||
|
||||
/**
|
||||
* An {@link AuthenticationService} that accepts a single fixed token.
|
||||
*/
|
||||
public sealed class StaticAuthenticationService : Object, AuthenticationService {
|
||||
/**
|
||||
* The SHA-256 hash of the accepted token.
|
||||
*/
|
||||
public string token_hash {
|
||||
get;
|
||||
construct;
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a service that accepts the given token.
|
||||
*
|
||||
* @param token the token clients must present
|
||||
*/
|
||||
public StaticAuthenticationService (string token) {
|
||||
Object (token_hash: Checksum.compute_for_string (SHA256, token));
|
||||
}
|
||||
@@ -906,11 +865,6 @@ namespace Frida {
|
||||
throw_not_authorized ();
|
||||
}
|
||||
|
||||
public async void enable_spawn_gating_with_options (HashTable<string, Variant> options,
|
||||
Cancellable? cancellable) throws Error, IOError {
|
||||
throw_not_authorized ();
|
||||
}
|
||||
|
||||
public async void disable_spawn_gating (Cancellable? cancellable) throws Error, IOError {
|
||||
throw_not_authorized ();
|
||||
}
|
||||
@@ -990,57 +944,8 @@ namespace Frida {
|
||||
throw new Error.PERMISSION_DENIED ("Not authorized, authentication required");
|
||||
}
|
||||
|
||||
// Fires `expired` when a gated process goes unresumed too long, so the backend can cancel
|
||||
// gating instead of letting a stalled client wedge process creation.
|
||||
public sealed class SpawnGatingWatchdog : Object {
|
||||
public signal void expired ();
|
||||
|
||||
public uint timeout_msec {
|
||||
get;
|
||||
construct;
|
||||
}
|
||||
|
||||
private Gee.Map<uint, Source> deadlines = new Gee.HashMap<uint, Source> ();
|
||||
|
||||
// Default deadline: under the OS's own spawn-start timeouts (Android's is 10s).
|
||||
public SpawnGatingWatchdog (uint timeout_msec = 8000) {
|
||||
Object (timeout_msec: timeout_msec);
|
||||
}
|
||||
|
||||
public void arm (uint pid) {
|
||||
var deadline = new TimeoutSource (timeout_msec);
|
||||
deadline.set_callback (() => {
|
||||
expired ();
|
||||
return Source.REMOVE;
|
||||
});
|
||||
deadline.attach (MainContext.get_thread_default ());
|
||||
deadlines[pid] = deadline;
|
||||
}
|
||||
|
||||
public void cancel (uint pid) {
|
||||
Source? deadline;
|
||||
if (deadlines.unset (pid, out deadline))
|
||||
deadline.destroy ();
|
||||
}
|
||||
|
||||
public void clear () {
|
||||
foreach (var deadline in deadlines.values)
|
||||
deadline.destroy ();
|
||||
deadlines.clear ();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* The realm an agent should run in.
|
||||
*/
|
||||
public enum Realm {
|
||||
/**
|
||||
* The process's native realm.
|
||||
*/
|
||||
NATIVE,
|
||||
/**
|
||||
* An emulated realm, such as code running under binary translation.
|
||||
*/
|
||||
EMULATED;
|
||||
|
||||
public static Realm from_nick (string nick) throws Error {
|
||||
@@ -1052,32 +957,6 @@ namespace Frida {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* How the agent should take over exception handling in the target.
|
||||
*/
|
||||
public enum Exceptor {
|
||||
/**
|
||||
* Install handlers and keep the target from overriding them.
|
||||
*/
|
||||
FULL,
|
||||
/**
|
||||
* Install handlers but let the target replace them.
|
||||
*/
|
||||
HANDLER_ONLY,
|
||||
/**
|
||||
* Do not handle exceptions.
|
||||
*/
|
||||
OFF;
|
||||
|
||||
public static Exceptor from_nick (string nick) throws Error {
|
||||
return Marshal.enum_from_nick<Exceptor> (nick);
|
||||
}
|
||||
|
||||
public string to_nick () {
|
||||
return Marshal.enum_to_nick<Exceptor> (this);
|
||||
}
|
||||
}
|
||||
|
||||
public enum SpawnStartState {
|
||||
RUNNING,
|
||||
SUSPENDED;
|
||||
@@ -1152,60 +1031,11 @@ namespace Frida {
|
||||
}
|
||||
#endif
|
||||
|
||||
#if PROSPERO
|
||||
public struct ProsperoInjectorState {
|
||||
public int fifo_fd;
|
||||
public int agent_ctrlfd;
|
||||
public Gum.MemoryRange? mapped_range;
|
||||
}
|
||||
#endif
|
||||
|
||||
/**
|
||||
* Why spawn gating was disabled on a {@link Device}.
|
||||
*/
|
||||
public enum SpawnGatingDisabledReason {
|
||||
/**
|
||||
* A client asked to disable spawn gating.
|
||||
*/
|
||||
APPLICATION_REQUESTED = 1,
|
||||
/**
|
||||
* A caught process went unresumed long enough that the gater cancelled gating to
|
||||
* avoid stalling process creation.
|
||||
*/
|
||||
WATCHDOG_TIMEOUT;
|
||||
|
||||
public static SpawnGatingDisabledReason from_nick (string nick) throws Error {
|
||||
return Marshal.enum_from_nick<SpawnGatingDisabledReason> (nick);
|
||||
}
|
||||
|
||||
public string to_nick () {
|
||||
return Marshal.enum_to_nick<SpawnGatingDisabledReason> (this);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Why a {@link Session} was detached from its target.
|
||||
*/
|
||||
public enum SessionDetachReason {
|
||||
/**
|
||||
* The host asked to detach.
|
||||
*/
|
||||
APPLICATION_REQUESTED = 1,
|
||||
/**
|
||||
* The target process was replaced, for example by an exec.
|
||||
*/
|
||||
PROCESS_REPLACED,
|
||||
/**
|
||||
* The target process exited.
|
||||
*/
|
||||
PROCESS_TERMINATED,
|
||||
/**
|
||||
* The connection to the target was lost.
|
||||
*/
|
||||
CONNECTION_TERMINATED,
|
||||
/**
|
||||
* The device became unreachable.
|
||||
*/
|
||||
DEVICE_LOST;
|
||||
|
||||
public static SessionDetachReason from_nick (string nick) throws Error {
|
||||
@@ -1218,61 +1048,19 @@ namespace Frida {
|
||||
}
|
||||
|
||||
[DBus (name = "re.frida.Error")]
|
||||
/**
|
||||
* The errors that Frida operations can fail with.
|
||||
*/
|
||||
public errordomain Error {
|
||||
/**
|
||||
* The frida-server is not running.
|
||||
*/
|
||||
SERVER_NOT_RUNNING,
|
||||
/**
|
||||
* The specified executable was not found.
|
||||
*/
|
||||
EXECUTABLE_NOT_FOUND,
|
||||
/**
|
||||
* The specified executable is not supported.
|
||||
*/
|
||||
EXECUTABLE_NOT_SUPPORTED,
|
||||
/**
|
||||
* No process matched the request.
|
||||
*/
|
||||
PROCESS_NOT_FOUND,
|
||||
/**
|
||||
* The process is not responding.
|
||||
*/
|
||||
PROCESS_NOT_RESPONDING,
|
||||
/**
|
||||
* An argument was invalid.
|
||||
*/
|
||||
INVALID_ARGUMENT,
|
||||
/**
|
||||
* The operation is not valid in the current state.
|
||||
*/
|
||||
INVALID_OPERATION,
|
||||
/**
|
||||
* Permission was denied.
|
||||
*/
|
||||
PERMISSION_DENIED,
|
||||
/**
|
||||
* The requested address is already in use.
|
||||
*/
|
||||
ADDRESS_IN_USE,
|
||||
/**
|
||||
* The operation timed out.
|
||||
*/
|
||||
TIMED_OUT,
|
||||
/**
|
||||
* The operation is not supported.
|
||||
*/
|
||||
NOT_SUPPORTED,
|
||||
/**
|
||||
* A protocol error occurred.
|
||||
*/
|
||||
PROTOCOL,
|
||||
/**
|
||||
* A transport-level error occurred.
|
||||
*/
|
||||
TRANSPORT
|
||||
}
|
||||
|
||||
@@ -1339,13 +1127,7 @@ namespace Frida {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Options for {@link Device.get_frontmost_application}.
|
||||
*/
|
||||
public sealed class FrontmostQueryOptions : Object {
|
||||
/**
|
||||
* How much detail to include about the application.
|
||||
*/
|
||||
public Scope scope {
|
||||
get;
|
||||
set;
|
||||
@@ -1375,14 +1157,7 @@ namespace Frida {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Options for {@link Device.enumerate_applications}, including an optional
|
||||
* set of identifiers to restrict the results to.
|
||||
*/
|
||||
public sealed class ApplicationQueryOptions : Object {
|
||||
/**
|
||||
* How much detail to include about each application.
|
||||
*/
|
||||
public Scope scope {
|
||||
get;
|
||||
set;
|
||||
@@ -1391,30 +1166,14 @@ namespace Frida {
|
||||
|
||||
private Gee.List<string> identifiers = new Gee.ArrayList<string> ();
|
||||
|
||||
/**
|
||||
* Restricts the query to the given application identifier. May be called
|
||||
* multiple times to select several.
|
||||
*
|
||||
* @param identifier the application identifier to include
|
||||
*/
|
||||
public void select_identifier (string identifier) {
|
||||
identifiers.add (identifier);
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks whether any identifiers have been selected.
|
||||
*
|
||||
* @return true if the query is restricted to specific identifiers
|
||||
*/
|
||||
public bool has_selected_identifiers () {
|
||||
return !identifiers.is_empty;
|
||||
}
|
||||
|
||||
/**
|
||||
* Invokes @func for each selected identifier.
|
||||
*
|
||||
* @param func function called with each identifier
|
||||
*/
|
||||
public void enumerate_selected_identifiers (Func<string> func) {
|
||||
foreach (var identifier in identifiers)
|
||||
func (identifier);
|
||||
@@ -1456,14 +1215,7 @@ namespace Frida {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Options for {@link Device.enumerate_processes}, including an optional set
|
||||
* of PIDs to restrict the results to.
|
||||
*/
|
||||
public sealed class ProcessQueryOptions : Object {
|
||||
/**
|
||||
* How much detail to include about each process.
|
||||
*/
|
||||
public Scope scope {
|
||||
get;
|
||||
set;
|
||||
@@ -1472,30 +1224,14 @@ namespace Frida {
|
||||
|
||||
private Gee.List<uint> pids = new Gee.ArrayList<uint> ();
|
||||
|
||||
/**
|
||||
* Restricts the query to the given PID. May be called multiple times to
|
||||
* select several.
|
||||
*
|
||||
* @param pid the process ID to include
|
||||
*/
|
||||
public void select_pid (uint pid) {
|
||||
pids.add (pid);
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks whether any PIDs have been selected.
|
||||
*
|
||||
* @return true if the query is restricted to specific PIDs
|
||||
*/
|
||||
public bool has_selected_pids () {
|
||||
return !pids.is_empty;
|
||||
}
|
||||
|
||||
/**
|
||||
* Invokes @func for each selected PID.
|
||||
*
|
||||
* @param func function called with each PID
|
||||
*/
|
||||
public void enumerate_selected_pids (Func<uint> func) {
|
||||
foreach (var pid in pids)
|
||||
func (pid);
|
||||
@@ -1537,21 +1273,9 @@ namespace Frida {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* How much detail to include in query results.
|
||||
*/
|
||||
public enum Scope {
|
||||
/**
|
||||
* Only the essential fields.
|
||||
*/
|
||||
MINIMAL,
|
||||
/**
|
||||
* Essential fields plus metadata.
|
||||
*/
|
||||
METADATA,
|
||||
/**
|
||||
* Everything available.
|
||||
*/
|
||||
FULL;
|
||||
|
||||
public static Scope from_nick (string nick) throws Error {
|
||||
@@ -1563,67 +1287,6 @@ namespace Frida {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Options for {@link Device.enable_spawn_gating}.
|
||||
*/
|
||||
public sealed class SpawnGatingOptions : Object {
|
||||
/**
|
||||
* Which processes to gate. Anything other than DEFAULT requires a Frida new enough to
|
||||
* support scoping, and fails rather than silently gating something broader than asked.
|
||||
*/
|
||||
public SpawnGatingScope scope {
|
||||
get;
|
||||
set;
|
||||
default = DEFAULT;
|
||||
}
|
||||
|
||||
public HashTable<string, Variant> _serialize () {
|
||||
var dict = make_parameters_dict ();
|
||||
|
||||
if (scope != DEFAULT)
|
||||
dict["scope"] = new Variant.string (scope.to_nick ());
|
||||
|
||||
return dict;
|
||||
}
|
||||
|
||||
public static SpawnGatingOptions _deserialize (HashTable<string, Variant> dict) throws Error {
|
||||
var options = new SpawnGatingOptions ();
|
||||
|
||||
Variant? scope = dict["scope"];
|
||||
if (scope != null) {
|
||||
if (!scope.is_of_type (VariantType.STRING))
|
||||
throw new Error.INVALID_ARGUMENT ("The 'scope' option must be a string");
|
||||
options.scope = SpawnGatingScope.from_nick (scope.get_string ());
|
||||
}
|
||||
|
||||
return options;
|
||||
}
|
||||
}
|
||||
|
||||
public enum SpawnGatingScope {
|
||||
/**
|
||||
* Leave the choice to the implementation. Sent as a plain enable_spawn_gating call, so
|
||||
* it still works against a Frida too old to know about scopes.
|
||||
*/
|
||||
DEFAULT,
|
||||
/**
|
||||
* Application launches only.
|
||||
*/
|
||||
APPLICATIONS,
|
||||
/**
|
||||
* Every process created on the system. More potent but far more intrusive.
|
||||
*/
|
||||
PROCESSES;
|
||||
|
||||
public static SpawnGatingScope from_nick (string nick) throws Error {
|
||||
return Marshal.enum_from_nick<SpawnGatingScope> (nick);
|
||||
}
|
||||
|
||||
public string to_nick () {
|
||||
return Marshal.enum_to_nick<SpawnGatingScope> (this);
|
||||
}
|
||||
}
|
||||
|
||||
public struct HostSpawnOptions {
|
||||
public bool has_argv;
|
||||
public string[] argv;
|
||||
@@ -1694,103 +1357,24 @@ namespace Frida {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Options controlling how {@link Device.attach} sets up a {@link Session}.
|
||||
*/
|
||||
public sealed class SessionOptions : Object {
|
||||
/**
|
||||
* The realm to attach in.
|
||||
*/
|
||||
public Realm realm {
|
||||
get;
|
||||
set;
|
||||
default = NATIVE;
|
||||
}
|
||||
|
||||
/**
|
||||
* How long the session may survive a disconnection before being torn
|
||||
* down, in seconds; 0 disables persistence.
|
||||
*/
|
||||
public uint persist_timeout {
|
||||
get;
|
||||
set;
|
||||
default = 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Path to a custom agent to use in the emulated realm.
|
||||
*/
|
||||
public string? emulated_agent_path {
|
||||
get;
|
||||
set;
|
||||
}
|
||||
|
||||
/**
|
||||
* How the agent should handle exceptions in the target.
|
||||
*/
|
||||
public Exceptor exceptor {
|
||||
get;
|
||||
set;
|
||||
default = FULL;
|
||||
}
|
||||
|
||||
/**
|
||||
* Whether to install the unwind broker so exceptions can propagate
|
||||
* through instrumented code.
|
||||
*/
|
||||
public bool unwind_broker {
|
||||
get;
|
||||
set;
|
||||
default = true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Whether to monitor the target for exit so the session is cleaned up.
|
||||
*/
|
||||
public bool exit_monitor {
|
||||
get;
|
||||
set;
|
||||
default = true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Whether to monitor thread suspension in the target.
|
||||
*/
|
||||
public bool thread_suspend_monitor {
|
||||
get;
|
||||
set;
|
||||
default = true;
|
||||
}
|
||||
|
||||
private Gee.List<uint> linker_notifier_offsets = new Gee.ArrayList<uint> ();
|
||||
|
||||
/**
|
||||
* Clears the configured linker notifier offsets.
|
||||
*/
|
||||
public void clear_linker_notifier_offsets () {
|
||||
linker_notifier_offsets.clear ();
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds a linker notifier offset, used to detect module load and unload
|
||||
* events in the target.
|
||||
*
|
||||
* @param offset the offset into the linker to instrument
|
||||
*/
|
||||
public void add_linker_notifier_offset (uint offset) {
|
||||
linker_notifier_offsets.add (offset);
|
||||
}
|
||||
|
||||
/**
|
||||
* Invokes @func for each configured linker notifier offset.
|
||||
*
|
||||
* @param func function called with each offset
|
||||
*/
|
||||
public void enumerate_linker_notifier_offsets (Func<uint> func) {
|
||||
foreach (var offset in linker_notifier_offsets)
|
||||
func (offset);
|
||||
}
|
||||
|
||||
public HashTable<string, Variant> _serialize () {
|
||||
var dict = make_parameters_dict ();
|
||||
|
||||
@@ -1803,25 +1387,6 @@ namespace Frida {
|
||||
if (emulated_agent_path != null)
|
||||
dict["emulated-agent-path"] = new Variant.string (emulated_agent_path);
|
||||
|
||||
if (exceptor != FULL)
|
||||
dict["exceptor"] = new Variant.string (exceptor.to_nick ());
|
||||
|
||||
if (!unwind_broker)
|
||||
dict["unwind-broker"] = new Variant.string ("off");
|
||||
|
||||
if (!exit_monitor)
|
||||
dict["exit-monitor"] = new Variant.string ("off");
|
||||
|
||||
if (!thread_suspend_monitor)
|
||||
dict["thread-suspend-monitor"] = new Variant.string ("off");
|
||||
|
||||
if (!linker_notifier_offsets.is_empty) {
|
||||
var builder = new VariantBuilder (new VariantType ("au"));
|
||||
foreach (uint offset in linker_notifier_offsets)
|
||||
builder.add ("u", offset);
|
||||
dict["linker-notifier-offsets"] = builder.end ();
|
||||
}
|
||||
|
||||
return dict;
|
||||
}
|
||||
|
||||
@@ -1849,61 +1414,12 @@ namespace Frida {
|
||||
options.emulated_agent_path = path.get_string ();
|
||||
}
|
||||
|
||||
Variant? exceptor = dict["exceptor"];
|
||||
if (exceptor != null) {
|
||||
if (!exceptor.is_of_type (VariantType.STRING))
|
||||
throw new Error.INVALID_ARGUMENT ("The 'exceptor' option must be a string");
|
||||
options.exceptor = Exceptor.from_nick (exceptor.get_string ());
|
||||
}
|
||||
|
||||
Variant? unwind_broker = dict["unwind-broker"];
|
||||
if (unwind_broker != null) {
|
||||
if (!unwind_broker.is_of_type (VariantType.STRING) || unwind_broker.get_string () != "off")
|
||||
throw new Error.INVALID_ARGUMENT ("The 'unwind-broker' option is invalid");
|
||||
options.unwind_broker = false;
|
||||
}
|
||||
|
||||
Variant? exit_monitor = dict["exit-monitor"];
|
||||
if (exit_monitor != null) {
|
||||
if (!exit_monitor.is_of_type (VariantType.STRING) || exit_monitor.get_string () != "off")
|
||||
throw new Error.INVALID_ARGUMENT ("The 'exit-monitor' option is invalid");
|
||||
options.exit_monitor = false;
|
||||
}
|
||||
|
||||
Variant? thread_suspend_monitor = dict["thread-suspend-monitor"];
|
||||
if (thread_suspend_monitor != null) {
|
||||
if (!thread_suspend_monitor.is_of_type (VariantType.STRING) ||
|
||||
thread_suspend_monitor.get_string () != "off")
|
||||
throw new Error.INVALID_ARGUMENT ("The 'thread-suspend-monitor' option is invalid");
|
||||
options.thread_suspend_monitor = false;
|
||||
}
|
||||
|
||||
Variant? offsets = dict["linker-notifier-offsets"];
|
||||
if (offsets != null) {
|
||||
if (!offsets.is_of_type (new VariantType ("au")))
|
||||
throw new Error.INVALID_ARGUMENT (
|
||||
"The 'linker-notifier-offsets' option must be an array of uint32");
|
||||
uint n = (uint) offsets.n_children ();
|
||||
for (uint i = 0; i != n; i++)
|
||||
options.add_linker_notifier_offset (offsets.get_child_value (i).get_uint32 ());
|
||||
}
|
||||
|
||||
return options;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* How to set up the standard I/O streams of a spawned process.
|
||||
*/
|
||||
public enum Stdio {
|
||||
/**
|
||||
* Inherit the host's streams.
|
||||
*/
|
||||
INHERIT,
|
||||
/**
|
||||
* Pipe the streams through Frida, surfaced via {@link Device.output}
|
||||
* and {@link Device.input}.
|
||||
*/
|
||||
PIPE;
|
||||
|
||||
public static Stdio from_nick (string nick) throws Error {
|
||||
@@ -1967,21 +1483,9 @@ namespace Frida {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* How a {@link Child} came to be.
|
||||
*/
|
||||
public enum ChildOrigin {
|
||||
/**
|
||||
* Created by fork().
|
||||
*/
|
||||
FORK,
|
||||
/**
|
||||
* The result of an exec() replacing the image.
|
||||
*/
|
||||
EXEC,
|
||||
/**
|
||||
* Spawned as a new process.
|
||||
*/
|
||||
SPAWN;
|
||||
|
||||
public static ChildOrigin from_nick (string nick) throws Error {
|
||||
@@ -2098,39 +1602,23 @@ namespace Frida {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Options for creating a {@link Script} with {@link Session.create_script}.
|
||||
*/
|
||||
public sealed class ScriptOptions : Object {
|
||||
/**
|
||||
* A name for the script, used in logging and debugging.
|
||||
*/
|
||||
public string? name {
|
||||
get;
|
||||
set;
|
||||
}
|
||||
|
||||
/**
|
||||
* A heap snapshot to start the script from, as produced by
|
||||
* {@link Session.snapshot_script}.
|
||||
*/
|
||||
public Bytes? snapshot {
|
||||
get;
|
||||
set;
|
||||
}
|
||||
|
||||
/**
|
||||
* How the snapshot is delivered to the runtime.
|
||||
*/
|
||||
public SnapshotTransport snapshot_transport {
|
||||
get;
|
||||
set;
|
||||
default = INLINE;
|
||||
}
|
||||
|
||||
/**
|
||||
* Which JavaScript runtime to run the script in.
|
||||
*/
|
||||
public ScriptRuntime runtime {
|
||||
get;
|
||||
set;
|
||||
@@ -2199,35 +1687,17 @@ namespace Frida {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* How a script's heap snapshot is delivered to the runtime.
|
||||
*/
|
||||
public enum SnapshotTransport {
|
||||
/**
|
||||
* Embed the snapshot inline with the script.
|
||||
*/
|
||||
INLINE,
|
||||
/**
|
||||
* Pass the snapshot through shared memory.
|
||||
*/
|
||||
SHARED_MEMORY
|
||||
}
|
||||
|
||||
/**
|
||||
* Options for building a heap snapshot with {@link Session.snapshot_script}.
|
||||
*/
|
||||
public sealed class SnapshotOptions : Object {
|
||||
/**
|
||||
* Script to run to warm up the runtime before capturing the snapshot.
|
||||
*/
|
||||
public string? warmup_script {
|
||||
get;
|
||||
set;
|
||||
}
|
||||
|
||||
/**
|
||||
* Which JavaScript runtime to capture the snapshot for.
|
||||
*/
|
||||
public ScriptRuntime runtime {
|
||||
get;
|
||||
set;
|
||||
@@ -2267,21 +1737,9 @@ namespace Frida {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Which JavaScript runtime a script should use.
|
||||
*/
|
||||
public enum ScriptRuntime {
|
||||
/**
|
||||
* Let Frida choose.
|
||||
*/
|
||||
DEFAULT,
|
||||
/**
|
||||
* The QuickJS runtime.
|
||||
*/
|
||||
QJS,
|
||||
/**
|
||||
* The V8 runtime.
|
||||
*/
|
||||
V8;
|
||||
|
||||
public static ScriptRuntime from_nick (string nick) throws Error {
|
||||
@@ -2309,29 +1767,17 @@ namespace Frida {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Options for {@link Session.join_portal}.
|
||||
*/
|
||||
public sealed class PortalOptions : Object {
|
||||
/**
|
||||
* TLS certificate to present to the portal.
|
||||
*/
|
||||
public TlsCertificate? certificate {
|
||||
get;
|
||||
set;
|
||||
}
|
||||
|
||||
/**
|
||||
* Authentication token to present to the portal.
|
||||
*/
|
||||
public string? token {
|
||||
get;
|
||||
set;
|
||||
}
|
||||
|
||||
/**
|
||||
* Access-control tags scoping what this membership may reach.
|
||||
*/
|
||||
public string[]? acl {
|
||||
get;
|
||||
set;
|
||||
@@ -2384,14 +1830,7 @@ namespace Frida {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Options for {@link Session.setup_peer_connection}, configuring how the
|
||||
* peer-to-peer connection is negotiated.
|
||||
*/
|
||||
public sealed class PeerOptions : Object {
|
||||
/**
|
||||
* The STUN server to use for discovering the public address, if any.
|
||||
*/
|
||||
public string? stun_server {
|
||||
get;
|
||||
set;
|
||||
@@ -2399,27 +1838,14 @@ namespace Frida {
|
||||
|
||||
private Gee.List<Relay> relays = new Gee.ArrayList<Relay> ();
|
||||
|
||||
/**
|
||||
* Removes all configured relays.
|
||||
*/
|
||||
public void clear_relays () {
|
||||
relays.clear ();
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds a relay to use when a direct connection cannot be established.
|
||||
*
|
||||
* @param relay the relay to add
|
||||
*/
|
||||
public void add_relay (Relay relay) {
|
||||
relays.add (relay);
|
||||
}
|
||||
|
||||
/**
|
||||
* Invokes @func for each configured relay.
|
||||
*
|
||||
* @param func function called with each relay
|
||||
*/
|
||||
public void enumerate_relays (Func<Relay> func) {
|
||||
foreach (var relay in relays)
|
||||
func (relay);
|
||||
@@ -2465,51 +1891,27 @@ namespace Frida {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* A TURN relay used to establish a peer-to-peer connection when a direct
|
||||
* one is not possible.
|
||||
*/
|
||||
public sealed class Relay : Object {
|
||||
/**
|
||||
* The relay's address, as host and port.
|
||||
*/
|
||||
public string address {
|
||||
get;
|
||||
construct;
|
||||
}
|
||||
|
||||
/**
|
||||
* The username to authenticate with.
|
||||
*/
|
||||
public string username {
|
||||
get;
|
||||
construct;
|
||||
}
|
||||
|
||||
/**
|
||||
* The password to authenticate with.
|
||||
*/
|
||||
public string password {
|
||||
get;
|
||||
construct;
|
||||
}
|
||||
|
||||
/**
|
||||
* The kind of relay and transport to use.
|
||||
*/
|
||||
public RelayKind kind {
|
||||
get;
|
||||
construct;
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a relay.
|
||||
*
|
||||
* @param address the relay's address, as host and port
|
||||
* @param username the username to authenticate with
|
||||
* @param password the password to authenticate with
|
||||
* @param kind the kind of relay and transport
|
||||
*/
|
||||
public Relay (string address, string username, string password, RelayKind kind) {
|
||||
Object (
|
||||
address: address,
|
||||
@@ -2536,21 +1938,9 @@ namespace Frida {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* The kind of a {@link Relay} used for peer-to-peer connections.
|
||||
*/
|
||||
public enum RelayKind {
|
||||
/**
|
||||
* A TURN relay reached over UDP.
|
||||
*/
|
||||
TURN_UDP,
|
||||
/**
|
||||
* A TURN relay reached over TCP.
|
||||
*/
|
||||
TURN_TCP,
|
||||
/**
|
||||
* A TURN relay reached over TLS.
|
||||
*/
|
||||
TURN_TLS
|
||||
}
|
||||
|
||||
@@ -2780,10 +2170,7 @@ namespace Frida {
|
||||
|
||||
public static string enum_to_nick<T> (int val) {
|
||||
var klass = (EnumClass) typeof (T).class_ref ();
|
||||
unowned EnumValue? v = klass.get_value (val);
|
||||
if (v == null)
|
||||
return "unknown-0x%x".printf (val);
|
||||
return v.value_nick;
|
||||
return klass.get_value (val).value_nick;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2809,13 +2196,5 @@ namespace Frida {
|
||||
uint64 b = val_b;
|
||||
return a == b;
|
||||
}
|
||||
|
||||
public uint bytes_hash (Bytes b) {
|
||||
return b.hash ();
|
||||
}
|
||||
|
||||
public static bool bytes_equal (Bytes a, Bytes b) {
|
||||
return a.compare (b) == 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
+11
-244
@@ -97,77 +97,37 @@ namespace Frida {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Configures the network endpoint a {@link PortalService} or
|
||||
* {@link ControlService} listens on.
|
||||
*/
|
||||
public sealed class EndpointParameters : Object {
|
||||
/**
|
||||
* The address to bind to, or null for the default.
|
||||
*/
|
||||
public string? address {
|
||||
get;
|
||||
construct;
|
||||
}
|
||||
|
||||
/**
|
||||
* The port to listen on, or 0 for the default.
|
||||
*/
|
||||
public uint16 port {
|
||||
get;
|
||||
construct;
|
||||
}
|
||||
|
||||
/**
|
||||
* TLS certificate to serve, enabling TLS when set.
|
||||
*/
|
||||
public TlsCertificate? certificate {
|
||||
get;
|
||||
construct;
|
||||
}
|
||||
|
||||
/**
|
||||
* Origin to require from connecting clients, if any.
|
||||
*/
|
||||
public string? origin {
|
||||
get;
|
||||
construct;
|
||||
}
|
||||
|
||||
/**
|
||||
* Service used to authenticate connecting clients, if any.
|
||||
*/
|
||||
public AuthenticationService? auth_service {
|
||||
get;
|
||||
construct;
|
||||
}
|
||||
|
||||
/**
|
||||
* Directory whose files are served as static web assets, if any.
|
||||
*/
|
||||
public File? asset_root {
|
||||
get;
|
||||
set;
|
||||
}
|
||||
|
||||
/**
|
||||
* Handler invoked for web requests, if any.
|
||||
*/
|
||||
public WebRequestHandler? request_handler {
|
||||
get;
|
||||
set;
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates endpoint parameters.
|
||||
*
|
||||
* @param address the address to bind to, or null for the default
|
||||
* @param port the port to listen on, or 0 for the default
|
||||
* @param certificate TLS certificate to serve, or null for plaintext
|
||||
* @param origin origin to require from clients, or null
|
||||
* @param auth_service service used to authenticate clients, or null
|
||||
* @param asset_root directory of static assets to serve, or null
|
||||
*/
|
||||
public EndpointParameters (string? address = null, uint16 port = 0, TlsCertificate? certificate = null,
|
||||
string? origin = null, AuthenticationService? auth_service = null, File? asset_root = null) {
|
||||
Object (
|
||||
@@ -181,132 +141,6 @@ namespace Frida {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Handles web requests made to an endpoint's served assets.
|
||||
*/
|
||||
public interface WebRequestHandler : Object {
|
||||
/**
|
||||
* Handles a single web request.
|
||||
*
|
||||
* @param request the incoming request
|
||||
* @return the response to send, or null to fall through to the default
|
||||
* handling
|
||||
*/
|
||||
public abstract async WebResponse? handle_request (WebRequest request, Cancellable? cancellable) throws Error, IOError;
|
||||
}
|
||||
|
||||
/**
|
||||
* An incoming web request passed to a {@link WebRequestHandler}.
|
||||
*/
|
||||
public sealed class WebRequest : Object {
|
||||
/**
|
||||
* The HTTP method, such as `GET` or `POST`.
|
||||
*/
|
||||
public string method {
|
||||
get;
|
||||
construct;
|
||||
}
|
||||
|
||||
/**
|
||||
* The request path.
|
||||
*/
|
||||
public string path {
|
||||
get;
|
||||
construct;
|
||||
}
|
||||
|
||||
/**
|
||||
* The raw query string, if any.
|
||||
*/
|
||||
public string? query_string {
|
||||
get;
|
||||
construct;
|
||||
}
|
||||
|
||||
/**
|
||||
* The request body, if any.
|
||||
*/
|
||||
public Bytes? body {
|
||||
get;
|
||||
construct;
|
||||
}
|
||||
|
||||
private Soup.MessageHeaders raw_headers;
|
||||
|
||||
internal WebRequest (string method, string path, string? query_string, Soup.MessageHeaders headers, Bytes? body) {
|
||||
Object (method: method, path: path, query_string: query_string, body: body);
|
||||
raw_headers = headers;
|
||||
}
|
||||
|
||||
/**
|
||||
* Invokes @func for each request header.
|
||||
*
|
||||
* @param func function called with each header's name and value
|
||||
*/
|
||||
public void foreach_header (WebRequestHeaderFunc func) {
|
||||
raw_headers.foreach ((name, val) => {
|
||||
func (name, val);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Callback invoked for each header while iterating a {@link WebRequest}.
|
||||
*
|
||||
* @param name the header name
|
||||
* @param val the header value
|
||||
*/
|
||||
public delegate void WebRequestHeaderFunc (string name, string val);
|
||||
|
||||
/**
|
||||
* A response returned from a {@link WebRequestHandler}.
|
||||
*/
|
||||
public sealed class WebResponse : Object {
|
||||
/**
|
||||
* The HTTP status code.
|
||||
*/
|
||||
public uint status {
|
||||
get;
|
||||
construct;
|
||||
}
|
||||
|
||||
/**
|
||||
* The response body.
|
||||
*/
|
||||
public Bytes body {
|
||||
get;
|
||||
construct;
|
||||
}
|
||||
|
||||
private Soup.MessageHeaders raw_headers = new Soup.MessageHeaders (RESPONSE);
|
||||
|
||||
/**
|
||||
* Creates a response.
|
||||
*
|
||||
* @param status the HTTP status code
|
||||
* @param body the response body
|
||||
*/
|
||||
public WebResponse (uint status, Bytes body) {
|
||||
Object (status: status, body: body);
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds a header to the response.
|
||||
*
|
||||
* @param name the header name
|
||||
* @param val the header value
|
||||
*/
|
||||
public void add_header (string name, string val) {
|
||||
raw_headers.append (name, val);
|
||||
}
|
||||
|
||||
internal void write_headers_to (Soup.MessageHeaders target) {
|
||||
raw_headers.foreach ((name, val) => {
|
||||
target.replace (name, val);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
public async IOStream negotiate_connection (IOStream stream, WebServiceTransport transport, string host, string? origin,
|
||||
Cancellable? cancellable) throws Error, IOError {
|
||||
var input = (DataInputStream) Object.new (typeof (DataInputStream),
|
||||
@@ -634,14 +468,14 @@ namespace Frida {
|
||||
|
||||
server.add_websocket_handler ("/ws", endpoint_params.origin, null, on_websocket_opened);
|
||||
|
||||
if (endpoint_params.request_handler != null || endpoint_params.asset_root != null)
|
||||
server.add_handler (null, on_http_request);
|
||||
if (endpoint_params.asset_root != null)
|
||||
server.add_handler (null, on_asset_request);
|
||||
}
|
||||
|
||||
public void close () {
|
||||
io_cancellable.cancel ();
|
||||
|
||||
if (endpoint_params.request_handler != null || endpoint_params.asset_root != null)
|
||||
if (endpoint_params.asset_root != null)
|
||||
server.remove_handler ("/");
|
||||
server.remove_handler ("/ws");
|
||||
|
||||
@@ -726,8 +560,7 @@ namespace Frida {
|
||||
try {
|
||||
remote_address = sc.get_remote_address ();
|
||||
} catch (GLib.Error e) {
|
||||
remove_connection (peer);
|
||||
return;
|
||||
assert_not_reached ();
|
||||
}
|
||||
|
||||
incoming (peer, remote_address);
|
||||
@@ -742,77 +575,20 @@ namespace Frida {
|
||||
connections.remove (connection);
|
||||
}
|
||||
|
||||
private void on_http_request (Soup.Server server, Soup.ServerMessage msg, string path,
|
||||
private void on_asset_request (Soup.Server server, Soup.ServerMessage msg, string path,
|
||||
HashTable<string, string>? query) {
|
||||
msg.get_response_headers ().replace ("Server", "Frida/" + _version_string ());
|
||||
|
||||
msg.pause ();
|
||||
handle_http_request.begin (msg, path);
|
||||
}
|
||||
|
||||
private async void handle_http_request (Soup.ServerMessage msg, string path) {
|
||||
WebRequestHandler? handler = endpoint_params.request_handler;
|
||||
if (handler != null) {
|
||||
if (yield try_request_handler (handler, msg, path, io_cancellable))
|
||||
return;
|
||||
}
|
||||
|
||||
File? asset_root = endpoint_params.asset_root;
|
||||
if (asset_root != null) {
|
||||
unowned string method = msg.get_method ();
|
||||
if (method != "GET" && method != "HEAD") {
|
||||
msg.set_status (Soup.Status.METHOD_NOT_ALLOWED, null);
|
||||
msg.unpause ();
|
||||
return;
|
||||
}
|
||||
|
||||
File location = asset_root.resolve_relative_path (path.next_char ());
|
||||
yield handle_asset_request (path, location, msg);
|
||||
unowned string method = msg.get_method ();
|
||||
if (method != "GET" && method != "HEAD") {
|
||||
msg.set_status (Soup.Status.METHOD_NOT_ALLOWED, null);
|
||||
return;
|
||||
}
|
||||
|
||||
msg.set_status (Soup.Status.NOT_FOUND, null);
|
||||
msg.unpause ();
|
||||
}
|
||||
File location = endpoint_params.asset_root.resolve_relative_path (path.next_char ());
|
||||
|
||||
private static async bool try_request_handler (WebRequestHandler handler, Soup.ServerMessage msg, string path,
|
||||
Cancellable? cancellable) {
|
||||
var body = msg.get_request_body ();
|
||||
Bytes? request_body = (body.length != 0) ? body.flatten () : null;
|
||||
unowned Uri? uri = msg.get_uri ();
|
||||
string? query_string = (uri != null) ? uri.get_query () : null;
|
||||
var request = new WebRequest (msg.get_method (), path, query_string, msg.get_request_headers (),
|
||||
request_body);
|
||||
|
||||
WebResponse? response;
|
||||
try {
|
||||
response = yield handler.handle_request (request, cancellable);
|
||||
} catch (Error e) {
|
||||
msg.set_status (Soup.Status.INTERNAL_SERVER_ERROR, null);
|
||||
msg.set_response ("text/plain; charset=utf-8", Soup.MemoryUse.COPY, e.message.data);
|
||||
msg.unpause ();
|
||||
return true;
|
||||
} catch (IOError e) {
|
||||
msg.unpause ();
|
||||
return true;
|
||||
}
|
||||
|
||||
if (response == null)
|
||||
return false;
|
||||
|
||||
apply_response (msg, response);
|
||||
msg.unpause ();
|
||||
return true;
|
||||
}
|
||||
|
||||
private static void apply_response (Soup.ServerMessage msg, WebResponse response) {
|
||||
msg.set_status (response.status, null);
|
||||
|
||||
response.write_headers_to (msg.get_response_headers ());
|
||||
|
||||
Bytes body = response.body;
|
||||
if (body.length > 0)
|
||||
msg.get_response_body ().append_bytes (body);
|
||||
msg.pause ();
|
||||
handle_asset_request.begin (path, location, msg);
|
||||
}
|
||||
|
||||
private async void handle_asset_request (string path, File file, Soup.ServerMessage msg) {
|
||||
@@ -1164,12 +940,6 @@ namespace Frida {
|
||||
Memory.copy (buffer, recv_queue.data, n);
|
||||
recv_queue.remove_range (0, (uint) n);
|
||||
|
||||
if (recv_queue.len == 0) {
|
||||
#if HAVE_SOUP_WEBSOCKET_BACKPRESSURE
|
||||
websocket.resume_input ();
|
||||
#endif
|
||||
}
|
||||
|
||||
update_pending_io ();
|
||||
} else {
|
||||
if (state == OPEN)
|
||||
@@ -1236,9 +1006,6 @@ namespace Frida {
|
||||
private void on_message (int type, Bytes message) {
|
||||
with_state_lock (() => {
|
||||
recv_queue.append (message.get_data ());
|
||||
#if HAVE_SOUP_WEBSOCKET_BACKPRESSURE
|
||||
websocket.pause_input ();
|
||||
#endif
|
||||
update_pending_io ();
|
||||
});
|
||||
}
|
||||
|
||||
+1
-26
@@ -288,7 +288,7 @@ namespace Frida {
|
||||
|
||||
public JsonObjectReader (string json) throws Error {
|
||||
try {
|
||||
reader = make_json_reader (json);
|
||||
reader = new Json.Reader (Json.from_string (json));
|
||||
} catch (GLib.Error e) {
|
||||
throw new Error.INVALID_ARGUMENT ("%s", e.message);
|
||||
}
|
||||
@@ -404,29 +404,4 @@ namespace Frida {
|
||||
throw new Error.PROTOCOL ("%s", e.message);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Constructs a Json.Reader for the given JSON string, working around the
|
||||
* json_node_copy() bug in unpatched json-glib (GNOME bugzilla #774684).
|
||||
*
|
||||
* Json.Reader's set_root() copies the supplied node via json_node_copy().
|
||||
* For object/array nodes that copy is a thin shell that shares the original
|
||||
* JsonObject/JsonArray via refcount, but the members inside the shared
|
||||
* container have their parent pointers set to the *original* root, not the
|
||||
* shell. If the original is then dropped, json_reader_end_member()'s walk
|
||||
* via json_node_get_parent() touches a freed node — which on builds with
|
||||
* glib checks enabled (e.g. Fedora) trips JSON_NODE_IS_VALID and aborts.
|
||||
*
|
||||
* We keep the original root alive by attaching it to the reader as object
|
||||
* data; the destroy notify drops our reference when the reader is finalized.
|
||||
*/
|
||||
public Json.Reader make_json_reader (string json) throws GLib.Error {
|
||||
return make_json_reader_taking_node (Json.from_string (json));
|
||||
}
|
||||
|
||||
public Json.Reader make_json_reader_taking_node (owned Json.Node root) {
|
||||
var reader = new Json.Reader (root);
|
||||
reader.set_data<Json.Node> ("frida-json-root", (owned) root);
|
||||
return reader;
|
||||
}
|
||||
}
|
||||
@@ -1,376 +0,0 @@
|
||||
#include "frida-base.h"
|
||||
|
||||
#include <windows.h>
|
||||
|
||||
#define FRIDA_TYPE_WINDOWS_HANDLE_STREAM (frida_windows_handle_stream_get_type ())
|
||||
#define FRIDA_TYPE_WINDOWS_HANDLE_INPUT_STREAM (frida_windows_handle_input_stream_get_type ())
|
||||
#define FRIDA_TYPE_WINDOWS_HANDLE_OUTPUT_STREAM (frida_windows_handle_output_stream_get_type ())
|
||||
|
||||
#define FRIDA_WINDOWS_HANDLE_STREAM(o) ((FridaWindowsHandleStream *) (o))
|
||||
#define FRIDA_WINDOWS_HANDLE_INPUT_STREAM(o) ((FridaWindowsHandleInputStream *) (o))
|
||||
#define FRIDA_WINDOWS_HANDLE_OUTPUT_STREAM(o) ((FridaWindowsHandleOutputStream *) (o))
|
||||
|
||||
typedef struct _FridaWindowsHandleStream FridaWindowsHandleStream;
|
||||
typedef struct _FridaWindowsHandleStreamClass FridaWindowsHandleStreamClass;
|
||||
typedef struct _FridaWindowsHandleInputStream FridaWindowsHandleInputStream;
|
||||
typedef struct _FridaWindowsHandleInputStreamClass FridaWindowsHandleInputStreamClass;
|
||||
typedef struct _FridaWindowsHandleOutputStream FridaWindowsHandleOutputStream;
|
||||
typedef struct _FridaWindowsHandleOutputStreamClass FridaWindowsHandleOutputStreamClass;
|
||||
|
||||
struct _FridaWindowsHandleStream
|
||||
{
|
||||
GIOStream parent;
|
||||
|
||||
HANDLE handle;
|
||||
HANDLE read_complete;
|
||||
HANDLE read_cancel;
|
||||
HANDLE write_complete;
|
||||
HANDLE write_cancel;
|
||||
|
||||
GInputStream * input;
|
||||
GOutputStream * output;
|
||||
};
|
||||
|
||||
struct _FridaWindowsHandleStreamClass
|
||||
{
|
||||
GIOStreamClass parent_class;
|
||||
};
|
||||
|
||||
struct _FridaWindowsHandleInputStream
|
||||
{
|
||||
GInputStream parent;
|
||||
|
||||
FridaWindowsHandleStream * stream;
|
||||
};
|
||||
|
||||
struct _FridaWindowsHandleInputStreamClass
|
||||
{
|
||||
GInputStreamClass parent_class;
|
||||
};
|
||||
|
||||
struct _FridaWindowsHandleOutputStream
|
||||
{
|
||||
GOutputStream parent;
|
||||
|
||||
FridaWindowsHandleStream * stream;
|
||||
};
|
||||
|
||||
struct _FridaWindowsHandleOutputStreamClass
|
||||
{
|
||||
GOutputStreamClass parent_class;
|
||||
};
|
||||
|
||||
static GIOStream * frida_windows_handle_stream_new (HANDLE handle);
|
||||
|
||||
static void frida_windows_handle_stream_finalize (GObject * object);
|
||||
static GInputStream * frida_windows_handle_stream_get_input_stream (GIOStream * stream);
|
||||
static GOutputStream * frida_windows_handle_stream_get_output_stream (GIOStream * stream);
|
||||
static gboolean frida_windows_handle_stream_close_fn (GIOStream * stream, GCancellable * cancellable, GError ** error);
|
||||
|
||||
static gssize frida_windows_handle_input_stream_read (GInputStream * base, void * buffer, gsize count,
|
||||
GCancellable * cancellable, GError ** error);
|
||||
static gboolean frida_windows_handle_input_stream_close (GInputStream * base, GCancellable * cancellable, GError ** error);
|
||||
|
||||
static gssize frida_windows_handle_output_stream_write (GOutputStream * base, const void * buffer, gsize count,
|
||||
GCancellable * cancellable, GError ** error);
|
||||
static gboolean frida_windows_handle_output_stream_close (GOutputStream * base, GCancellable * cancellable,
|
||||
GError ** error);
|
||||
|
||||
static gboolean frida_windows_handle_stream_await (FridaWindowsHandleStream * self, HANDLE complete, HANDLE cancel,
|
||||
GCancellable * cancellable, GError ** error);
|
||||
static void frida_windows_handle_stream_on_cancel (GCancellable * cancellable, gpointer user_data);
|
||||
|
||||
G_DEFINE_TYPE (FridaWindowsHandleStream, frida_windows_handle_stream, G_TYPE_IO_STREAM)
|
||||
G_DEFINE_TYPE (FridaWindowsHandleInputStream, frida_windows_handle_input_stream, G_TYPE_INPUT_STREAM)
|
||||
G_DEFINE_TYPE (FridaWindowsHandleOutputStream, frida_windows_handle_output_stream, G_TYPE_OUTPUT_STREAM)
|
||||
|
||||
GIOStream *
|
||||
frida_windows_named_pipe_open_client (const gchar * path, GError ** error)
|
||||
{
|
||||
HANDLE handle;
|
||||
WCHAR * path_utf16;
|
||||
DWORD last_error;
|
||||
|
||||
path_utf16 = (WCHAR *) g_utf8_to_utf16 (path, -1, NULL, NULL, NULL);
|
||||
if (path_utf16 == NULL)
|
||||
goto invalid_path;
|
||||
|
||||
handle = CreateFileW (path_utf16,
|
||||
GENERIC_READ | GENERIC_WRITE,
|
||||
0,
|
||||
NULL,
|
||||
OPEN_EXISTING,
|
||||
FILE_FLAG_OVERLAPPED,
|
||||
NULL);
|
||||
last_error = GetLastError ();
|
||||
g_free (path_utf16);
|
||||
|
||||
if (handle == INVALID_HANDLE_VALUE)
|
||||
goto cannot_open;
|
||||
|
||||
return frida_windows_handle_stream_new (handle);
|
||||
|
||||
invalid_path:
|
||||
{
|
||||
g_set_error (error, G_IO_ERROR, G_IO_ERROR_INVALID_ARGUMENT, "Invalid pipe path");
|
||||
return NULL;
|
||||
}
|
||||
cannot_open:
|
||||
{
|
||||
g_set_error (error,
|
||||
G_IO_ERROR,
|
||||
g_io_error_from_win32_error (last_error),
|
||||
"Unable to open %s (CreateFile returned 0x%08lx)",
|
||||
path, last_error);
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
static GIOStream *
|
||||
frida_windows_handle_stream_new (HANDLE handle)
|
||||
{
|
||||
FridaWindowsHandleStream * stream;
|
||||
FridaWindowsHandleInputStream * input;
|
||||
FridaWindowsHandleOutputStream * output;
|
||||
|
||||
stream = g_object_new (FRIDA_TYPE_WINDOWS_HANDLE_STREAM, NULL);
|
||||
stream->handle = handle;
|
||||
stream->read_complete = CreateEvent (NULL, TRUE, FALSE, NULL);
|
||||
stream->read_cancel = CreateEvent (NULL, TRUE, FALSE, NULL);
|
||||
stream->write_complete = CreateEvent (NULL, TRUE, FALSE, NULL);
|
||||
stream->write_cancel = CreateEvent (NULL, TRUE, FALSE, NULL);
|
||||
|
||||
input = g_object_new (FRIDA_TYPE_WINDOWS_HANDLE_INPUT_STREAM, NULL);
|
||||
input->stream = stream;
|
||||
stream->input = G_INPUT_STREAM (input);
|
||||
|
||||
output = g_object_new (FRIDA_TYPE_WINDOWS_HANDLE_OUTPUT_STREAM, NULL);
|
||||
output->stream = stream;
|
||||
stream->output = G_OUTPUT_STREAM (output);
|
||||
|
||||
return G_IO_STREAM (stream);
|
||||
}
|
||||
|
||||
static void
|
||||
frida_windows_handle_stream_class_init (FridaWindowsHandleStreamClass * klass)
|
||||
{
|
||||
GObjectClass * object_class = G_OBJECT_CLASS (klass);
|
||||
GIOStreamClass * stream_class = G_IO_STREAM_CLASS (klass);
|
||||
|
||||
object_class->finalize = frida_windows_handle_stream_finalize;
|
||||
|
||||
stream_class->get_input_stream = frida_windows_handle_stream_get_input_stream;
|
||||
stream_class->get_output_stream = frida_windows_handle_stream_get_output_stream;
|
||||
stream_class->close_fn = frida_windows_handle_stream_close_fn;
|
||||
}
|
||||
|
||||
static void
|
||||
frida_windows_handle_stream_init (FridaWindowsHandleStream * self)
|
||||
{
|
||||
self->handle = INVALID_HANDLE_VALUE;
|
||||
}
|
||||
|
||||
static void
|
||||
frida_windows_handle_stream_finalize (GObject * object)
|
||||
{
|
||||
FridaWindowsHandleStream * self = FRIDA_WINDOWS_HANDLE_STREAM (object);
|
||||
|
||||
g_clear_object (&self->input);
|
||||
g_clear_object (&self->output);
|
||||
|
||||
CloseHandle (self->read_complete);
|
||||
CloseHandle (self->read_cancel);
|
||||
CloseHandle (self->write_complete);
|
||||
CloseHandle (self->write_cancel);
|
||||
|
||||
if (self->handle != INVALID_HANDLE_VALUE)
|
||||
CloseHandle (self->handle);
|
||||
|
||||
G_OBJECT_CLASS (frida_windows_handle_stream_parent_class)->finalize (object);
|
||||
}
|
||||
|
||||
static GInputStream *
|
||||
frida_windows_handle_stream_get_input_stream (GIOStream * stream)
|
||||
{
|
||||
return FRIDA_WINDOWS_HANDLE_STREAM (stream)->input;
|
||||
}
|
||||
|
||||
static GOutputStream *
|
||||
frida_windows_handle_stream_get_output_stream (GIOStream * stream)
|
||||
{
|
||||
return FRIDA_WINDOWS_HANDLE_STREAM (stream)->output;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
frida_windows_handle_stream_close_fn (GIOStream * stream, GCancellable * cancellable, GError ** error)
|
||||
{
|
||||
FridaWindowsHandleStream * self = FRIDA_WINDOWS_HANDLE_STREAM (stream);
|
||||
|
||||
SetEvent (self->read_cancel);
|
||||
SetEvent (self->write_cancel);
|
||||
|
||||
if (self->handle != INVALID_HANDLE_VALUE)
|
||||
{
|
||||
CancelIo (self->handle);
|
||||
CloseHandle (self->handle);
|
||||
self->handle = INVALID_HANDLE_VALUE;
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static void
|
||||
frida_windows_handle_input_stream_class_init (FridaWindowsHandleInputStreamClass * klass)
|
||||
{
|
||||
GInputStreamClass * stream_class = G_INPUT_STREAM_CLASS (klass);
|
||||
|
||||
stream_class->read_fn = frida_windows_handle_input_stream_read;
|
||||
stream_class->close_fn = frida_windows_handle_input_stream_close;
|
||||
}
|
||||
|
||||
static void
|
||||
frida_windows_handle_input_stream_init (FridaWindowsHandleInputStream * self)
|
||||
{
|
||||
}
|
||||
|
||||
static gssize
|
||||
frida_windows_handle_input_stream_read (GInputStream * base, void * buffer, gsize count, GCancellable * cancellable,
|
||||
GError ** error)
|
||||
{
|
||||
FridaWindowsHandleStream * stream = FRIDA_WINDOWS_HANDLE_INPUT_STREAM (base)->stream;
|
||||
OVERLAPPED overlapped = { 0, };
|
||||
DWORD bytes_transferred, last_error;
|
||||
|
||||
if (stream->handle == INVALID_HANDLE_VALUE)
|
||||
return 0;
|
||||
|
||||
overlapped.hEvent = stream->read_complete;
|
||||
if (!ReadFile (stream->handle, buffer, count, NULL, &overlapped) && GetLastError () != ERROR_IO_PENDING)
|
||||
goto failure;
|
||||
|
||||
if (!frida_windows_handle_stream_await (stream, stream->read_complete, stream->read_cancel, cancellable, error))
|
||||
return -1;
|
||||
|
||||
if (!GetOverlappedResult (stream->handle, &overlapped, &bytes_transferred, FALSE))
|
||||
goto failure;
|
||||
|
||||
return bytes_transferred;
|
||||
|
||||
failure:
|
||||
{
|
||||
last_error = GetLastError ();
|
||||
if (last_error == ERROR_BROKEN_PIPE || last_error == ERROR_PIPE_NOT_CONNECTED)
|
||||
return 0;
|
||||
g_set_error (error,
|
||||
G_IO_ERROR,
|
||||
g_io_error_from_win32_error (last_error),
|
||||
"Error reading from pipe");
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
static gboolean
|
||||
frida_windows_handle_input_stream_close (GInputStream * base, GCancellable * cancellable, GError ** error)
|
||||
{
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static void
|
||||
frida_windows_handle_output_stream_class_init (FridaWindowsHandleOutputStreamClass * klass)
|
||||
{
|
||||
GOutputStreamClass * stream_class = G_OUTPUT_STREAM_CLASS (klass);
|
||||
|
||||
stream_class->write_fn = frida_windows_handle_output_stream_write;
|
||||
stream_class->close_fn = frida_windows_handle_output_stream_close;
|
||||
}
|
||||
|
||||
static void
|
||||
frida_windows_handle_output_stream_init (FridaWindowsHandleOutputStream * self)
|
||||
{
|
||||
}
|
||||
|
||||
static gssize
|
||||
frida_windows_handle_output_stream_write (GOutputStream * base, const void * buffer, gsize count,
|
||||
GCancellable * cancellable, GError ** error)
|
||||
{
|
||||
FridaWindowsHandleStream * stream = FRIDA_WINDOWS_HANDLE_OUTPUT_STREAM (base)->stream;
|
||||
OVERLAPPED overlapped = { 0, };
|
||||
DWORD bytes_transferred, last_error;
|
||||
|
||||
if (stream->handle == INVALID_HANDLE_VALUE)
|
||||
goto closed;
|
||||
|
||||
overlapped.hEvent = stream->write_complete;
|
||||
if (!WriteFile (stream->handle, buffer, count, NULL, &overlapped) && GetLastError () != ERROR_IO_PENDING)
|
||||
goto failure;
|
||||
|
||||
if (!frida_windows_handle_stream_await (stream, stream->write_complete, stream->write_cancel, cancellable, error))
|
||||
return -1;
|
||||
|
||||
if (!GetOverlappedResult (stream->handle, &overlapped, &bytes_transferred, FALSE))
|
||||
goto failure;
|
||||
|
||||
return bytes_transferred;
|
||||
|
||||
closed:
|
||||
{
|
||||
g_set_error (error, G_IO_ERROR, G_IO_ERROR_CLOSED, "Pipe is closed");
|
||||
return -1;
|
||||
}
|
||||
failure:
|
||||
{
|
||||
last_error = GetLastError ();
|
||||
g_set_error (error,
|
||||
G_IO_ERROR,
|
||||
g_io_error_from_win32_error (last_error),
|
||||
"Error writing to pipe");
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
static gboolean
|
||||
frida_windows_handle_output_stream_close (GOutputStream * base, GCancellable * cancellable, GError ** error)
|
||||
{
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
frida_windows_handle_stream_await (FridaWindowsHandleStream * self, HANDLE complete, HANDLE cancel,
|
||||
GCancellable * cancellable, GError ** error)
|
||||
{
|
||||
gulong handler_id = 0;
|
||||
HANDLE events[2];
|
||||
|
||||
if (cancellable != NULL)
|
||||
handler_id = g_cancellable_connect (cancellable, G_CALLBACK (frida_windows_handle_stream_on_cancel), cancel, NULL);
|
||||
|
||||
events[0] = complete;
|
||||
events[1] = cancel;
|
||||
WaitForMultipleObjects (G_N_ELEMENTS (events), events, FALSE, INFINITE);
|
||||
|
||||
if (cancellable != NULL)
|
||||
{
|
||||
g_cancellable_disconnect (cancellable, handler_id);
|
||||
if (g_cancellable_set_error_if_cancelled (cancellable, error))
|
||||
{
|
||||
CancelIo (self->handle);
|
||||
return FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
if (WaitForSingleObject (cancel, 0) == WAIT_OBJECT_0)
|
||||
{
|
||||
g_set_error (error, G_IO_ERROR, G_IO_ERROR_CLOSED, "Pipe is closed");
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static void
|
||||
frida_windows_handle_stream_on_cancel (GCancellable * cancellable, gpointer user_data)
|
||||
{
|
||||
HANDLE cancel = (HANDLE) user_data;
|
||||
|
||||
SetEvent (cancel);
|
||||
}
|
||||
@@ -1,8 +1,4 @@
|
||||
namespace Frida {
|
||||
namespace WindowsNamedPipe {
|
||||
public extern IOStream open_client (string path) throws GLib.Error;
|
||||
}
|
||||
|
||||
public sealed class StdioPipes : Object {
|
||||
public OutputStream input {
|
||||
get;
|
||||
|
||||
@@ -1,860 +0,0 @@
|
||||
#!/usr/bin/env python3
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
from __future__ import annotations
|
||||
|
||||
import argparse
|
||||
import re
|
||||
from dataclasses import dataclass
|
||||
from pathlib import Path
|
||||
from typing import Dict, List, Optional, Tuple
|
||||
|
||||
MAX_ARGS = 9
|
||||
|
||||
|
||||
@dataclass(frozen=True)
|
||||
class SyscallArg:
|
||||
type: str
|
||||
name: str
|
||||
|
||||
|
||||
@dataclass(frozen=True)
|
||||
class SyscallSignature:
|
||||
name: str
|
||||
args: Tuple[SyscallArg, ...]
|
||||
|
||||
|
||||
MACH_TRAP_INDEXED_CALL_RE = re.compile(r"/\*\s*(?P<idx>\d+)\s*\*/\s*MACH_TRAP\s*\(")
|
||||
MACH_TRAPS_IFNDEF_KERNEL_RE = re.compile(r"^\s*#ifndef\s+KERNEL\b", re.MULTILINE)
|
||||
MACH_TRAPS_ELSE_KERNEL_RE = re.compile(r"^\s*#else\b.*\bKERNEL\b", re.MULTILINE)
|
||||
|
||||
USER_EXTERN_PROTO_RE = re.compile(
|
||||
r"^\s*extern\s+(?P<ret>.+?)\s+(?P<fn>[A-Za-z_]\w*)\s*\((?P<args>.*?)\)\s*;",
|
||||
re.MULTILINE | re.DOTALL,
|
||||
)
|
||||
KERNEL_STRUCT_RE = re.compile(
|
||||
r"\bstruct\s+(?P<name>[A-Za-z_]\w*)\s*\{\s*(?P<body>.*?)\s*\}\s*;",
|
||||
re.DOTALL,
|
||||
)
|
||||
KERNEL_TRAP_EXTERN_RE = re.compile(
|
||||
r"^\s*(?:extern\s+)?(?P<ret>.+?)\s+(?P<fn>[A-Za-z_]\w*)\s*\(\s*struct\s+(?P<args_struct>[A-Za-z_]\w*)\s*\*\s*args\s*\)\s*;",
|
||||
re.MULTILINE | re.DOTALL,
|
||||
)
|
||||
PAD_ARG_RE = re.compile(
|
||||
r"\bPAD_ARG_\s*\(\s*(?P<ty>[^,]+?)\s*,\s*(?P<name>[^)]+?)\s*\)\s*;",
|
||||
)
|
||||
PLAIN_FIELD_RE = re.compile(r"^\s*(?P<ty>.+?)\s+(?P<name>[A-Za-z_]\w*)\s*;\s*$")
|
||||
|
||||
BSD_MASTER_ENTRY_RE = re.compile(
|
||||
r"^\s*(?P<nr>\d+)\s+(?P<audit>\S+)\s+(?P<files>\S+)\s+\{\s*(?P<proto>[^}]+?)\s*\}\s*(?:\{.*\})?\s*$"
|
||||
)
|
||||
BSD_MASTER_PROTO_RE = re.compile(
|
||||
r"^\s*(?P<ret>.+?)\s+(?P<fn>[A-Za-z_]\w*)\s*\((?P<args>.*)\)\s*(?P<attrs>.*)$",
|
||||
re.DOTALL,
|
||||
)
|
||||
|
||||
LINE_COMMENT_RE = re.compile(r"//.*$")
|
||||
BLOCK_COMMENT_RE = re.compile(r"/\*[^*]*\*+(?:[^/*][^*]*\*+)*/")
|
||||
|
||||
TRAILING_ARRAY_SUFFIX_RE = re.compile(r"\[[^\]]*\]\s*$")
|
||||
POINTER_SPACING_RE = re.compile(r"\s*\*\s*")
|
||||
PARAM_NAME_RE = re.compile(r"[A-Za-z_]\w*$")
|
||||
|
||||
|
||||
def main() -> int:
|
||||
ap = argparse.ArgumentParser()
|
||||
ap.add_argument("--kernel-tree", required=True)
|
||||
ap.add_argument("--out-vala", required=True)
|
||||
ap.add_argument("--out-c", required=True)
|
||||
args = ap.parse_args()
|
||||
|
||||
kernel_tree = Path(args.kernel_tree).resolve()
|
||||
if not kernel_tree.exists():
|
||||
raise SystemExit(f"--kernel-tree does not exist: {kernel_tree}")
|
||||
|
||||
mach_numbers, mach_sigs = load_mach_traps(kernel_tree)
|
||||
bsd_numbers, bsd_sigs = load_bsd_syscalls_master(kernel_tree)
|
||||
|
||||
vala = render_vala(
|
||||
mach_numbers=mach_numbers,
|
||||
bsd_numbers=bsd_numbers,
|
||||
)
|
||||
c_src = render_c_source(
|
||||
mach_numbers=mach_numbers,
|
||||
bsd_numbers=bsd_numbers,
|
||||
mach_sigs=mach_sigs,
|
||||
bsd_sigs=bsd_sigs,
|
||||
)
|
||||
|
||||
out_vala = Path(args.out_vala)
|
||||
out_c = Path(args.out_c)
|
||||
out_vala.parent.mkdir(parents=True, exist_ok=True)
|
||||
out_c.parent.mkdir(parents=True, exist_ok=True)
|
||||
out_vala.write_text(vala, encoding="utf-8")
|
||||
out_c.write_text(c_src, encoding="utf-8")
|
||||
|
||||
return 0
|
||||
|
||||
|
||||
def load_mach_traps(
|
||||
kernel_tree: Path,
|
||||
) -> Tuple[Dict[int, str], Dict[str, SyscallSignature]]:
|
||||
table_path = kernel_tree / "osfmk" / "kern" / "syscall_sw.c"
|
||||
if not table_path.exists():
|
||||
raise RuntimeError(f"Missing Mach trap table source: {table_path}")
|
||||
|
||||
header_path = kernel_tree / "osfmk" / "mach" / "mach_traps.h"
|
||||
if not header_path.exists():
|
||||
raise RuntimeError(f"Missing Mach traps header: {header_path}")
|
||||
|
||||
table_text = table_path.read_text(encoding="utf-8", errors="ignore")
|
||||
trap_routines = parse_mach_trap_table(table_text, table_path)
|
||||
|
||||
header_text = header_path.read_text(encoding="utf-8", errors="ignore")
|
||||
userspace_text, kernel_text = split_mach_traps_header(header_text, header_path)
|
||||
|
||||
userspace_protos = parse_userspace_mach_traps_prototypes(
|
||||
userspace_text, header_path
|
||||
)
|
||||
kernel_argmap = parse_kernel_mach_traps_args(kernel_text, header_path)
|
||||
|
||||
numbers: Dict[int, str] = {}
|
||||
sigs: Dict[str, SyscallSignature] = {}
|
||||
|
||||
for index, routine in trap_routines:
|
||||
if routine == "kern_invalid":
|
||||
continue
|
||||
|
||||
nr = -index
|
||||
public_name = normalize_mach_name(routine)
|
||||
if public_name == "":
|
||||
raise RuntimeError(f"{table_path}: empty normalized name from {routine!r}")
|
||||
|
||||
if nr in numbers:
|
||||
raise RuntimeError(f"{table_path}: duplicate mach trap number {nr}")
|
||||
if public_name in sigs:
|
||||
raise RuntimeError(
|
||||
f"{table_path}: normalized Mach name collision for {public_name!r}"
|
||||
)
|
||||
|
||||
args = resolve_mach_trap_signature(
|
||||
routine=routine,
|
||||
userspace_protos=userspace_protos,
|
||||
kernel_argmap=kernel_argmap,
|
||||
table_path=table_path,
|
||||
)
|
||||
|
||||
if len(args) > MAX_ARGS:
|
||||
raise RuntimeError(
|
||||
f"{table_path}: trap {routine!r} has {len(args)} args; max supported is {MAX_ARGS}"
|
||||
)
|
||||
|
||||
numbers[nr] = public_name
|
||||
sigs[public_name] = SyscallSignature(name=public_name, args=tuple(args))
|
||||
|
||||
return numbers, sigs
|
||||
|
||||
|
||||
def parse_mach_trap_table(text: str, path: Path) -> List[Tuple[int, str]]:
|
||||
anchor = text.find("mach_trap_table")
|
||||
if anchor == -1:
|
||||
raise RuntimeError(f"{path}: mach_trap_table not found")
|
||||
|
||||
brace = text.find("{", anchor)
|
||||
if brace == -1:
|
||||
raise RuntimeError(f"{path}: mach_trap_table '{{' not found")
|
||||
|
||||
payload, _ = extract_brace_payload(text, brace, path)
|
||||
|
||||
by_index: Dict[int, str] = {}
|
||||
|
||||
off = 0
|
||||
while True:
|
||||
m = MACH_TRAP_INDEXED_CALL_RE.search(payload, off)
|
||||
if m is None:
|
||||
break
|
||||
|
||||
idx = int(m.group("idx"), 10)
|
||||
open_paren = m.end(0) - 1
|
||||
args_blob, end_off = extract_parentheses_payload(payload, open_paren, path)
|
||||
|
||||
parts = [
|
||||
a.strip() for a in split_top_level_commas(args_blob) if a.strip() != ""
|
||||
]
|
||||
if len(parts) < 1:
|
||||
raise RuntimeError(f"{path}: bad MACH_TRAP() entry: {args_blob!r}")
|
||||
|
||||
routine = parts[0]
|
||||
|
||||
prev = by_index.get(idx)
|
||||
if prev is None:
|
||||
by_index[idx] = routine
|
||||
else:
|
||||
if prev == routine:
|
||||
pass
|
||||
elif prev == "kern_invalid" and routine != "kern_invalid":
|
||||
by_index[idx] = routine
|
||||
elif routine == "kern_invalid" and prev != "kern_invalid":
|
||||
pass
|
||||
else:
|
||||
raise RuntimeError(
|
||||
f"{path}: conflicting MACH_TRAP entries for index {idx}: {prev!r} vs {routine!r}"
|
||||
)
|
||||
|
||||
off = end_off
|
||||
|
||||
return sorted(by_index.items(), key=lambda kv: kv[0])
|
||||
|
||||
|
||||
def split_mach_traps_header(text: str, path: Path) -> Tuple[str, str]:
|
||||
m_start = MACH_TRAPS_IFNDEF_KERNEL_RE.search(text)
|
||||
if m_start is None:
|
||||
raise RuntimeError(f"{path}: missing '#ifndef KERNEL'")
|
||||
|
||||
m_else = MACH_TRAPS_ELSE_KERNEL_RE.search(text, m_start.end())
|
||||
if m_else is None:
|
||||
raise RuntimeError(f"{path}: missing '#else ... KERNEL ...'")
|
||||
|
||||
userspace = text[m_start.end():m_else.start()]
|
||||
kernel = text[m_else.end():]
|
||||
return userspace, kernel
|
||||
|
||||
|
||||
def parse_userspace_mach_traps_prototypes(
|
||||
userspace_text: str, path: Path
|
||||
) -> Dict[str, Tuple[SyscallArg, ...]]:
|
||||
protos: Dict[str, Tuple[SyscallArg, ...]] = {}
|
||||
|
||||
for m in USER_EXTERN_PROTO_RE.finditer(userspace_text):
|
||||
fn = m.group("fn").strip()
|
||||
args_blob = m.group("args").strip()
|
||||
ret_blob = strip_c_comments(m.group("ret")).strip()
|
||||
if ret_blob == "":
|
||||
raise RuntimeError(f"{path}: empty return type for {fn!r}")
|
||||
|
||||
line_no = line_number_at_offset(userspace_text, m.start())
|
||||
|
||||
args = parse_c_param_list(args_blob, path, line_no)
|
||||
cur = tuple(args)
|
||||
|
||||
prev = protos.get(fn)
|
||||
if prev is not None and prev != cur:
|
||||
raise RuntimeError(f"{path}:{line_no}: conflicting prototype for {fn!r}")
|
||||
|
||||
protos[fn] = cur
|
||||
|
||||
return protos
|
||||
|
||||
|
||||
def parse_kernel_mach_traps_args(
|
||||
kernel_text: str, path: Path
|
||||
) -> Dict[str, Tuple[SyscallArg, ...]]:
|
||||
text = strip_c_comments(kernel_text)
|
||||
|
||||
structs: Dict[str, str] = {}
|
||||
for m in KERNEL_STRUCT_RE.finditer(text):
|
||||
name = m.group("name").strip()
|
||||
body = m.group("body")
|
||||
structs[name] = body
|
||||
|
||||
fn_to_struct: Dict[str, str] = {}
|
||||
for m in KERNEL_TRAP_EXTERN_RE.finditer(text):
|
||||
fn = m.group("fn").strip()
|
||||
args_struct = m.group("args_struct").strip()
|
||||
fn_to_struct[fn] = args_struct
|
||||
|
||||
out: Dict[str, Tuple[SyscallArg, ...]] = {}
|
||||
|
||||
for fn, args_struct in fn_to_struct.items():
|
||||
body = structs.get(args_struct)
|
||||
if body is None:
|
||||
continue
|
||||
|
||||
args = parse_mach_args_struct_body(body, path)
|
||||
out[fn] = tuple(args)
|
||||
|
||||
return out
|
||||
|
||||
|
||||
def parse_mach_args_struct_body(body: str, path: Path) -> List[SyscallArg]:
|
||||
args: List[SyscallArg] = []
|
||||
|
||||
body = strip_c_comments(body)
|
||||
for raw_ln in body.splitlines():
|
||||
ln = raw_ln.strip()
|
||||
if ln == "" or ln.startswith("#"):
|
||||
continue
|
||||
if "PAD_ARG_8" in ln:
|
||||
continue
|
||||
|
||||
m = PAD_ARG_RE.search(ln)
|
||||
if m is not None:
|
||||
ty = normalize_whitespace(m.group("ty").strip())
|
||||
name = normalize_whitespace(m.group("name").strip())
|
||||
if ty == "" or name == "":
|
||||
raise RuntimeError(f"{path}: bad PAD_ARG_ in args struct: {raw_ln!r}")
|
||||
args.append(SyscallArg(type=ty, name=name))
|
||||
continue
|
||||
|
||||
m = PLAIN_FIELD_RE.match(ln)
|
||||
if m is not None:
|
||||
ty = normalize_whitespace(m.group("ty").strip())
|
||||
name = m.group("name").strip()
|
||||
if ty == "" or name == "":
|
||||
raise RuntimeError(f"{path}: bad field in args struct: {raw_ln!r}")
|
||||
args.append(SyscallArg(type=ty, name=name))
|
||||
continue
|
||||
|
||||
if len(args) == 1 and args[0].name == "dummy":
|
||||
return []
|
||||
|
||||
return args
|
||||
|
||||
|
||||
def resolve_mach_trap_signature(
|
||||
*,
|
||||
routine: str,
|
||||
userspace_protos: Dict[str, Tuple[SyscallArg, ...]],
|
||||
kernel_argmap: Dict[str, Tuple[SyscallArg, ...]],
|
||||
table_path: Path,
|
||||
) -> List[SyscallArg]:
|
||||
def get_userspace(name: str) -> Optional[Tuple[SyscallArg, ...]]:
|
||||
return userspace_protos.get(name)
|
||||
|
||||
def get_kernel(name: str) -> Optional[Tuple[SyscallArg, ...]]:
|
||||
return kernel_argmap.get(name)
|
||||
|
||||
proto_args = get_userspace(routine)
|
||||
|
||||
if proto_args is None and routine.endswith("_trap"):
|
||||
proto_args = get_userspace(routine[: -len("_trap")])
|
||||
|
||||
if proto_args is not None:
|
||||
return list(proto_args)
|
||||
|
||||
proto_args = get_kernel(routine)
|
||||
if proto_args is None and routine.endswith("_trap"):
|
||||
proto_args = get_kernel(routine[: -len("_trap")])
|
||||
|
||||
if proto_args is None:
|
||||
raise RuntimeError(
|
||||
f"{table_path}: missing userspace prototype for {routine!r}, and no kernel extern(struct *_args *args) mapping found"
|
||||
)
|
||||
|
||||
return list(proto_args)
|
||||
|
||||
|
||||
def normalize_mach_name(routine: str) -> str:
|
||||
if routine.startswith("_"):
|
||||
routine = routine[1:]
|
||||
if routine.startswith("kernelrpc_"):
|
||||
routine = routine[len("kernelrpc_"):]
|
||||
if routine.endswith("_trap"):
|
||||
routine = routine[: -len("_trap")]
|
||||
return routine
|
||||
|
||||
|
||||
def load_bsd_syscalls_master(
|
||||
kernel_tree: Path,
|
||||
) -> Tuple[Dict[int, str], Dict[str, SyscallSignature]]:
|
||||
path = kernel_tree / "bsd" / "kern" / "syscalls.master"
|
||||
if not path.exists():
|
||||
raise RuntimeError(f"Missing BSD master file: {path}")
|
||||
|
||||
numbers: Dict[int, str] = {}
|
||||
sigs: Dict[str, SyscallSignature] = {}
|
||||
|
||||
lines = path.read_text(encoding="utf-8", errors="ignore").splitlines()
|
||||
|
||||
stack: List[bool] = []
|
||||
active = True
|
||||
|
||||
for line_no, raw in enumerate(lines, start=1):
|
||||
line = raw.rstrip("\n")
|
||||
stripped = line.lstrip()
|
||||
|
||||
if (
|
||||
stripped.startswith("#if ")
|
||||
or stripped.startswith("#ifdef ")
|
||||
or stripped.startswith("#ifndef ")
|
||||
):
|
||||
stack.append(active)
|
||||
continue
|
||||
|
||||
if stripped.startswith("#else"):
|
||||
if not stack:
|
||||
raise RuntimeError(f"{path}:{line_no}: #else without #if")
|
||||
active = False
|
||||
continue
|
||||
|
||||
if stripped.startswith("#endif"):
|
||||
if not stack:
|
||||
raise RuntimeError(f"{path}:{line_no}: #endif without #if")
|
||||
active = stack.pop()
|
||||
continue
|
||||
|
||||
if not active:
|
||||
continue
|
||||
|
||||
m = BSD_MASTER_ENTRY_RE.match(line)
|
||||
if m is None:
|
||||
continue
|
||||
|
||||
nr = int(m.group("nr"), 10)
|
||||
proto_blob = strip_c_comments(m.group("proto")).strip()
|
||||
|
||||
mp = BSD_MASTER_PROTO_RE.match(proto_blob)
|
||||
if mp is None:
|
||||
raise RuntimeError(
|
||||
f"{path}:{line_no}: cannot parse prototype: {proto_blob!r}"
|
||||
)
|
||||
|
||||
fn = mp.group("fn").strip()
|
||||
args_blob = mp.group("args").strip()
|
||||
|
||||
if fn in {"nosys", "enosys"}:
|
||||
continue
|
||||
|
||||
public_name = normalize_bsd_name(fn)
|
||||
if public_name == "":
|
||||
raise RuntimeError(f"{path}:{line_no}: empty normalized name from {fn!r}")
|
||||
|
||||
if nr in numbers:
|
||||
raise RuntimeError(f"{path}:{line_no}: duplicate syscall number {nr}")
|
||||
if public_name in sigs:
|
||||
raise RuntimeError(
|
||||
f"{path}:{line_no}: duplicate syscall name {public_name!r}"
|
||||
)
|
||||
|
||||
args = parse_c_param_list(args_blob, path, line_no)
|
||||
|
||||
if len(args) > MAX_ARGS:
|
||||
raise RuntimeError(
|
||||
f"{path}:{line_no}: syscall {public_name!r} has {len(args)} args; max supported is {MAX_ARGS}"
|
||||
)
|
||||
|
||||
numbers[nr] = public_name
|
||||
sigs[public_name] = SyscallSignature(name=public_name, args=tuple(args))
|
||||
|
||||
return numbers, sigs
|
||||
|
||||
|
||||
def normalize_bsd_name(fn: str) -> str:
|
||||
if fn.startswith("sys_"):
|
||||
return fn[len("sys_"):]
|
||||
if fn.startswith("__"):
|
||||
return fn[2:]
|
||||
return fn
|
||||
|
||||
|
||||
def strip_c_comments(s: str) -> str:
|
||||
s = LINE_COMMENT_RE.sub("", s)
|
||||
while True:
|
||||
new_s = BLOCK_COMMENT_RE.sub("", s)
|
||||
if new_s == s:
|
||||
break
|
||||
s = new_s
|
||||
return s
|
||||
|
||||
|
||||
def split_top_level_commas(text: str) -> List[str]:
|
||||
parts: List[str] = []
|
||||
buf: List[str] = []
|
||||
depth = 0
|
||||
in_string = False
|
||||
string_quote = ""
|
||||
|
||||
cursor = 0
|
||||
while cursor < len(text):
|
||||
ch = text[cursor]
|
||||
|
||||
if in_string:
|
||||
buf.append(ch)
|
||||
if ch == "\\" and cursor + 1 < len(text):
|
||||
buf.append(text[cursor + 1])
|
||||
cursor += 2
|
||||
continue
|
||||
if ch == string_quote:
|
||||
in_string = False
|
||||
cursor += 1
|
||||
continue
|
||||
|
||||
if ch in ("'", '"'):
|
||||
in_string = True
|
||||
string_quote = ch
|
||||
buf.append(ch)
|
||||
cursor += 1
|
||||
continue
|
||||
|
||||
if ch == "(":
|
||||
depth += 1
|
||||
elif ch == ")":
|
||||
depth = max(0, depth - 1)
|
||||
|
||||
if ch == "," and depth == 0:
|
||||
parts.append("".join(buf).strip())
|
||||
buf = []
|
||||
cursor += 1
|
||||
continue
|
||||
|
||||
buf.append(ch)
|
||||
cursor += 1
|
||||
|
||||
parts.append("".join(buf).strip())
|
||||
return parts
|
||||
|
||||
|
||||
def parse_c_param_list(args_blob: str, path: Path, line_no: int) -> List[SyscallArg]:
|
||||
raw = strip_c_comments(args_blob).strip()
|
||||
if raw == "" or raw == "void":
|
||||
return []
|
||||
|
||||
raw_params = [p.strip() for p in split_top_level_commas(raw) if p.strip() != ""]
|
||||
if len(raw_params) == 1 and raw_params[0] == "void":
|
||||
return []
|
||||
|
||||
args: List[SyscallArg] = []
|
||||
for idx, p in enumerate(raw_params):
|
||||
ty, name = split_param_decl(p, path, line_no)
|
||||
if name is None:
|
||||
name = f"arg{idx}"
|
||||
if ty == "user_addr_t" and name in {"attrname", "link", "path"}:
|
||||
ty = "char *"
|
||||
args.append(SyscallArg(type=ty, name=name))
|
||||
return args
|
||||
|
||||
|
||||
def split_param_decl(decl: str, path: Path, line_no: int) -> Tuple[str, Optional[str]]:
|
||||
d = strip_c_comments(decl).strip()
|
||||
|
||||
if d == "" or d == "void":
|
||||
raise RuntimeError(f"{path}:{line_no}: bad parameter decl: {decl!r}")
|
||||
|
||||
tokens = _tokenize_decl(d)
|
||||
ty_tokens, name = _split_type_and_name(tokens)
|
||||
|
||||
ty = _format_type(ty_tokens)
|
||||
if not ty:
|
||||
raise RuntimeError(
|
||||
f"{path}:{line_no}: cannot parse parameter type from {decl!r}"
|
||||
)
|
||||
|
||||
return ty, _camel_to_snake(name) if name else None
|
||||
|
||||
|
||||
def _tokenize_decl(s: str) -> list[str]:
|
||||
out = []
|
||||
for c in s:
|
||||
out.append(" * " if c == "*" else c)
|
||||
return "".join(out).split()
|
||||
|
||||
|
||||
def _split_type_and_name(tokens: list[str]) -> Tuple[list[str], Optional[str]]:
|
||||
if not tokens:
|
||||
return [], None
|
||||
|
||||
last = tokens[-1]
|
||||
|
||||
if last == "*":
|
||||
return tokens, None
|
||||
|
||||
stars, remainder = _split_leading_stars(last)
|
||||
if stars:
|
||||
if _is_identifier(remainder):
|
||||
return tokens[:-1] + ["*"] * stars, remainder
|
||||
return tokens, None
|
||||
|
||||
if _is_identifier(last):
|
||||
return tokens[:-1], last
|
||||
|
||||
return tokens, None
|
||||
|
||||
|
||||
def _format_type(tokens: list[str]) -> str:
|
||||
formatted: list[str] = []
|
||||
i = 0
|
||||
while i < len(tokens):
|
||||
if tokens[i] != "*":
|
||||
formatted.append(tokens[i])
|
||||
i += 1
|
||||
continue
|
||||
|
||||
j = i
|
||||
while j < len(tokens) and tokens[j] == "*":
|
||||
j += 1
|
||||
formatted.append("*" * (j - i))
|
||||
i = j
|
||||
|
||||
return " ".join(formatted).strip()
|
||||
|
||||
|
||||
def _split_leading_stars(token: str) -> Tuple[int, str]:
|
||||
i = 0
|
||||
while i < len(token) and token[i] == "*":
|
||||
i += 1
|
||||
return i, token[i:]
|
||||
|
||||
|
||||
def _is_identifier(s: str) -> bool:
|
||||
if not s:
|
||||
return False
|
||||
if not (s[0].isalpha() or s[0] == "_"):
|
||||
return False
|
||||
return all(c.isalnum() or c == "_" for c in s)
|
||||
|
||||
|
||||
def _camel_to_snake(name: str) -> str:
|
||||
out = []
|
||||
for i, c in enumerate(name):
|
||||
if (
|
||||
c.isupper()
|
||||
and i > 0
|
||||
and (name[i - 1].islower() or (i + 1 < len(name) and name[i + 1].islower()))
|
||||
):
|
||||
out.append("_")
|
||||
out.append(c.lower())
|
||||
return "".join(out)
|
||||
|
||||
|
||||
def normalize_whitespace(s: str) -> str:
|
||||
return " ".join(s.split())
|
||||
|
||||
|
||||
def line_number_at_offset(text: str, offset: int) -> int:
|
||||
return text.count("\n", 0, offset) + 1
|
||||
|
||||
|
||||
def extract_parentheses_payload(
|
||||
text: str, open_paren_offset: int, path: Path
|
||||
) -> Tuple[str, int]:
|
||||
if (
|
||||
open_paren_offset < 0
|
||||
or open_paren_offset >= len(text)
|
||||
or text[open_paren_offset] != "("
|
||||
):
|
||||
raise RuntimeError(f"{path}: expected '(' at offset {open_paren_offset}")
|
||||
|
||||
depth = 0
|
||||
cursor = open_paren_offset
|
||||
start = open_paren_offset + 1
|
||||
|
||||
in_string = False
|
||||
string_quote = ""
|
||||
|
||||
while cursor < len(text):
|
||||
ch = text[cursor]
|
||||
|
||||
if in_string:
|
||||
if ch == "\\":
|
||||
cursor += 2
|
||||
continue
|
||||
if ch == string_quote:
|
||||
in_string = False
|
||||
cursor += 1
|
||||
continue
|
||||
|
||||
if ch in ("'", '"'):
|
||||
in_string = True
|
||||
string_quote = ch
|
||||
cursor += 1
|
||||
continue
|
||||
|
||||
if ch == "(":
|
||||
depth += 1
|
||||
elif ch == ")":
|
||||
depth -= 1
|
||||
if depth == 0:
|
||||
return text[start:cursor], cursor + 1
|
||||
|
||||
cursor += 1
|
||||
|
||||
raise RuntimeError(f"{path}: unterminated parentheses payload")
|
||||
|
||||
|
||||
def extract_brace_payload(
|
||||
text: str, open_brace_offset: int, path: Path
|
||||
) -> Tuple[str, int]:
|
||||
if (
|
||||
open_brace_offset < 0
|
||||
or open_brace_offset >= len(text)
|
||||
or text[open_brace_offset] != "{"
|
||||
):
|
||||
raise RuntimeError(f"{path}: expected '{{' at offset {open_brace_offset}")
|
||||
|
||||
depth = 0
|
||||
cursor = open_brace_offset
|
||||
start = open_brace_offset + 1
|
||||
|
||||
in_string = False
|
||||
string_quote = ""
|
||||
|
||||
while cursor < len(text):
|
||||
ch = text[cursor]
|
||||
|
||||
if in_string:
|
||||
if ch == "\\":
|
||||
cursor += 2
|
||||
continue
|
||||
if ch == string_quote:
|
||||
in_string = False
|
||||
cursor += 1
|
||||
continue
|
||||
|
||||
if ch in ("'", '"'):
|
||||
in_string = True
|
||||
string_quote = ch
|
||||
cursor += 1
|
||||
continue
|
||||
|
||||
if ch == "{":
|
||||
depth += 1
|
||||
elif ch == "}":
|
||||
depth -= 1
|
||||
if depth == 0:
|
||||
return text[start:cursor], cursor + 1
|
||||
|
||||
cursor += 1
|
||||
|
||||
raise RuntimeError(f"{path}: unterminated brace payload")
|
||||
|
||||
|
||||
def render_vala(*, mach_numbers: Dict[int, str], bsd_numbers: Dict[int, str]) -> str:
|
||||
out: List[str] = []
|
||||
|
||||
out += [
|
||||
"// AUTO-GENERATED FILE. DO NOT EDIT.\n",
|
||||
"\n",
|
||||
"namespace Frida {\n",
|
||||
"\tpublic extern unowned XnuSyscallSignature[] get_xnu_mach_traps ();\n",
|
||||
"\tpublic extern unowned XnuSyscallSignature[] get_xnu_bsd_syscalls ();\n",
|
||||
"\n",
|
||||
"\tpublic struct XnuSyscallSignature {\n",
|
||||
"\t\tpublic int nr;\n",
|
||||
"\t\tpublic string name;\n",
|
||||
"\t\tpublic uint8 nargs;\n",
|
||||
f"\t\tpublic XnuSyscallArg args[{MAX_ARGS}];\n",
|
||||
"\t}\n",
|
||||
"\n",
|
||||
"\tpublic struct XnuSyscallArg {\n",
|
||||
"\t\tpublic string? type;\n",
|
||||
"\t\tpublic string? name;\n",
|
||||
"\t}\n",
|
||||
"\n",
|
||||
"\tpublic enum XnuMachTrap {\n",
|
||||
]
|
||||
|
||||
for nr, name in sorted(mach_numbers.items(), key=lambda kv: kv[0], reverse=True):
|
||||
out += [f"\t\t{name.upper()} = {nr},\n"]
|
||||
|
||||
out += [
|
||||
"\t}\n",
|
||||
"\n",
|
||||
"\tpublic enum XnuBsdSyscall {\n",
|
||||
]
|
||||
|
||||
for nr, name in sorted(bsd_numbers.items(), key=lambda kv: kv[0]):
|
||||
out += [f"\t\t{name.upper()} = {nr},\n"]
|
||||
|
||||
out += [
|
||||
"\t}\n",
|
||||
"}\n",
|
||||
]
|
||||
|
||||
return "".join(out)
|
||||
|
||||
|
||||
def render_c_source(
|
||||
*,
|
||||
mach_numbers: Dict[int, str],
|
||||
bsd_numbers: Dict[int, str],
|
||||
mach_sigs: Dict[str, SyscallSignature],
|
||||
bsd_sigs: Dict[str, SyscallSignature],
|
||||
) -> str:
|
||||
out: List[str] = []
|
||||
|
||||
out += [
|
||||
"/* AUTO-GENERATED FILE. DO NOT EDIT. */\n",
|
||||
"\n",
|
||||
'#include "frida-base.h"\n',
|
||||
"\n",
|
||||
]
|
||||
|
||||
emit_c_signature_table(
|
||||
out,
|
||||
c_var="frida_xnu_mach_traps",
|
||||
numbers=mach_numbers,
|
||||
sigs=mach_sigs,
|
||||
reverse=True,
|
||||
)
|
||||
|
||||
emit_c_signature_table(
|
||||
out,
|
||||
c_var="frida_xnu_bsd_syscalls",
|
||||
numbers=bsd_numbers,
|
||||
sigs=bsd_sigs,
|
||||
)
|
||||
|
||||
emit_c_table_getter(
|
||||
out, c_func="frida_get_xnu_mach_traps", c_var="frida_xnu_mach_traps"
|
||||
)
|
||||
out += ["\n"]
|
||||
emit_c_table_getter(
|
||||
out, c_func="frida_get_xnu_bsd_syscalls", c_var="frida_xnu_bsd_syscalls"
|
||||
)
|
||||
|
||||
return "".join(out)
|
||||
|
||||
|
||||
def emit_c_signature_table(
|
||||
out: List[str],
|
||||
*,
|
||||
c_var: str,
|
||||
numbers: Dict[int, str],
|
||||
sigs: Dict[str, SyscallSignature],
|
||||
reverse: bool = False,
|
||||
) -> None:
|
||||
out += [
|
||||
f"static const FridaXnuSyscallSignature {c_var}[] =\n",
|
||||
"{\n",
|
||||
]
|
||||
|
||||
for nr, name in sorted(numbers.items(), key=lambda kv: kv[0], reverse=reverse):
|
||||
sig = sigs[name]
|
||||
|
||||
args_parts: List[str] = []
|
||||
for a in sig.args:
|
||||
args_parts += [f"{{ {c_escape(a.type)}, {c_escape(a.name)} }}"]
|
||||
|
||||
args_blob = ", ".join(args_parts)
|
||||
|
||||
if args_blob != "":
|
||||
out += [
|
||||
f" {{ {nr}, {c_escape(name)}, {len(sig.args)}, {{ {args_blob} }} }},\n"
|
||||
]
|
||||
else:
|
||||
out += [f" {{ {nr}, {c_escape(name)}, 0, {{}} }},\n"]
|
||||
|
||||
out += [
|
||||
"};\n",
|
||||
"\n",
|
||||
]
|
||||
|
||||
|
||||
def emit_c_table_getter(out: List[str], *, c_func: str, c_var: str) -> None:
|
||||
out += [
|
||||
"FridaXnuSyscallSignature *\n",
|
||||
f"{c_func} (int * len)\n",
|
||||
"{\n",
|
||||
" if (len != NULL)\n",
|
||||
f" *len = G_N_ELEMENTS ({c_var});\n",
|
||||
f" return (FridaXnuSyscallSignature *) {c_var};\n",
|
||||
"}\n",
|
||||
]
|
||||
|
||||
|
||||
def c_escape(s: str) -> str:
|
||||
return '"' + s.replace("\\", "\\\\").replace('"', '\\"') + '"'
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
raise SystemExit(main())
|
||||
@@ -1,542 +0,0 @@
|
||||
/* AUTO-GENERATED FILE. DO NOT EDIT. */
|
||||
|
||||
#include "frida-base.h"
|
||||
|
||||
static const FridaXnuSyscallSignature frida_xnu_mach_traps[] =
|
||||
{
|
||||
{ -10, "mach_vm_allocate", 4, { { "mach_port_name_t", "target" }, { "mach_vm_offset_t *", "addr" }, { "mach_vm_size_t", "size" }, { "int", "flags" } } },
|
||||
{ -11, "mach_vm_purgable_control", 4, { { "mach_port_name_t", "target" }, { "mach_vm_offset_t", "address" }, { "vm_purgable_t", "control" }, { "int *", "state" } } },
|
||||
{ -12, "mach_vm_deallocate", 3, { { "mach_port_name_t", "target" }, { "mach_vm_address_t", "address" }, { "mach_vm_size_t", "size" } } },
|
||||
{ -13, "task_dyld_process_info_notify_get", 2, { { "mach_port_name_array_t", "names_addr" }, { "natural_t *", "names_count_addr" } } },
|
||||
{ -14, "mach_vm_protect", 5, { { "mach_port_name_t", "target" }, { "mach_vm_address_t", "address" }, { "mach_vm_size_t", "size" }, { "boolean_t", "set_maximum" }, { "vm_prot_t", "new_protection" } } },
|
||||
{ -15, "mach_vm_map", 6, { { "mach_port_name_t", "target" }, { "mach_vm_offset_t *", "address" }, { "mach_vm_size_t", "size" }, { "mach_vm_offset_t", "mask" }, { "int", "flags" }, { "vm_prot_t", "cur_protection" } } },
|
||||
{ -16, "mach_port_allocate", 3, { { "mach_port_name_t", "target" }, { "mach_port_right_t", "right" }, { "mach_port_name_t *", "name" } } },
|
||||
{ -18, "mach_port_deallocate", 2, { { "mach_port_name_t", "target" }, { "mach_port_name_t", "name" } } },
|
||||
{ -19, "mach_port_mod_refs", 4, { { "mach_port_name_t", "target" }, { "mach_port_name_t", "name" }, { "mach_port_right_t", "right" }, { "mach_port_delta_t", "delta" } } },
|
||||
{ -20, "mach_port_move_member", 3, { { "mach_port_name_t", "target" }, { "mach_port_name_t", "member" }, { "mach_port_name_t", "after" } } },
|
||||
{ -21, "mach_port_insert_right", 4, { { "mach_port_name_t", "target" }, { "mach_port_name_t", "name" }, { "mach_port_name_t", "poly" }, { "mach_msg_type_name_t", "poly_poly" } } },
|
||||
{ -22, "mach_port_insert_member", 3, { { "mach_port_name_t", "target" }, { "mach_port_name_t", "name" }, { "mach_port_name_t", "pset" } } },
|
||||
{ -23, "mach_port_extract_member", 3, { { "mach_port_name_t", "target" }, { "mach_port_name_t", "name" }, { "mach_port_name_t", "pset" } } },
|
||||
{ -24, "mach_port_construct", 4, { { "mach_port_name_t", "target" }, { "mach_port_options_t *", "options" }, { "uint64_t", "context" }, { "mach_port_name_t *", "name" } } },
|
||||
{ -25, "mach_port_destruct", 4, { { "mach_port_name_t", "target" }, { "mach_port_name_t", "name" }, { "mach_port_delta_t", "srdelta" }, { "uint64_t", "guard" } } },
|
||||
{ -26, "mach_reply_port", 0, {} },
|
||||
{ -27, "thread_self", 0, {} },
|
||||
{ -28, "task_self", 0, {} },
|
||||
{ -29, "host_self", 0, {} },
|
||||
{ -31, "mach_msg", 7, { { "mach_msg_header_t *", "msg" }, { "mach_msg_option_t", "option" }, { "mach_msg_size_t", "send_size" }, { "mach_msg_size_t", "rcv_size" }, { "mach_port_name_t", "rcv_name" }, { "mach_msg_timeout_t", "timeout" }, { "mach_port_name_t", "notify" } } },
|
||||
{ -32, "mach_msg_overwrite", 9, { { "mach_msg_header_t *", "msg" }, { "mach_msg_option_t", "option" }, { "mach_msg_size_t", "send_size" }, { "mach_msg_size_t", "rcv_size" }, { "mach_port_name_t", "rcv_name" }, { "mach_msg_timeout_t", "timeout" }, { "mach_msg_priority_t", "priority" }, { "mach_msg_header_t *", "rcv_msg" }, { "mach_msg_size_t", "rcv_limit" } } },
|
||||
{ -33, "semaphore_signal", 1, { { "mach_port_name_t", "signal_name" } } },
|
||||
{ -34, "semaphore_signal_all", 1, { { "mach_port_name_t", "signal_name" } } },
|
||||
{ -35, "semaphore_signal_thread", 2, { { "mach_port_name_t", "signal_name" }, { "mach_port_name_t", "thread_name" } } },
|
||||
{ -36, "semaphore_wait", 1, { { "mach_port_name_t", "wait_name" } } },
|
||||
{ -37, "semaphore_wait_signal", 2, { { "mach_port_name_t", "wait_name" }, { "mach_port_name_t", "signal_name" } } },
|
||||
{ -38, "semaphore_timedwait", 3, { { "mach_port_name_t", "wait_name" }, { "unsigned int", "sec" }, { "clock_res_t", "nsec" } } },
|
||||
{ -39, "semaphore_timedwait_signal", 4, { { "mach_port_name_t", "wait_name" }, { "mach_port_name_t", "signal_name" }, { "unsigned int", "sec" }, { "clock_res_t", "nsec" } } },
|
||||
{ -40, "mach_port_get_attributes", 5, { { "mach_port_name_t", "target" }, { "mach_port_name_t", "name" }, { "mach_port_flavor_t", "flavor" }, { "mach_port_info_t", "port_info_out" }, { "mach_msg_type_number_t *", "port_info_out_cnt" } } },
|
||||
{ -41, "mach_port_guard", 4, { { "mach_port_name_t", "target" }, { "mach_port_name_t", "name" }, { "uint64_t", "guard" }, { "boolean_t", "strict" } } },
|
||||
{ -42, "mach_port_unguard", 3, { { "mach_port_name_t", "target" }, { "mach_port_name_t", "name" }, { "uint64_t", "guard" } } },
|
||||
{ -43, "mach_generate_activity_id", 3, { { "mach_port_name_t", "target" }, { "int", "count" }, { "uint64_t *", "activity_id" } } },
|
||||
{ -44, "task_name_for_pid", 3, { { "mach_port_name_t", "target_tport" }, { "int", "pid" }, { "mach_port_name_t *", "tn" } } },
|
||||
{ -45, "task_for_pid", 3, { { "mach_port_name_t", "target_tport" }, { "int", "pid" }, { "mach_port_name_t *", "t" } } },
|
||||
{ -46, "pid_for_task", 2, { { "mach_port_name_t", "t" }, { "int *", "x" } } },
|
||||
{ -47, "mach_msg2", 8, { { "void *", "data" }, { "mach_msg_option64_t", "options" }, { "uint64_t", "msgh_bits_and_send_size" }, { "uint64_t", "msgh_remote_and_local_port" }, { "uint64_t", "msgh_voucher_and_id" }, { "uint64_t", "desc_count_and_rcv_name" }, { "uint64_t", "rcv_size_and_priority" }, { "uint64_t", "timeout" } } },
|
||||
{ -48, "macx_swapon", 4, { { "uint64_t", "filename" }, { "int", "flags" }, { "int", "size" }, { "int", "priority" } } },
|
||||
{ -49, "macx_swapoff", 2, { { "uint64_t", "filename" }, { "int", "flags" } } },
|
||||
{ -50, "thread_get_special_reply_port", 0, {} },
|
||||
{ -51, "macx_triggers", 4, { { "int", "hi_water" }, { "int", "low_water" }, { "int", "flags" }, { "mach_port_t", "alert_port" } } },
|
||||
{ -52, "macx_backing_store_suspend", 1, { { "boolean_t", "suspend" } } },
|
||||
{ -53, "macx_backing_store_recovery", 1, { { "int", "pid" } } },
|
||||
{ -58, "pfz_exit", 0, {} },
|
||||
{ -59, "swtch_pri", 1, { { "int", "pri" } } },
|
||||
{ -60, "swtch", 0, {} },
|
||||
{ -61, "thread_switch", 3, { { "mach_port_name_t", "thread_name" }, { "int", "option" }, { "mach_msg_timeout_t", "option_time" } } },
|
||||
{ -62, "clock_sleep", 5, { { "mach_port_name_t", "clock_name" }, { "sleep_type_t", "sleep_type" }, { "int", "sleep_sec" }, { "int", "sleep_nsec" }, { "mach_timespec_t *", "wakeup_time" } } },
|
||||
{ -63, "mach_vm_reclaim_update_kernel_accounting", 2, { { "mach_port_name_t", "target_tport" }, { "uint64_t *", "bytes_reclaimed" } } },
|
||||
{ -70, "host_create_mach_voucher", 4, { { "mach_port_name_t", "host" }, { "mach_voucher_attr_raw_recipe_array_t", "recipes" }, { "int", "recipes_size" }, { "mach_port_name_t *", "voucher" } } },
|
||||
{ -72, "mach_voucher_extract_attr_recipe", 4, { { "mach_port_name_t", "voucher_name" }, { "mach_voucher_attr_key_t", "key" }, { "mach_voucher_attr_raw_recipe_t", "recipe" }, { "mach_msg_type_number_t *", "recipe_size" } } },
|
||||
{ -76, "mach_port_type", 3, { { "ipc_space_t", "task" }, { "mach_port_name_t", "name" }, { "mach_port_type_t *", "ptype" } } },
|
||||
{ -77, "mach_port_request_notification", 7, { { "ipc_space_t", "task" }, { "mach_port_name_t", "name" }, { "mach_msg_id_t", "msgid" }, { "mach_port_mscount_t", "sync" }, { "mach_port_name_t", "notify" }, { "mach_msg_type_name_t", "notify_poly" }, { "mach_port_name_t *", "previous" } } },
|
||||
{ -88, "exclaves_ctl", 8, { { "mach_port_name_t", "name" }, { "uint32_t", "operation_and_flags" }, { "uint64_t", "identifier" }, { "mach_vm_address_t", "buffer" }, { "mach_vm_size_t", "size" }, { "mach_vm_size_t", "size2" }, { "mach_vm_size_t", "offset" }, { "mach_vm_address_t", "status" } } },
|
||||
{ -89, "mach_timebase_info", 1, { { "user_addr_t", "info" } } },
|
||||
{ -90, "mach_wait_until", 1, { { "uint64_t", "deadline" } } },
|
||||
{ -91, "mk_timer_create", 0, {} },
|
||||
{ -92, "mk_timer_destroy", 1, { { "mach_port_name_t", "name" } } },
|
||||
{ -93, "mk_timer_arm", 2, { { "mach_port_name_t", "name" }, { "uint64_t", "expire_time" } } },
|
||||
{ -94, "mk_timer_cancel", 2, { { "mach_port_name_t", "name" }, { "user_addr_t", "result_time" } } },
|
||||
{ -95, "mk_timer_arm_leeway", 4, { { "mach_port_name_t", "name" }, { "uint64_t", "mk_timer_flags" }, { "uint64_t", "expire_time" }, { "uint64_t", "mk_leeway" } } },
|
||||
{ -96, "debug_control_port_for_pid", 3, { { "mach_port_name_t", "target_tport" }, { "int", "pid" }, { "mach_port_name_t *", "t" } } },
|
||||
{ -100, "iokit_user_client", 8, { { "void *", "userClientRef" }, { "uint32_t", "index" }, { "void *", "p1" }, { "void *", "p2" }, { "void *", "p3" }, { "void *", "p4" }, { "void *", "p5" }, { "void *", "p6" } } },
|
||||
};
|
||||
|
||||
static const FridaXnuSyscallSignature frida_xnu_bsd_syscalls[] =
|
||||
{
|
||||
{ 1, "exit", 1, { { "int", "rval" } } },
|
||||
{ 2, "fork", 0, {} },
|
||||
{ 3, "read", 3, { { "int", "fd" }, { "user_addr_t", "cbuf" }, { "user_size_t", "nbyte" } } },
|
||||
{ 4, "write", 3, { { "int", "fd" }, { "user_addr_t", "cbuf" }, { "user_size_t", "nbyte" } } },
|
||||
{ 5, "open", 3, { { "char *", "path" }, { "int", "flags" }, { "int", "mode" } } },
|
||||
{ 6, "close", 1, { { "int", "fd" } } },
|
||||
{ 7, "wait4", 4, { { "int", "pid" }, { "user_addr_t", "status" }, { "int", "options" }, { "user_addr_t", "rusage" } } },
|
||||
{ 9, "link", 2, { { "char *", "path" }, { "char *", "link" } } },
|
||||
{ 10, "unlink", 1, { { "char *", "path" } } },
|
||||
{ 12, "chdir", 1, { { "char *", "path" } } },
|
||||
{ 13, "fchdir", 1, { { "int", "fd" } } },
|
||||
{ 14, "mknod", 3, { { "char *", "path" }, { "int", "mode" }, { "int", "dev" } } },
|
||||
{ 15, "chmod", 2, { { "char *", "path" }, { "int", "mode" } } },
|
||||
{ 16, "chown", 3, { { "char *", "path" }, { "int", "uid" }, { "int", "gid" } } },
|
||||
{ 18, "getfsstat", 3, { { "user_addr_t", "buf" }, { "int", "bufsize" }, { "int", "flags" } } },
|
||||
{ 20, "getpid", 0, {} },
|
||||
{ 23, "setuid", 1, { { "uid_t", "uid" } } },
|
||||
{ 24, "getuid", 0, {} },
|
||||
{ 25, "geteuid", 0, {} },
|
||||
{ 26, "ptrace", 4, { { "int", "req" }, { "pid_t", "pid" }, { "caddr_t", "addr" }, { "int", "data" } } },
|
||||
{ 27, "recvmsg", 3, { { "int", "s" }, { "struct msghdr *", "msg" }, { "int", "flags" } } },
|
||||
{ 28, "sendmsg", 3, { { "int", "s" }, { "caddr_t", "msg" }, { "int", "flags" } } },
|
||||
{ 29, "recvfrom", 6, { { "int", "s" }, { "void *", "buf" }, { "size_t", "len" }, { "int", "flags" }, { "struct sockaddr *", "from" }, { "int *", "fromlenaddr" } } },
|
||||
{ 30, "accept", 3, { { "int", "s" }, { "caddr_t", "name" }, { "socklen_t *", "anamelen" } } },
|
||||
{ 31, "getpeername", 3, { { "int", "fdes" }, { "caddr_t", "asa" }, { "socklen_t *", "alen" } } },
|
||||
{ 32, "getsockname", 3, { { "int", "fdes" }, { "caddr_t", "asa" }, { "socklen_t *", "alen" } } },
|
||||
{ 33, "access", 2, { { "char *", "path" }, { "int", "flags" } } },
|
||||
{ 34, "chflags", 2, { { "char *", "path" }, { "int", "flags" } } },
|
||||
{ 35, "fchflags", 2, { { "int", "fd" }, { "int", "flags" } } },
|
||||
{ 36, "sync", 0, {} },
|
||||
{ 37, "kill", 3, { { "int", "pid" }, { "int", "signum" }, { "int", "posix" } } },
|
||||
{ 38, "crossarch_trap", 1, { { "uint32_t", "name" } } },
|
||||
{ 39, "getppid", 0, {} },
|
||||
{ 41, "dup", 1, { { "u_int", "fd" } } },
|
||||
{ 42, "pipe", 0, {} },
|
||||
{ 43, "getegid", 0, {} },
|
||||
{ 46, "sigaction", 3, { { "int", "signum" }, { "struct __sigaction *", "nsa" }, { "struct sigaction *", "osa" } } },
|
||||
{ 47, "getgid", 0, {} },
|
||||
{ 48, "sigprocmask", 3, { { "int", "how" }, { "user_addr_t", "mask" }, { "user_addr_t", "omask" } } },
|
||||
{ 49, "getlogin", 2, { { "char *", "namebuf" }, { "u_int", "namelen" } } },
|
||||
{ 50, "setlogin", 1, { { "char *", "namebuf" } } },
|
||||
{ 51, "acct", 1, { { "char *", "path" } } },
|
||||
{ 52, "sigpending", 1, { { "struct sigvec *", "osv" } } },
|
||||
{ 53, "sigaltstack", 2, { { "struct sigaltstack *", "nss" }, { "struct sigaltstack *", "oss" } } },
|
||||
{ 54, "ioctl", 3, { { "int", "fd" }, { "u_long", "com" }, { "caddr_t", "data" } } },
|
||||
{ 55, "reboot", 2, { { "int", "opt" }, { "char *", "msg" } } },
|
||||
{ 56, "revoke", 1, { { "char *", "path" } } },
|
||||
{ 57, "symlink", 2, { { "char *", "path" }, { "char *", "link" } } },
|
||||
{ 58, "readlink", 3, { { "char *", "path" }, { "char *", "buf" }, { "int", "count" } } },
|
||||
{ 59, "execve", 3, { { "char *", "fname" }, { "char **", "argp" }, { "char **", "envp" } } },
|
||||
{ 60, "umask", 1, { { "int", "newmask" } } },
|
||||
{ 61, "chroot", 1, { { "char *", "path" } } },
|
||||
{ 65, "msync", 3, { { "caddr_ut", "addr" }, { "size_ut", "len" }, { "int", "flags" } } },
|
||||
{ 66, "vfork", 0, {} },
|
||||
{ 67, "oslog_coproc_reg", 3, { { "const char *", "uuid" }, { "const char *", "file_path" }, { "size_t", "file_path_len" } } },
|
||||
{ 68, "oslog_coproc", 7, { { "void *", "buff" }, { "uint64_t", "buff_len" }, { "uint32_t", "type" }, { "const char *", "uuid" }, { "uint64_t", "timestamp" }, { "uint32_t", "offset" }, { "uint32_t", "stream_log" } } },
|
||||
{ 73, "munmap", 2, { { "caddr_ut", "addr" }, { "size_ut", "len" } } },
|
||||
{ 74, "mprotect", 3, { { "caddr_ut", "addr" }, { "size_ut", "len" }, { "int", "prot" } } },
|
||||
{ 75, "madvise", 3, { { "caddr_ut", "addr" }, { "size_ut", "len" }, { "int", "behav" } } },
|
||||
{ 78, "mincore", 3, { { "caddr_ut", "addr" }, { "size_ut", "len" }, { "user_addr_t", "vec" } } },
|
||||
{ 79, "getgroups", 2, { { "u_int", "gidsetsize" }, { "gid_t *", "gidset" } } },
|
||||
{ 80, "setgroups", 2, { { "u_int", "gidsetsize" }, { "gid_t *", "gidset" } } },
|
||||
{ 81, "getpgrp", 0, {} },
|
||||
{ 82, "setpgid", 2, { { "int", "pid" }, { "int", "pgid" } } },
|
||||
{ 83, "setitimer", 3, { { "u_int", "which" }, { "struct itimerval *", "itv" }, { "struct itimerval *", "oitv" } } },
|
||||
{ 85, "swapon", 0, {} },
|
||||
{ 86, "getitimer", 2, { { "u_int", "which" }, { "struct itimerval *", "itv" } } },
|
||||
{ 89, "getdtablesize", 0, {} },
|
||||
{ 90, "dup2", 2, { { "u_int", "from" }, { "u_int", "to" } } },
|
||||
{ 92, "fcntl", 3, { { "int", "fd" }, { "int", "cmd" }, { "long", "arg" } } },
|
||||
{ 93, "select", 5, { { "int", "nd" }, { "u_int32_t *", "in" }, { "u_int32_t *", "ou" }, { "u_int32_t *", "ex" }, { "struct timeval *", "tv" } } },
|
||||
{ 95, "fsync", 1, { { "int", "fd" } } },
|
||||
{ 96, "setpriority", 3, { { "int", "which" }, { "id_t", "who" }, { "int", "prio" } } },
|
||||
{ 97, "socket", 3, { { "int", "domain" }, { "int", "type" }, { "int", "protocol" } } },
|
||||
{ 98, "connect", 3, { { "int", "s" }, { "caddr_t", "name" }, { "socklen_t", "namelen" } } },
|
||||
{ 100, "getpriority", 2, { { "int", "which" }, { "id_t", "who" } } },
|
||||
{ 104, "bind", 3, { { "int", "s" }, { "caddr_t", "name" }, { "socklen_t", "namelen" } } },
|
||||
{ 105, "setsockopt", 5, { { "int", "s" }, { "int", "level" }, { "int", "name" }, { "caddr_t", "val" }, { "socklen_t", "valsize" } } },
|
||||
{ 106, "listen", 2, { { "int", "s" }, { "int", "backlog" } } },
|
||||
{ 111, "sigsuspend", 1, { { "sigset_t", "mask" } } },
|
||||
{ 116, "gettimeofday", 3, { { "struct timeval *", "tp" }, { "struct timezone *", "tzp" }, { "uint64_t *", "mach_absolute_time" } } },
|
||||
{ 117, "getrusage", 2, { { "int", "who" }, { "struct rusage *", "rusage" } } },
|
||||
{ 118, "getsockopt", 5, { { "int", "s" }, { "int", "level" }, { "int", "name" }, { "caddr_t", "val" }, { "socklen_t *", "avalsize" } } },
|
||||
{ 120, "readv", 3, { { "int", "fd" }, { "struct iovec *", "iovp" }, { "u_int", "iovcnt" } } },
|
||||
{ 121, "writev", 3, { { "int", "fd" }, { "struct iovec *", "iovp" }, { "u_int", "iovcnt" } } },
|
||||
{ 122, "settimeofday", 2, { { "struct timeval *", "tv" }, { "struct timezone *", "tzp" } } },
|
||||
{ 123, "fchown", 3, { { "int", "fd" }, { "int", "uid" }, { "int", "gid" } } },
|
||||
{ 124, "fchmod", 2, { { "int", "fd" }, { "int", "mode" } } },
|
||||
{ 126, "setreuid", 2, { { "uid_t", "ruid" }, { "uid_t", "euid" } } },
|
||||
{ 127, "setregid", 2, { { "gid_t", "rgid" }, { "gid_t", "egid" } } },
|
||||
{ 128, "rename", 2, { { "char *", "from" }, { "char *", "to" } } },
|
||||
{ 131, "flock", 2, { { "int", "fd" }, { "int", "how" } } },
|
||||
{ 132, "mkfifo", 2, { { "char *", "path" }, { "int", "mode" } } },
|
||||
{ 133, "sendto", 6, { { "int", "s" }, { "caddr_t", "buf" }, { "size_t", "len" }, { "int", "flags" }, { "caddr_t", "to" }, { "socklen_t", "tolen" } } },
|
||||
{ 134, "shutdown", 2, { { "int", "s" }, { "int", "how" } } },
|
||||
{ 135, "socketpair", 4, { { "int", "domain" }, { "int", "type" }, { "int", "protocol" }, { "int *", "rsv" } } },
|
||||
{ 136, "mkdir", 2, { { "char *", "path" }, { "int", "mode" } } },
|
||||
{ 137, "rmdir", 1, { { "char *", "path" } } },
|
||||
{ 138, "utimes", 2, { { "char *", "path" }, { "struct timeval *", "tptr" } } },
|
||||
{ 139, "futimes", 2, { { "int", "fd" }, { "struct timeval *", "tptr" } } },
|
||||
{ 140, "adjtime", 2, { { "struct timeval *", "delta" }, { "struct timeval *", "olddelta" } } },
|
||||
{ 142, "gethostuuid", 2, { { "unsigned char *", "uuid_buf" }, { "const struct timespec *", "timeoutp" } } },
|
||||
{ 147, "setsid", 0, {} },
|
||||
{ 151, "getpgid", 1, { { "pid_t", "pid" } } },
|
||||
{ 152, "setprivexec", 1, { { "int", "flag" } } },
|
||||
{ 153, "pread", 4, { { "int", "fd" }, { "user_addr_t", "buf" }, { "user_size_t", "nbyte" }, { "off_t", "offset" } } },
|
||||
{ 154, "pwrite", 4, { { "int", "fd" }, { "user_addr_t", "buf" }, { "user_size_t", "nbyte" }, { "off_t", "offset" } } },
|
||||
{ 155, "nfssvc", 2, { { "int", "flag" }, { "caddr_t", "argp" } } },
|
||||
{ 157, "statfs", 2, { { "char *", "path" }, { "struct statfs *", "buf" } } },
|
||||
{ 158, "fstatfs", 2, { { "int", "fd" }, { "struct statfs *", "buf" } } },
|
||||
{ 159, "unmount", 2, { { "char *", "path" }, { "int", "flags" } } },
|
||||
{ 161, "getfh", 2, { { "char *", "fname" }, { "fhandle_t *", "fhp" } } },
|
||||
{ 164, "funmount", 2, { { "int", "fd" }, { "int", "flags" } } },
|
||||
{ 165, "quotactl", 4, { { "const char *", "path" }, { "int", "cmd" }, { "int", "uid" }, { "caddr_t", "arg" } } },
|
||||
{ 167, "mount", 4, { { "char *", "type" }, { "char *", "path" }, { "int", "flags" }, { "caddr_t", "data" } } },
|
||||
{ 169, "csops", 4, { { "pid_t", "pid" }, { "uint32_t", "ops" }, { "user_addr_t", "useraddr" }, { "user_size_t", "usersize" } } },
|
||||
{ 170, "csops_audittoken", 5, { { "pid_t", "pid" }, { "uint32_t", "ops" }, { "user_addr_t", "useraddr" }, { "user_size_t", "usersize" }, { "user_addr_t", "uaudittoken" } } },
|
||||
{ 173, "waitid", 4, { { "idtype_t", "idtype" }, { "id_t", "id" }, { "siginfo_t *", "infop" }, { "int", "options" } } },
|
||||
{ 177, "kdebug_typefilter", 2, { { "void **", "addr" }, { "size_t *", "size" } } },
|
||||
{ 178, "kdebug_trace_string", 3, { { "uint32_t", "debugid" }, { "uint64_t", "str_id" }, { "const char *", "str" } } },
|
||||
{ 179, "kdebug_trace64", 5, { { "uint32_t", "code" }, { "uint64_t", "arg1" }, { "uint64_t", "arg2" }, { "uint64_t", "arg3" }, { "uint64_t", "arg4" } } },
|
||||
{ 180, "kdebug_trace", 5, { { "uint32_t", "code" }, { "u_long", "arg1" }, { "u_long", "arg2" }, { "u_long", "arg3" }, { "u_long", "arg4" } } },
|
||||
{ 181, "setgid", 1, { { "gid_t", "gid" } } },
|
||||
{ 182, "setegid", 1, { { "gid_t", "egid" } } },
|
||||
{ 183, "seteuid", 1, { { "uid_t", "euid" } } },
|
||||
{ 184, "sigreturn", 3, { { "struct ucontext *", "uctx" }, { "int", "infostyle" }, { "user_addr_t", "token" } } },
|
||||
{ 185, "panic_with_data", 5, { { "uuid_t", "uuid" }, { "void *", "addr" }, { "uint32_t", "len" }, { "uint32_t", "flags" }, { "const char *", "msg" } } },
|
||||
{ 186, "thread_selfcounts", 3, { { "uint32_t", "kind" }, { "user_addr_t", "buf" }, { "user_size_t", "size" } } },
|
||||
{ 187, "fdatasync", 1, { { "int", "fd" } } },
|
||||
{ 188, "stat", 2, { { "char *", "path" }, { "user_addr_t", "ub" } } },
|
||||
{ 189, "fstat", 2, { { "int", "fd" }, { "user_addr_t", "ub" } } },
|
||||
{ 190, "lstat", 2, { { "char *", "path" }, { "user_addr_t", "ub" } } },
|
||||
{ 191, "pathconf", 2, { { "char *", "path" }, { "int", "name" } } },
|
||||
{ 192, "fpathconf", 2, { { "int", "fd" }, { "int", "name" } } },
|
||||
{ 194, "getrlimit", 2, { { "u_int", "which" }, { "struct rlimit *", "rlp" } } },
|
||||
{ 195, "setrlimit", 2, { { "u_int", "which" }, { "struct rlimit *", "rlp" } } },
|
||||
{ 196, "getdirentries", 4, { { "int", "fd" }, { "char *", "buf" }, { "u_int", "count" }, { "long *", "basep" } } },
|
||||
{ 197, "mmap", 6, { { "caddr_ut", "addr" }, { "size_ut", "len" }, { "int", "prot" }, { "int", "flags" }, { "int", "fd" }, { "off_t", "pos" } } },
|
||||
{ 199, "lseek", 3, { { "int", "fd" }, { "off_t", "offset" }, { "int", "whence" } } },
|
||||
{ 200, "truncate", 2, { { "char *", "path" }, { "off_t", "length" } } },
|
||||
{ 201, "ftruncate", 2, { { "int", "fd" }, { "off_t", "length" } } },
|
||||
{ 202, "sysctl", 6, { { "int *", "name" }, { "u_int", "namelen" }, { "void *", "old" }, { "size_t *", "oldlenp" }, { "void *", "new" }, { "size_t", "newlen" } } },
|
||||
{ 203, "mlock", 2, { { "caddr_ut", "addr" }, { "size_ut", "len" } } },
|
||||
{ 204, "munlock", 2, { { "caddr_ut", "addr" }, { "size_ut", "len" } } },
|
||||
{ 205, "undelete", 1, { { "char *", "path" } } },
|
||||
{ 216, "open_dprotected_np", 5, { { "char *", "path" }, { "int", "flags" }, { "int", "class" }, { "int", "dpflags" }, { "int", "mode" } } },
|
||||
{ 217, "fsgetpath_ext", 5, { { "user_addr_t", "buf" }, { "size_t", "bufsize" }, { "user_addr_t", "fsid" }, { "uint64_t", "objid" }, { "uint32_t", "options" } } },
|
||||
{ 218, "openat_dprotected_np", 7, { { "int", "fd" }, { "char *", "path" }, { "int", "flags" }, { "int", "class" }, { "int", "dpflags" }, { "int", "mode" }, { "int", "authfd" } } },
|
||||
{ 220, "getattrlist", 5, { { "const char *", "path" }, { "struct attrlist *", "alist" }, { "void *", "attribute_buffer" }, { "size_t", "buffer_size" }, { "u_long", "options" } } },
|
||||
{ 221, "setattrlist", 5, { { "const char *", "path" }, { "struct attrlist *", "alist" }, { "void *", "attribute_buffer" }, { "size_t", "buffer_size" }, { "u_long", "options" } } },
|
||||
{ 222, "getdirentriesattr", 8, { { "int", "fd" }, { "struct attrlist *", "alist" }, { "void *", "buffer" }, { "size_t", "buffersize" }, { "u_long *", "count" }, { "u_long *", "basep" }, { "u_long *", "newstate" }, { "u_long", "options" } } },
|
||||
{ 223, "exchangedata", 3, { { "const char *", "path1" }, { "const char *", "path2" }, { "u_long", "options" } } },
|
||||
{ 225, "searchfs", 6, { { "const char *", "path" }, { "struct fssearchblock *", "searchblock" }, { "uint32_t *", "nummatches" }, { "uint32_t", "scriptcode" }, { "uint32_t", "options" }, { "struct searchstate *", "state" } } },
|
||||
{ 226, "delete", 1, { { "char *", "path" } } },
|
||||
{ 227, "copyfile", 4, { { "char *", "from" }, { "char *", "to" }, { "int", "mode" }, { "int", "flags" } } },
|
||||
{ 228, "fgetattrlist", 5, { { "int", "fd" }, { "struct attrlist *", "alist" }, { "void *", "attribute_buffer" }, { "size_t", "buffer_size" }, { "u_long", "options" } } },
|
||||
{ 229, "fsetattrlist", 5, { { "int", "fd" }, { "struct attrlist *", "alist" }, { "void *", "attribute_buffer" }, { "size_t", "buffer_size" }, { "u_long", "options" } } },
|
||||
{ 230, "poll", 3, { { "struct pollfd *", "fds" }, { "u_int", "nfds" }, { "int", "timeout" } } },
|
||||
{ 234, "getxattr", 6, { { "char *", "path" }, { "char *", "attrname" }, { "user_addr_t", "value" }, { "size_t", "size" }, { "uint32_t", "position" }, { "int", "options" } } },
|
||||
{ 235, "fgetxattr", 6, { { "int", "fd" }, { "char *", "attrname" }, { "user_addr_t", "value" }, { "size_t", "size" }, { "uint32_t", "position" }, { "int", "options" } } },
|
||||
{ 236, "setxattr", 6, { { "char *", "path" }, { "char *", "attrname" }, { "user_addr_t", "value" }, { "size_t", "size" }, { "uint32_t", "position" }, { "int", "options" } } },
|
||||
{ 237, "fsetxattr", 6, { { "int", "fd" }, { "char *", "attrname" }, { "user_addr_t", "value" }, { "size_t", "size" }, { "uint32_t", "position" }, { "int", "options" } } },
|
||||
{ 238, "removexattr", 3, { { "char *", "path" }, { "char *", "attrname" }, { "int", "options" } } },
|
||||
{ 239, "fremovexattr", 3, { { "int", "fd" }, { "char *", "attrname" }, { "int", "options" } } },
|
||||
{ 240, "listxattr", 4, { { "char *", "path" }, { "user_addr_t", "namebuf" }, { "size_t", "bufsize" }, { "int", "options" } } },
|
||||
{ 241, "flistxattr", 4, { { "int", "fd" }, { "user_addr_t", "namebuf" }, { "size_t", "bufsize" }, { "int", "options" } } },
|
||||
{ 242, "fsctl", 4, { { "const char *", "path" }, { "u_long", "cmd" }, { "caddr_t", "data" }, { "u_int", "options" } } },
|
||||
{ 243, "initgroups", 3, { { "u_int", "gidsetsize" }, { "gid_t *", "gidset" }, { "int", "gmuid" } } },
|
||||
{ 244, "posix_spawn", 5, { { "pid_t *", "pid" }, { "const char *", "path" }, { "const struct _posix_spawn_args_desc *", "adesc" }, { "char **", "argv" }, { "char **", "envp" } } },
|
||||
{ 245, "ffsctl", 4, { { "int", "fd" }, { "u_long", "cmd" }, { "caddr_t", "data" }, { "u_int", "options" } } },
|
||||
{ 248, "fhopen", 2, { { "const struct fhandle *", "u_fhp" }, { "int", "flags" } } },
|
||||
{ 250, "minherit", 3, { { "caddr_ut", "addr" }, { "size_ut", "len" }, { "int", "inherit" } } },
|
||||
{ 251, "semsys", 5, { { "u_int", "which" }, { "int", "a2" }, { "int", "a3" }, { "int", "a4" }, { "int", "a5" } } },
|
||||
{ 252, "msgsys", 5, { { "u_int", "which" }, { "int", "a2" }, { "int", "a3" }, { "int", "a4" }, { "int", "a5" } } },
|
||||
{ 253, "shmsys", 4, { { "u_int", "which" }, { "int", "a2" }, { "int", "a3" }, { "int", "a4" } } },
|
||||
{ 254, "semctl", 4, { { "int", "semid" }, { "int", "semnum" }, { "int", "cmd" }, { "semun_t", "arg" } } },
|
||||
{ 255, "semget", 3, { { "key_t", "key" }, { "int", "nsems" }, { "int", "semflg" } } },
|
||||
{ 256, "semop", 3, { { "int", "semid" }, { "struct sembuf *", "sops" }, { "int", "nsops" } } },
|
||||
{ 258, "msgctl", 3, { { "int", "msqid" }, { "int", "cmd" }, { "struct msqid_ds *", "buf" } } },
|
||||
{ 259, "msgget", 2, { { "key_t", "key" }, { "int", "msgflg" } } },
|
||||
{ 260, "msgsnd", 4, { { "int", "msqid" }, { "void *", "msgp" }, { "size_t", "msgsz" }, { "int", "msgflg" } } },
|
||||
{ 261, "msgrcv", 5, { { "int", "msqid" }, { "void *", "msgp" }, { "size_t", "msgsz" }, { "long", "msgtyp" }, { "int", "msgflg" } } },
|
||||
{ 262, "shmat", 3, { { "int", "shmid" }, { "void *", "shmaddr" }, { "int", "shmflg" } } },
|
||||
{ 263, "shmctl", 3, { { "int", "shmid" }, { "int", "cmd" }, { "struct shmid_ds *", "buf" } } },
|
||||
{ 264, "shmdt", 1, { { "void *", "shmaddr" } } },
|
||||
{ 265, "shmget", 3, { { "key_t", "key" }, { "size_t", "size" }, { "int", "shmflg" } } },
|
||||
{ 266, "shm_open", 3, { { "const char *", "name" }, { "int", "oflag" }, { "int", "mode" } } },
|
||||
{ 267, "shm_unlink", 1, { { "const char *", "name" } } },
|
||||
{ 268, "sem_open", 4, { { "const char *", "name" }, { "int", "oflag" }, { "int", "mode" }, { "int", "value" } } },
|
||||
{ 269, "sem_close", 1, { { "sem_t *", "sem" } } },
|
||||
{ 270, "sem_unlink", 1, { { "const char *", "name" } } },
|
||||
{ 271, "sem_wait", 1, { { "sem_t *", "sem" } } },
|
||||
{ 272, "sem_trywait", 1, { { "sem_t *", "sem" } } },
|
||||
{ 273, "sem_post", 1, { { "sem_t *", "sem" } } },
|
||||
{ 274, "sysctlbyname", 6, { { "const char *", "name" }, { "size_t", "namelen" }, { "void *", "old" }, { "size_t *", "oldlenp" }, { "void *", "new" }, { "size_t", "newlen" } } },
|
||||
{ 277, "open_extended", 6, { { "char *", "path" }, { "int", "flags" }, { "uid_t", "uid" }, { "gid_t", "gid" }, { "int", "mode" }, { "user_addr_t", "xsecurity" } } },
|
||||
{ 278, "umask_extended", 2, { { "int", "newmask" }, { "user_addr_t", "xsecurity" } } },
|
||||
{ 279, "stat_extended", 4, { { "char *", "path" }, { "user_addr_t", "ub" }, { "user_addr_t", "xsecurity" }, { "user_addr_t", "xsecurity_size" } } },
|
||||
{ 280, "lstat_extended", 4, { { "char *", "path" }, { "user_addr_t", "ub" }, { "user_addr_t", "xsecurity" }, { "user_addr_t", "xsecurity_size" } } },
|
||||
{ 281, "fstat_extended", 4, { { "int", "fd" }, { "user_addr_t", "ub" }, { "user_addr_t", "xsecurity" }, { "user_addr_t", "xsecurity_size" } } },
|
||||
{ 282, "chmod_extended", 5, { { "char *", "path" }, { "uid_t", "uid" }, { "gid_t", "gid" }, { "int", "mode" }, { "user_addr_t", "xsecurity" } } },
|
||||
{ 283, "fchmod_extended", 5, { { "int", "fd" }, { "uid_t", "uid" }, { "gid_t", "gid" }, { "int", "mode" }, { "user_addr_t", "xsecurity" } } },
|
||||
{ 284, "access_extended", 4, { { "user_addr_t", "entries" }, { "size_t", "size" }, { "user_addr_t", "results" }, { "uid_t", "uid" } } },
|
||||
{ 285, "settid", 2, { { "uid_t", "uid" }, { "gid_t", "gid" } } },
|
||||
{ 286, "gettid", 2, { { "uid_t *", "uidp" }, { "gid_t *", "gidp" } } },
|
||||
{ 287, "setsgroups", 2, { { "int", "setlen" }, { "user_addr_t", "guidset" } } },
|
||||
{ 288, "getsgroups", 2, { { "user_addr_t", "setlen" }, { "user_addr_t", "guidset" } } },
|
||||
{ 289, "setwgroups", 2, { { "int", "setlen" }, { "user_addr_t", "guidset" } } },
|
||||
{ 290, "getwgroups", 2, { { "user_addr_t", "setlen" }, { "user_addr_t", "guidset" } } },
|
||||
{ 291, "mkfifo_extended", 5, { { "char *", "path" }, { "uid_t", "uid" }, { "gid_t", "gid" }, { "int", "mode" }, { "user_addr_t", "xsecurity" } } },
|
||||
{ 292, "mkdir_extended", 5, { { "char *", "path" }, { "uid_t", "uid" }, { "gid_t", "gid" }, { "int", "mode" }, { "user_addr_t", "xsecurity" } } },
|
||||
{ 293, "identitysvc", 2, { { "int", "opcode" }, { "user_addr_t", "message" } } },
|
||||
{ 294, "shared_region_check_np", 1, { { "uint64_t *", "start_address" } } },
|
||||
{ 296, "vm_pressure_monitor", 3, { { "int", "wait_for_pressure" }, { "int", "nsecs_monitored" }, { "uint32_t *", "pages_reclaimed" } } },
|
||||
{ 297, "psynch_rw_longrdlock", 5, { { "user_addr_t", "rwlock" }, { "uint32_t", "lgenval" }, { "uint32_t", "ugenval" }, { "uint32_t", "rw_wc" }, { "int", "flags" } } },
|
||||
{ 298, "psynch_rw_yieldwrlock", 5, { { "user_addr_t", "rwlock" }, { "uint32_t", "lgenval" }, { "uint32_t", "ugenval" }, { "uint32_t", "rw_wc" }, { "int", "flags" } } },
|
||||
{ 299, "psynch_rw_downgrade", 5, { { "user_addr_t", "rwlock" }, { "uint32_t", "lgenval" }, { "uint32_t", "ugenval" }, { "uint32_t", "rw_wc" }, { "int", "flags" } } },
|
||||
{ 300, "psynch_rw_upgrade", 5, { { "user_addr_t", "rwlock" }, { "uint32_t", "lgenval" }, { "uint32_t", "ugenval" }, { "uint32_t", "rw_wc" }, { "int", "flags" } } },
|
||||
{ 301, "psynch_mutexwait", 5, { { "user_addr_t", "mutex" }, { "uint32_t", "mgen" }, { "uint32_t", "ugen" }, { "uint64_t", "tid" }, { "uint32_t", "flags" } } },
|
||||
{ 302, "psynch_mutexdrop", 5, { { "user_addr_t", "mutex" }, { "uint32_t", "mgen" }, { "uint32_t", "ugen" }, { "uint64_t", "tid" }, { "uint32_t", "flags" } } },
|
||||
{ 303, "psynch_cvbroad", 7, { { "user_addr_t", "cv" }, { "uint64_t", "cvlsgen" }, { "uint64_t", "cvudgen" }, { "uint32_t", "flags" }, { "user_addr_t", "mutex" }, { "uint64_t", "mugen" }, { "uint64_t", "tid" } } },
|
||||
{ 304, "psynch_cvsignal", 8, { { "user_addr_t", "cv" }, { "uint64_t", "cvlsgen" }, { "uint32_t", "cvugen" }, { "int", "thread_port" }, { "user_addr_t", "mutex" }, { "uint64_t", "mugen" }, { "uint64_t", "tid" }, { "uint32_t", "flags" } } },
|
||||
{ 305, "psynch_cvwait", 8, { { "user_addr_t", "cv" }, { "uint64_t", "cvlsgen" }, { "uint32_t", "cvugen" }, { "user_addr_t", "mutex" }, { "uint64_t", "mugen" }, { "uint32_t", "flags" }, { "int64_t", "sec" }, { "uint32_t", "nsec" } } },
|
||||
{ 306, "psynch_rw_rdlock", 5, { { "user_addr_t", "rwlock" }, { "uint32_t", "lgenval" }, { "uint32_t", "ugenval" }, { "uint32_t", "rw_wc" }, { "int", "flags" } } },
|
||||
{ 307, "psynch_rw_wrlock", 5, { { "user_addr_t", "rwlock" }, { "uint32_t", "lgenval" }, { "uint32_t", "ugenval" }, { "uint32_t", "rw_wc" }, { "int", "flags" } } },
|
||||
{ 308, "psynch_rw_unlock", 5, { { "user_addr_t", "rwlock" }, { "uint32_t", "lgenval" }, { "uint32_t", "ugenval" }, { "uint32_t", "rw_wc" }, { "int", "flags" } } },
|
||||
{ 309, "psynch_rw_unlock2", 5, { { "user_addr_t", "rwlock" }, { "uint32_t", "lgenval" }, { "uint32_t", "ugenval" }, { "uint32_t", "rw_wc" }, { "int", "flags" } } },
|
||||
{ 310, "getsid", 1, { { "pid_t", "pid" } } },
|
||||
{ 311, "settid_with_pid", 2, { { "pid_t", "pid" }, { "int", "assume" } } },
|
||||
{ 312, "psynch_cvclrprepost", 7, { { "user_addr_t", "cv" }, { "uint32_t", "cvgen" }, { "uint32_t", "cvugen" }, { "uint32_t", "cvsgen" }, { "uint32_t", "prepocnt" }, { "uint32_t", "preposeq" }, { "uint32_t", "flags" } } },
|
||||
{ 313, "aio_fsync", 2, { { "int", "op" }, { "user_addr_t", "aiocbp" } } },
|
||||
{ 314, "aio_return", 1, { { "user_addr_t", "aiocbp" } } },
|
||||
{ 315, "aio_suspend", 3, { { "user_addr_t", "aiocblist" }, { "int", "nent" }, { "user_addr_t", "timeoutp" } } },
|
||||
{ 316, "aio_cancel", 2, { { "int", "fd" }, { "user_addr_t", "aiocbp" } } },
|
||||
{ 317, "aio_error", 1, { { "user_addr_t", "aiocbp" } } },
|
||||
{ 318, "aio_read", 1, { { "user_addr_t", "aiocbp" } } },
|
||||
{ 319, "aio_write", 1, { { "user_addr_t", "aiocbp" } } },
|
||||
{ 320, "lio_listio", 4, { { "int", "mode" }, { "user_addr_t", "aiocblist" }, { "int", "nent" }, { "user_addr_t", "sigp" } } },
|
||||
{ 322, "iopolicysys", 2, { { "int", "cmd" }, { "void *", "arg" } } },
|
||||
{ 323, "process_policy", 7, { { "int", "scope" }, { "int", "action" }, { "int", "policy" }, { "int", "policy_subtype" }, { "user_addr_t", "attrp" }, { "pid_t", "target_pid" }, { "uint64_t", "target_threadid" } } },
|
||||
{ 324, "mlockall", 1, { { "int", "how" } } },
|
||||
{ 325, "munlockall", 1, { { "int", "how" } } },
|
||||
{ 327, "issetugid", 0, {} },
|
||||
{ 328, "pthread_kill", 2, { { "int", "thread_port" }, { "int", "sig" } } },
|
||||
{ 329, "pthread_sigmask", 3, { { "int", "how" }, { "user_addr_t", "set" }, { "user_addr_t", "oset" } } },
|
||||
{ 330, "sigwait", 2, { { "user_addr_t", "set" }, { "user_addr_t", "sig" } } },
|
||||
{ 331, "disable_threadsignal", 1, { { "int", "value" } } },
|
||||
{ 332, "pthread_markcancel", 1, { { "int", "thread_port" } } },
|
||||
{ 333, "pthread_canceled", 1, { { "int", "action" } } },
|
||||
{ 334, "semwait_signal", 6, { { "int", "cond_sem" }, { "int", "mutex_sem" }, { "int", "timeout" }, { "int", "relative" }, { "int64_t", "tv_sec" }, { "int32_t", "tv_nsec" } } },
|
||||
{ 336, "proc_info", 6, { { "int32_t", "callnum" }, { "int32_t", "pid" }, { "uint32_t", "flavor" }, { "uint64_t", "arg" }, { "user_addr_t", "buffer" }, { "int32_t", "buffersize" } } },
|
||||
{ 337, "sendfile", 6, { { "int", "fd" }, { "int", "s" }, { "off_t", "offset" }, { "off_t *", "nbytes" }, { "struct sf_hdtr *", "hdtr" }, { "int", "flags" } } },
|
||||
{ 338, "stat64", 2, { { "char *", "path" }, { "user_addr_t", "ub" } } },
|
||||
{ 339, "fstat64", 2, { { "int", "fd" }, { "user_addr_t", "ub" } } },
|
||||
{ 340, "lstat64", 2, { { "char *", "path" }, { "user_addr_t", "ub" } } },
|
||||
{ 341, "stat64_extended", 4, { { "char *", "path" }, { "user_addr_t", "ub" }, { "user_addr_t", "xsecurity" }, { "user_addr_t", "xsecurity_size" } } },
|
||||
{ 342, "lstat64_extended", 4, { { "char *", "path" }, { "user_addr_t", "ub" }, { "user_addr_t", "xsecurity" }, { "user_addr_t", "xsecurity_size" } } },
|
||||
{ 343, "fstat64_extended", 4, { { "int", "fd" }, { "user_addr_t", "ub" }, { "user_addr_t", "xsecurity" }, { "user_addr_t", "xsecurity_size" } } },
|
||||
{ 344, "getdirentries64", 4, { { "int", "fd" }, { "void *", "buf" }, { "user_size_t", "bufsize" }, { "off_t *", "position" } } },
|
||||
{ 345, "statfs64", 2, { { "char *", "path" }, { "struct statfs64 *", "buf" } } },
|
||||
{ 346, "fstatfs64", 2, { { "int", "fd" }, { "struct statfs64 *", "buf" } } },
|
||||
{ 347, "getfsstat64", 3, { { "user_addr_t", "buf" }, { "int", "bufsize" }, { "int", "flags" } } },
|
||||
{ 348, "pthread_chdir", 1, { { "char *", "path" } } },
|
||||
{ 349, "pthread_fchdir", 1, { { "int", "fd" } } },
|
||||
{ 350, "audit", 2, { { "void *", "record" }, { "int", "length" } } },
|
||||
{ 351, "auditon", 3, { { "int", "cmd" }, { "void *", "data" }, { "int", "length" } } },
|
||||
{ 353, "getauid", 1, { { "au_id_t *", "auid" } } },
|
||||
{ 354, "setauid", 1, { { "au_id_t *", "auid" } } },
|
||||
{ 357, "getaudit_addr", 2, { { "struct auditinfo_addr *", "auditinfo_addr" }, { "int", "length" } } },
|
||||
{ 358, "setaudit_addr", 2, { { "struct auditinfo_addr *", "auditinfo_addr" }, { "int", "length" } } },
|
||||
{ 359, "auditctl", 1, { { "char *", "path" } } },
|
||||
{ 360, "bsdthread_create", 5, { { "user_addr_t", "func" }, { "user_addr_t", "func_arg" }, { "user_addr_t", "stack" }, { "user_addr_t", "pthread" }, { "uint32_t", "flags" } } },
|
||||
{ 361, "bsdthread_terminate", 4, { { "user_addr_t", "stackaddr" }, { "size_t", "freesize" }, { "uint32_t", "port" }, { "user_addr_t", "sema_or_ulock" } } },
|
||||
{ 362, "kqueue", 0, {} },
|
||||
{ 363, "kevent", 6, { { "int", "fd" }, { "const struct kevent *", "changelist" }, { "int", "nchanges" }, { "struct kevent *", "eventlist" }, { "int", "nevents" }, { "const struct timespec *", "timeout" } } },
|
||||
{ 364, "lchown", 3, { { "char *", "path" }, { "uid_t", "owner" }, { "gid_t", "group" } } },
|
||||
{ 366, "bsdthread_register", 7, { { "user_addr_t", "threadstart" }, { "user_addr_t", "wqthread" }, { "uint32_t", "flags" }, { "user_addr_t", "stack_addr_hint" }, { "user_addr_t", "targetconc_ptr" }, { "uint32_t", "dispatchqueue_offset" }, { "uint32_t", "tsd_offset" } } },
|
||||
{ 367, "workq_open", 0, {} },
|
||||
{ 368, "workq_kernreturn", 4, { { "int", "options" }, { "user_addr_t", "item" }, { "int", "affinity" }, { "int", "prio" } } },
|
||||
{ 369, "kevent64", 7, { { "int", "fd" }, { "const struct kevent64_s *", "changelist" }, { "int", "nchanges" }, { "struct kevent64_s *", "eventlist" }, { "int", "nevents" }, { "unsigned int", "flags" }, { "const struct timespec *", "timeout" } } },
|
||||
{ 372, "thread_selfid", 0, {} },
|
||||
{ 373, "ledger", 4, { { "int", "cmd" }, { "caddr_t", "arg1" }, { "caddr_t", "arg2" }, { "caddr_t", "arg3" } } },
|
||||
{ 374, "kevent_qos", 8, { { "int", "fd" }, { "const struct kevent_qos_s *", "changelist" }, { "int", "nchanges" }, { "struct kevent_qos_s *", "eventlist" }, { "int", "nevents" }, { "void *", "data_out" }, { "size_t *", "data_available" }, { "unsigned int", "flags" } } },
|
||||
{ 375, "kevent_id", 8, { { "uint64_t", "id" }, { "const struct kevent_qos_s *", "changelist" }, { "int", "nchanges" }, { "struct kevent_qos_s *", "eventlist" }, { "int", "nevents" }, { "void *", "data_out" }, { "size_t *", "data_available" }, { "unsigned int", "flags" } } },
|
||||
{ 380, "mac_execve", 4, { { "char *", "fname" }, { "char **", "argp" }, { "char **", "envp" }, { "struct mac *", "mac_p" } } },
|
||||
{ 381, "mac_syscall", 3, { { "char *", "policy" }, { "int", "call" }, { "user_addr_t", "arg" } } },
|
||||
{ 382, "mac_get_file", 2, { { "char *", "path_p" }, { "struct mac *", "mac_p" } } },
|
||||
{ 383, "mac_set_file", 2, { { "char *", "path_p" }, { "struct mac *", "mac_p" } } },
|
||||
{ 384, "mac_get_link", 2, { { "char *", "path_p" }, { "struct mac *", "mac_p" } } },
|
||||
{ 385, "mac_set_link", 2, { { "char *", "path_p" }, { "struct mac *", "mac_p" } } },
|
||||
{ 386, "mac_get_proc", 1, { { "struct mac *", "mac_p" } } },
|
||||
{ 387, "mac_set_proc", 1, { { "struct mac *", "mac_p" } } },
|
||||
{ 388, "mac_get_fd", 2, { { "int", "fd" }, { "struct mac *", "mac_p" } } },
|
||||
{ 389, "mac_set_fd", 2, { { "int", "fd" }, { "struct mac *", "mac_p" } } },
|
||||
{ 390, "mac_get_pid", 2, { { "pid_t", "pid" }, { "struct mac *", "mac_p" } } },
|
||||
{ 394, "pselect", 6, { { "int", "nd" }, { "u_int32_t *", "in" }, { "u_int32_t *", "ou" }, { "u_int32_t *", "ex" }, { "const struct timespec *", "ts" }, { "const struct sigset_t *", "mask" } } },
|
||||
{ 395, "pselect_nocancel", 6, { { "int", "nd" }, { "u_int32_t *", "in" }, { "u_int32_t *", "ou" }, { "u_int32_t *", "ex" }, { "const struct timespec *", "ts" }, { "const struct sigset_t *", "mask" } } },
|
||||
{ 396, "read_nocancel", 3, { { "int", "fd" }, { "user_addr_t", "cbuf" }, { "user_size_t", "nbyte" } } },
|
||||
{ 397, "write_nocancel", 3, { { "int", "fd" }, { "user_addr_t", "cbuf" }, { "user_size_t", "nbyte" } } },
|
||||
{ 398, "open_nocancel", 3, { { "char *", "path" }, { "int", "flags" }, { "int", "mode" } } },
|
||||
{ 399, "close_nocancel", 1, { { "int", "fd" } } },
|
||||
{ 400, "wait4_nocancel", 4, { { "int", "pid" }, { "user_addr_t", "status" }, { "int", "options" }, { "user_addr_t", "rusage" } } },
|
||||
{ 401, "recvmsg_nocancel", 3, { { "int", "s" }, { "struct msghdr *", "msg" }, { "int", "flags" } } },
|
||||
{ 402, "sendmsg_nocancel", 3, { { "int", "s" }, { "caddr_t", "msg" }, { "int", "flags" } } },
|
||||
{ 403, "recvfrom_nocancel", 6, { { "int", "s" }, { "void *", "buf" }, { "size_t", "len" }, { "int", "flags" }, { "struct sockaddr *", "from" }, { "int *", "fromlenaddr" } } },
|
||||
{ 404, "accept_nocancel", 3, { { "int", "s" }, { "caddr_t", "name" }, { "socklen_t *", "anamelen" } } },
|
||||
{ 405, "msync_nocancel", 3, { { "caddr_ut", "addr" }, { "size_ut", "len" }, { "int", "flags" } } },
|
||||
{ 406, "fcntl_nocancel", 3, { { "int", "fd" }, { "int", "cmd" }, { "long", "arg" } } },
|
||||
{ 407, "select_nocancel", 5, { { "int", "nd" }, { "u_int32_t *", "in" }, { "u_int32_t *", "ou" }, { "u_int32_t *", "ex" }, { "struct timeval *", "tv" } } },
|
||||
{ 408, "fsync_nocancel", 1, { { "int", "fd" } } },
|
||||
{ 409, "connect_nocancel", 3, { { "int", "s" }, { "caddr_t", "name" }, { "socklen_t", "namelen" } } },
|
||||
{ 410, "sigsuspend_nocancel", 1, { { "sigset_t", "mask" } } },
|
||||
{ 411, "readv_nocancel", 3, { { "int", "fd" }, { "struct iovec *", "iovp" }, { "u_int", "iovcnt" } } },
|
||||
{ 412, "writev_nocancel", 3, { { "int", "fd" }, { "struct iovec *", "iovp" }, { "u_int", "iovcnt" } } },
|
||||
{ 413, "sendto_nocancel", 6, { { "int", "s" }, { "caddr_t", "buf" }, { "size_t", "len" }, { "int", "flags" }, { "caddr_t", "to" }, { "socklen_t", "tolen" } } },
|
||||
{ 414, "pread_nocancel", 4, { { "int", "fd" }, { "user_addr_t", "buf" }, { "user_size_t", "nbyte" }, { "off_t", "offset" } } },
|
||||
{ 415, "pwrite_nocancel", 4, { { "int", "fd" }, { "user_addr_t", "buf" }, { "user_size_t", "nbyte" }, { "off_t", "offset" } } },
|
||||
{ 416, "waitid_nocancel", 4, { { "idtype_t", "idtype" }, { "id_t", "id" }, { "siginfo_t *", "infop" }, { "int", "options" } } },
|
||||
{ 417, "poll_nocancel", 3, { { "struct pollfd *", "fds" }, { "u_int", "nfds" }, { "int", "timeout" } } },
|
||||
{ 418, "msgsnd_nocancel", 4, { { "int", "msqid" }, { "void *", "msgp" }, { "size_t", "msgsz" }, { "int", "msgflg" } } },
|
||||
{ 419, "msgrcv_nocancel", 5, { { "int", "msqid" }, { "void *", "msgp" }, { "size_t", "msgsz" }, { "long", "msgtyp" }, { "int", "msgflg" } } },
|
||||
{ 420, "sem_wait_nocancel", 1, { { "sem_t *", "sem" } } },
|
||||
{ 421, "aio_suspend_nocancel", 3, { { "user_addr_t", "aiocblist" }, { "int", "nent" }, { "user_addr_t", "timeoutp" } } },
|
||||
{ 422, "sigwait_nocancel", 2, { { "user_addr_t", "set" }, { "user_addr_t", "sig" } } },
|
||||
{ 423, "semwait_signal_nocancel", 6, { { "int", "cond_sem" }, { "int", "mutex_sem" }, { "int", "timeout" }, { "int", "relative" }, { "int64_t", "tv_sec" }, { "int32_t", "tv_nsec" } } },
|
||||
{ 424, "mac_mount", 5, { { "char *", "type" }, { "char *", "path" }, { "int", "flags" }, { "caddr_t", "data" }, { "struct mac *", "mac_p" } } },
|
||||
{ 425, "mac_get_mount", 2, { { "char *", "path" }, { "struct mac *", "mac_p" } } },
|
||||
{ 426, "mac_getfsstat", 5, { { "user_addr_t", "buf" }, { "int", "bufsize" }, { "user_addr_t", "mac" }, { "int", "macsize" }, { "int", "flags" } } },
|
||||
{ 427, "fsgetpath", 4, { { "user_addr_t", "buf" }, { "size_t", "bufsize" }, { "user_addr_t", "fsid" }, { "uint64_t", "objid" } } },
|
||||
{ 428, "audit_session_self", 0, {} },
|
||||
{ 429, "audit_session_join", 1, { { "mach_port_name_t", "port" } } },
|
||||
{ 430, "fileport_makeport", 2, { { "int", "fd" }, { "user_addr_t", "portnamep" } } },
|
||||
{ 431, "fileport_makefd", 1, { { "mach_port_name_t", "port" } } },
|
||||
{ 432, "audit_session_port", 2, { { "au_asid_t", "asid" }, { "user_addr_t", "portnamep" } } },
|
||||
{ 433, "pid_suspend", 1, { { "int", "pid" } } },
|
||||
{ 434, "pid_resume", 1, { { "int", "pid" } } },
|
||||
{ 435, "pid_hibernate", 1, { { "int", "pid" } } },
|
||||
{ 436, "pid_shutdown_sockets", 2, { { "int", "pid" }, { "int", "level" } } },
|
||||
{ 439, "kas_info", 3, { { "int", "selector" }, { "void *", "value" }, { "size_t *", "size" } } },
|
||||
{ 440, "memorystatus_control", 5, { { "uint32_t", "command" }, { "int32_t", "pid" }, { "uint32_t", "flags" }, { "user_addr_t", "buffer" }, { "size_t", "buffersize" } } },
|
||||
{ 441, "guarded_open_np", 5, { { "char *", "path" }, { "const guardid_t *", "guard" }, { "u_int", "guardflags" }, { "int", "flags" }, { "int", "mode" } } },
|
||||
{ 442, "guarded_close_np", 2, { { "int", "fd" }, { "const guardid_t *", "guard" } } },
|
||||
{ 443, "guarded_kqueue_np", 2, { { "const guardid_t *", "guard" }, { "u_int", "guardflags" } } },
|
||||
{ 444, "change_fdguard_np", 6, { { "int", "fd" }, { "const guardid_t *", "guard" }, { "u_int", "guardflags" }, { "const guardid_t *", "nguard" }, { "u_int", "nguardflags" }, { "int *", "fdflagsp" } } },
|
||||
{ 445, "usrctl", 1, { { "uint32_t", "flags" } } },
|
||||
{ 446, "proc_rlimit_control", 3, { { "pid_t", "pid" }, { "int", "flavor" }, { "void *", "arg" } } },
|
||||
{ 447, "connectx", 8, { { "int", "socket" }, { "const sa_endpoints_t *", "endpoints" }, { "sae_associd_t", "associd" }, { "unsigned int", "flags" }, { "const struct iovec *", "iov" }, { "unsigned int", "iovcnt" }, { "size_t *", "len" }, { "sae_connid_t *", "connid" } } },
|
||||
{ 448, "disconnectx", 3, { { "int", "s" }, { "sae_associd_t", "aid" }, { "sae_connid_t", "cid" } } },
|
||||
{ 449, "peeloff", 2, { { "int", "s" }, { "sae_associd_t", "aid" } } },
|
||||
{ 450, "socket_delegate", 4, { { "int", "domain" }, { "int", "type" }, { "int", "protocol" }, { "pid_t", "epid" } } },
|
||||
{ 451, "telemetry", 6, { { "uint64_t", "cmd" }, { "uint64_t", "deadline" }, { "uint64_t", "interval" }, { "uint64_t", "leeway" }, { "uint64_t", "arg4" }, { "uint64_t", "arg5" } } },
|
||||
{ 452, "proc_uuid_policy", 4, { { "uint32_t", "operation" }, { "uuid_t", "uuid" }, { "size_t", "uuidlen" }, { "uint32_t", "flags" } } },
|
||||
{ 453, "memorystatus_get_level", 1, { { "user_addr_t", "level" } } },
|
||||
{ 454, "system_override", 2, { { "uint64_t", "timeout" }, { "uint64_t", "flags" } } },
|
||||
{ 455, "vfs_purge", 0, {} },
|
||||
{ 456, "sfi_ctl", 4, { { "uint32_t", "operation" }, { "uint32_t", "sfi_class" }, { "uint64_t", "time" }, { "uint64_t *", "out_time" } } },
|
||||
{ 457, "sfi_pidctl", 4, { { "uint32_t", "operation" }, { "pid_t", "pid" }, { "uint32_t", "sfi_flags" }, { "uint32_t *", "out_sfi_flags" } } },
|
||||
{ 458, "coalition", 3, { { "uint32_t", "operation" }, { "uint64_t *", "cid" }, { "uint32_t", "flags" } } },
|
||||
{ 459, "coalition_info", 4, { { "uint32_t", "flavor" }, { "uint64_t *", "cid" }, { "void *", "buffer" }, { "size_t *", "bufsize" } } },
|
||||
{ 460, "necp_match_policy", 3, { { "uint8_t *", "parameters" }, { "size_t", "parameters_size" }, { "struct necp_aggregate_result *", "returned_result" } } },
|
||||
{ 461, "getattrlistbulk", 5, { { "int", "dirfd" }, { "struct attrlist *", "alist" }, { "void *", "attribute_buffer" }, { "size_t", "buffer_size" }, { "uint64_t", "options" } } },
|
||||
{ 462, "clonefileat", 5, { { "int", "src_dirfd" }, { "user_addr_t", "src" }, { "int", "dst_dirfd" }, { "user_addr_t", "dst" }, { "uint32_t", "flags" } } },
|
||||
{ 463, "openat", 4, { { "int", "fd" }, { "char *", "path" }, { "int", "flags" }, { "int", "mode" } } },
|
||||
{ 464, "openat_nocancel", 4, { { "int", "fd" }, { "char *", "path" }, { "int", "flags" }, { "int", "mode" } } },
|
||||
{ 465, "renameat", 4, { { "int", "fromfd" }, { "char *", "from" }, { "int", "tofd" }, { "char *", "to" } } },
|
||||
{ 466, "faccessat", 4, { { "int", "fd" }, { "char *", "path" }, { "int", "amode" }, { "int", "flag" } } },
|
||||
{ 467, "fchmodat", 4, { { "int", "fd" }, { "char *", "path" }, { "int", "mode" }, { "int", "flag" } } },
|
||||
{ 468, "fchownat", 5, { { "int", "fd" }, { "char *", "path" }, { "uid_t", "uid" }, { "gid_t", "gid" }, { "int", "flag" } } },
|
||||
{ 469, "fstatat", 4, { { "int", "fd" }, { "char *", "path" }, { "user_addr_t", "ub" }, { "int", "flag" } } },
|
||||
{ 470, "fstatat64", 4, { { "int", "fd" }, { "char *", "path" }, { "user_addr_t", "ub" }, { "int", "flag" } } },
|
||||
{ 471, "linkat", 5, { { "int", "fd1" }, { "char *", "path" }, { "int", "fd2" }, { "char *", "link" }, { "int", "flag" } } },
|
||||
{ 472, "unlinkat", 3, { { "int", "fd" }, { "char *", "path" }, { "int", "flag" } } },
|
||||
{ 473, "readlinkat", 4, { { "int", "fd" }, { "char *", "path" }, { "user_addr_t", "buf" }, { "size_t", "bufsize" } } },
|
||||
{ 474, "symlinkat", 3, { { "user_addr_t *", "path1" }, { "int", "fd" }, { "user_addr_t", "path2" } } },
|
||||
{ 475, "mkdirat", 3, { { "int", "fd" }, { "char *", "path" }, { "int", "mode" } } },
|
||||
{ 476, "getattrlistat", 6, { { "int", "fd" }, { "const char *", "path" }, { "struct attrlist *", "alist" }, { "void *", "attribute_buffer" }, { "size_t", "buffer_size" }, { "u_long", "options" } } },
|
||||
{ 477, "proc_trace_log", 2, { { "pid_t", "pid" }, { "uint64_t", "uniqueid" } } },
|
||||
{ 478, "bsdthread_ctl", 4, { { "user_addr_t", "cmd" }, { "user_addr_t", "arg1" }, { "user_addr_t", "arg2" }, { "user_addr_t", "arg3" } } },
|
||||
{ 479, "openbyid_np", 3, { { "user_addr_t", "fsid" }, { "user_addr_t", "objid" }, { "int", "oflags" } } },
|
||||
{ 480, "recvmsg_x", 4, { { "int", "s" }, { "struct msghdr_x *", "msgp" }, { "u_int", "cnt" }, { "int", "flags" } } },
|
||||
{ 481, "sendmsg_x", 4, { { "int", "s" }, { "struct msghdr_x *", "msgp" }, { "u_int", "cnt" }, { "int", "flags" } } },
|
||||
{ 482, "thread_selfusage", 0, {} },
|
||||
{ 483, "csrctl", 3, { { "uint32_t", "op" }, { "user_addr_t", "useraddr" }, { "user_addr_t", "usersize" } } },
|
||||
{ 484, "guarded_open_dprotected_np", 7, { { "char *", "path" }, { "const guardid_t *", "guard" }, { "u_int", "guardflags" }, { "int", "flags" }, { "int", "dpclass" }, { "int", "dpflags" }, { "int", "mode" } } },
|
||||
{ 485, "guarded_write_np", 4, { { "int", "fd" }, { "const guardid_t *", "guard" }, { "user_addr_t", "cbuf" }, { "user_size_t", "nbyte" } } },
|
||||
{ 486, "guarded_pwrite_np", 5, { { "int", "fd" }, { "const guardid_t *", "guard" }, { "user_addr_t", "buf" }, { "user_size_t", "nbyte" }, { "off_t", "offset" } } },
|
||||
{ 487, "guarded_writev_np", 4, { { "int", "fd" }, { "const guardid_t *", "guard" }, { "struct iovec *", "iovp" }, { "int", "iovcnt" } } },
|
||||
{ 488, "renameatx_np", 5, { { "int", "fromfd" }, { "char *", "from" }, { "int", "tofd" }, { "char *", "to" }, { "u_int", "flags" } } },
|
||||
{ 489, "mremap_encrypted", 5, { { "caddr_ut", "addr" }, { "size_ut", "len" }, { "uint32_t", "cryptid" }, { "uint32_t", "cputype" }, { "uint32_t", "cpusubtype" } } },
|
||||
{ 490, "netagent_trigger", 2, { { "uuid_t", "agent_uuid" }, { "size_t", "agent_uuidlen" } } },
|
||||
{ 491, "stack_snapshot_with_config", 3, { { "int", "stackshot_config_version" }, { "user_addr_t", "stackshot_config" }, { "size_t", "stackshot_config_size" } } },
|
||||
{ 492, "microstackshot", 3, { { "user_addr_t", "tracebuf" }, { "uint32_t", "tracebuf_size" }, { "uint32_t", "flags" } } },
|
||||
{ 493, "grab_pgo_data", 4, { { "user_addr_t", "uuid" }, { "int", "flags" }, { "user_addr_t", "buffer" }, { "user_ssize_t", "size" } } },
|
||||
{ 494, "persona", 6, { { "uint32_t", "operation" }, { "uint32_t", "flags" }, { "struct kpersona_info *", "info" }, { "uid_t *", "id" }, { "size_t *", "idlen" }, { "char *", "path" } } },
|
||||
{ 496, "mach_eventlink_signal", 2, { { "mach_port_name_t", "eventlink_port" }, { "uint64_t", "signal_count" } } },
|
||||
{ 497, "mach_eventlink_wait_until", 5, { { "mach_port_name_t", "eventlink_port" }, { "uint64_t", "wait_count" }, { "uint64_t", "deadline" }, { "uint32_t", "clock_id" }, { "uint32_t", "option" } } },
|
||||
{ 498, "mach_eventlink_signal_wait_until", 6, { { "mach_port_name_t", "eventlink_port" }, { "uint64_t", "wait_count" }, { "uint64_t", "signal_count" }, { "uint64_t", "deadline" }, { "uint32_t", "clock_id" }, { "uint32_t", "option" } } },
|
||||
{ 499, "work_interval_ctl", 4, { { "uint32_t", "operation" }, { "uint64_t", "work_interval_id" }, { "void *", "arg" }, { "size_t", "len" } } },
|
||||
{ 500, "getentropy", 2, { { "void *", "buffer" }, { "size_t", "size" } } },
|
||||
{ 502, "necp_client_action", 6, { { "int", "necp_fd" }, { "uint32_t", "action" }, { "uuid_t", "client_id" }, { "size_t", "client_id_len" }, { "uint8_t *", "buffer" }, { "size_t", "buffer_size" } } },
|
||||
{ 503, "nexus_open", 2, { { "struct nxctl_init *", "init" }, { "uint32_t", "init_len" } } },
|
||||
{ 504, "nexus_register", 5, { { "int", "ctl" }, { "struct nxprov_reg *", "reg" }, { "uint32_t", "reg_len" }, { "uuid_t *", "prov_uuid" }, { "uint32_t", "prov_uuid_len" } } },
|
||||
{ 505, "nexus_deregister", 3, { { "int", "ctl" }, { "uuid_t", "prov_uuid" }, { "uint32_t", "prov_uuid_len" } } },
|
||||
{ 506, "nexus_create", 5, { { "int", "ctl" }, { "uuid_t", "prov_uuid" }, { "uint32_t", "prov_uuid_len" }, { "uuid_t *", "nx_uuid" }, { "uint32_t", "nx_uuid_len" } } },
|
||||
{ 507, "nexus_destroy", 3, { { "int", "ctl" }, { "uuid_t", "nx_uuid" }, { "uint32_t", "nx_uuid_len" } } },
|
||||
{ 508, "nexus_get_opt", 4, { { "int", "ctl" }, { "uint32_t", "opt" }, { "void *", "aoptval" }, { "uint32_t *", "aoptlen" } } },
|
||||
{ 509, "nexus_set_opt", 4, { { "int", "ctl" }, { "uint32_t", "opt" }, { "const void *", "aoptval" }, { "uint32_t", "optlen" } } },
|
||||
{ 510, "channel_open", 2, { { "struct ch_init *", "init" }, { "uint32_t", "init_len" } } },
|
||||
{ 511, "channel_get_info", 3, { { "int", "c" }, { "struct ch_info *", "cinfo" }, { "uint32_t", "cinfolen" } } },
|
||||
{ 512, "channel_sync", 3, { { "int", "c" }, { "int", "mode" }, { "int", "flags" } } },
|
||||
{ 513, "channel_get_opt", 4, { { "int", "c" }, { "uint32_t", "opt" }, { "void *", "aoptval" }, { "uint32_t *", "aoptlen" } } },
|
||||
{ 514, "channel_set_opt", 4, { { "int", "c" }, { "uint32_t", "opt" }, { "const void *", "aoptval" }, { "uint32_t", "optlen" } } },
|
||||
{ 515, "ulock_wait", 4, { { "uint32_t", "operation" }, { "void *", "addr" }, { "uint64_t", "value" }, { "uint32_t", "timeout" } } },
|
||||
{ 516, "ulock_wake", 3, { { "uint32_t", "operation" }, { "void *", "addr" }, { "uint64_t", "wake_value" } } },
|
||||
{ 517, "fclonefileat", 4, { { "int", "src_fd" }, { "int", "dst_dirfd" }, { "user_addr_t", "dst" }, { "uint32_t", "flags" } } },
|
||||
{ 518, "fs_snapshot", 6, { { "uint32_t", "op" }, { "int", "dirfd" }, { "user_addr_t", "name1" }, { "user_addr_t", "name2" }, { "user_addr_t", "data" }, { "uint32_t", "flags" } } },
|
||||
{ 520, "terminate_with_payload", 7, { { "int", "pid" }, { "uint32_t", "reason_namespace" }, { "uint64_t", "reason_code" }, { "void *", "payload" }, { "uint32_t", "payload_size" }, { "const char *", "reason_string" }, { "uint64_t", "reason_flags" } } },
|
||||
{ 521, "abort_with_payload", 6, { { "uint32_t", "reason_namespace" }, { "uint64_t", "reason_code" }, { "void *", "payload" }, { "uint32_t", "payload_size" }, { "const char *", "reason_string" }, { "uint64_t", "reason_flags" } } },
|
||||
{ 523, "necp_session_action", 6, { { "int", "necp_fd" }, { "uint32_t", "action" }, { "uint8_t *", "in_buffer" }, { "size_t", "in_buffer_length" }, { "uint8_t *", "out_buffer" }, { "size_t", "out_buffer_length" } } },
|
||||
{ 524, "setattrlistat", 6, { { "int", "fd" }, { "const char *", "path" }, { "struct attrlist *", "alist" }, { "void *", "attribute_buffer" }, { "size_t", "buffer_size" }, { "uint32_t", "options" } } },
|
||||
{ 525, "net_qos_guideline", 2, { { "struct net_qos_param *", "param" }, { "uint32_t", "param_len" } } },
|
||||
{ 526, "fmount", 4, { { "const char *", "type" }, { "int", "fd" }, { "int", "flags" }, { "void *", "data" } } },
|
||||
{ 527, "ntp_adjtime", 1, { { "struct timex *", "tp" } } },
|
||||
{ 528, "ntp_gettime", 1, { { "struct ntptimeval *", "ntvp" } } },
|
||||
{ 529, "os_fault_with_payload", 6, { { "uint32_t", "reason_namespace" }, { "uint64_t", "reason_code" }, { "void *", "payload" }, { "uint32_t", "payload_size" }, { "const char *", "reason_string" }, { "uint64_t", "reason_flags" } } },
|
||||
{ 530, "kqueue_workloop_ctl", 4, { { "user_addr_t", "cmd" }, { "uint64_t", "options" }, { "user_addr_t", "addr" }, { "size_t", "sz" } } },
|
||||
{ 531, "mach_bridge_remote_time", 1, { { "uint64_t", "local_timestamp" } } },
|
||||
{ 532, "coalition_ledger", 4, { { "uint32_t", "operation" }, { "uint64_t *", "cid" }, { "void *", "buffer" }, { "size_t *", "bufsize" } } },
|
||||
{ 533, "log_data", 4, { { "unsigned int", "tag" }, { "unsigned int", "flags" }, { "void *", "buffer" }, { "unsigned int", "size" } } },
|
||||
{ 534, "memorystatus_available_memory", 0, {} },
|
||||
{ 535, "objc_bp_assist_cfg_np", 2, { { "uint64_t", "adr" }, { "uint64_t", "ctl" } } },
|
||||
{ 536, "shared_region_map_and_slide_2_np", 4, { { "uint32_t", "files_count" }, { "const struct shared_file_np *", "files" }, { "uint32_t", "mappings_count" }, { "const shared_file_mapping_slide_np_ut *", "mappings_u" } } },
|
||||
{ 537, "pivot_root", 2, { { "const char *", "new_rootfs_path_before" }, { "const char *", "old_rootfs_path_after" } } },
|
||||
{ 538, "task_inspect_for_pid", 3, { { "mach_port_name_t", "target_tport" }, { "int", "pid" }, { "mach_port_name_t *", "t" } } },
|
||||
{ 539, "task_read_for_pid", 3, { { "mach_port_name_t", "target_tport" }, { "int", "pid" }, { "mach_port_name_t *", "t" } } },
|
||||
{ 540, "preadv", 4, { { "int", "fd" }, { "struct iovec *", "iovp" }, { "int", "iovcnt" }, { "off_t", "offset" } } },
|
||||
{ 541, "pwritev", 4, { { "int", "fd" }, { "struct iovec *", "iovp" }, { "int", "iovcnt" }, { "off_t", "offset" } } },
|
||||
{ 542, "preadv_nocancel", 4, { { "int", "fd" }, { "struct iovec *", "iovp" }, { "int", "iovcnt" }, { "off_t", "offset" } } },
|
||||
{ 543, "pwritev_nocancel", 4, { { "int", "fd" }, { "struct iovec *", "iovp" }, { "int", "iovcnt" }, { "off_t", "offset" } } },
|
||||
{ 544, "ulock_wait2", 5, { { "uint32_t", "operation" }, { "void *", "addr" }, { "uint64_t", "value" }, { "uint64_t", "timeout" }, { "uint64_t", "value2" } } },
|
||||
{ 545, "proc_info_extended_id", 8, { { "int32_t", "callnum" }, { "int32_t", "pid" }, { "uint32_t", "flavor" }, { "uint32_t", "flags" }, { "uint64_t", "ext_id" }, { "uint64_t", "arg" }, { "user_addr_t", "buffer" }, { "int32_t", "buffersize" } } },
|
||||
{ 546, "tracker_action", 3, { { "int", "action" }, { "char *", "buffer" }, { "size_t", "buffer_size" } } },
|
||||
{ 547, "debug_syscall_reject", 1, { { "uint64_t", "packed_selectors" } } },
|
||||
{ 548, "debug_syscall_reject_config", 3, { { "uint64_t", "packed_selectors1" }, { "uint64_t", "packed_selectors2" }, { "uint64_t", "flags" } } },
|
||||
{ 549, "graftdmg", 4, { { "int", "dmg_fd" }, { "const char *", "mountdir" }, { "uint32_t", "graft_type" }, { "graftdmg_args_un *", "gda" } } },
|
||||
{ 550, "map_with_linking_np", 4, { { "void *", "regions" }, { "uint32_t", "region_count" }, { "void *", "link_info" }, { "uint32_t", "link_info_size" } } },
|
||||
{ 551, "freadlink", 3, { { "int", "fd" }, { "user_addr_t", "buf" }, { "user_size_t", "bufsize" } } },
|
||||
{ 552, "record_system_event", 4, { { "uint32_t", "type" }, { "uint32_t", "subsystem" }, { "const char *", "event" }, { "const char *", "payload" } } },
|
||||
{ 553, "mkfifoat", 3, { { "int", "fd" }, { "char *", "path" }, { "int", "mode" } } },
|
||||
{ 554, "mknodat", 4, { { "int", "fd" }, { "char *", "path" }, { "int", "mode" }, { "int", "dev" } } },
|
||||
{ 555, "ungraftdmg", 2, { { "const char *", "mountdir" }, { "uint64_t", "flags" } } },
|
||||
{ 556, "coalition_policy_set", 3, { { "uint64_t", "cid" }, { "uint32_t", "flavor" }, { "uint32_t", "value" } } },
|
||||
{ 557, "coalition_policy_get", 2, { { "uint64_t", "cid" }, { "uint32_t", "flavor" } } },
|
||||
};
|
||||
|
||||
FridaXnuSyscallSignature *
|
||||
frida_get_xnu_mach_traps (int * len)
|
||||
{
|
||||
if (len != NULL)
|
||||
*len = G_N_ELEMENTS (frida_xnu_mach_traps);
|
||||
return (FridaXnuSyscallSignature *) frida_xnu_mach_traps;
|
||||
}
|
||||
|
||||
FridaXnuSyscallSignature *
|
||||
frida_get_xnu_bsd_syscalls (int * len)
|
||||
{
|
||||
if (len != NULL)
|
||||
*len = G_N_ELEMENTS (frida_xnu_bsd_syscalls);
|
||||
return (FridaXnuSyscallSignature *) frida_xnu_bsd_syscalls;
|
||||
}
|
||||
@@ -1,545 +0,0 @@
|
||||
// AUTO-GENERATED FILE. DO NOT EDIT.
|
||||
|
||||
namespace Frida {
|
||||
public extern unowned XnuSyscallSignature[] get_xnu_mach_traps ();
|
||||
public extern unowned XnuSyscallSignature[] get_xnu_bsd_syscalls ();
|
||||
|
||||
public struct XnuSyscallSignature {
|
||||
public int nr;
|
||||
public string name;
|
||||
public uint8 nargs;
|
||||
public XnuSyscallArg args[9];
|
||||
}
|
||||
|
||||
public struct XnuSyscallArg {
|
||||
public string? type;
|
||||
public string? name;
|
||||
}
|
||||
|
||||
/**
|
||||
* The XNU Mach trap numbers, as used on Apple platforms.
|
||||
*/
|
||||
public enum XnuMachTrap {
|
||||
MACH_VM_ALLOCATE = -10,
|
||||
MACH_VM_PURGABLE_CONTROL = -11,
|
||||
MACH_VM_DEALLOCATE = -12,
|
||||
TASK_DYLD_PROCESS_INFO_NOTIFY_GET = -13,
|
||||
MACH_VM_PROTECT = -14,
|
||||
MACH_VM_MAP = -15,
|
||||
MACH_PORT_ALLOCATE = -16,
|
||||
MACH_PORT_DEALLOCATE = -18,
|
||||
MACH_PORT_MOD_REFS = -19,
|
||||
MACH_PORT_MOVE_MEMBER = -20,
|
||||
MACH_PORT_INSERT_RIGHT = -21,
|
||||
MACH_PORT_INSERT_MEMBER = -22,
|
||||
MACH_PORT_EXTRACT_MEMBER = -23,
|
||||
MACH_PORT_CONSTRUCT = -24,
|
||||
MACH_PORT_DESTRUCT = -25,
|
||||
MACH_REPLY_PORT = -26,
|
||||
THREAD_SELF = -27,
|
||||
TASK_SELF = -28,
|
||||
HOST_SELF = -29,
|
||||
MACH_MSG = -31,
|
||||
MACH_MSG_OVERWRITE = -32,
|
||||
SEMAPHORE_SIGNAL = -33,
|
||||
SEMAPHORE_SIGNAL_ALL = -34,
|
||||
SEMAPHORE_SIGNAL_THREAD = -35,
|
||||
SEMAPHORE_WAIT = -36,
|
||||
SEMAPHORE_WAIT_SIGNAL = -37,
|
||||
SEMAPHORE_TIMEDWAIT = -38,
|
||||
SEMAPHORE_TIMEDWAIT_SIGNAL = -39,
|
||||
MACH_PORT_GET_ATTRIBUTES = -40,
|
||||
MACH_PORT_GUARD = -41,
|
||||
MACH_PORT_UNGUARD = -42,
|
||||
MACH_GENERATE_ACTIVITY_ID = -43,
|
||||
TASK_NAME_FOR_PID = -44,
|
||||
TASK_FOR_PID = -45,
|
||||
PID_FOR_TASK = -46,
|
||||
MACH_MSG2 = -47,
|
||||
MACX_SWAPON = -48,
|
||||
MACX_SWAPOFF = -49,
|
||||
THREAD_GET_SPECIAL_REPLY_PORT = -50,
|
||||
MACX_TRIGGERS = -51,
|
||||
MACX_BACKING_STORE_SUSPEND = -52,
|
||||
MACX_BACKING_STORE_RECOVERY = -53,
|
||||
PFZ_EXIT = -58,
|
||||
SWTCH_PRI = -59,
|
||||
SWTCH = -60,
|
||||
THREAD_SWITCH = -61,
|
||||
CLOCK_SLEEP = -62,
|
||||
MACH_VM_RECLAIM_UPDATE_KERNEL_ACCOUNTING = -63,
|
||||
HOST_CREATE_MACH_VOUCHER = -70,
|
||||
MACH_VOUCHER_EXTRACT_ATTR_RECIPE = -72,
|
||||
MACH_PORT_TYPE = -76,
|
||||
MACH_PORT_REQUEST_NOTIFICATION = -77,
|
||||
EXCLAVES_CTL = -88,
|
||||
MACH_TIMEBASE_INFO = -89,
|
||||
MACH_WAIT_UNTIL = -90,
|
||||
MK_TIMER_CREATE = -91,
|
||||
MK_TIMER_DESTROY = -92,
|
||||
MK_TIMER_ARM = -93,
|
||||
MK_TIMER_CANCEL = -94,
|
||||
MK_TIMER_ARM_LEEWAY = -95,
|
||||
DEBUG_CONTROL_PORT_FOR_PID = -96,
|
||||
IOKIT_USER_CLIENT = -100,
|
||||
}
|
||||
|
||||
/**
|
||||
* The XNU BSD syscall numbers, as used on Apple platforms.
|
||||
*/
|
||||
public enum XnuBsdSyscall {
|
||||
EXIT = 1,
|
||||
FORK = 2,
|
||||
READ = 3,
|
||||
WRITE = 4,
|
||||
OPEN = 5,
|
||||
CLOSE = 6,
|
||||
WAIT4 = 7,
|
||||
LINK = 9,
|
||||
UNLINK = 10,
|
||||
CHDIR = 12,
|
||||
FCHDIR = 13,
|
||||
MKNOD = 14,
|
||||
CHMOD = 15,
|
||||
CHOWN = 16,
|
||||
GETFSSTAT = 18,
|
||||
GETPID = 20,
|
||||
SETUID = 23,
|
||||
GETUID = 24,
|
||||
GETEUID = 25,
|
||||
PTRACE = 26,
|
||||
RECVMSG = 27,
|
||||
SENDMSG = 28,
|
||||
RECVFROM = 29,
|
||||
ACCEPT = 30,
|
||||
GETPEERNAME = 31,
|
||||
GETSOCKNAME = 32,
|
||||
ACCESS = 33,
|
||||
CHFLAGS = 34,
|
||||
FCHFLAGS = 35,
|
||||
SYNC = 36,
|
||||
KILL = 37,
|
||||
CROSSARCH_TRAP = 38,
|
||||
GETPPID = 39,
|
||||
DUP = 41,
|
||||
PIPE = 42,
|
||||
GETEGID = 43,
|
||||
SIGACTION = 46,
|
||||
GETGID = 47,
|
||||
SIGPROCMASK = 48,
|
||||
GETLOGIN = 49,
|
||||
SETLOGIN = 50,
|
||||
ACCT = 51,
|
||||
SIGPENDING = 52,
|
||||
SIGALTSTACK = 53,
|
||||
IOCTL = 54,
|
||||
REBOOT = 55,
|
||||
REVOKE = 56,
|
||||
SYMLINK = 57,
|
||||
READLINK = 58,
|
||||
EXECVE = 59,
|
||||
UMASK = 60,
|
||||
CHROOT = 61,
|
||||
MSYNC = 65,
|
||||
VFORK = 66,
|
||||
OSLOG_COPROC_REG = 67,
|
||||
OSLOG_COPROC = 68,
|
||||
MUNMAP = 73,
|
||||
MPROTECT = 74,
|
||||
MADVISE = 75,
|
||||
MINCORE = 78,
|
||||
GETGROUPS = 79,
|
||||
SETGROUPS = 80,
|
||||
GETPGRP = 81,
|
||||
SETPGID = 82,
|
||||
SETITIMER = 83,
|
||||
SWAPON = 85,
|
||||
GETITIMER = 86,
|
||||
GETDTABLESIZE = 89,
|
||||
DUP2 = 90,
|
||||
FCNTL = 92,
|
||||
SELECT = 93,
|
||||
FSYNC = 95,
|
||||
SETPRIORITY = 96,
|
||||
SOCKET = 97,
|
||||
CONNECT = 98,
|
||||
GETPRIORITY = 100,
|
||||
BIND = 104,
|
||||
SETSOCKOPT = 105,
|
||||
LISTEN = 106,
|
||||
SIGSUSPEND = 111,
|
||||
GETTIMEOFDAY = 116,
|
||||
GETRUSAGE = 117,
|
||||
GETSOCKOPT = 118,
|
||||
READV = 120,
|
||||
WRITEV = 121,
|
||||
SETTIMEOFDAY = 122,
|
||||
FCHOWN = 123,
|
||||
FCHMOD = 124,
|
||||
SETREUID = 126,
|
||||
SETREGID = 127,
|
||||
RENAME = 128,
|
||||
FLOCK = 131,
|
||||
MKFIFO = 132,
|
||||
SENDTO = 133,
|
||||
SHUTDOWN = 134,
|
||||
SOCKETPAIR = 135,
|
||||
MKDIR = 136,
|
||||
RMDIR = 137,
|
||||
UTIMES = 138,
|
||||
FUTIMES = 139,
|
||||
ADJTIME = 140,
|
||||
GETHOSTUUID = 142,
|
||||
SETSID = 147,
|
||||
GETPGID = 151,
|
||||
SETPRIVEXEC = 152,
|
||||
PREAD = 153,
|
||||
PWRITE = 154,
|
||||
NFSSVC = 155,
|
||||
STATFS = 157,
|
||||
FSTATFS = 158,
|
||||
UNMOUNT = 159,
|
||||
GETFH = 161,
|
||||
FUNMOUNT = 164,
|
||||
QUOTACTL = 165,
|
||||
MOUNT = 167,
|
||||
CSOPS = 169,
|
||||
CSOPS_AUDITTOKEN = 170,
|
||||
WAITID = 173,
|
||||
KDEBUG_TYPEFILTER = 177,
|
||||
KDEBUG_TRACE_STRING = 178,
|
||||
KDEBUG_TRACE64 = 179,
|
||||
KDEBUG_TRACE = 180,
|
||||
SETGID = 181,
|
||||
SETEGID = 182,
|
||||
SETEUID = 183,
|
||||
SIGRETURN = 184,
|
||||
PANIC_WITH_DATA = 185,
|
||||
THREAD_SELFCOUNTS = 186,
|
||||
FDATASYNC = 187,
|
||||
STAT = 188,
|
||||
FSTAT = 189,
|
||||
LSTAT = 190,
|
||||
PATHCONF = 191,
|
||||
FPATHCONF = 192,
|
||||
GETRLIMIT = 194,
|
||||
SETRLIMIT = 195,
|
||||
GETDIRENTRIES = 196,
|
||||
MMAP = 197,
|
||||
LSEEK = 199,
|
||||
TRUNCATE = 200,
|
||||
FTRUNCATE = 201,
|
||||
SYSCTL = 202,
|
||||
MLOCK = 203,
|
||||
MUNLOCK = 204,
|
||||
UNDELETE = 205,
|
||||
OPEN_DPROTECTED_NP = 216,
|
||||
FSGETPATH_EXT = 217,
|
||||
OPENAT_DPROTECTED_NP = 218,
|
||||
GETATTRLIST = 220,
|
||||
SETATTRLIST = 221,
|
||||
GETDIRENTRIESATTR = 222,
|
||||
EXCHANGEDATA = 223,
|
||||
SEARCHFS = 225,
|
||||
DELETE = 226,
|
||||
COPYFILE = 227,
|
||||
FGETATTRLIST = 228,
|
||||
FSETATTRLIST = 229,
|
||||
POLL = 230,
|
||||
GETXATTR = 234,
|
||||
FGETXATTR = 235,
|
||||
SETXATTR = 236,
|
||||
FSETXATTR = 237,
|
||||
REMOVEXATTR = 238,
|
||||
FREMOVEXATTR = 239,
|
||||
LISTXATTR = 240,
|
||||
FLISTXATTR = 241,
|
||||
FSCTL = 242,
|
||||
INITGROUPS = 243,
|
||||
POSIX_SPAWN = 244,
|
||||
FFSCTL = 245,
|
||||
FHOPEN = 248,
|
||||
MINHERIT = 250,
|
||||
SEMSYS = 251,
|
||||
MSGSYS = 252,
|
||||
SHMSYS = 253,
|
||||
SEMCTL = 254,
|
||||
SEMGET = 255,
|
||||
SEMOP = 256,
|
||||
MSGCTL = 258,
|
||||
MSGGET = 259,
|
||||
MSGSND = 260,
|
||||
MSGRCV = 261,
|
||||
SHMAT = 262,
|
||||
SHMCTL = 263,
|
||||
SHMDT = 264,
|
||||
SHMGET = 265,
|
||||
SHM_OPEN = 266,
|
||||
SHM_UNLINK = 267,
|
||||
SEM_OPEN = 268,
|
||||
SEM_CLOSE = 269,
|
||||
SEM_UNLINK = 270,
|
||||
SEM_WAIT = 271,
|
||||
SEM_TRYWAIT = 272,
|
||||
SEM_POST = 273,
|
||||
SYSCTLBYNAME = 274,
|
||||
OPEN_EXTENDED = 277,
|
||||
UMASK_EXTENDED = 278,
|
||||
STAT_EXTENDED = 279,
|
||||
LSTAT_EXTENDED = 280,
|
||||
FSTAT_EXTENDED = 281,
|
||||
CHMOD_EXTENDED = 282,
|
||||
FCHMOD_EXTENDED = 283,
|
||||
ACCESS_EXTENDED = 284,
|
||||
SETTID = 285,
|
||||
GETTID = 286,
|
||||
SETSGROUPS = 287,
|
||||
GETSGROUPS = 288,
|
||||
SETWGROUPS = 289,
|
||||
GETWGROUPS = 290,
|
||||
MKFIFO_EXTENDED = 291,
|
||||
MKDIR_EXTENDED = 292,
|
||||
IDENTITYSVC = 293,
|
||||
SHARED_REGION_CHECK_NP = 294,
|
||||
VM_PRESSURE_MONITOR = 296,
|
||||
PSYNCH_RW_LONGRDLOCK = 297,
|
||||
PSYNCH_RW_YIELDWRLOCK = 298,
|
||||
PSYNCH_RW_DOWNGRADE = 299,
|
||||
PSYNCH_RW_UPGRADE = 300,
|
||||
PSYNCH_MUTEXWAIT = 301,
|
||||
PSYNCH_MUTEXDROP = 302,
|
||||
PSYNCH_CVBROAD = 303,
|
||||
PSYNCH_CVSIGNAL = 304,
|
||||
PSYNCH_CVWAIT = 305,
|
||||
PSYNCH_RW_RDLOCK = 306,
|
||||
PSYNCH_RW_WRLOCK = 307,
|
||||
PSYNCH_RW_UNLOCK = 308,
|
||||
PSYNCH_RW_UNLOCK2 = 309,
|
||||
GETSID = 310,
|
||||
SETTID_WITH_PID = 311,
|
||||
PSYNCH_CVCLRPREPOST = 312,
|
||||
AIO_FSYNC = 313,
|
||||
AIO_RETURN = 314,
|
||||
AIO_SUSPEND = 315,
|
||||
AIO_CANCEL = 316,
|
||||
AIO_ERROR = 317,
|
||||
AIO_READ = 318,
|
||||
AIO_WRITE = 319,
|
||||
LIO_LISTIO = 320,
|
||||
IOPOLICYSYS = 322,
|
||||
PROCESS_POLICY = 323,
|
||||
MLOCKALL = 324,
|
||||
MUNLOCKALL = 325,
|
||||
ISSETUGID = 327,
|
||||
PTHREAD_KILL = 328,
|
||||
PTHREAD_SIGMASK = 329,
|
||||
SIGWAIT = 330,
|
||||
DISABLE_THREADSIGNAL = 331,
|
||||
PTHREAD_MARKCANCEL = 332,
|
||||
PTHREAD_CANCELED = 333,
|
||||
SEMWAIT_SIGNAL = 334,
|
||||
PROC_INFO = 336,
|
||||
SENDFILE = 337,
|
||||
STAT64 = 338,
|
||||
FSTAT64 = 339,
|
||||
LSTAT64 = 340,
|
||||
STAT64_EXTENDED = 341,
|
||||
LSTAT64_EXTENDED = 342,
|
||||
FSTAT64_EXTENDED = 343,
|
||||
GETDIRENTRIES64 = 344,
|
||||
STATFS64 = 345,
|
||||
FSTATFS64 = 346,
|
||||
GETFSSTAT64 = 347,
|
||||
PTHREAD_CHDIR = 348,
|
||||
PTHREAD_FCHDIR = 349,
|
||||
AUDIT = 350,
|
||||
AUDITON = 351,
|
||||
GETAUID = 353,
|
||||
SETAUID = 354,
|
||||
GETAUDIT_ADDR = 357,
|
||||
SETAUDIT_ADDR = 358,
|
||||
AUDITCTL = 359,
|
||||
BSDTHREAD_CREATE = 360,
|
||||
BSDTHREAD_TERMINATE = 361,
|
||||
KQUEUE = 362,
|
||||
KEVENT = 363,
|
||||
LCHOWN = 364,
|
||||
BSDTHREAD_REGISTER = 366,
|
||||
WORKQ_OPEN = 367,
|
||||
WORKQ_KERNRETURN = 368,
|
||||
KEVENT64 = 369,
|
||||
THREAD_SELFID = 372,
|
||||
LEDGER = 373,
|
||||
KEVENT_QOS = 374,
|
||||
KEVENT_ID = 375,
|
||||
MAC_EXECVE = 380,
|
||||
MAC_SYSCALL = 381,
|
||||
MAC_GET_FILE = 382,
|
||||
MAC_SET_FILE = 383,
|
||||
MAC_GET_LINK = 384,
|
||||
MAC_SET_LINK = 385,
|
||||
MAC_GET_PROC = 386,
|
||||
MAC_SET_PROC = 387,
|
||||
MAC_GET_FD = 388,
|
||||
MAC_SET_FD = 389,
|
||||
MAC_GET_PID = 390,
|
||||
PSELECT = 394,
|
||||
PSELECT_NOCANCEL = 395,
|
||||
READ_NOCANCEL = 396,
|
||||
WRITE_NOCANCEL = 397,
|
||||
OPEN_NOCANCEL = 398,
|
||||
CLOSE_NOCANCEL = 399,
|
||||
WAIT4_NOCANCEL = 400,
|
||||
RECVMSG_NOCANCEL = 401,
|
||||
SENDMSG_NOCANCEL = 402,
|
||||
RECVFROM_NOCANCEL = 403,
|
||||
ACCEPT_NOCANCEL = 404,
|
||||
MSYNC_NOCANCEL = 405,
|
||||
FCNTL_NOCANCEL = 406,
|
||||
SELECT_NOCANCEL = 407,
|
||||
FSYNC_NOCANCEL = 408,
|
||||
CONNECT_NOCANCEL = 409,
|
||||
SIGSUSPEND_NOCANCEL = 410,
|
||||
READV_NOCANCEL = 411,
|
||||
WRITEV_NOCANCEL = 412,
|
||||
SENDTO_NOCANCEL = 413,
|
||||
PREAD_NOCANCEL = 414,
|
||||
PWRITE_NOCANCEL = 415,
|
||||
WAITID_NOCANCEL = 416,
|
||||
POLL_NOCANCEL = 417,
|
||||
MSGSND_NOCANCEL = 418,
|
||||
MSGRCV_NOCANCEL = 419,
|
||||
SEM_WAIT_NOCANCEL = 420,
|
||||
AIO_SUSPEND_NOCANCEL = 421,
|
||||
SIGWAIT_NOCANCEL = 422,
|
||||
SEMWAIT_SIGNAL_NOCANCEL = 423,
|
||||
MAC_MOUNT = 424,
|
||||
MAC_GET_MOUNT = 425,
|
||||
MAC_GETFSSTAT = 426,
|
||||
FSGETPATH = 427,
|
||||
AUDIT_SESSION_SELF = 428,
|
||||
AUDIT_SESSION_JOIN = 429,
|
||||
FILEPORT_MAKEPORT = 430,
|
||||
FILEPORT_MAKEFD = 431,
|
||||
AUDIT_SESSION_PORT = 432,
|
||||
PID_SUSPEND = 433,
|
||||
PID_RESUME = 434,
|
||||
PID_HIBERNATE = 435,
|
||||
PID_SHUTDOWN_SOCKETS = 436,
|
||||
KAS_INFO = 439,
|
||||
MEMORYSTATUS_CONTROL = 440,
|
||||
GUARDED_OPEN_NP = 441,
|
||||
GUARDED_CLOSE_NP = 442,
|
||||
GUARDED_KQUEUE_NP = 443,
|
||||
CHANGE_FDGUARD_NP = 444,
|
||||
USRCTL = 445,
|
||||
PROC_RLIMIT_CONTROL = 446,
|
||||
CONNECTX = 447,
|
||||
DISCONNECTX = 448,
|
||||
PEELOFF = 449,
|
||||
SOCKET_DELEGATE = 450,
|
||||
TELEMETRY = 451,
|
||||
PROC_UUID_POLICY = 452,
|
||||
MEMORYSTATUS_GET_LEVEL = 453,
|
||||
SYSTEM_OVERRIDE = 454,
|
||||
VFS_PURGE = 455,
|
||||
SFI_CTL = 456,
|
||||
SFI_PIDCTL = 457,
|
||||
COALITION = 458,
|
||||
COALITION_INFO = 459,
|
||||
NECP_MATCH_POLICY = 460,
|
||||
GETATTRLISTBULK = 461,
|
||||
CLONEFILEAT = 462,
|
||||
OPENAT = 463,
|
||||
OPENAT_NOCANCEL = 464,
|
||||
RENAMEAT = 465,
|
||||
FACCESSAT = 466,
|
||||
FCHMODAT = 467,
|
||||
FCHOWNAT = 468,
|
||||
FSTATAT = 469,
|
||||
FSTATAT64 = 470,
|
||||
LINKAT = 471,
|
||||
UNLINKAT = 472,
|
||||
READLINKAT = 473,
|
||||
SYMLINKAT = 474,
|
||||
MKDIRAT = 475,
|
||||
GETATTRLISTAT = 476,
|
||||
PROC_TRACE_LOG = 477,
|
||||
BSDTHREAD_CTL = 478,
|
||||
OPENBYID_NP = 479,
|
||||
RECVMSG_X = 480,
|
||||
SENDMSG_X = 481,
|
||||
THREAD_SELFUSAGE = 482,
|
||||
CSRCTL = 483,
|
||||
GUARDED_OPEN_DPROTECTED_NP = 484,
|
||||
GUARDED_WRITE_NP = 485,
|
||||
GUARDED_PWRITE_NP = 486,
|
||||
GUARDED_WRITEV_NP = 487,
|
||||
RENAMEATX_NP = 488,
|
||||
MREMAP_ENCRYPTED = 489,
|
||||
NETAGENT_TRIGGER = 490,
|
||||
STACK_SNAPSHOT_WITH_CONFIG = 491,
|
||||
MICROSTACKSHOT = 492,
|
||||
GRAB_PGO_DATA = 493,
|
||||
PERSONA = 494,
|
||||
MACH_EVENTLINK_SIGNAL = 496,
|
||||
MACH_EVENTLINK_WAIT_UNTIL = 497,
|
||||
MACH_EVENTLINK_SIGNAL_WAIT_UNTIL = 498,
|
||||
WORK_INTERVAL_CTL = 499,
|
||||
GETENTROPY = 500,
|
||||
NECP_CLIENT_ACTION = 502,
|
||||
NEXUS_OPEN = 503,
|
||||
NEXUS_REGISTER = 504,
|
||||
NEXUS_DEREGISTER = 505,
|
||||
NEXUS_CREATE = 506,
|
||||
NEXUS_DESTROY = 507,
|
||||
NEXUS_GET_OPT = 508,
|
||||
NEXUS_SET_OPT = 509,
|
||||
CHANNEL_OPEN = 510,
|
||||
CHANNEL_GET_INFO = 511,
|
||||
CHANNEL_SYNC = 512,
|
||||
CHANNEL_GET_OPT = 513,
|
||||
CHANNEL_SET_OPT = 514,
|
||||
ULOCK_WAIT = 515,
|
||||
ULOCK_WAKE = 516,
|
||||
FCLONEFILEAT = 517,
|
||||
FS_SNAPSHOT = 518,
|
||||
TERMINATE_WITH_PAYLOAD = 520,
|
||||
ABORT_WITH_PAYLOAD = 521,
|
||||
NECP_SESSION_ACTION = 523,
|
||||
SETATTRLISTAT = 524,
|
||||
NET_QOS_GUIDELINE = 525,
|
||||
FMOUNT = 526,
|
||||
NTP_ADJTIME = 527,
|
||||
NTP_GETTIME = 528,
|
||||
OS_FAULT_WITH_PAYLOAD = 529,
|
||||
KQUEUE_WORKLOOP_CTL = 530,
|
||||
MACH_BRIDGE_REMOTE_TIME = 531,
|
||||
COALITION_LEDGER = 532,
|
||||
LOG_DATA = 533,
|
||||
MEMORYSTATUS_AVAILABLE_MEMORY = 534,
|
||||
OBJC_BP_ASSIST_CFG_NP = 535,
|
||||
SHARED_REGION_MAP_AND_SLIDE_2_NP = 536,
|
||||
PIVOT_ROOT = 537,
|
||||
TASK_INSPECT_FOR_PID = 538,
|
||||
TASK_READ_FOR_PID = 539,
|
||||
PREADV = 540,
|
||||
PWRITEV = 541,
|
||||
PREADV_NOCANCEL = 542,
|
||||
PWRITEV_NOCANCEL = 543,
|
||||
ULOCK_WAIT2 = 544,
|
||||
PROC_INFO_EXTENDED_ID = 545,
|
||||
TRACKER_ACTION = 546,
|
||||
DEBUG_SYSCALL_REJECT = 547,
|
||||
DEBUG_SYSCALL_REJECT_CONFIG = 548,
|
||||
GRAFTDMG = 549,
|
||||
MAP_WITH_LINKING_NP = 550,
|
||||
FREADLINK = 551,
|
||||
RECORD_SYSTEM_EVENT = 552,
|
||||
MKFIFOAT = 553,
|
||||
MKNODAT = 554,
|
||||
UNGRAFTDMG = 555,
|
||||
COALITION_POLICY_SET = 556,
|
||||
COALITION_POLICY_GET = 557,
|
||||
}
|
||||
}
|
||||
@@ -1,11 +0,0 @@
|
||||
FRIDA_1.0 {
|
||||
local:
|
||||
*;
|
||||
};
|
||||
|
||||
GLIBC_2.2.5 {
|
||||
local:
|
||||
fopen*;
|
||||
fseeko*;
|
||||
ftello*;
|
||||
} FRIDA_1.0;
|
||||
@@ -144,8 +144,10 @@ frida_gadget_environment_ensure_debugger_breakpoints_only (void)
|
||||
|
||||
interceptor = gum_interceptor_obtain ();
|
||||
|
||||
gum_interceptor_attach (interceptor, exceptions_set, frida_dont_steal_my_breakpoints, NULL);
|
||||
gum_interceptor_attach (interceptor, exceptions_swap, frida_dont_steal_my_breakpoints, NULL);
|
||||
gum_interceptor_attach (interceptor, exceptions_set, frida_dont_steal_my_breakpoints,
|
||||
NULL, GUM_ATTACH_FLAGS_NONE);
|
||||
gum_interceptor_attach (interceptor, exceptions_swap, frida_dont_steal_my_breakpoints,
|
||||
NULL, GUM_ATTACH_FLAGS_NONE);
|
||||
|
||||
g_object_unref (interceptor);
|
||||
}
|
||||
|
||||
@@ -9,9 +9,7 @@
|
||||
# include <signal.h>
|
||||
#endif
|
||||
#include <gumjs/gumscriptbackend.h>
|
||||
#if defined (HAVE_GIOAPPLE)
|
||||
# include <gioapple.h>
|
||||
#elif defined (HAVE_GIOOPENSSL)
|
||||
#ifdef HAVE_GIOOPENSSL
|
||||
# include <gioopenssl.h>
|
||||
#endif
|
||||
|
||||
@@ -93,9 +91,7 @@ frida_gadget_environment_init (void)
|
||||
|
||||
g_thread_set_garbage_handler (_frida_gadget_on_pending_thread_garbage, NULL);
|
||||
|
||||
#if defined (HAVE_GIOAPPLE)
|
||||
g_io_module_apple_register ();
|
||||
#elif defined (HAVE_GIOOPENSSL)
|
||||
#ifdef HAVE_GIOOPENSSL
|
||||
g_io_module_openssl_register ();
|
||||
#endif
|
||||
|
||||
@@ -122,8 +118,6 @@ frida_gadget_environment_deinit (void)
|
||||
|
||||
g_assert (worker_loop != NULL);
|
||||
|
||||
frida_libc_shim_prepare_to_deinit ();
|
||||
|
||||
source = g_idle_source_new ();
|
||||
g_source_set_priority (source, G_PRIORITY_LOW);
|
||||
g_source_set_callback (source, stop_worker_loop, NULL, NULL);
|
||||
|
||||
@@ -1810,11 +1810,6 @@ namespace Frida.Gadget {
|
||||
throw new Error.NOT_SUPPORTED ("Not possible when embedded");
|
||||
}
|
||||
|
||||
public async void enable_spawn_gating_with_options (HashTable<string, Variant> options,
|
||||
Cancellable? cancellable) throws Error, IOError {
|
||||
throw new Error.NOT_SUPPORTED ("Not possible when embedded");
|
||||
}
|
||||
|
||||
public async void disable_spawn_gating (Cancellable? cancellable) throws Error, IOError {
|
||||
throw new Error.NOT_SUPPORTED ("Not possible when embedded");
|
||||
}
|
||||
|
||||
@@ -45,7 +45,7 @@ elif host_os_family == 'darwin'
|
||||
extra_link_args += '-Wl,-exported_symbols_list,' + meson.current_source_dir() / symlist
|
||||
extra_link_depends += symlist
|
||||
else
|
||||
symscript = (libc == 'glibc') ? 'frida-gadget-glibc.version' : 'frida-gadget.version'
|
||||
symscript = 'frida-gadget.version'
|
||||
extra_link_args += '-Wl,--version-script,' + meson.current_source_dir() / symscript
|
||||
extra_link_depends += symscript
|
||||
endif
|
||||
@@ -55,10 +55,6 @@ if host_os_family in ['linux', 'qnx']
|
||||
extra_link_args += ['-Wl,-Bsymbolic']
|
||||
endif
|
||||
|
||||
if host_is_prospero
|
||||
extra_link_args += [prospero_crt_link_args, '-Wl,--defsym=main=0']
|
||||
endif
|
||||
|
||||
raw_gadget = shared_library('frida-gadget-raw', gadget_sources,
|
||||
name_prefix: 'lib',
|
||||
vala_args: [base_vala_args, payload_vala_args, extra_vala_args],
|
||||
|
||||
+2
-4
@@ -4,12 +4,10 @@ endif
|
||||
subdir('base')
|
||||
subdir('netif')
|
||||
subdir('pipe')
|
||||
if have_in_tree_payloads
|
||||
subdir('payload')
|
||||
endif
|
||||
subdir('payload')
|
||||
if have_local_backend
|
||||
subdir('agent')
|
||||
endif
|
||||
if have_in_tree_payloads and build_gadget
|
||||
if build_gadget
|
||||
subdir('gadget')
|
||||
endif
|
||||
@@ -179,18 +179,6 @@ namespace Frida {
|
||||
yield script_engine.load_script (script_id);
|
||||
}
|
||||
|
||||
public async void interrupt_script (AgentScriptId script_id, Cancellable? cancellable) throws Error, IOError {
|
||||
check_open ();
|
||||
|
||||
script_engine.interrupt_script (script_id);
|
||||
}
|
||||
|
||||
public async void terminate_script (AgentScriptId script_id, Cancellable? cancellable) throws Error, IOError {
|
||||
check_open ();
|
||||
|
||||
yield script_engine.terminate_script (script_id);
|
||||
}
|
||||
|
||||
public async void eternalize_script (AgentScriptId script_id, Cancellable? cancellable) throws Error, IOError {
|
||||
check_open ();
|
||||
|
||||
|
||||
@@ -35,21 +35,15 @@ namespace Frida {
|
||||
interceptor.attach ((void *) Gum.Process.find_module_by_name ("kernel32.dll").find_export_by_name ("ExitProcess"),
|
||||
listener);
|
||||
#else
|
||||
var libc = Gum.Process.get_libc_module ();
|
||||
const string[] apis = {
|
||||
"exit",
|
||||
"_exit",
|
||||
"abort",
|
||||
};
|
||||
#if PROSPERO
|
||||
foreach (var symbol in apis) {
|
||||
interceptor.attach ((void *) Gum.Module.find_global_export_by_name (symbol), listener);
|
||||
}
|
||||
#else
|
||||
var libc = Gum.Process.get_libc_module ();
|
||||
foreach (var symbol in apis) {
|
||||
interceptor.attach ((void *) libc.find_export_by_name (symbol), listener);
|
||||
}
|
||||
#endif
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
@@ -65,9 +65,7 @@ namespace Frida {
|
||||
if (runtime != null) {
|
||||
var set_argv0 = (void *) runtime.find_export_by_name ("_Z27android_os_Process_setArgV0P7_JNIEnvP8_jobjectP8_jstring");
|
||||
if (set_argv0 != null) {
|
||||
var set_argv0_options = Gum.AttachOptions ();
|
||||
set_argv0_options.listener_function_data = (void *) HookId.SET_ARGV0;
|
||||
interceptor.attach (set_argv0, listener, set_argv0_options);
|
||||
interceptor.attach (set_argv0, listener, (void *) HookId.SET_ARGV0);
|
||||
child_recovery_behavior = DEFERRED_UNTIL_SET_ARGV0;
|
||||
}
|
||||
}
|
||||
@@ -75,11 +73,8 @@ namespace Frida {
|
||||
var selinux = Gum.Process.find_module_by_name ("libselinux.so");
|
||||
if (selinux != null) {
|
||||
var setcontext = (void *) selinux.find_export_by_name ("selinux_android_setcontext");
|
||||
if (setcontext != null) {
|
||||
var setcontext_options = Gum.AttachOptions ();
|
||||
setcontext_options.listener_function_data = (void *) HookId.SET_CTX;
|
||||
interceptor.attach (setcontext, listener, setcontext_options);
|
||||
}
|
||||
if (setcontext != null)
|
||||
interceptor.attach (setcontext, listener, (void *) HookId.SET_CTX);
|
||||
}
|
||||
}
|
||||
} catch (FileError e) {
|
||||
@@ -87,9 +82,7 @@ namespace Frida {
|
||||
}
|
||||
#endif
|
||||
|
||||
var fork_options = Gum.AttachOptions ();
|
||||
fork_options.listener_function_data = (void *) HookId.FORK;
|
||||
interceptor.attach (fork_impl, listener, fork_options);
|
||||
interceptor.attach (fork_impl, listener, (void *) HookId.FORK);
|
||||
interceptor.replace (vfork_impl, fork_impl);
|
||||
}
|
||||
|
||||
|
||||
+35
-422
@@ -10,7 +10,6 @@
|
||||
# include <assert.h>
|
||||
# include <fcntl.h>
|
||||
# include <unistd.h>
|
||||
# include <wchar.h>
|
||||
#endif
|
||||
#if defined (HAVE_DARWIN)
|
||||
# include <sys/attr.h>
|
||||
@@ -24,51 +23,23 @@
|
||||
# include <xlocale.h>
|
||||
#endif
|
||||
|
||||
#undef __srget
|
||||
#undef feof
|
||||
#undef ferror
|
||||
#undef fgetwc
|
||||
#undef fileno
|
||||
#undef fopen
|
||||
#undef fopen64
|
||||
#undef fputwc
|
||||
#undef fseek
|
||||
#undef fseeko
|
||||
#undef fseeko64
|
||||
#undef ftell
|
||||
#undef ftello
|
||||
#undef ftello64
|
||||
#undef getc
|
||||
#undef getc_unlocked
|
||||
#undef getwc
|
||||
#undef memcpy
|
||||
#undef putc
|
||||
#undef putchar
|
||||
#undef putwc
|
||||
#undef setbuf
|
||||
#undef setbuffer
|
||||
#undef setlinebuf
|
||||
#undef snprintf
|
||||
#undef sprintf
|
||||
#undef stderr
|
||||
#undef stdin
|
||||
#undef stdout
|
||||
#undef ungetc
|
||||
#undef ungetwc
|
||||
#undef vsnprintf
|
||||
|
||||
#ifdef HAVE_MUSL
|
||||
# define FRIDA_STDIO_OPAQUE_FILE 1
|
||||
#endif
|
||||
|
||||
static gboolean frida_deinit_expected = FALSE;
|
||||
|
||||
void
|
||||
frida_libc_shim_prepare_to_deinit (void)
|
||||
{
|
||||
frida_deinit_expected = TRUE;
|
||||
}
|
||||
|
||||
#if defined (HAVE_WINDOWS) || defined (HAVE_ASAN)
|
||||
|
||||
void
|
||||
@@ -99,9 +70,6 @@ __attribute__ ((destructor)) static
|
||||
void
|
||||
frida_libc_shim_deinit (void)
|
||||
{
|
||||
if (!frida_deinit_expected)
|
||||
return;
|
||||
|
||||
# ifdef HAVE_ASAN
|
||||
gum_deinit ();
|
||||
# else
|
||||
@@ -166,18 +134,16 @@ struct _FridaFile
|
||||
int err;
|
||||
|
||||
guint8 * rbuf;
|
||||
gboolean owns_rbuf;
|
||||
size_t rcap;
|
||||
size_t rpos;
|
||||
size_t rlen;
|
||||
|
||||
guint8 * wbuf;
|
||||
gboolean owns_wbuf;
|
||||
size_t wcap;
|
||||
size_t wlen;
|
||||
|
||||
guint8 ungot_buf[8];
|
||||
guint ungot_len;
|
||||
int ungot;
|
||||
gboolean has_ungot;
|
||||
};
|
||||
|
||||
struct _FridaFileHandle
|
||||
@@ -205,17 +171,12 @@ struct _FridaDir
|
||||
|
||||
#endif
|
||||
|
||||
static FILE * frida_fopen_impl (const char * pathname, const char * mode);
|
||||
static int frida_fseek_impl (FILE * stream, off_t offset, int whence);
|
||||
static off_t frida_ftell_impl (FILE * stream);
|
||||
|
||||
static void frida_stdio_register_stream (FILE * stream);
|
||||
static void frida_stdio_unregister_stream (FILE * stream);
|
||||
#ifdef HAVE_FRIDA_DIR
|
||||
static void frida_stdio_register_dir (DIR * dirp);
|
||||
static void frida_stdio_unregister_dir (DIR * dirp);
|
||||
#endif
|
||||
static void frida_stdio_ensure_registries (void);
|
||||
static void frida_flush_all_streams (int * result);
|
||||
|
||||
static FridaFile * frida_file_get_impl (FILE * stream);
|
||||
@@ -232,8 +193,6 @@ static void frida_parse_fopen_mode (const char * mode, int * oflags);
|
||||
|
||||
static int frida_write_formatted_to_fd (int fd, const char * format, va_list args);
|
||||
|
||||
static gboolean frida_utf8_expected_len (guint8 first, guint * out_len);
|
||||
|
||||
#ifdef HAVE_FRIDA_DIR
|
||||
static FridaDir * frida_dir_get_impl (DIR * dirp);
|
||||
static DIR * frida_dir_wrap (FridaDir * impl);
|
||||
@@ -303,7 +262,10 @@ frida_libc_shim_init (void)
|
||||
|
||||
G_LOCK (frida_stdio);
|
||||
|
||||
frida_stdio_ensure_registries ();
|
||||
frida_streams = g_hash_table_new (g_direct_hash, g_direct_equal);
|
||||
#ifdef HAVE_FRIDA_DIR
|
||||
frida_dirs = g_hash_table_new (g_direct_hash, g_direct_equal);
|
||||
#endif
|
||||
|
||||
G_UNLOCK (frida_stdio);
|
||||
|
||||
@@ -355,9 +317,6 @@ frida_libc_shim_deinit (void)
|
||||
|
||||
fflush (NULL);
|
||||
|
||||
if (!frida_deinit_expected)
|
||||
return;
|
||||
|
||||
G_LOCK (frida_stdio);
|
||||
|
||||
g_hash_table_iter_init (&iter, frida_streams);
|
||||
@@ -637,7 +596,7 @@ __vsnprintf_chk (char * string, size_t size, int flags, size_t len, const char *
|
||||
return gum_vsnprintf (string, size, format, args);
|
||||
}
|
||||
|
||||
#if defined (HAVE_XLOCALE_H) && !defined (HAVE_PROSPERO)
|
||||
#ifdef HAVE_XLOCALE_H
|
||||
|
||||
G_GNUC_INTERNAL int
|
||||
sprintf_l (char * string, locale_t loc, const char * format, ...)
|
||||
@@ -680,34 +639,8 @@ asprintf_l (char ** ret, locale_t loc, const char * format, ...)
|
||||
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_GLIBC
|
||||
|
||||
G_GNUC_INTERNAL FILE *
|
||||
frida_fopen_glibc_225 (const char * pathname, const char * mode)
|
||||
{
|
||||
return frida_fopen_impl (pathname, mode);
|
||||
}
|
||||
__asm__ (".symver frida_fopen_glibc_225,fopen@@GLIBC_2.2.5");
|
||||
|
||||
G_GNUC_INTERNAL FILE *
|
||||
frida_fopen64_glibc_225 (const char * pathname, const char * mode)
|
||||
{
|
||||
return frida_fopen_impl (pathname, mode);
|
||||
}
|
||||
__asm__ (".symver frida_fopen64_glibc_225,fopen64@@GLIBC_2.2.5");
|
||||
|
||||
#else
|
||||
|
||||
G_GNUC_INTERNAL FILE *
|
||||
fopen (const char * pathname, const char * mode)
|
||||
{
|
||||
return frida_fopen_impl (pathname, mode);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
static FILE *
|
||||
frida_fopen_impl (const char * pathname, const char * mode)
|
||||
{
|
||||
FILE * result;
|
||||
int oflags, fd;
|
||||
@@ -781,17 +714,8 @@ setvbuf (FILE * stream, char * buf, int mode, size_t size)
|
||||
|
||||
if (mode == _IONBF)
|
||||
{
|
||||
if (f->owns_rbuf)
|
||||
g_clear_pointer (&f->rbuf, g_free);
|
||||
else
|
||||
f->rbuf = NULL;
|
||||
f->owns_rbuf = FALSE;
|
||||
|
||||
if (f->owns_wbuf)
|
||||
g_clear_pointer (&f->wbuf, g_free);
|
||||
else
|
||||
f->wbuf = NULL;
|
||||
f->owns_wbuf = FALSE;
|
||||
g_clear_pointer (&f->rbuf, g_free);
|
||||
g_clear_pointer (&f->wbuf, g_free);
|
||||
|
||||
f->rcap = 0;
|
||||
f->wcap = 0;
|
||||
@@ -803,40 +727,13 @@ setvbuf (FILE * stream, char * buf, int mode, size_t size)
|
||||
}
|
||||
|
||||
if (size == 0)
|
||||
size = BUFSIZ;
|
||||
|
||||
if (!f->owns_rbuf)
|
||||
{
|
||||
f->rbuf = NULL;
|
||||
f->rcap = 0;
|
||||
}
|
||||
size = FRIDA_STDIO_BUFSIZE;
|
||||
|
||||
f->rbuf = g_realloc (f->rbuf, size);
|
||||
f->owns_rbuf = TRUE;
|
||||
f->wbuf = g_realloc (f->wbuf, size);
|
||||
|
||||
f->rcap = size;
|
||||
|
||||
if (buf != NULL)
|
||||
{
|
||||
if (f->owns_wbuf)
|
||||
g_clear_pointer (&f->wbuf, g_free);
|
||||
|
||||
f->wbuf = (guint8 *) buf;
|
||||
f->owns_wbuf = FALSE;
|
||||
f->wcap = size;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (!f->owns_wbuf)
|
||||
{
|
||||
f->wbuf = NULL;
|
||||
f->wcap = 0;
|
||||
}
|
||||
|
||||
f->wbuf = g_realloc (f->wbuf, size);
|
||||
f->owns_wbuf = TRUE;
|
||||
f->wcap = size;
|
||||
}
|
||||
|
||||
f->wcap = size;
|
||||
f->rpos = 0;
|
||||
f->rlen = 0;
|
||||
f->wlen = 0;
|
||||
@@ -844,39 +741,6 @@ setvbuf (FILE * stream, char * buf, int mode, size_t size)
|
||||
return 0;
|
||||
}
|
||||
|
||||
G_GNUC_INTERNAL void
|
||||
setbuf (FILE * stream, char * buf)
|
||||
{
|
||||
if (buf == NULL)
|
||||
(void) setvbuf (stream, NULL, _IONBF, 0);
|
||||
else
|
||||
(void) setvbuf (stream, buf, _IOFBF, BUFSIZ);
|
||||
}
|
||||
|
||||
#if defined (HAVE_DARWIN) || defined (HAVE_ANDROID) || defined (HAVE_FREEBSD)
|
||||
G_GNUC_INTERNAL int
|
||||
setlinebuf (FILE * stream)
|
||||
{
|
||||
return setvbuf (stream, NULL, _IOLBF, 0);
|
||||
}
|
||||
#else
|
||||
G_GNUC_INTERNAL void
|
||||
setlinebuf (FILE * stream)
|
||||
{
|
||||
setvbuf (stream, NULL, _IOLBF, 0);
|
||||
}
|
||||
#endif
|
||||
|
||||
G_GNUC_INTERNAL void
|
||||
#if defined (HAVE_DARWIN) || defined (HAVE_ANDROID) || defined (HAVE_FREEBSD)
|
||||
setbuffer (FILE * stream, char * buf, int size)
|
||||
#else
|
||||
setbuffer (FILE * stream, char * buf, size_t size)
|
||||
#endif
|
||||
{
|
||||
(void) setvbuf (stream, buf, (buf != NULL) ? _IOFBF : _IONBF, size);
|
||||
}
|
||||
|
||||
G_GNUC_INTERNAL int
|
||||
fflush (FILE * stream)
|
||||
{
|
||||
@@ -937,8 +801,11 @@ getc_unlocked (FILE * stream)
|
||||
|
||||
f = frida_file_get_impl (stream);
|
||||
|
||||
if (f->ungot_len != 0)
|
||||
return f->ungot_buf[--f->ungot_len];
|
||||
if (f->has_ungot)
|
||||
{
|
||||
f->has_ungot = FALSE;
|
||||
return f->ungot;
|
||||
}
|
||||
|
||||
if (f->buf_mode == _IONBF)
|
||||
{
|
||||
@@ -979,64 +846,6 @@ getc (FILE * stream)
|
||||
return getc_unlocked (stream);
|
||||
}
|
||||
|
||||
G_GNUC_INTERNAL int
|
||||
__srget (FILE * stream)
|
||||
{
|
||||
return getc_unlocked (stream);
|
||||
}
|
||||
|
||||
G_GNUC_INTERNAL wint_t
|
||||
getwc (FILE * stream)
|
||||
{
|
||||
return fgetwc (stream);
|
||||
}
|
||||
|
||||
G_GNUC_INTERNAL wint_t
|
||||
fgetwc (FILE * stream)
|
||||
{
|
||||
char bytes[4];
|
||||
guint need, have;
|
||||
int c;
|
||||
gunichar ch;
|
||||
|
||||
c = getc_unlocked (stream);
|
||||
if (c == EOF)
|
||||
return WEOF;
|
||||
|
||||
bytes[0] = c;
|
||||
|
||||
if (!frida_utf8_expected_len (bytes[0], &need))
|
||||
{
|
||||
errno = EILSEQ;
|
||||
frida_file_get_impl (stream)->err = errno;
|
||||
return WEOF;
|
||||
}
|
||||
|
||||
have = 1;
|
||||
while (have != need)
|
||||
{
|
||||
c = getc_unlocked (stream);
|
||||
if (c == EOF)
|
||||
{
|
||||
errno = EILSEQ;
|
||||
frida_file_get_impl (stream)->err = errno;
|
||||
return WEOF;
|
||||
}
|
||||
|
||||
bytes[have++] = c;
|
||||
}
|
||||
|
||||
ch = g_utf8_get_char_validated (bytes, (gssize) need);
|
||||
if (ch == (gunichar) -1 || ch == (gunichar) -2)
|
||||
{
|
||||
errno = EILSEQ;
|
||||
frida_file_get_impl (stream)->err = errno;
|
||||
return WEOF;
|
||||
}
|
||||
|
||||
return (wint_t) ch;
|
||||
}
|
||||
|
||||
G_GNUC_INTERNAL int
|
||||
ungetc (int c, FILE * stream)
|
||||
{
|
||||
@@ -1047,46 +856,16 @@ ungetc (int c, FILE * stream)
|
||||
if (c == EOF)
|
||||
return EOF;
|
||||
|
||||
if (f->ungot_len == G_N_ELEMENTS (f->ungot_buf))
|
||||
if (f->has_ungot)
|
||||
return EOF;
|
||||
|
||||
f->ungot_buf[f->ungot_len++] = c;
|
||||
f->ungot = c;
|
||||
f->has_ungot = TRUE;
|
||||
f->eof = FALSE;
|
||||
|
||||
return c;
|
||||
}
|
||||
|
||||
G_GNUC_INTERNAL wint_t
|
||||
ungetwc (wint_t wc, FILE * stream)
|
||||
{
|
||||
FridaFile * f;
|
||||
char tmp[4];
|
||||
int len;
|
||||
int i;
|
||||
|
||||
if (wc == WEOF)
|
||||
return WEOF;
|
||||
|
||||
f = frida_file_get_impl (stream);
|
||||
|
||||
len = g_unichar_to_utf8 ((gunichar) wc, tmp);
|
||||
if (len <= 0 || len > 4)
|
||||
{
|
||||
errno = EILSEQ;
|
||||
f->err = errno;
|
||||
return WEOF;
|
||||
}
|
||||
|
||||
if (f->ungot_len + len > G_N_ELEMENTS (f->ungot_buf))
|
||||
return WEOF;
|
||||
|
||||
for (i = 0; i != len; i++)
|
||||
f->ungot_buf[f->ungot_len++] = tmp[i];
|
||||
|
||||
f->eof = FALSE;
|
||||
return wc;
|
||||
}
|
||||
|
||||
G_GNUC_INTERNAL size_t
|
||||
fread (void * ptr, size_t size, size_t nmemb, FILE * stream)
|
||||
{
|
||||
@@ -1105,9 +884,10 @@ fread (void * ptr, size_t size, size_t nmemb, FILE * stream)
|
||||
|
||||
while (got != want)
|
||||
{
|
||||
if (f->ungot_len != 0)
|
||||
if (f->has_ungot)
|
||||
{
|
||||
out[got++] = f->ungot_buf[--f->ungot_len];
|
||||
out[got++] = (guint8) f->ungot;
|
||||
f->has_ungot = FALSE;
|
||||
continue;
|
||||
}
|
||||
|
||||
@@ -1226,12 +1006,6 @@ fwrite (const void * ptr, size_t size, size_t nmemb, FILE * stream)
|
||||
return off / size;
|
||||
}
|
||||
|
||||
G_GNUC_INTERNAL int
|
||||
putc (int c, FILE * stream)
|
||||
{
|
||||
return fputc (c, stream);
|
||||
}
|
||||
|
||||
G_GNUC_INTERNAL int
|
||||
fputc (int c, FILE * stream)
|
||||
{
|
||||
@@ -1245,37 +1019,6 @@ fputc (int c, FILE * stream)
|
||||
return ch;
|
||||
}
|
||||
|
||||
G_GNUC_INTERNAL wint_t
|
||||
putwc (wchar_t wc, FILE * stream)
|
||||
{
|
||||
return fputwc (wc, stream);
|
||||
}
|
||||
|
||||
G_GNUC_INTERNAL wint_t
|
||||
fputwc (wchar_t wc, FILE * stream)
|
||||
{
|
||||
char tmp[4];
|
||||
int len;
|
||||
size_t n;
|
||||
|
||||
if (wc == WEOF)
|
||||
return WEOF;
|
||||
|
||||
len = g_unichar_to_utf8 ((gunichar) wc, tmp);
|
||||
if (len <= 0 || len > 4)
|
||||
{
|
||||
errno = EILSEQ;
|
||||
frida_file_get_impl (stream)->err = errno;
|
||||
return WEOF;
|
||||
}
|
||||
|
||||
n = fwrite (tmp, 1, len, stream);
|
||||
if (n != len)
|
||||
return WEOF;
|
||||
|
||||
return (wint_t) wc;
|
||||
}
|
||||
|
||||
G_GNUC_INTERNAL int
|
||||
fputs (const char * s, FILE * stream)
|
||||
{
|
||||
@@ -1319,84 +1062,6 @@ fgets (char * s, int size, FILE * stream)
|
||||
|
||||
G_GNUC_INTERNAL int
|
||||
fseek (FILE * stream, long offset, int whence)
|
||||
{
|
||||
return frida_fseek_impl (stream, (off_t) offset, whence);
|
||||
}
|
||||
|
||||
G_GNUC_INTERNAL long
|
||||
ftell (FILE * stream)
|
||||
{
|
||||
off_t pos = frida_ftell_impl (stream);
|
||||
if (pos == (off_t) -1)
|
||||
return -1;
|
||||
|
||||
return (long) pos;
|
||||
}
|
||||
|
||||
#ifdef HAVE_GLIBC
|
||||
|
||||
G_GNUC_INTERNAL int
|
||||
frida_fseeko_glibc_225 (FILE * stream, off_t offset, int whence)
|
||||
{
|
||||
return frida_fseek_impl (stream, offset, whence);
|
||||
}
|
||||
__asm__ (".symver frida_fseeko_glibc_225,fseeko@@GLIBC_2.2.5");
|
||||
|
||||
G_GNUC_INTERNAL int
|
||||
frida_fseeko64_glibc_225 (FILE * stream, off_t offset, int whence)
|
||||
{
|
||||
return frida_fseek_impl (stream, offset, whence);
|
||||
}
|
||||
__asm__ (".symver frida_fseeko64_glibc_225,fseeko64@@GLIBC_2.2.5");
|
||||
|
||||
G_GNUC_INTERNAL off_t
|
||||
frida_ftello_glibc_225 (FILE * stream)
|
||||
{
|
||||
return frida_ftell_impl (stream);
|
||||
}
|
||||
__asm__ (".symver frida_ftello_glibc_225,ftello@@GLIBC_2.2.5");
|
||||
|
||||
G_GNUC_INTERNAL off_t
|
||||
frida_ftello64_glibc_225 (FILE * stream)
|
||||
{
|
||||
return frida_ftell_impl (stream);
|
||||
}
|
||||
__asm__ (".symver frida_ftello64_glibc_225,ftello64@@GLIBC_2.2.5");
|
||||
|
||||
#else
|
||||
|
||||
G_GNUC_INTERNAL int
|
||||
fseeko (FILE * stream, off_t offset, int whence)
|
||||
{
|
||||
return frida_fseek_impl (stream, offset, whence);
|
||||
}
|
||||
|
||||
G_GNUC_INTERNAL off_t
|
||||
ftello (FILE * stream)
|
||||
{
|
||||
return frida_ftell_impl (stream);
|
||||
}
|
||||
|
||||
# ifndef HAVE_QNX
|
||||
|
||||
G_GNUC_INTERNAL int
|
||||
fseeko64 (FILE * stream, off_t offset, int whence)
|
||||
{
|
||||
return frida_fseek_impl (stream, offset, whence);
|
||||
}
|
||||
|
||||
G_GNUC_INTERNAL off_t
|
||||
ftello64 (FILE * stream)
|
||||
{
|
||||
return frida_ftell_impl (stream);
|
||||
}
|
||||
|
||||
# endif
|
||||
|
||||
#endif
|
||||
|
||||
static int
|
||||
frida_fseek_impl (FILE * stream, off_t offset, int whence)
|
||||
{
|
||||
FridaFile * f;
|
||||
off_t r;
|
||||
@@ -1408,10 +1073,10 @@ frida_fseek_impl (FILE * stream, off_t offset, int whence)
|
||||
|
||||
f->rpos = 0;
|
||||
f->rlen = 0;
|
||||
f->ungot_len = 0;
|
||||
f->has_ungot = FALSE;
|
||||
f->eof = FALSE;
|
||||
|
||||
r = frida_lseek_nointr (f->fd, offset, whence);
|
||||
r = frida_lseek_nointr (f->fd, (off_t) offset, whence);
|
||||
if (r == (off_t) -1)
|
||||
{
|
||||
f->err = errno;
|
||||
@@ -1421,8 +1086,8 @@ frida_fseek_impl (FILE * stream, off_t offset, int whence)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static off_t
|
||||
frida_ftell_impl (FILE * stream)
|
||||
G_GNUC_INTERNAL long
|
||||
ftell (FILE * stream)
|
||||
{
|
||||
FridaFile * f;
|
||||
off_t pos;
|
||||
@@ -1439,9 +1104,10 @@ frida_ftell_impl (FILE * stream)
|
||||
if (f->buf_mode != _IONBF)
|
||||
pos -= (off_t) (f->rlen - f->rpos);
|
||||
|
||||
pos -= f->ungot_len;
|
||||
if (f->has_ungot)
|
||||
pos -= 1;
|
||||
|
||||
return pos;
|
||||
return (long) pos;
|
||||
}
|
||||
|
||||
G_GNUC_INTERNAL void
|
||||
@@ -1903,7 +1569,6 @@ frida_stdio_register_stream (FILE * stream)
|
||||
{
|
||||
G_LOCK (frida_stdio);
|
||||
|
||||
frida_stdio_ensure_registries ();
|
||||
g_hash_table_add (frida_streams, stream);
|
||||
|
||||
G_UNLOCK (frida_stdio);
|
||||
@@ -1926,7 +1591,6 @@ frida_stdio_register_dir (DIR * dirp)
|
||||
{
|
||||
G_LOCK (frida_stdio);
|
||||
|
||||
frida_stdio_ensure_registries ();
|
||||
g_hash_table_add (frida_dirs, dirp);
|
||||
|
||||
G_UNLOCK (frida_stdio);
|
||||
@@ -1944,18 +1608,6 @@ frida_stdio_unregister_dir (DIR * dirp)
|
||||
|
||||
#endif
|
||||
|
||||
static void
|
||||
frida_stdio_ensure_registries (void)
|
||||
{
|
||||
if (frida_streams != NULL)
|
||||
return;
|
||||
|
||||
frida_streams = g_hash_table_new (g_direct_hash, g_direct_equal);
|
||||
#ifdef HAVE_FRIDA_DIR
|
||||
frida_dirs = g_hash_table_new (g_direct_hash, g_direct_equal);
|
||||
#endif
|
||||
}
|
||||
|
||||
static void
|
||||
frida_flush_all_streams (int * result)
|
||||
{
|
||||
@@ -2066,12 +1718,10 @@ frida_file_new (int fd, gboolean close_fd, int buf_mode)
|
||||
if (buf_mode != _IONBF)
|
||||
{
|
||||
f->rcap = FRIDA_STDIO_BUFSIZE;
|
||||
f->rbuf = g_malloc (f->rcap);
|
||||
f->owns_rbuf = TRUE;
|
||||
|
||||
f->wcap = FRIDA_STDIO_BUFSIZE;
|
||||
|
||||
f->rbuf = g_malloc (f->rcap);
|
||||
f->wbuf = g_malloc (f->wcap);
|
||||
f->owns_wbuf = TRUE;
|
||||
}
|
||||
|
||||
return f;
|
||||
@@ -2083,15 +1733,8 @@ frida_file_free (FridaFile * f)
|
||||
if (f == NULL)
|
||||
return;
|
||||
|
||||
if (f->owns_rbuf)
|
||||
g_clear_pointer (&f->rbuf, g_free);
|
||||
else
|
||||
f->rbuf = NULL;
|
||||
|
||||
if (f->owns_wbuf)
|
||||
g_clear_pointer (&f->wbuf, g_free);
|
||||
else
|
||||
f->wbuf = NULL;
|
||||
g_clear_pointer (&f->rbuf, g_free);
|
||||
g_clear_pointer (&f->wbuf, g_free);
|
||||
|
||||
g_free (f);
|
||||
}
|
||||
@@ -2223,36 +1866,6 @@ beach:
|
||||
}
|
||||
}
|
||||
|
||||
static gboolean
|
||||
frida_utf8_expected_len (guint8 first, guint * out_len)
|
||||
{
|
||||
if (first < 0x80)
|
||||
{
|
||||
*out_len = 1;
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
if ((first & 0xe0) == 0xc0)
|
||||
{
|
||||
*out_len = 2;
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
if ((first & 0xf0) == 0xe0)
|
||||
{
|
||||
*out_len = 3;
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
if ((first & 0xf8) == 0xf0)
|
||||
{
|
||||
*out_len = 4;
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
#ifdef HAVE_FRIDA_DIR
|
||||
|
||||
static FridaDir *
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
namespace Frida {
|
||||
public extern void libc_shim_prepare_to_deinit ();
|
||||
#if DARWIN
|
||||
public extern void libc_shim_deinit ();
|
||||
#endif
|
||||
|
||||
@@ -166,14 +166,6 @@ namespace Frida {
|
||||
yield get_instance (script_id).load ();
|
||||
}
|
||||
|
||||
public void interrupt_script (AgentScriptId script_id) throws Error {
|
||||
get_instance (script_id).interrupt ();
|
||||
}
|
||||
|
||||
public async void terminate_script (AgentScriptId script_id) throws Error {
|
||||
yield get_instance (script_id).terminate ();
|
||||
}
|
||||
|
||||
public Gum.Script eternalize_script (AgentScriptId script_id) throws Error {
|
||||
var instance = get_instance (script_id);
|
||||
|
||||
@@ -362,16 +354,6 @@ namespace Frida {
|
||||
load_request.resolve (true);
|
||||
}
|
||||
|
||||
public void interrupt () {
|
||||
script.interrupt ();
|
||||
}
|
||||
|
||||
public async void terminate () {
|
||||
script.interrupt ();
|
||||
|
||||
yield close ();
|
||||
}
|
||||
|
||||
private Promise<bool> unload () {
|
||||
var request = new Promise<bool> ();
|
||||
|
||||
|
||||
@@ -59,9 +59,7 @@ namespace Frida {
|
||||
|
||||
interceptor.attach ((void *) posix_spawn, this);
|
||||
|
||||
var replace_options = Gum.ReplaceOptions ();
|
||||
replace_options.replacement_data = this;
|
||||
interceptor.replace (execve, (void *) replacement_execve, null, replace_options);
|
||||
interceptor.replace (execve, (void *) replacement_execve, this);
|
||||
#else
|
||||
Gum.Address execve = 0;
|
||||
#if ANDROID
|
||||
|
||||
@@ -31,11 +31,9 @@ namespace Frida {
|
||||
thread_suspend = (ThreadSuspendFunc) kernel.find_export_by_name ("thread_suspend");
|
||||
thread_resume = (ThreadResumeFunc) kernel.find_export_by_name ("thread_resume");
|
||||
|
||||
var replace_options = Gum.ReplaceOptions ();
|
||||
replace_options.replacement_data = this;
|
||||
interceptor.replace ((void *) task_threads, (void *) replacement_task_threads, null, replace_options);
|
||||
interceptor.replace ((void *) thread_suspend, (void *) replacement_thread_suspend, null, replace_options);
|
||||
interceptor.replace ((void *) thread_resume, (void *) replacement_thread_resume, null, replace_options);
|
||||
interceptor.replace ((void *) task_threads, (void *) replacement_task_threads, this);
|
||||
interceptor.replace ((void *) thread_suspend, (void *) replacement_thread_suspend, this);
|
||||
interceptor.replace ((void *) thread_resume, (void *) replacement_thread_resume, this);
|
||||
}
|
||||
|
||||
public override void dispose () {
|
||||
|
||||
@@ -2,14 +2,29 @@
|
||||
|
||||
#ifdef HAVE_DARWIN
|
||||
|
||||
#include <capstone.h>
|
||||
#include <gum/gumdarwin.h>
|
||||
#include <gum/gummemory.h>
|
||||
#include <ptrauth.h>
|
||||
|
||||
#define FRIDA_MH_MAGIC_64 0xfeedfacf
|
||||
#define FRIDA_LIBUNWIND_PATH "/usr/lib/system/libunwind.dylib"
|
||||
#define FRIDA_UNWIND_CURSOR_VTABLE_OFFSET_SET_INFO 0x68
|
||||
#define FRIDA_UNWIND_CURSOR_VTABLE_OFFSET_GET_REG 0x18
|
||||
#define FRIDA_FP_TO_SP(fp) (fp + 0x10)
|
||||
#ifdef HAVE_ARM64
|
||||
# define FRIDA_UNWIND_CURSOR_unwindInfoMissing 0x268
|
||||
# define FRIDA_UNWAARCH64_X29 29
|
||||
# define FRIDA_STRIP_MASK 0x0000007fffffffffULL
|
||||
#else
|
||||
# define FRIDA_UNWIND_CURSOR_unwindInfoMissing 0x100
|
||||
# define FRIDA_UNWX86_64_RBP 6
|
||||
#endif
|
||||
|
||||
typedef struct _FridaFillInfoContext FridaFillInfoContext;
|
||||
typedef struct _FridaDyldUnwindSections FridaDyldUnwindSections;
|
||||
typedef struct _FridaCreateArgs FridaCreateArgs;
|
||||
typedef struct _FridaUnwindHookState FridaUnwindHookState;
|
||||
|
||||
struct _FridaFillInfoContext
|
||||
{
|
||||
@@ -32,9 +47,37 @@ struct _FridaCreateArgs
|
||||
GumAddress range_end;
|
||||
};
|
||||
|
||||
struct _FridaUnwindHookState
|
||||
{
|
||||
gpointer vtable;
|
||||
gssize shift;
|
||||
gpointer * set_info_slot;
|
||||
gpointer set_info_original;
|
||||
void (* set_info) (gpointer cursor, gint is_return_address);
|
||||
gpointer (* get_reg) (gpointer cursor, gint reg);
|
||||
GumInterceptor * interceptor;
|
||||
};
|
||||
|
||||
#if __has_feature (ptrauth_calls)
|
||||
# define FRIDA_RESIGN_PTR(x) GSIZE_TO_POINTER (gum_sign_code_address (gum_strip_code_address (GUM_ADDRESS (x))))
|
||||
#else
|
||||
# define FRIDA_RESIGN_PTR(x) (x)
|
||||
#endif
|
||||
|
||||
static FridaDyldUnwindSections * frida_get_cached_sections (GumAddress range_start, GumAddress range_end);
|
||||
static FridaDyldUnwindSections * frida_create_cached_sections (FridaCreateArgs * args);
|
||||
static gboolean frida_fill_info (const GumDarwinSectionDetails * details, FridaFillInfoContext * ctx);
|
||||
static void frida_unwind_cursor_set_info_replacement (gpointer cursor, gint is_return_address);
|
||||
static gpointer frida_find_vtable (void);
|
||||
static gboolean frida_compute_vtable_shift (gpointer vtable, gssize * shift);
|
||||
#ifdef HAVE_ARM64
|
||||
static gboolean frida_find_bss_range (const GumSectionDetails * details, GumMemoryRange * range);
|
||||
#else
|
||||
static gboolean frida_is_empty_function (GumAddress address);
|
||||
static gboolean frida_has_first_match (GumAddress address, gsize size, gboolean * matches);
|
||||
#endif
|
||||
|
||||
static FridaUnwindHookState * state = NULL;
|
||||
|
||||
void
|
||||
_frida_unwind_sitter_fill_unwind_sections (GumAddress invader_start, GumAddress invader_end, void * info)
|
||||
@@ -49,6 +92,63 @@ _frida_unwind_sitter_fill_unwind_sections (GumAddress invader_start, GumAddress
|
||||
memcpy (unwind_sections, cached, sizeof (FridaDyldUnwindSections));
|
||||
}
|
||||
|
||||
void
|
||||
_frida_unwind_sitter_hook_libunwind (void)
|
||||
{
|
||||
#if GLIB_SIZEOF_VOID_P == 8
|
||||
gpointer * set_info_slot;
|
||||
gpointer get_reg_impl;
|
||||
|
||||
if (state != NULL)
|
||||
return;
|
||||
|
||||
state = g_slice_new0 (FridaUnwindHookState);
|
||||
if (state == NULL)
|
||||
return;
|
||||
|
||||
state->vtable = frida_find_vtable ();
|
||||
if (state->vtable == NULL)
|
||||
goto unsupported_version;
|
||||
|
||||
if (!frida_compute_vtable_shift (state->vtable, &state->shift))
|
||||
goto unsupported_version;
|
||||
|
||||
set_info_slot = (gpointer *) (GUM_ADDRESS (state->vtable) + FRIDA_UNWIND_CURSOR_VTABLE_OFFSET_SET_INFO + state->shift);
|
||||
get_reg_impl = *(gpointer *) (GUM_ADDRESS (state->vtable) + FRIDA_UNWIND_CURSOR_VTABLE_OFFSET_GET_REG + state->shift);
|
||||
|
||||
state->set_info_slot = set_info_slot;
|
||||
state->set_info_original = *set_info_slot;
|
||||
state->set_info = FRIDA_RESIGN_PTR (state->set_info_original);
|
||||
state->get_reg = FRIDA_RESIGN_PTR (get_reg_impl);
|
||||
|
||||
state->interceptor = gum_interceptor_obtain ();
|
||||
|
||||
if (gum_interceptor_replace (state->interceptor, state->set_info_original, frida_unwind_cursor_set_info_replacement, NULL, NULL)
|
||||
!= GUM_REPLACE_OK)
|
||||
goto unsupported_version;
|
||||
|
||||
return;
|
||||
|
||||
unsupported_version:
|
||||
g_slice_free (FridaUnwindHookState, state);
|
||||
state = NULL;
|
||||
#endif
|
||||
}
|
||||
|
||||
void
|
||||
_frida_unwind_sitter_unhook_libunwind (void)
|
||||
{
|
||||
if (state == NULL)
|
||||
return;
|
||||
|
||||
gum_interceptor_revert (state->interceptor, state->set_info_original);
|
||||
|
||||
g_object_unref (state->interceptor);
|
||||
|
||||
g_slice_free (FridaUnwindHookState, state);
|
||||
state = NULL;
|
||||
}
|
||||
|
||||
static FridaDyldUnwindSections *
|
||||
frida_get_cached_sections (GumAddress range_start, GumAddress range_end)
|
||||
{
|
||||
@@ -87,8 +187,7 @@ frida_create_cached_sections (FridaCreateArgs * args)
|
||||
cached_sections = g_slice_new0 (FridaDyldUnwindSections);
|
||||
cached_sections->mh = header;
|
||||
|
||||
module = gum_darwin_module_new_from_memory ("Frida", mach_task_self (), GPOINTER_TO_SIZE (header),
|
||||
GUM_DARWIN_MODULE_FLAGS_NONE, NULL);
|
||||
module = gum_darwin_module_new_from_memory ("Frida", mach_task_self (), GPOINTER_TO_SIZE (header), GUM_DARWIN_MODULE_FLAGS_NONE, NULL);
|
||||
if (module == NULL)
|
||||
return cached_sections;
|
||||
|
||||
@@ -123,4 +222,308 @@ frida_fill_info (const GumDarwinSectionDetails * details, FridaFillInfoContext *
|
||||
return ctx->missing_info > 0;
|
||||
}
|
||||
|
||||
static void
|
||||
frida_unwind_cursor_set_info_replacement (gpointer self, gint is_return_address)
|
||||
{
|
||||
gboolean missing_info;
|
||||
GumAddress fp, stored_pc;
|
||||
gpointer * stored_pc_slot;
|
||||
#if defined (HAVE_ARM64) && !__has_feature (ptrauth_calls)
|
||||
gboolean was_signed = FALSE;
|
||||
#endif
|
||||
|
||||
if (state == NULL)
|
||||
return;
|
||||
|
||||
state->set_info (self, is_return_address);
|
||||
|
||||
#ifdef HAVE_ARM64
|
||||
fp = GUM_ADDRESS (state->get_reg (self, FRIDA_UNWAARCH64_X29));
|
||||
#else
|
||||
fp = GUM_ADDRESS (state->get_reg (self, FRIDA_UNWX86_64_RBP));
|
||||
#endif
|
||||
if (fp == 0 || fp == -1)
|
||||
return;
|
||||
|
||||
missing_info = *((guint8 *) self + FRIDA_UNWIND_CURSOR_unwindInfoMissing);
|
||||
|
||||
stored_pc_slot = GSIZE_TO_POINTER (fp + GLIB_SIZEOF_VOID_P);
|
||||
stored_pc = GUM_ADDRESS (*stored_pc_slot);
|
||||
#if __has_feature (ptrauth_calls)
|
||||
stored_pc = gum_strip_code_address (stored_pc);
|
||||
#elif defined (HAVE_ARM64)
|
||||
was_signed = (stored_pc & ~FRIDA_STRIP_MASK) != 0ULL;
|
||||
if (was_signed)
|
||||
stored_pc &= FRIDA_STRIP_MASK;
|
||||
#endif
|
||||
|
||||
if (!missing_info)
|
||||
{
|
||||
GumAddress translated;
|
||||
|
||||
translated = GUM_ADDRESS (gum_invocation_stack_translate (gum_interceptor_get_current_stack (), GSIZE_TO_POINTER (stored_pc)));
|
||||
if (translated != stored_pc)
|
||||
{
|
||||
#if __has_feature (ptrauth_calls)
|
||||
*stored_pc_slot = ptrauth_sign_unauthenticated (
|
||||
ptrauth_strip (GSIZE_TO_POINTER (translated), ptrauth_key_asia), ptrauth_key_asib, FRIDA_FP_TO_SP (fp));
|
||||
#elif defined (HAVE_ARM64)
|
||||
if (was_signed)
|
||||
{
|
||||
GumAddress resigned;
|
||||
|
||||
asm volatile (
|
||||
"mov x17, %1\n\t"
|
||||
"mov x16, %2\n\t"
|
||||
".byte 0x5f, 0x21, 0x03, 0xd5\n\t" /* pacib1716 */
|
||||
"mov %0, x17\n\t"
|
||||
: "=r" (resigned)
|
||||
: "r" (translated & FRIDA_STRIP_MASK),
|
||||
"r" (FRIDA_FP_TO_SP (fp))
|
||||
: "x16", "x17"
|
||||
);
|
||||
|
||||
*stored_pc_slot = GSIZE_TO_POINTER (resigned);
|
||||
}
|
||||
else
|
||||
{
|
||||
*stored_pc_slot = GSIZE_TO_POINTER (translated);
|
||||
}
|
||||
#else
|
||||
*stored_pc_slot = GSIZE_TO_POINTER (translated);
|
||||
#endif
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static gpointer
|
||||
frida_find_vtable (void)
|
||||
{
|
||||
GumAddress result = 0;
|
||||
GumModule * libunwind;
|
||||
GumAddress export;
|
||||
uint64_t address;
|
||||
G_GNUC_UNUSED cs_err err;
|
||||
csh capstone;
|
||||
cs_insn * insn = NULL;
|
||||
const uint8_t * code;
|
||||
size_t size;
|
||||
const size_t max_size = 2048;
|
||||
|
||||
libunwind = gum_process_find_module_by_name (FRIDA_LIBUNWIND_PATH);
|
||||
if (libunwind == NULL)
|
||||
goto beach;
|
||||
|
||||
export = gum_module_find_export_by_name (libunwind, "unw_init_local");
|
||||
if (export == 0)
|
||||
export = gum_module_find_export_by_name (libunwind, "_Unwind_RaiseException");
|
||||
if (export == 0)
|
||||
goto beach;
|
||||
export = gum_strip_code_address (export);
|
||||
address = export;
|
||||
|
||||
#ifdef HAVE_ARM64
|
||||
cs_arch_register_arm64 ();
|
||||
err = cs_open (CS_ARCH_ARM64, CS_MODE_LITTLE_ENDIAN, &capstone);
|
||||
#else
|
||||
cs_arch_register_x86 ();
|
||||
err = cs_open (CS_ARCH_X86, CS_MODE_64, &capstone);
|
||||
#endif
|
||||
g_assert (err == CS_ERR_OK);
|
||||
|
||||
err = cs_option (capstone, CS_OPT_DETAIL, CS_OPT_ON);
|
||||
g_assert (err == CS_ERR_OK);
|
||||
|
||||
insn = cs_malloc (capstone);
|
||||
code = GSIZE_TO_POINTER (export);
|
||||
size = max_size;
|
||||
|
||||
#ifdef HAVE_ARM64
|
||||
{
|
||||
GumAddress last_adrp;
|
||||
guint last_adrp_reg;
|
||||
GumMemoryRange bss_range;
|
||||
|
||||
bss_range.base_address = 0;
|
||||
gum_module_enumerate_sections (libunwind, (GumFoundSectionFunc) frida_find_bss_range, &bss_range);
|
||||
|
||||
while (cs_disasm_iter (capstone, &code, &size, &address, insn))
|
||||
{
|
||||
if (insn->id == ARM64_INS_RET || insn->id == ARM64_INS_RETAA || insn->id == ARM64_INS_RETAB)
|
||||
break;
|
||||
if (insn->id == ARM64_INS_ADRP)
|
||||
{
|
||||
if (result != 0)
|
||||
break;
|
||||
last_adrp = (GumAddress) insn->detail->arm64.operands[1].imm;
|
||||
last_adrp_reg = insn->detail->arm64.operands[0].reg;
|
||||
}
|
||||
else if (insn->id == ARM64_INS_ADD && insn->detail->arm64.operands[0].reg == last_adrp_reg)
|
||||
{
|
||||
GumAddress candidate;
|
||||
gboolean is_bss;
|
||||
|
||||
candidate = last_adrp + (GumAddress) insn->detail->arm64.operands[2].imm;
|
||||
|
||||
is_bss = bss_range.base_address != 0 &&
|
||||
bss_range.base_address <= candidate &&
|
||||
candidate < bss_range.base_address + bss_range.size;
|
||||
if (!is_bss)
|
||||
{
|
||||
if (result == 0)
|
||||
{
|
||||
result = candidate;
|
||||
last_adrp = candidate;
|
||||
}
|
||||
else
|
||||
{
|
||||
result = candidate;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (result != 0)
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
#else
|
||||
while (cs_disasm_iter (capstone, &code, &size, &address, insn))
|
||||
{
|
||||
if (insn->id == X86_INS_RET)
|
||||
break;
|
||||
if (insn->id == X86_INS_LEA)
|
||||
{
|
||||
const cs_x86_op * op = &insn->detail->x86.operands[1];
|
||||
if (op->type == X86_OP_MEM && op->mem.base == X86_REG_RIP)
|
||||
{
|
||||
result = address + op->mem.disp * op->mem.scale;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
if (insn != NULL)
|
||||
cs_free (insn, 1);
|
||||
cs_close (&capstone);
|
||||
|
||||
beach:
|
||||
g_clear_object (&libunwind);
|
||||
|
||||
return GSIZE_TO_POINTER (result);
|
||||
}
|
||||
|
||||
#ifdef HAVE_ARM64
|
||||
|
||||
static gboolean
|
||||
frida_find_bss_range (const GumSectionDetails * details, GumMemoryRange * range)
|
||||
{
|
||||
if (strcmp (details->name, "__bss") == 0)
|
||||
{
|
||||
range->base_address = details->address;
|
||||
range->size = details->size;
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
frida_compute_vtable_shift (gpointer vtable, gssize * shift)
|
||||
{
|
||||
gboolean result = FALSE;
|
||||
G_GNUC_UNUSED cs_err err;
|
||||
csh capstone;
|
||||
cs_insn * insn = NULL;
|
||||
const uint8_t * code;
|
||||
uint64_t address;
|
||||
size_t size = 4;
|
||||
|
||||
cs_arch_register_arm64 ();
|
||||
err = cs_open (CS_ARCH_ARM64, CS_MODE_LITTLE_ENDIAN, &capstone);
|
||||
g_assert (err == CS_ERR_OK);
|
||||
|
||||
insn = cs_malloc (capstone);
|
||||
code = gum_strip_code_pointer (*(gpointer *) vtable);
|
||||
address = GPOINTER_TO_SIZE (code);
|
||||
|
||||
if (cs_disasm_iter (capstone, &code, &size, &address, insn))
|
||||
{
|
||||
if (insn->id == ARM64_INS_RET || insn->id == ARM64_INS_RETAA || insn->id == ARM64_INS_RETAB)
|
||||
*shift = 0;
|
||||
else
|
||||
*shift = -2 * GLIB_SIZEOF_VOID_P;
|
||||
|
||||
result = TRUE;
|
||||
}
|
||||
|
||||
if (insn != NULL)
|
||||
cs_free (insn, 1);
|
||||
cs_close (&capstone);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
static gboolean
|
||||
frida_compute_vtable_shift (gpointer vtable, gssize * shift)
|
||||
{
|
||||
GumAddress cursor = GPOINTER_TO_SIZE (vtable);
|
||||
GumAddress error = cursor + 16 * GLIB_SIZEOF_VOID_P;
|
||||
|
||||
while (cursor < error && *(gpointer *) GSIZE_TO_POINTER (cursor) == NULL)
|
||||
cursor += GLIB_SIZEOF_VOID_P;
|
||||
if (cursor == error)
|
||||
return FALSE;
|
||||
|
||||
if (frida_is_empty_function (GUM_ADDRESS (*(gpointer *) GSIZE_TO_POINTER (cursor))) &&
|
||||
frida_is_empty_function (GUM_ADDRESS (*(gpointer *) GSIZE_TO_POINTER (cursor + GLIB_SIZEOF_VOID_P))))
|
||||
{
|
||||
*shift = cursor - GPOINTER_TO_SIZE (vtable);
|
||||
}
|
||||
else
|
||||
{
|
||||
*shift = cursor - GPOINTER_TO_SIZE (vtable) - 2 * GLIB_SIZEOF_VOID_P;
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
frida_is_empty_function (GumAddress address)
|
||||
{
|
||||
gboolean matches = FALSE;
|
||||
GumMemoryRange range;
|
||||
GumMatchPattern * pattern;
|
||||
|
||||
range.base_address = address;
|
||||
range.size = 6;
|
||||
|
||||
/*
|
||||
* 55 push rbp
|
||||
* 4889e5 mov rbp, rsp
|
||||
* 5d pop rbp
|
||||
* c3 ret
|
||||
*/
|
||||
pattern = gum_match_pattern_new_from_string ("55 48 89 e5 5d c3");
|
||||
|
||||
gum_memory_scan (&range, pattern, (GumMemoryScanMatchFunc) frida_has_first_match, &matches);
|
||||
|
||||
gum_match_pattern_unref (pattern);
|
||||
|
||||
return matches;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
frida_has_first_match (GumAddress address, gsize size, gboolean * matches)
|
||||
{
|
||||
*matches = TRUE;
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
#endif
|
||||
@@ -1,41 +1,65 @@
|
||||
namespace Frida {
|
||||
#if DARWIN
|
||||
public sealed class UnwindSitter : Object, Gum.UnwindSectionsProvider {
|
||||
public sealed class UnwindSitter : Object {
|
||||
public weak ProcessInvader invader {
|
||||
get;
|
||||
construct;
|
||||
}
|
||||
|
||||
public unowned Gum.MemoryRange? range {
|
||||
get { return _range; }
|
||||
}
|
||||
private DyldFindUnwindSectionsFunc dyld_find_unwind_sections;
|
||||
|
||||
private Gum.MemoryRange? _range;
|
||||
private Gum.UnwindBroker broker;
|
||||
private const string LIBDYLD = "/usr/lib/system/libdyld.dylib";
|
||||
|
||||
[CCode (has_target = false)]
|
||||
private delegate int DyldFindUnwindSectionsFunc (void * addr, void * info);
|
||||
|
||||
public UnwindSitter (ProcessInvader invader) {
|
||||
Object (invader: invader);
|
||||
}
|
||||
|
||||
construct {
|
||||
_range = invader.get_memory_range ();
|
||||
var interceptor = Gum.Interceptor.obtain ();
|
||||
|
||||
broker = Gum.UnwindBroker.obtain ();
|
||||
broker.add_sections_provider (this);
|
||||
dyld_find_unwind_sections = (DyldFindUnwindSectionsFunc)
|
||||
Gum.Process.find_module_by_name (LIBDYLD).find_export_by_name ("_dyld_find_unwind_sections");
|
||||
|
||||
interceptor.replace ((void *) dyld_find_unwind_sections, (void *) replacement_dyld_find_unwind_sections, this);
|
||||
|
||||
_hook_libunwind ();
|
||||
}
|
||||
|
||||
public override void dispose () {
|
||||
broker.remove_sections_provider (this);
|
||||
var interceptor = Gum.Interceptor.obtain ();
|
||||
|
||||
_unhook_libunwind ();
|
||||
interceptor.revert ((void *) dyld_find_unwind_sections);
|
||||
|
||||
base.dispose ();
|
||||
}
|
||||
|
||||
public bool fill (Gum.Address address, void * info) {
|
||||
_fill_unwind_sections (_range.base_address, _range.base_address + _range.size, info);
|
||||
return true;
|
||||
private static int replacement_dyld_find_unwind_sections (void * addr, void * info) {
|
||||
unowned Gum.InvocationContext context = Gum.Interceptor.get_current_invocation ();
|
||||
unowned UnwindSitter sitter = (UnwindSitter) context.get_replacement_data ();
|
||||
|
||||
Gum.MemoryRange range = sitter.invader.get_memory_range ();
|
||||
var range_end = range.base_address + range.size;
|
||||
|
||||
var address = Gum.Address.from_pointer (addr);
|
||||
#if ARM64
|
||||
address &= 0x7ffffffffULL;
|
||||
#endif
|
||||
var is_ours = address >= range.base_address && address < range_end;
|
||||
if (!is_ours)
|
||||
return sitter.dyld_find_unwind_sections (addr, info);
|
||||
|
||||
_fill_unwind_sections (range.base_address, range_end, info);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
public extern static void _fill_unwind_sections (Gum.Address invader_start, Gum.Address invader_end, void * info);
|
||||
public extern static void _hook_libunwind ();
|
||||
public extern static void _unhook_libunwind ();
|
||||
}
|
||||
#else
|
||||
public sealed class UnwindSitter : Object {
|
||||
|
||||
+2
-15
@@ -12,27 +12,14 @@ frida_pipe_get_sddl_string_for_pipe (void)
|
||||
#define DACL_ACE_EVERYONE_RW L"(A;;GRGW;;;WD)"
|
||||
#define SACL_START L"S:"
|
||||
#define SACL_ACE_LOWINTEGRITY_NORW L"(ML;;NWNR;;;LW)"
|
||||
#define DACL_ACE_SYSTEM_RW L"(A;;GRGW;;;SY)"
|
||||
#define DACL_ACE_ADMINS_RW L"(A;;GRGW;;;BA)"
|
||||
|
||||
if (frida_pipe_is_windows_8_or_greater ())
|
||||
{
|
||||
return DACL_START_NOINHERIT
|
||||
DACL_ACE_APPCONTAINER_RW
|
||||
DACL_ACE_EVERYONE_RW
|
||||
DACL_ACE_SYSTEM_RW
|
||||
DACL_ACE_ADMINS_RW
|
||||
SACL_START
|
||||
SACL_ACE_LOWINTEGRITY_NORW;
|
||||
return DACL_START_NOINHERIT DACL_ACE_APPCONTAINER_RW DACL_ACE_EVERYONE_RW SACL_START SACL_ACE_LOWINTEGRITY_NORW;
|
||||
}
|
||||
else if (frida_pipe_is_windows_vista_or_greater ())
|
||||
{
|
||||
return DACL_START_NOINHERIT
|
||||
DACL_ACE_EVERYONE_RW
|
||||
DACL_ACE_SYSTEM_RW
|
||||
DACL_ACE_ADMINS_RW
|
||||
SACL_START
|
||||
SACL_ACE_LOWINTEGRITY_NORW;
|
||||
return DACL_START_NOINHERIT DACL_ACE_EVERYONE_RW SACL_START SACL_ACE_LOWINTEGRITY_NORW;
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
+83
-323
@@ -130,10 +130,6 @@ if host_os_family == 'darwin'
|
||||
add_languages('objc', 'objcpp', native: false)
|
||||
endif
|
||||
|
||||
if meson.is_cross_build()
|
||||
add_languages('c', 'cpp', 'vala', native: true)
|
||||
endif
|
||||
|
||||
python = import('python').find_installation()
|
||||
|
||||
if cc.get_argument_syntax() == 'msvc'
|
||||
@@ -228,21 +224,15 @@ helper_name = 'frida-helper' + exe_suffix
|
||||
agent_name = 'frida-agent' + shlib_suffix
|
||||
gadget_name = 'frida-gadget' + shlib_suffix
|
||||
|
||||
frida_libdir_name = f'frida-@api_version@'
|
||||
root_asset_dir = get_option('libdir') / frida_libdir_name
|
||||
root_asset_dir = get_option('libdir') / 'frida'
|
||||
if host_os_family == 'darwin'
|
||||
asset_dir = root_asset_dir
|
||||
default_asset_path_template = get_option('prefix') / get_option('libdir') / frida_libdir_name
|
||||
elif host_os_family == 'windows'
|
||||
asset_dir = root_asset_dir / host_abi
|
||||
asset_dir_modern = root_asset_dir / 'x86_64'
|
||||
asset_dir_legacy = root_asset_dir / 'x86'
|
||||
default_asset_path_template = get_option('prefix') / get_option('libdir') / frida_libdir_name / '<arch>'
|
||||
default_asset_path_template = get_option('prefix') / get_option('libdir') / 'frida'
|
||||
else
|
||||
asset_dir = root_asset_dir / host_cpu_mode
|
||||
asset_dir_modern = root_asset_dir / '64'
|
||||
asset_dir_legacy = root_asset_dir / '32'
|
||||
default_asset_path_template = get_option('prefix') / get_option('libdir') / frida_libdir_name / '<arch>'
|
||||
default_asset_path_template = get_option('prefix') / get_option('libdir') / 'frida' / '<arch>'
|
||||
endif
|
||||
|
||||
asset_path_template = get_option('asset_path_template')
|
||||
@@ -250,22 +240,11 @@ if asset_path_template == ''
|
||||
asset_path_template = default_asset_path_template
|
||||
endif
|
||||
|
||||
is_shared = get_option('default_library') == 'shared'
|
||||
|
||||
assets_mode = get_option('assets')
|
||||
if assets_mode == 'auto'
|
||||
assets_mode = is_shared ? 'installed' : 'embedded'
|
||||
endif
|
||||
|
||||
cdata.set_quoted('FRIDA_LIBDIR', get_option('libdir'))
|
||||
cdata.set_quoted('FRIDA_LIBDIR_NAME', frida_libdir_name)
|
||||
|
||||
if assets_mode == 'embedded'
|
||||
cdata.set('HAVE_EMBEDDED_ASSETS', 1)
|
||||
if get_option('assets') == 'embedded'
|
||||
vala_flags += '--define=HAVE_EMBEDDED_ASSETS'
|
||||
else
|
||||
cdata.set_quoted('FRIDA_HELPER_NAME', helper_name)
|
||||
cdata.set_quoted('FRIDA_AGENT_NAME', agent_name)
|
||||
cdata.set_quoted('FRIDA_HELPER_PATH', asset_path_template / helper_name)
|
||||
cdata.set_quoted('FRIDA_AGENT_PATH', asset_path_template / agent_name)
|
||||
endif
|
||||
|
||||
cdata.set('HAVE_' + host_os_family.to_upper(), 1)
|
||||
@@ -273,15 +252,6 @@ if host_os != host_os_family
|
||||
cdata.set('HAVE_' + host_os.to_upper(), 1)
|
||||
endif
|
||||
|
||||
host_is_prospero = host_os_family == 'freebsd' and cc.get_define('__PROSPERO__') != ''
|
||||
prospero_crt_link_args = []
|
||||
if host_is_prospero
|
||||
cdata.set('HAVE_PROSPERO', 1)
|
||||
vala_flags += '--define=PROSPERO'
|
||||
prospero_crt_link_args += \
|
||||
run_command(cc.cmd_array(), '-print-file-name=crt1.o', check: true).stdout().strip()
|
||||
endif
|
||||
|
||||
cpu_defines = [
|
||||
['x86', 'HAVE_I386'],
|
||||
['x86_64', 'HAVE_I386'],
|
||||
@@ -332,19 +302,21 @@ if host_os == 'linux'
|
||||
endif
|
||||
cdata.set('HAVE_' + libc.to_upper(), 1)
|
||||
vala_flags += '--define=' + libc.to_upper()
|
||||
elif host_os == 'android'
|
||||
libc = 'bionic'
|
||||
else
|
||||
libc = 'other'
|
||||
endif
|
||||
|
||||
if get_option('b_sanitize') == 'address'
|
||||
cdata.set('HAVE_ASAN', 1)
|
||||
endif
|
||||
|
||||
gum_dep = dependency('frida-gum-1.0', default_options: [
|
||||
f'frida_version=@frida_version@',
|
||||
'gumjs=enabled',
|
||||
])
|
||||
gumjs_dep = dependency('frida-gumjs-1.0')
|
||||
gumjs_inspector_dep = dependency('frida-gumjs-inspector-1.0')
|
||||
|
||||
glib_version_req = '>=2.74'
|
||||
glib_options = [
|
||||
'default_library=static',
|
||||
'cocoa=disabled',
|
||||
'selinux=disabled',
|
||||
'xattr=false',
|
||||
@@ -360,58 +332,24 @@ if optimize_for_prod
|
||||
]
|
||||
endif
|
||||
|
||||
glib_dep = dependency('glib-2.0', version: glib_version_req, default_options: glib_options)
|
||||
if glib_dep.type_name() == 'internal'
|
||||
have_shared_glib = get_option('default_library') != 'static'
|
||||
else
|
||||
glib_flavor_src = '''
|
||||
#include <glib.h>
|
||||
|
||||
#ifdef GLIB_STATIC_COMPILATION
|
||||
# error GLib is static
|
||||
#endif
|
||||
'''
|
||||
have_shared_glib = cc.compiles(glib_flavor_src, name: 'compiling with shared GLib', dependencies: [glib_dep])
|
||||
endif
|
||||
have_frida_glib = glib_dep.type_name() == 'internal' or cc.has_function('g_thread_set_callbacks', dependencies: [glib_dep])
|
||||
if have_frida_glib
|
||||
cdata.set('HAVE_FRIDA_GLIB', 1)
|
||||
vala_flags += '--define=HAVE_FRIDA_GLIB'
|
||||
endif
|
||||
|
||||
have_in_tree_payloads = not have_shared_glib
|
||||
gum_dep = dependency('frida-gum-1.0', default_options: [
|
||||
'default_library=static',
|
||||
f'frida_version=@frida_version@',
|
||||
'gumjs=' + (have_in_tree_payloads ? 'enabled' : 'disabled'),
|
||||
'inspector=enabled',
|
||||
])
|
||||
if have_in_tree_payloads
|
||||
gumjs_dep = dependency('frida-gumjs-1.0', default_options: ['default_library=static'])
|
||||
endif
|
||||
gumjs_inspector_dep = dependency('frida-gumjs-inspector-1.0', default_options: ['default_library=static'])
|
||||
|
||||
gee_options = [
|
||||
'default_library=static',
|
||||
'disable-introspection=true',
|
||||
]
|
||||
if optimize_for_prod
|
||||
gee_options += 'disable-internal-asserts=true'
|
||||
endif
|
||||
|
||||
glib_dep = dependency('glib-2.0', version: glib_version_req, default_options: glib_options)
|
||||
gobject_dep = dependency('gobject-2.0')
|
||||
gmodule_dep = dependency('gmodule-2.0')
|
||||
gio_dep = dependency('gio-2.0')
|
||||
gee_dep = dependency('gee-0.8', default_options: gee_options)
|
||||
json_glib_dep = dependency('json-glib-1.0', version: '>=1.8', default_options: [
|
||||
'default_library=static',
|
||||
'introspection=disabled',
|
||||
'gtk_doc=disabled',
|
||||
'tests=false',
|
||||
])
|
||||
libsoup_dep = dependency('libsoup-3.0', default_options: [
|
||||
'default_library=static',
|
||||
'sqlite:default_library=static',
|
||||
'gssapi=disabled',
|
||||
'ntlm=disabled',
|
||||
'brotli=disabled',
|
||||
@@ -423,48 +361,19 @@ libsoup_dep = dependency('libsoup-3.0', default_options: [
|
||||
'tests=false',
|
||||
'sysprof=disabled',
|
||||
])
|
||||
if libsoup_dep.type_name() == 'internal' \
|
||||
or cc.has_function('soup_websocket_connection_pause_input', dependencies: [libsoup_dep])
|
||||
vala_flags += '--define=HAVE_SOUP_WEBSOCKET_BACKPRESSURE'
|
||||
endif
|
||||
brotlidec_dep = dependency('libbrotlidec', default_options: ['default_library=static'])
|
||||
capstone_dep = dependency('capstone', default_options: ['default_library=static'])
|
||||
if capstone_dep.type_name() != 'internal' \
|
||||
and not cc.has_function('cs_arch_register_x86', dependencies: [capstone_dep])
|
||||
add_project_arguments(
|
||||
'-Dcs_arch_register_x86()=',
|
||||
'-Dcs_arch_register_arm()=',
|
||||
'-Dcs_arch_register_arm64()=',
|
||||
'-Dcs_arch_register_mips()=',
|
||||
language: ['c', 'objc'],
|
||||
)
|
||||
endif
|
||||
brotlidec_dep = dependency('libbrotlidec')
|
||||
quickjs_dep = dependency('quickjs', required: get_option('barebone_backend'), default_options: [
|
||||
'default_library=static',
|
||||
'libc=false',
|
||||
'bignum=true',
|
||||
'atomics=disabled',
|
||||
'stack_check=disabled',
|
||||
])
|
||||
lzfse_dep = dependency('lzfse', required: false, default_options: ['default_library=static'])
|
||||
lzfse_from_system = false
|
||||
if not lzfse_dep.found() and not meson.is_cross_build()
|
||||
if cc.has_header_symbol('lzfse.h', 'lzfse_decode_buffer')
|
||||
lzfse_lib = cc.find_library('lzfse', required: false)
|
||||
if lzfse_lib.found()
|
||||
lzfse_dep = declare_dependency(dependencies: lzfse_lib)
|
||||
lzfse_from_system = true
|
||||
endif
|
||||
endif
|
||||
endif
|
||||
if not lzfse_dep.found()
|
||||
lzfse_dep = dependency('lzfse', required: get_option('barebone_backend'), default_options: ['default_library=static'])
|
||||
endif
|
||||
lzfse_dep = dependency('lzfse', required: get_option('barebone_backend'))
|
||||
|
||||
native_glib_dep = dependency('glib-2.0', version: glib_version_req, native: true, default_options: glib_options)
|
||||
native_gio_dep = dependency('gio-2.0', native: true)
|
||||
native_gee_dep = dependency('gee-0.8', native: true, default_options: gee_options)
|
||||
native_brotlienc_dep = dependency('libbrotlienc', native: true, default_options: ['default_library=static'])
|
||||
native_brotlienc_dep = dependency('libbrotlienc', native: true)
|
||||
|
||||
if host_os_family == 'windows'
|
||||
gio_windows_dep = dependency('gio-windows-2.0')
|
||||
@@ -472,10 +381,8 @@ else
|
||||
gio_unix_dep = dependency('gio-unix-2.0')
|
||||
endif
|
||||
|
||||
have_local_backend = get_option('local_backend').allowed()
|
||||
|
||||
if host_os_family == 'linux' and have_local_backend
|
||||
libbpf_dep = dependency('libbpf', default_options: ['default_library=static'])
|
||||
if host_os_family == 'linux'
|
||||
libbpf_dep = dependency('libbpf')
|
||||
endif
|
||||
|
||||
if host_os == 'android'
|
||||
@@ -523,6 +430,7 @@ else
|
||||
codesign = ''
|
||||
endif
|
||||
|
||||
have_local_backend = get_option('local_backend').allowed()
|
||||
have_simmy_backend = get_option('simmy_backend') \
|
||||
.disable_auto_if(host_os != 'macos') \
|
||||
.require(host_os == 'macos', error_message: 'Simmy backend is only available on macOS') \
|
||||
@@ -536,12 +444,11 @@ have_droidy_backend = get_option('droidy_backend') \
|
||||
have_socket_backend = get_option('socket_backend').allowed()
|
||||
have_barebone_backend = get_option('barebone_backend') \
|
||||
.disable_if(not (quickjs_dep.found() and lzfse_dep.found())) \
|
||||
.disable_auto_if(not host_docks_mobile_devices and host_os != 'android') \
|
||||
.disable_auto_if(not host_docks_mobile_devices) \
|
||||
.allowed()
|
||||
compiler_backend_opt = get_option('compiler_backend') \
|
||||
.disable_auto_if(host_os == 'watchos')
|
||||
have_compiler_backend = false
|
||||
compiler_backend_mode = ''
|
||||
if compiler_backend_opt.allowed()
|
||||
go = find_program('go', native: true, required: false)
|
||||
if go.found()
|
||||
@@ -552,13 +459,9 @@ if compiler_backend_opt.allowed()
|
||||
files('tools' / 'cgo' / 'detect.py'),
|
||||
go,
|
||||
host_os,
|
||||
host_os_family,
|
||||
host_abi,
|
||||
libc,
|
||||
exe_suffix,
|
||||
shlib_suffix,
|
||||
cc.get_id(),
|
||||
assets_mode,
|
||||
'>>>', cc.cmd_array(), '<<<',
|
||||
'>>>', ar, '<<<',
|
||||
'>>>', nm, '<<<',
|
||||
@@ -571,29 +474,12 @@ if compiler_backend_opt.allowed()
|
||||
status = lines[0]
|
||||
if status == 'ok'
|
||||
have_compiler_backend = true
|
||||
cdata.set('HAVE_COMPILER_BACKEND', 1)
|
||||
compiler_backend_mode = lines[1]
|
||||
go_config = lines[2]
|
||||
|
||||
if compiler_backend_mode == 'c-archive'
|
||||
vala_flags += '--define=COMPILER_BACKEND_LINKED'
|
||||
cdata.set('HAVE_COMPILER_BACKEND_LINKED', 1)
|
||||
elif compiler_backend_mode == 'c-shared'
|
||||
if assets_mode == 'installed'
|
||||
vala_flags += '--define=COMPILER_BACKEND_INSTALLED_LIBRARY'
|
||||
cdata.set_quoted('FRIDA_COMPILER_BACKEND_NAME', 'frida-compiler-backend' + shlib_suffix)
|
||||
else
|
||||
vala_flags += '--define=COMPILER_BACKEND_EMBEDDED_LIBRARY'
|
||||
endif
|
||||
elif compiler_backend_mode == 'pie'
|
||||
if assets_mode == 'installed'
|
||||
vala_flags += '--define=COMPILER_BACKEND_INSTALLED_EXECUTABLE'
|
||||
cdata.set_quoted('FRIDA_COMPILER_BACKEND_NAME', 'frida-compiler-backend' + exe_suffix)
|
||||
else
|
||||
vala_flags += '--define=COMPILER_BACKEND_EMBEDDED_EXECUTABLE'
|
||||
endif
|
||||
else
|
||||
error('Unsupported compiler backend mode: ' + compiler_backend_mode)
|
||||
tokens = lines[1].split(' ')
|
||||
go_mode = tokens[0]
|
||||
go_config = tokens[1]
|
||||
compiler_backend_static_compilation = go_mode == 'c-archive'
|
||||
if compiler_backend_static_compilation
|
||||
vala_flags += '--define=COMPILER_BACKEND_STATIC_COMPILATION'
|
||||
endif
|
||||
else
|
||||
error_message = lines[1]
|
||||
@@ -604,9 +490,9 @@ if compiler_backend_opt.allowed()
|
||||
endif
|
||||
endif
|
||||
elif compiler_backend_opt.enabled()
|
||||
error('Need Go >= 1.26 to build the Compiler backend powered by ESBuild and typescript-go')
|
||||
error('Need Go >= 1.24 to build the Compiler backend powered by ESBuild and typescript-go')
|
||||
else
|
||||
warning('Building without Compiler backend: Go >= 1.26 not found')
|
||||
warning('Building without Compiler backend: Go >= 1.24 not found')
|
||||
endif
|
||||
endif
|
||||
|
||||
@@ -662,10 +548,8 @@ endif
|
||||
gi_dep = dependency('gobject-introspection-1.0', required: false)
|
||||
if gi_dep.found()
|
||||
girdir = gi_dep.get_variable('girdir')
|
||||
typelibdir = gi_dep.get_variable('typelibdir')
|
||||
else
|
||||
girdir = get_option('prefix') / get_option('datadir') / 'gir-1.0'
|
||||
typelibdir = get_option('prefix') / get_option('libdir') / 'girepository-1.0'
|
||||
endif
|
||||
|
||||
vapidir = get_option('prefix') / get_option('datadir') / 'vala' / 'vapi'
|
||||
@@ -674,15 +558,12 @@ gum_vala_args = [
|
||||
'--pkg=frida-gum-1.0',
|
||||
'--vapidir=' + gum_dep.get_variable('frida_vapidir'),
|
||||
]
|
||||
gumjs_vala_args = ['--pkg=frida-gumjs-1.0', '--pkg=gio-2.0', gum_vala_args]
|
||||
gumjs_inspector_vala_args = ['--pkg=frida-gumjs-inspector-1.0', gum_vala_args]
|
||||
|
||||
if have_in_tree_payloads
|
||||
gumjs_vala_args = ['--pkg=frida-gumjs-1.0', '--pkg=gio-2.0', gum_vala_args]
|
||||
|
||||
have_v8 = gumjs_dep.get_variable('gumjs_v8') == 'enabled'
|
||||
if have_v8
|
||||
vala_flags += ['--define=HAVE_V8']
|
||||
endif
|
||||
have_v8 = gumjs_dep.get_variable('gumjs_v8') == 'enabled'
|
||||
if have_v8
|
||||
vala_flags += ['--define=HAVE_V8']
|
||||
endif
|
||||
|
||||
backend_deps_private = []
|
||||
@@ -690,7 +571,6 @@ backend_reqs_private = []
|
||||
backend_libs_private = []
|
||||
|
||||
openssl_options = [
|
||||
'default_library=static',
|
||||
'cli=disabled',
|
||||
]
|
||||
if host_os_family == 'windows' and cc.get_argument_syntax() != 'msvc'
|
||||
@@ -703,48 +583,25 @@ openssl_dep = dependency('openssl',
|
||||
)
|
||||
|
||||
if have_fruity_backend
|
||||
backend_deps_private += dependency('libnghttp2', default_options: ['default_library=static'])
|
||||
backend_reqs_private += 'libnghttp2'
|
||||
foreach dep : ['libnghttp2', 'libngtcp2', 'libngtcp2_crypto_quictls', 'libusb-1.0']
|
||||
backend_deps_private += dependency(dep)
|
||||
backend_reqs_private += dep
|
||||
endforeach
|
||||
|
||||
if host_os != 'macos'
|
||||
backend_deps_private += dependency('libngtcp2', default_options: ['default_library=static'])
|
||||
backend_reqs_private += 'libngtcp2'
|
||||
|
||||
ngtcp2_crypto_quictls_dep = dependency('libngtcp2_crypto_quictls', required: false, default_options: ['default_library=static'])
|
||||
if ngtcp2_crypto_quictls_dep.found()
|
||||
backend_deps_private += ngtcp2_crypto_quictls_dep
|
||||
backend_reqs_private += 'libngtcp2_crypto_quictls'
|
||||
else
|
||||
backend_deps_private += dependency('libngtcp2_crypto_ossl', default_options: ['default_library=static'])
|
||||
backend_reqs_private += 'libngtcp2_crypto_ossl'
|
||||
vala_flags += '--define=HAVE_NGTCP2_CRYPTO_OSSL'
|
||||
endif
|
||||
|
||||
if have_frida_glib
|
||||
libusb_dep = dependency('libusb-1.0', default_options: ['default_library=static'])
|
||||
else
|
||||
subproject('libusb', default_options: ['default_library=static'])
|
||||
libusb_dep = dependency('libusb-1.0', default_options: ['default_library=static'])
|
||||
endif
|
||||
backend_deps_private += libusb_dep
|
||||
backend_reqs_private += 'libusb-1.0'
|
||||
|
||||
lwip_options = [
|
||||
'default_library=static',
|
||||
'ipv4=disabled',
|
||||
'ipv6=enabled',
|
||||
'dns=disabled',
|
||||
'arp=disabled',
|
||||
'ethernet=enabled',
|
||||
]
|
||||
if optimize_for_prod
|
||||
lwip_options += 'lwip_debug=disabled'
|
||||
else
|
||||
lwip_options += 'lwip_debug=enabled'
|
||||
endif
|
||||
backend_deps_private += dependency('lwip', default_options: lwip_options)
|
||||
backend_reqs_private += 'lwip'
|
||||
lwip_options = [
|
||||
'ipv4=disabled',
|
||||
'ipv6=enabled',
|
||||
'dns=disabled',
|
||||
'arp=disabled',
|
||||
'ethernet=enabled',
|
||||
]
|
||||
if optimize_for_prod
|
||||
lwip_options += 'lwip_debug=disabled'
|
||||
else
|
||||
lwip_options += 'lwip_debug=enabled'
|
||||
endif
|
||||
backend_deps_private += dependency('lwip', default_options: lwip_options)
|
||||
backend_reqs_private += 'lwip'
|
||||
endif
|
||||
|
||||
if quickjs_dep.found()
|
||||
@@ -754,113 +611,57 @@ endif
|
||||
|
||||
if lzfse_dep.found()
|
||||
backend_deps_private += lzfse_dep
|
||||
if lzfse_from_system
|
||||
backend_libs_private += '-llzfse'
|
||||
else
|
||||
backend_reqs_private += 'lzfse'
|
||||
endif
|
||||
backend_reqs_private += 'lzfse'
|
||||
endif
|
||||
|
||||
if host_os_family == 'linux' and have_local_backend
|
||||
if host_os_family == 'linux'
|
||||
backend_deps_private += libbpf_dep
|
||||
backend_reqs_private += 'libbpf'
|
||||
endif
|
||||
|
||||
if host_os_family == 'darwin' \
|
||||
or (host_os_family == 'freebsd' and not host_is_prospero) \
|
||||
or (host_os_family == 'linux' and cc.has_function('openpty', prefix: '#include <pty.h>'))
|
||||
if host_os_family in ['darwin', 'freebsd'] or (host_os_family == 'linux' and cc.has_function('openpty', prefix: '#include <pty.h>'))
|
||||
vala_flags += '--define=HAVE_OPENPTY'
|
||||
endif
|
||||
|
||||
if host_os == 'android'
|
||||
termux_elf_cleaner = find_program('termux-elf-cleaner', native: true)
|
||||
libselinux_dep = dependency('libselinux', version: '>=3.0', default_options: ['default_library=static'])
|
||||
libsepol_dep = dependency('libsepol', version: '>=3.0', default_options: ['default_library=static'])
|
||||
libselinux_dep = dependency('libselinux', version: '>=3.0')
|
||||
libsepol_dep = dependency('libsepol', version: '>=3.0')
|
||||
backend_deps_private += [libselinux_dep, libsepol_dep]
|
||||
backend_reqs_private += ['libselinux', 'libsepol']
|
||||
else
|
||||
termux_elf_cleaner = []
|
||||
endif
|
||||
|
||||
tls_provider_dep = dependency('gioopenssl', required: get_option('connectivity'), default_options: [
|
||||
'gnutls=disabled',
|
||||
'openssl=enabled',
|
||||
'libproxy=disabled',
|
||||
'gnome_proxy=disabled',
|
||||
'tests=false',
|
||||
])
|
||||
tls_provider_vala_args = []
|
||||
use_apple_tls = false
|
||||
if have_shared_glib
|
||||
tls_provider_dep = gio_dep
|
||||
else
|
||||
apple_tls_opt = get_option('apple_tls')
|
||||
if host_os_family == 'darwin' and not apple_tls_opt.disabled()
|
||||
apple_tls_deployment_check = '''
|
||||
#include <Availability.h>
|
||||
|
||||
#if defined (__MAC_OS_X_VERSION_MIN_REQUIRED) && __MAC_OS_X_VERSION_MIN_REQUIRED < 150000
|
||||
# error macOS deployment target below 15.0
|
||||
#endif
|
||||
#if defined (__IPHONE_OS_VERSION_MIN_REQUIRED) && __IPHONE_OS_VERSION_MIN_REQUIRED < 180000
|
||||
# error iOS deployment target below 18.0
|
||||
#endif
|
||||
#if defined (__TV_OS_VERSION_MIN_REQUIRED) && __TV_OS_VERSION_MIN_REQUIRED < 180000
|
||||
# error tvOS deployment target below 18.0
|
||||
#endif
|
||||
#if defined (__WATCH_OS_VERSION_MIN_REQUIRED) && __WATCH_OS_VERSION_MIN_REQUIRED < 110000
|
||||
# error watchOS deployment target below 11.0
|
||||
#endif
|
||||
'''
|
||||
use_apple_tls = cc.compiles(apple_tls_deployment_check, name: 'Apple TLS backend deployment target')
|
||||
if apple_tls_opt.enabled() and not use_apple_tls
|
||||
error('apple_tls explicitly enabled but deployment target is too old')
|
||||
endif
|
||||
elif apple_tls_opt.enabled()
|
||||
error('apple_tls is only supported on Darwin hosts')
|
||||
endif
|
||||
if use_apple_tls
|
||||
tls_provider_name = 'gioapple'
|
||||
tls_provider_define_name = 'HAVE_GIOAPPLE'
|
||||
tls_provider_backend_options = [
|
||||
'gnutls=disabled',
|
||||
'openssl=disabled',
|
||||
'apple=enabled',
|
||||
]
|
||||
else
|
||||
tls_provider_name = 'gioopenssl'
|
||||
tls_provider_define_name = 'HAVE_GIOOPENSSL'
|
||||
tls_provider_backend_options = [
|
||||
'gnutls=disabled',
|
||||
'openssl=enabled',
|
||||
'apple=disabled',
|
||||
]
|
||||
endif
|
||||
tls_provider_dep = dependency(tls_provider_name,
|
||||
required: get_option('connectivity'),
|
||||
default_options: tls_provider_backend_options + [
|
||||
'libproxy=disabled',
|
||||
'gnome_proxy=disabled',
|
||||
'tests=false',
|
||||
],
|
||||
)
|
||||
if tls_provider_dep.found()
|
||||
tls_provider_vala_args += [
|
||||
'--pkg=' + tls_provider_name,
|
||||
'--vapidir=' + tls_provider_dep.get_variable('vapidir'),
|
||||
]
|
||||
cdata.set(tls_provider_define_name, 1)
|
||||
vala_flags += ['--define=' + tls_provider_define_name]
|
||||
backend_deps_private += tls_provider_dep
|
||||
backend_reqs_private += tls_provider_name
|
||||
endif
|
||||
if tls_provider_dep.found()
|
||||
tls_provider_vala_args += [
|
||||
'--pkg=gioopenssl',
|
||||
'--vapidir=' + tls_provider_dep.get_variable('vapidir'),
|
||||
]
|
||||
cdata.set('HAVE_GIOOPENSSL', 1)
|
||||
vala_flags += ['--define=HAVE_GIOOPENSSL']
|
||||
backend_deps_private += tls_provider_dep
|
||||
backend_reqs_private += 'gioopenssl'
|
||||
endif
|
||||
|
||||
nice_dep = dependency('nice', required: get_option('connectivity'), default_options: [
|
||||
'default_library=static',
|
||||
'gupnp=disabled',
|
||||
'gstreamer=disabled',
|
||||
'crypto-library=auto',
|
||||
'crypto-library=openssl',
|
||||
'examples=disabled',
|
||||
'tests=disabled',
|
||||
'introspection=disabled',
|
||||
])
|
||||
if nice_dep.found()
|
||||
usrsctp_dep = dependency('usrsctp', default_options: [
|
||||
'default_library=static',
|
||||
'sctp_inet=false',
|
||||
'sctp_inet6=false',
|
||||
'sctp_build_programs=false',
|
||||
@@ -868,12 +669,8 @@ if nice_dep.found()
|
||||
|
||||
cdata.set('HAVE_NICE', 1)
|
||||
vala_flags += ['--define=HAVE_NICE']
|
||||
backend_deps_private += [nice_dep, usrsctp_dep]
|
||||
backend_reqs_private += ['nice', 'usrsctp']
|
||||
if host_os != 'macos'
|
||||
backend_deps_private += openssl_dep
|
||||
backend_reqs_private += 'openssl'
|
||||
endif
|
||||
backend_deps_private += [nice_dep, openssl_dep, usrsctp_dep]
|
||||
backend_reqs_private += ['nice', 'openssl', 'usrsctp']
|
||||
|
||||
if host_os_family in ['darwin', 'freebsd', 'qnx']
|
||||
cdata.set('HAVE_SCONN_LEN', 1)
|
||||
@@ -883,26 +680,20 @@ else
|
||||
endif
|
||||
|
||||
if host_os_family == 'windows'
|
||||
backend_libs_private += ['-lsetupapi', '-lshlwapi']
|
||||
backend_libs_private += ['-lsetupapi']
|
||||
endif
|
||||
if host_os_family == 'darwin'
|
||||
backend_libs_private += ['-Wl,-framework,Foundation', '-Wl,-framework,CoreFoundation', '-lbsm']
|
||||
backend_libs_private += ['-Wl,-framework,Foundation', '-lbsm']
|
||||
endif
|
||||
if host_os == 'macos'
|
||||
backend_libs_private += ['-Wl,-framework,AppKit']
|
||||
if have_compiler_backend
|
||||
backend_libs_private += ['-Wl,-framework,CoreServices']
|
||||
endif
|
||||
endif
|
||||
if host_os in ['ios', 'tvos']
|
||||
backend_libs_private += ['-Wl,-framework,CoreGraphics', '-Wl,-framework,UIKit']
|
||||
endif
|
||||
if host_os_family == 'freebsd' and not host_is_prospero
|
||||
if host_os_family == 'freebsd'
|
||||
backend_libs_private += ['-lutil']
|
||||
endif
|
||||
if host_is_prospero
|
||||
backend_libs_private += ['-lSceSystemService', '-lSceUserService']
|
||||
endif
|
||||
|
||||
if get_option('devkits').length() != 0
|
||||
if get_option('default_library') != 'static'
|
||||
@@ -962,19 +753,6 @@ post_process = [
|
||||
'@INPUT0@',
|
||||
]
|
||||
|
||||
executable_no_exports_link_args = []
|
||||
executable_no_exports_link_depends = []
|
||||
if host_os_family == 'darwin'
|
||||
script = meson.project_source_root() / 'tools' / 'executable-no-exports.symbols'
|
||||
executable_no_exports_link_args = ['-Wl,-exported_symbols_list,' + script]
|
||||
executable_no_exports_link_depends = [script]
|
||||
elif host_os_family != 'windows'
|
||||
script_name = (host_os == 'freebsd' and not host_is_prospero) ? 'executable-no-exports-freebsd.version' : 'executable-no-exports.version'
|
||||
script = meson.project_source_root() / 'tools' / script_name
|
||||
executable_no_exports_link_args = ['-Wl,--version-script,' + script]
|
||||
executable_no_exports_link_depends = [script]
|
||||
endif
|
||||
|
||||
compile_js_agent = files('tools' / 'compile-js-agent.py')
|
||||
|
||||
mapper_opt = get_option('mapper')
|
||||
@@ -1005,20 +783,11 @@ if cc.get_id() == 'gcc' and cc.compiles('#if __GNUC__ >= 5\n#error NOTNEEDED\n#e
|
||||
add_project_arguments('-w', language: 'c')
|
||||
endif
|
||||
|
||||
local_vapidir = meson.current_source_dir() / 'vapi'
|
||||
vapidir = meson.current_source_dir() / 'vapi'
|
||||
vala_flags += [
|
||||
'--vapidir=' + local_vapidir,
|
||||
'--vapidir=' + vapidir,
|
||||
'--pkg', 'config',
|
||||
]
|
||||
if gee_dep.type_name() not in ['internal', 'cmake']
|
||||
gee_prefix = gee_dep.get_variable('prefix', default_value: '')
|
||||
if gee_prefix != ''
|
||||
gee_vapidir = gee_prefix / 'share' / 'vala' / 'vapi'
|
||||
if fs.is_dir(gee_vapidir)
|
||||
vala_flags += '--vapidir=' + gee_vapidir
|
||||
endif
|
||||
endif
|
||||
endif
|
||||
|
||||
vala_flags += '--define=' + host_os_family.to_upper()
|
||||
if host_os != host_os_family
|
||||
@@ -1030,22 +799,13 @@ if host_abi != host_arch
|
||||
endif
|
||||
vala_flags += '--define=' + host_machine.endian().to_upper() + '_ENDIAN'
|
||||
add_project_arguments(vala_flags, language: 'vala')
|
||||
add_project_arguments('-I' + local_vapidir, language: 'c')
|
||||
add_project_arguments('-I' + vapidir, language: 'c')
|
||||
|
||||
native_vala_flags = [
|
||||
'--vapidir=' + local_vapidir,
|
||||
'--vapidir=' + meson.current_source_dir() / 'vapi',
|
||||
]
|
||||
if native_gee_dep.type_name() not in ['internal', 'cmake']
|
||||
native_gee_prefix = native_gee_dep.get_variable('prefix', default_value: '')
|
||||
if native_gee_prefix != ''
|
||||
native_gee_vapidir = native_gee_prefix / 'share' / 'vala' / 'vapi'
|
||||
if fs.is_dir(native_gee_vapidir)
|
||||
native_vala_flags += '--vapidir=' + native_gee_vapidir
|
||||
endif
|
||||
endif
|
||||
endif
|
||||
add_project_arguments(native_vala_flags, language: 'vala', native: true)
|
||||
add_project_arguments('-I' + local_vapidir, language: 'c', native: true)
|
||||
add_project_arguments('-I' + vapidir, language: 'c', native: true)
|
||||
|
||||
subdir('compat')
|
||||
subdir('tools')
|
||||
@@ -1080,7 +840,7 @@ summary(
|
||||
summary(
|
||||
{
|
||||
'compat': compat_summary,
|
||||
'assets': assets_mode,
|
||||
'assets': get_option('assets'),
|
||||
'mapper': have_mapper,
|
||||
'connectivity': tls_provider_dep.found(),
|
||||
'gadget': build_gadget,
|
||||
|
||||
+2
-8
@@ -48,8 +48,8 @@ option('compiler_backend',
|
||||
|
||||
option('assets',
|
||||
type: 'combo',
|
||||
choices: ['auto', 'embedded', 'installed'],
|
||||
value: 'auto',
|
||||
choices: ['embedded', 'installed'],
|
||||
value: 'embedded',
|
||||
description: 'Whether assets such as frida-agent should be embedded vs installed and loaded at runtime'
|
||||
)
|
||||
|
||||
@@ -143,12 +143,6 @@ option('connectivity',
|
||||
description: 'Internet connectivity features (TLS and ICE support)'
|
||||
)
|
||||
|
||||
option('apple_tls',
|
||||
type: 'feature',
|
||||
value: 'auto',
|
||||
description: 'Use the Apple TLS backend (requires recent deployment targets); auto-detected when on a Darwin host'
|
||||
)
|
||||
|
||||
option('mapper',
|
||||
type: 'feature',
|
||||
value: 'auto',
|
||||
|
||||
@@ -0,0 +1 @@
|
||||
# No exported symbols.
|
||||
@@ -0,0 +1,9 @@
|
||||
{
|
||||
global:
|
||||
# FreeBSD needs these two:
|
||||
__progname;
|
||||
environ;
|
||||
|
||||
local:
|
||||
*;
|
||||
};
|
||||
+14
-2
@@ -2,6 +2,18 @@ portal_sources = [
|
||||
'portal.vala',
|
||||
]
|
||||
|
||||
extra_link_args = []
|
||||
extra_link_depends = []
|
||||
if host_os_family == 'darwin'
|
||||
symlist = 'frida-portal.symbols'
|
||||
extra_link_args += ['-Wl,-exported_symbols_list,' + meson.current_source_dir() / symlist]
|
||||
extra_link_depends += [symlist]
|
||||
elif host_os_family != 'windows'
|
||||
symscript = 'frida-portal.version'
|
||||
extra_link_args += ['-Wl,--version-script,' + meson.current_source_dir() / symscript]
|
||||
extra_link_depends += [symscript]
|
||||
endif
|
||||
|
||||
extra_deps = []
|
||||
if tls_provider_dep.found()
|
||||
extra_deps += tls_provider_dep
|
||||
@@ -9,8 +21,8 @@ endif
|
||||
|
||||
raw_portal = executable('frida-portal-raw', portal_sources,
|
||||
vala_args: [core_vala_args, tls_provider_vala_args, '--pkg=posix'],
|
||||
link_args: executable_no_exports_link_args,
|
||||
link_depends: executable_no_exports_link_depends,
|
||||
link_args: extra_link_args,
|
||||
link_depends: extra_link_depends,
|
||||
dependencies: [core_dep] + extra_deps,
|
||||
)
|
||||
|
||||
|
||||
+1
-3
@@ -39,9 +39,7 @@ namespace Frida.Portal {
|
||||
};
|
||||
|
||||
private static int main (string[] args) {
|
||||
#if HAVE_GIOAPPLE
|
||||
GIOApple.register ();
|
||||
#elif HAVE_GIOOPENSSL
|
||||
#if HAVE_GIOOPENSSL
|
||||
GIOOpenSSL.register ();
|
||||
#endif
|
||||
|
||||
|
||||
+1
-1
Submodule releng updated: d6b56b460b...7ed66fe687.
@@ -1,11 +0,0 @@
|
||||
{
|
||||
global:
|
||||
# FreeBSD needs these two:
|
||||
__progname;
|
||||
environ;
|
||||
# Allow users to load the server as a shared library with dlopen() and call main() directly
|
||||
main;
|
||||
|
||||
local:
|
||||
*;
|
||||
};
|
||||
@@ -1,2 +1 @@
|
||||
# Allow users to load the server as a shared library with dlopen() and call main() directly
|
||||
_main
|
||||
# No exported symbols.
|
||||
@@ -1,5 +1,8 @@
|
||||
{
|
||||
global:
|
||||
# FreeBSD needs these two:
|
||||
__progname;
|
||||
environ;
|
||||
# Allow users to load the server as a shared library with dlopen() and call main() directly
|
||||
main;
|
||||
|
||||
|
||||
+3
-8
@@ -19,7 +19,7 @@ if host_os_family == 'darwin'
|
||||
extra_link_args += ['-Wl,-exported_symbols_list,' + meson.current_source_dir() / symlist]
|
||||
extra_link_depends += [symlist]
|
||||
elif host_os_family != 'windows'
|
||||
symscript = (host_os == 'freebsd' and not host_is_prospero) ? 'frida-server-freebsd.version' : 'frida-server.version'
|
||||
symscript = 'frida-server.version'
|
||||
extra_link_args += ['-Wl,--version-script,' + meson.current_source_dir() / symscript]
|
||||
extra_link_depends += [symscript]
|
||||
endif
|
||||
@@ -29,20 +29,15 @@ if host_os == 'macos'
|
||||
extra_link_depends += [server_plist]
|
||||
endif
|
||||
|
||||
server_deps = [core_dep]
|
||||
if host_os_family == 'darwin'
|
||||
server_deps += dependency('appleframeworks', modules: ['CoreFoundation'])
|
||||
endif
|
||||
|
||||
raw_server = executable('frida-server-raw', server_sources,
|
||||
vala_args: [core_vala_args, '--pkg=posix'],
|
||||
link_args: extra_link_args,
|
||||
link_depends: extra_link_depends,
|
||||
dependencies: server_deps,
|
||||
dependencies: [core_dep],
|
||||
)
|
||||
|
||||
server_name = 'frida-server' + exe_suffix
|
||||
need_universal_server = assets_mode == 'installed' and server_compat != ''
|
||||
need_universal_server = get_option('assets') == 'installed' and server_compat != ''
|
||||
|
||||
server = custom_target('frida-server',
|
||||
input: [raw_server, 'frida-server.xcent'],
|
||||
|
||||
@@ -29,8 +29,6 @@ void CFLog (CFLogLevel level, CFStringRef format, ...);
|
||||
|
||||
#elif defined (HAVE_ANDROID)
|
||||
# include <android/log.h>
|
||||
#elif defined (HAVE_PROSPERO)
|
||||
# include <ps5/klog.h>
|
||||
#else
|
||||
# include <stdio.h>
|
||||
#endif
|
||||
@@ -139,13 +137,6 @@ frida_server_on_log_message (const gchar * log_domain, GLogLevelFlags log_level,
|
||||
}
|
||||
|
||||
__android_log_write (priority, log_domain, message);
|
||||
#elif defined (HAVE_PROSPERO)
|
||||
(void) user_data;
|
||||
|
||||
if (log_domain != NULL)
|
||||
klog_printf ("%s: %s\n", log_domain, message);
|
||||
else
|
||||
klog_printf ("%s\n", message);
|
||||
#else
|
||||
FILE * file = NULL;
|
||||
const gchar * severity = NULL;
|
||||
|
||||
+4
-2
@@ -104,8 +104,9 @@ namespace Frida.Server {
|
||||
return true;
|
||||
});
|
||||
int prefix_pos = program_path.last_index_of (Config.FRIDA_PREFIX + "/");
|
||||
if (prefix_pos != -1 && prefix_pos != 0)
|
||||
TemporaryDirectory.use_sysroot (program_path[:prefix_pos]);
|
||||
if (prefix_pos != -1 && prefix_pos != 0) {
|
||||
options.sysroot = program_path[:prefix_pos];
|
||||
}
|
||||
#endif
|
||||
|
||||
PolicySoftenerFlavor softener_flavor = SYSTEM;
|
||||
@@ -198,6 +199,7 @@ namespace Frida.Server {
|
||||
private static int run_application (string? device_id, EndpointParameters endpoint_params, ControlServiceOptions options,
|
||||
ReadyHandler on_ready) {
|
||||
TemporaryDirectory.always_use ((directory != null) ? directory : DEFAULT_DIRECTORY);
|
||||
TemporaryDirectory.use_sysroot (options.sysroot);
|
||||
|
||||
application = new Application (device_id, endpoint_params, options);
|
||||
|
||||
|
||||
@@ -11,7 +11,7 @@ helper.dex: build/frida-helper.jar
|
||||
$<
|
||||
mv build/classes.dex $@
|
||||
|
||||
build/frida-helper.jar: re/frida/Helper.java re/frida/HelperBackend.java
|
||||
build/frida-helper.jar: re/frida/Helper.java
|
||||
javac \
|
||||
-cp .:$(android_jar) \
|
||||
-bootclasspath $(android_jar) \
|
||||
|
||||
+63
-161
@@ -1,94 +1,66 @@
|
||||
namespace Frida {
|
||||
public sealed class AndroidHelperClient : Object {
|
||||
public AndroidHelperTransport transport {
|
||||
public sealed class AndroidHelperClient : Object, AsyncInitable {
|
||||
public signal void closed ();
|
||||
|
||||
public IOStream stream {
|
||||
get;
|
||||
construct;
|
||||
}
|
||||
|
||||
private AdbShellSession? shell;
|
||||
private BufferedInputStream input;
|
||||
private OutputStream output;
|
||||
private Cancellable io_cancellable = new Cancellable ();
|
||||
|
||||
public AndroidHelperClient (AndroidHelperTransport transport) {
|
||||
Object (transport: transport);
|
||||
private State state = CLOSED;
|
||||
private Gee.Queue<Request> pending_requests = new Gee.ArrayQueue<Request> ();
|
||||
|
||||
private ByteArray pending_output = new ByteArray ();
|
||||
private bool writing = false;
|
||||
|
||||
private enum State {
|
||||
CLOSED,
|
||||
OPEN
|
||||
}
|
||||
|
||||
public static async AndroidHelperClient open (string serial, Cancellable? cancellable) throws Error, IOError {
|
||||
string instance_id = Uuid.string_random ().replace ("-", "");
|
||||
string helper_path = "/data/local/tmp/frida-helper-" + instance_id + ".dex";
|
||||
private const uint32 MAX_RESPONSE_SIZE = 100 * 1024 * 1024;
|
||||
|
||||
var helper_dex = new MemoryInputStream.from_bytes (
|
||||
new Bytes.static (Frida.Data.Android.get_helper_dex_blob ().data));
|
||||
var helper_meta = new AdbFileMetadata ();
|
||||
helper_meta.mode = 0100644;
|
||||
helper_meta.time_modified = new DateTime.now_utc ();
|
||||
yield AdbFileSync.send (helper_dex, helper_meta, helper_path, serial, cancellable);
|
||||
public AndroidHelperClient (IOStream stream) {
|
||||
Object (stream: stream);
|
||||
}
|
||||
|
||||
var shell = new AdbShellSession ();
|
||||
try {
|
||||
var output = new StringBuilder ();
|
||||
bool waiting = false;
|
||||
var output_handler = shell.output.connect ((pipe, bytes) => {
|
||||
if (pipe == STDOUT) {
|
||||
output.append ((string) bytes.get_data ());
|
||||
if (waiting)
|
||||
open.callback ();
|
||||
}
|
||||
});
|
||||
try {
|
||||
yield shell.open (serial, cancellable);
|
||||
construct {
|
||||
input = (BufferedInputStream) Object.new (typeof (BufferedInputStream),
|
||||
"base-stream", stream.get_input_stream (),
|
||||
"close-base-stream", false,
|
||||
"buffer-size", 128 * 1024);
|
||||
output = stream.get_output_stream ();
|
||||
|
||||
shell.send_command (("CLASSPATH=%s app_process /data/local/tmp " +
|
||||
"--nice-name=re.frida.helper re.frida.Helper %s; rm -f %s; echo BYE.")
|
||||
.printf (helper_path, instance_id, helper_path));
|
||||
state = OPEN;
|
||||
|
||||
while (!output.str.has_prefix ("READY.\n")) {
|
||||
waiting = true;
|
||||
yield;
|
||||
waiting = false;
|
||||
|
||||
if (output.str.has_prefix ("BYE.\n"))
|
||||
throw new Error.NOT_SUPPORTED ("Unable to start helper");
|
||||
}
|
||||
} finally {
|
||||
shell.disconnect (output_handler);
|
||||
}
|
||||
|
||||
var client = yield AdbClient.open (cancellable);
|
||||
try {
|
||||
yield client.request ("host:transport:" + serial, cancellable);
|
||||
yield client.request_protocol_change ("localabstract:/frida-helper-" + instance_id,
|
||||
cancellable);
|
||||
} catch (GLib.Error e) {
|
||||
client.close.begin ();
|
||||
throw e;
|
||||
}
|
||||
|
||||
var helper = new AndroidHelperClient (new AndroidHelperStreamTransport (client.stream));
|
||||
helper.shell = shell;
|
||||
helper.transport.closed.connect (helper.release_shell);
|
||||
|
||||
return helper;
|
||||
} catch (GLib.Error e) {
|
||||
shell.close.begin ();
|
||||
if (e is IOError.CANCELLED)
|
||||
throw (IOError) e;
|
||||
throw new Error.NOT_SUPPORTED ("%s", e.message);
|
||||
}
|
||||
process_incoming_responses.begin ();
|
||||
}
|
||||
|
||||
public async void close (Cancellable? cancellable) throws IOError {
|
||||
yield transport.close (cancellable);
|
||||
io_cancellable.cancel ();
|
||||
|
||||
if (shell != null) {
|
||||
yield shell.close (cancellable);
|
||||
shell = null;
|
||||
var source = new IdleSource ();
|
||||
source.set_callback (close.callback);
|
||||
source.attach (MainContext.get_thread_default ());
|
||||
yield;
|
||||
|
||||
try {
|
||||
yield stream.close_async (Priority.DEFAULT, cancellable);
|
||||
} catch (IOError e) {
|
||||
}
|
||||
|
||||
ensure_closed ();
|
||||
}
|
||||
|
||||
private void release_shell () {
|
||||
if (shell != null) {
|
||||
shell.close.begin ();
|
||||
shell = null;
|
||||
}
|
||||
private void ensure_closed () {
|
||||
if (state == CLOSED)
|
||||
return;
|
||||
state = CLOSED;
|
||||
closed ();
|
||||
}
|
||||
|
||||
public async HostApplicationInfo get_frontmost_application (FrontmostQueryOptions options,
|
||||
@@ -100,12 +72,12 @@ namespace Frida {
|
||||
.add_string_value (options.scope.to_nick ())
|
||||
.end_array ();
|
||||
|
||||
Json.Node response = yield transport.request (stanza.get_root (), cancellable);
|
||||
Json.Node response = yield request (stanza.get_root (), cancellable);
|
||||
|
||||
if (response.is_null ())
|
||||
return HostApplicationInfo.empty ();
|
||||
|
||||
Json.Reader reader = make_json_reader_taking_node ((owned) response);
|
||||
Json.Reader reader = new Json.Reader (response);
|
||||
|
||||
string? identifier = null;
|
||||
string? name = null;
|
||||
@@ -155,9 +127,9 @@ namespace Frida {
|
||||
.add_string_value (options.scope.to_nick ())
|
||||
.end_array ();
|
||||
|
||||
Json.Node response = yield transport.request (stanza.get_root (), cancellable);
|
||||
Json.Node response = yield request (stanza.get_root (), cancellable);
|
||||
|
||||
Json.Reader reader = make_json_reader_taking_node ((owned) response);
|
||||
Json.Reader reader = new Json.Reader (response);
|
||||
|
||||
int num_apps = reader.count_elements ();
|
||||
if (num_apps == -1)
|
||||
@@ -221,9 +193,9 @@ namespace Frida {
|
||||
.add_string_value (options.scope.to_nick ())
|
||||
.end_array ();
|
||||
|
||||
Json.Node response = yield transport.request (stanza.get_root (), cancellable);
|
||||
Json.Node response = yield request (stanza.get_root (), cancellable);
|
||||
|
||||
Json.Reader reader = make_json_reader_taking_node ((owned) response);
|
||||
Json.Reader reader = new Json.Reader (response);
|
||||
|
||||
int num_processes = reader.count_elements ();
|
||||
if (num_processes == -1)
|
||||
@@ -275,9 +247,9 @@ namespace Frida {
|
||||
.add_int_value (uid)
|
||||
.end_array ();
|
||||
|
||||
Json.Node response = yield transport.request (stanza.get_root (), cancellable);
|
||||
Json.Node response = yield request (stanza.get_root (), cancellable);
|
||||
|
||||
var r = make_json_reader_taking_node ((owned) response);
|
||||
var r = new Json.Reader (response);
|
||||
parse_envelope_or_throw (r);
|
||||
|
||||
r.read_element (1);
|
||||
@@ -345,9 +317,9 @@ namespace Frida {
|
||||
.add_int_value (uid)
|
||||
.end_array ();
|
||||
|
||||
Json.Node response = yield transport.request (stanza.get_root (), cancellable);
|
||||
Json.Node response = yield request (stanza.get_root (), cancellable);
|
||||
|
||||
var r = make_json_reader_taking_node ((owned) response);
|
||||
var r = new Json.Reader (response);
|
||||
parse_envelope_or_throw (r);
|
||||
}
|
||||
|
||||
@@ -359,9 +331,9 @@ namespace Frida {
|
||||
.add_int_value ((int) pid)
|
||||
.end_array ();
|
||||
|
||||
Json.Node response = yield transport.request (stanza.get_root (), cancellable);
|
||||
Json.Node response = yield request (stanza.get_root (), cancellable);
|
||||
|
||||
var r = make_json_reader_taking_node ((owned) response);
|
||||
var r = new Json.Reader (response);
|
||||
parse_envelope_or_throw (r);
|
||||
|
||||
r.read_element (1);
|
||||
@@ -371,13 +343,6 @@ namespace Frida {
|
||||
return r.get_boolean_value ();
|
||||
}
|
||||
|
||||
private async void request_ok (Json.Builder stanza, Cancellable? cancellable) throws Error, IOError {
|
||||
Json.Node response = yield transport.request (stanza.get_root (), cancellable);
|
||||
|
||||
var r = make_json_reader_taking_node ((owned) response);
|
||||
parse_envelope_or_throw (r);
|
||||
}
|
||||
|
||||
private void parse_envelope_or_throw (Json.Reader r) throws Error {
|
||||
r.read_element (0);
|
||||
string? kind = r.get_string_value ();
|
||||
@@ -487,76 +452,6 @@ namespace Frida {
|
||||
|
||||
throw new Error.PROTOCOL ("Unexpected JSON type: %s", type.name ());
|
||||
}
|
||||
}
|
||||
|
||||
public interface AndroidHelperTransport : Object {
|
||||
public signal void closed ();
|
||||
|
||||
public abstract async void close (Cancellable? cancellable) throws IOError;
|
||||
public abstract async Json.Node request (Json.Node stanza, Cancellable? cancellable) throws Error, IOError;
|
||||
}
|
||||
|
||||
public sealed class AndroidHelperStreamTransport : Object, AndroidHelperTransport {
|
||||
public IOStream stream {
|
||||
get;
|
||||
construct;
|
||||
}
|
||||
|
||||
private BufferedInputStream input;
|
||||
private OutputStream output;
|
||||
private Cancellable io_cancellable = new Cancellable ();
|
||||
|
||||
private State state = CLOSED;
|
||||
private Gee.Queue<Request> pending_requests = new Gee.ArrayQueue<Request> ();
|
||||
|
||||
private ByteArray pending_output = new ByteArray ();
|
||||
private bool writing = false;
|
||||
|
||||
private enum State {
|
||||
CLOSED,
|
||||
OPEN
|
||||
}
|
||||
|
||||
private const uint32 MAX_RESPONSE_SIZE = 100 * 1024 * 1024;
|
||||
|
||||
public AndroidHelperStreamTransport (IOStream stream) {
|
||||
Object (stream: stream);
|
||||
}
|
||||
|
||||
construct {
|
||||
input = (BufferedInputStream) Object.new (typeof (BufferedInputStream),
|
||||
"base-stream", stream.get_input_stream (),
|
||||
"close-base-stream", false,
|
||||
"buffer-size", 128 * 1024);
|
||||
output = stream.get_output_stream ();
|
||||
|
||||
state = OPEN;
|
||||
|
||||
process_incoming_responses.begin ();
|
||||
}
|
||||
|
||||
public async void close (Cancellable? cancellable) throws IOError {
|
||||
io_cancellable.cancel ();
|
||||
|
||||
var source = new IdleSource ();
|
||||
source.set_callback (close.callback);
|
||||
source.attach (MainContext.get_thread_default ());
|
||||
yield;
|
||||
|
||||
try {
|
||||
yield stream.close_async (Priority.DEFAULT, cancellable);
|
||||
} catch (IOError e) {
|
||||
}
|
||||
|
||||
ensure_closed ();
|
||||
}
|
||||
|
||||
private void ensure_closed () {
|
||||
if (state == CLOSED)
|
||||
return;
|
||||
state = CLOSED;
|
||||
closed ();
|
||||
}
|
||||
|
||||
public async Json.Node request (Json.Node stanza, Cancellable? cancellable) throws Error, IOError {
|
||||
if (state == CLOSED)
|
||||
@@ -592,6 +487,13 @@ namespace Frida {
|
||||
return r.response;
|
||||
}
|
||||
|
||||
private async void request_ok (Json.Builder stanza, Cancellable? cancellable) throws Error, IOError {
|
||||
Json.Node response = yield request (stanza.get_root (), cancellable);
|
||||
|
||||
var r = new Json.Reader (response);
|
||||
parse_envelope_or_throw (r);
|
||||
}
|
||||
|
||||
private void write_request (Json.Node request) {
|
||||
string request_str = Json.to_string (request, false);
|
||||
uint8[] request_data = request_str.data;
|
||||
|
||||
Binary file not shown.
File diff suppressed because it is too large.
Load diff
File diff suppressed because it is too large.
Load diff
File diff suppressed because it is too large.
Load diff
+50
-484
@@ -21,60 +21,59 @@ CORE_TAG_FIELD = f"{{{CORE_NAMESPACE}}}field"
|
||||
CORE_TAG_CONSTRUCTOR = f"{{{CORE_NAMESPACE}}}constructor"
|
||||
CORE_TAG_METHOD = f"{{{CORE_NAMESPACE}}}method"
|
||||
|
||||
INTERNAL_INTERFACES = {
|
||||
"Frida.HostSessionHub",
|
||||
"Frida.AgentMessageSink",
|
||||
"FridaBase.AgentMessageSink",
|
||||
"Json.Serializable",
|
||||
}
|
||||
|
||||
OBJECT_TYPE_PATTERN = re.compile(r"\bpublic\s+(sealed |abstract )?(class|interface)\s+(\w+)\b")
|
||||
|
||||
TOPLEVEL_NAMES = [
|
||||
"frida.vala",
|
||||
"linux-kernel-image.vala",
|
||||
"xnu-kernelcache.vala",
|
||||
"package-manager.vala",
|
||||
"control-service.vala",
|
||||
"portal-service.vala",
|
||||
"file-monitor.vala",
|
||||
Path("compiler") / "compiler.vala",
|
||||
]
|
||||
OBJECT_TYPE_PATTERN = re.compile(r"\bpublic\s+(sealed )?(class|interface)\s+(\w+)\b")
|
||||
|
||||
def main():
|
||||
parser = argparse.ArgumentParser(description="Generate refined Frida API definitions")
|
||||
parser.add_argument('--output', dest='output_type', choices=['bundle', 'header', 'gir', 'vapi', 'vapi-stamp', 'symbol-maps'], default='bundle')
|
||||
parser.add_argument('--output', dest='output_type', choices=['bundle', 'header', 'gir', 'vapi', 'vapi-stamp'], default='bundle')
|
||||
parser.add_argument('frida_version', metavar='frida-version', type=str)
|
||||
parser.add_argument('frida_major_version', metavar='frida-major-version', type=str)
|
||||
parser.add_argument('frida_minor_version', metavar='frida-minor-version', type=str)
|
||||
parser.add_argument('frida_micro_version', metavar='frida-micro-version', type=str)
|
||||
parser.add_argument('frida_nano_version', metavar='frida-nano-version', type=str)
|
||||
parser.add_argument('api_version', metavar='api-version', type=str)
|
||||
parser.add_argument('core_header', metavar='/path/to/frida-core.h', type=argparse.FileType('r', encoding='utf-8'))
|
||||
parser.add_argument('core_gir', metavar='/path/to/Frida-x.y.gir', type=argparse.FileType('r', encoding='utf-8'))
|
||||
parser.add_argument('core_vapi', metavar='/path/to/frida-core.vapi', type=argparse.FileType('r', encoding='utf-8'))
|
||||
parser.add_argument('base_header', metavar='/path/to/frida-base.h', type=argparse.FileType('r', encoding='utf-8'))
|
||||
parser.add_argument('base_gir', metavar='/path/to/FridaBase-x.y.gir', type=argparse.FileType('r', encoding='utf-8'))
|
||||
parser.add_argument('base_vapi', metavar='/path/to/frida-base.vapi', type=argparse.FileType('r', encoding='utf-8'))
|
||||
parser.add_argument('output_dir', metavar='/output/dir')
|
||||
parser.add_argument('extra_args', nargs='*')
|
||||
|
||||
args = parser.parse_args()
|
||||
|
||||
output_type = args.output_type
|
||||
frida_version = args.frida_version
|
||||
frida_version_components = (
|
||||
args.frida_major_version,
|
||||
args.frida_minor_version,
|
||||
args.frida_micro_version,
|
||||
args.frida_nano_version,
|
||||
)
|
||||
api_version = args.api_version
|
||||
core_header = args.core_header.read()
|
||||
core_gir = args.core_gir.read()
|
||||
core_vapi = args.core_vapi.read()
|
||||
base_header = args.base_header.read()
|
||||
base_gir = args.base_gir.read()
|
||||
base_vapi = args.base_vapi.read()
|
||||
output_dir = Path(args.output_dir)
|
||||
|
||||
if output_type == 'symbol-maps':
|
||||
emit_symbol_maps_from_source(output_dir)
|
||||
return
|
||||
|
||||
extra = args.extra_args
|
||||
frida_version = extra[0]
|
||||
frida_version_components = tuple(extra[1:5])
|
||||
api_version = extra[5]
|
||||
|
||||
if output_type == 'vapi-stamp':
|
||||
(output_dir / f"frida-core-{api_version}.vapi.stamp").write_bytes(b"")
|
||||
return
|
||||
|
||||
core_header = Path(extra[6]).read_text(encoding='utf-8')
|
||||
core_gir = Path(extra[7]).read_text(encoding='utf-8')
|
||||
core_vapi = Path(extra[8]).read_text(encoding='utf-8')
|
||||
base_header = Path(extra[9]).read_text(encoding='utf-8')
|
||||
base_gir = Path(extra[10]).read_text(encoding='utf-8')
|
||||
base_vapi = Path(extra[11]).read_text(encoding='utf-8')
|
||||
|
||||
toplevel_names = [
|
||||
"frida.vala",
|
||||
"package-manager.vala",
|
||||
"control-service.vala",
|
||||
"portal-service.vala",
|
||||
"file-monitor.vala",
|
||||
Path("compiler") / "compiler.vala",
|
||||
]
|
||||
toplevel_sources = []
|
||||
src_dir = Path(__file__).parent.parent.resolve()
|
||||
for name in TOPLEVEL_NAMES:
|
||||
for name in toplevel_names:
|
||||
toplevel_sources.append((src_dir / name).read_text(encoding='utf-8'))
|
||||
toplevel_code = "\n".join(toplevel_sources)
|
||||
|
||||
@@ -98,7 +97,7 @@ def main():
|
||||
emit_header(api, output_dir)
|
||||
|
||||
if enable_gir:
|
||||
emit_gir(api, core_gir, base_gir, output_dir, build_doc_index(src_dir))
|
||||
emit_gir(api, core_gir, base_gir, output_dir)
|
||||
|
||||
if enable_vapi:
|
||||
emit_vapi(api, output_dir)
|
||||
@@ -140,7 +139,6 @@ def emit_header(api, output_dir):
|
||||
|
||||
output_header_file.write("\n\n/* Library lifetime */")
|
||||
output_header_file.write("\nvoid frida_init (void);")
|
||||
output_header_file.write("\nvoid frida_init_with_runtime (FridaRuntime runtime);")
|
||||
output_header_file.write("\nvoid frida_shutdown (void);")
|
||||
output_header_file.write("\nvoid frida_deinit (void);")
|
||||
output_header_file.write("\nGMainContext * frida_get_main_context (void);")
|
||||
@@ -205,7 +203,7 @@ def emit_header(api, output_dir):
|
||||
|
||||
output_header_file.write("\n\n#endif\n")
|
||||
|
||||
def emit_gir(api: ApiSpec, core_gir: str, base_gir: str, output_dir: Path, docs: DocIndex) -> str:
|
||||
def emit_gir(api: ApiSpec, core_gir: str, base_gir: str, output_dir: Path) -> str:
|
||||
ET.register_namespace("", CORE_NAMESPACE)
|
||||
ET.register_namespace("c", C_NAMESPACE)
|
||||
ET.register_namespace("glib", GLIB_NAMESPACE)
|
||||
@@ -240,10 +238,10 @@ def emit_gir(api: ApiSpec, core_gir: str, base_gir: str, output_dir: Path, docs:
|
||||
for elem in core_elements + base_elements:
|
||||
if tag_name == "class":
|
||||
for child in list(elem):
|
||||
if (child.tag == CORE_TAG_IMPLEMENTS and child.get("name") in INTERNAL_INTERFACES) \
|
||||
if (child.tag == CORE_TAG_IMPLEMENTS and child.get("name") in {"Frida.HostSessionHub", "Frida.AgentMessageSink",
|
||||
"FridaBase.AgentMessageSink"}) \
|
||||
or child.tag == CORE_TAG_FIELD \
|
||||
or child.get("name").startswith("_") \
|
||||
or (child.tag == CORE_TAG_CONSTRUCTOR and is_async_constructor(child)):
|
||||
or child.get("name").startswith("_"):
|
||||
elem.remove(child)
|
||||
merged_namespace.append(elem)
|
||||
|
||||
@@ -251,38 +249,6 @@ def emit_gir(api: ApiSpec, core_gir: str, base_gir: str, output_dir: Path, docs:
|
||||
merge_and_transform_elements("interface", object_type_names)
|
||||
merge_and_transform_elements("enumeration", enum_type_names | error_type_names)
|
||||
|
||||
function_names = {func.name for func in api.functions}
|
||||
for source_root in [core_root, base_root]:
|
||||
source_namespace = source_root.find("namespace", GIR_NAMESPACES)
|
||||
for function in source_namespace.findall("function", GIR_NAMESPACES):
|
||||
if function.get("name") in function_names:
|
||||
merged_namespace.append(function)
|
||||
|
||||
for source_root in [core_root, base_root]:
|
||||
for record in source_root.findall(".//record", GIR_NAMESPACES):
|
||||
owner = record.get(f"{{{GLIB_NAMESPACE}}}is-gtype-struct-for")
|
||||
if owner is not None and owner in object_type_names:
|
||||
merged_namespace.append(record)
|
||||
|
||||
known_names = object_type_names | enum_type_names | error_type_names
|
||||
referenced_names = set()
|
||||
for elem in merged_namespace.iter():
|
||||
type_name = elem.get("name")
|
||||
if type_name is None:
|
||||
continue
|
||||
for prefix in ("Frida.", "FridaBase."):
|
||||
if type_name.startswith(prefix):
|
||||
referenced_names.add(type_name[len(prefix):])
|
||||
break
|
||||
needed_names = referenced_names - known_names
|
||||
for source_root in [core_root, base_root]:
|
||||
source_namespace = source_root.find("namespace", GIR_NAMESPACES)
|
||||
for callback in source_namespace.findall("callback", GIR_NAMESPACES):
|
||||
if callback.get("name") in needed_names:
|
||||
merged_namespace.append(callback)
|
||||
|
||||
inject_documentation(merged_namespace, docs)
|
||||
|
||||
ET.indent(merged_root, space=" ")
|
||||
result = ET.tostring(merged_root,
|
||||
encoding="unicode",
|
||||
@@ -294,347 +260,15 @@ def emit_gir(api: ApiSpec, core_gir: str, base_gir: str, output_dir: Path, docs:
|
||||
def filter_elements(elements: List[ET.Element], spec_set: Set[str]):
|
||||
return [elem for elem in elements if elem.get("name") in spec_set]
|
||||
|
||||
def is_async_constructor(constructor: ET.Element) -> bool:
|
||||
for type_elem in constructor.iter(f"{{{CORE_NAMESPACE}}}type"):
|
||||
if type_elem.get("name") == "Gio.Cancellable":
|
||||
return True
|
||||
return False
|
||||
|
||||
@dataclass
|
||||
class DocComment:
|
||||
body: str
|
||||
params: dict
|
||||
returns: str
|
||||
filename: str = "<generated>"
|
||||
line: int = 0
|
||||
|
||||
@dataclass
|
||||
class DocIndex:
|
||||
types: dict # type_name -> DocComment
|
||||
members: dict # (type_name, member_name) -> DocComment
|
||||
enum_members: dict # (enum_name, member_name) -> DocComment
|
||||
|
||||
DOC_TYPE_PATTERN = re.compile(r"public\s+(?:sealed\s+|abstract\s+)?(class|interface|enum|errordomain)\s+(\w+)")
|
||||
DOC_SIGNAL_PATTERN = re.compile(r"public\s+signal\s+\S.*?\b(\w+)\s*\(")
|
||||
DOC_PROPERTY_PATTERN = re.compile(r"public\s+(?:unowned\s+)?\S.*?\b(\w+)\s*\{")
|
||||
DOC_METHOD_PATTERN = re.compile(r"public\s+\S.*?\b(\w+)\s*\(")
|
||||
DOC_ENUM_MEMBER_PATTERN = re.compile(r"([A-Z][A-Z0-9_]*)\b")
|
||||
|
||||
def build_doc_index(src_dir: Path) -> DocIndex:
|
||||
repo_root = src_dir.parent
|
||||
sources = []
|
||||
for name in TOPLEVEL_NAMES:
|
||||
path = src_dir / name
|
||||
if path.exists():
|
||||
sources.append(path)
|
||||
base_dir = src_dir.parent / "lib" / "base"
|
||||
if base_dir.is_dir():
|
||||
sources.extend(sorted(base_dir.rglob("*.vala")))
|
||||
|
||||
index = DocIndex(types={}, members={}, enum_members={})
|
||||
for path in sources:
|
||||
try:
|
||||
filename = path.relative_to(repo_root).as_posix()
|
||||
except ValueError:
|
||||
filename = path.name
|
||||
_collect_docs_from_source(path.read_text(encoding="utf-8"), index, filename)
|
||||
return index
|
||||
|
||||
def _collect_docs_from_source(source: str, index: DocIndex, filename: str):
|
||||
lines = source.split("\n")
|
||||
pending = None
|
||||
current_type = None
|
||||
current_is_enum = False
|
||||
i = 0
|
||||
n = len(lines)
|
||||
while i < n:
|
||||
line = lines[i]
|
||||
stripped = line.strip()
|
||||
|
||||
if stripped.startswith("/**"):
|
||||
start_line = i + 1
|
||||
block = [line]
|
||||
while "*/" not in lines[i]:
|
||||
i += 1
|
||||
block.append(lines[i])
|
||||
pending = _parse_doc_block(block)
|
||||
pending.filename = filename
|
||||
pending.line = start_line
|
||||
i += 1
|
||||
continue
|
||||
|
||||
if stripped == "" or stripped.startswith("//") or stripped.startswith("["):
|
||||
i += 1
|
||||
continue
|
||||
|
||||
indent = len(line) - len(line.lstrip("\t"))
|
||||
|
||||
type_match = DOC_TYPE_PATTERN.match(stripped)
|
||||
if indent == 1 and type_match is not None:
|
||||
current_type = type_match.group(2)
|
||||
current_is_enum = type_match.group(1) in ("enum", "errordomain")
|
||||
if pending is not None:
|
||||
index.types[current_type] = pending
|
||||
pending = None
|
||||
i += 1
|
||||
continue
|
||||
|
||||
if pending is not None and current_type is not None and indent >= 2:
|
||||
if current_is_enum:
|
||||
member_match = DOC_ENUM_MEMBER_PATTERN.match(stripped)
|
||||
if member_match is not None:
|
||||
index.enum_members[(current_type, member_match.group(1))] = pending
|
||||
else:
|
||||
name = _parse_member_name(stripped, current_type)
|
||||
if name is not None:
|
||||
index.members[(current_type, name)] = pending
|
||||
pending = None
|
||||
i += 1
|
||||
continue
|
||||
|
||||
pending = None
|
||||
i += 1
|
||||
|
||||
def _parse_member_name(stripped: str, type_name: str):
|
||||
if not stripped.startswith("public"):
|
||||
return None
|
||||
signal_match = DOC_SIGNAL_PATTERN.match(stripped)
|
||||
if signal_match is not None:
|
||||
return signal_match.group(1)
|
||||
brace = stripped.find("{")
|
||||
if brace != -1 and "(" not in stripped[:brace]:
|
||||
property_match = DOC_PROPERTY_PATTERN.match(stripped)
|
||||
if property_match is not None:
|
||||
return property_match.group(1)
|
||||
ctor_match = re.match(r"public\s+" + re.escape(type_name) + r"(?:\.(\w+))?\s*\(", stripped)
|
||||
if ctor_match is not None:
|
||||
return "new" if ctor_match.group(1) is None else ctor_match.group(1)
|
||||
method_match = DOC_METHOD_PATTERN.match(stripped)
|
||||
if method_match is not None:
|
||||
return method_match.group(1)
|
||||
return None
|
||||
|
||||
def _parse_doc_block(block: List[str]) -> DocComment:
|
||||
text_lines = []
|
||||
for raw in block:
|
||||
s = raw.strip()
|
||||
if s.startswith("/**"):
|
||||
s = s[3:]
|
||||
if s.endswith("*/"):
|
||||
s = s[:-2]
|
||||
s = s.strip()
|
||||
if s.startswith("*"):
|
||||
s = s[1:]
|
||||
if s.startswith(" "):
|
||||
s = s[1:]
|
||||
text_lines.append(s.rstrip())
|
||||
|
||||
# Valadoc block tags: "@param <name> <description>" and "@return <description>".
|
||||
body_lines = []
|
||||
params = {}
|
||||
returns_lines = []
|
||||
target = body_lines
|
||||
for line in text_lines:
|
||||
param_match = re.match(r"@param\s+(\w+)\s*(.*)", line)
|
||||
return_match = re.match(r"@returns?\s*(.*)", line)
|
||||
if param_match is not None:
|
||||
params[param_match.group(1)] = [param_match.group(2)]
|
||||
target = params[param_match.group(1)]
|
||||
continue
|
||||
if return_match is not None:
|
||||
returns_lines = [return_match.group(1)]
|
||||
target = returns_lines
|
||||
continue
|
||||
target.append(line)
|
||||
|
||||
def finish(lines):
|
||||
return _valadoc_to_markdown("\n".join(lines).strip())
|
||||
|
||||
return DocComment(
|
||||
body=finish(body_lines),
|
||||
params={k: finish(v) for k, v in params.items()},
|
||||
returns=finish(returns_lines),
|
||||
)
|
||||
|
||||
def _valadoc_to_markdown(text: str) -> str:
|
||||
if not text:
|
||||
return text
|
||||
# Code blocks: {{{ ... }}} -> fenced ``` blocks.
|
||||
def code_block(match):
|
||||
code = match.group(1).strip("\n")
|
||||
return "\n```\n" + code + "\n```\n"
|
||||
text = re.sub(r"\{\{\{(.*?)\}\}\}", code_block, text, flags=re.DOTALL)
|
||||
# Note: {@link ...} cross-references are resolved later, at injection time,
|
||||
# where the full symbol table is available (see inject_documentation).
|
||||
# Inline monospace: ``x`` -> `x` (valadoc) is already markdown-compatible.
|
||||
# Bold: ''x'' -> **x**.
|
||||
text = re.sub(r"''(.+?)''", r"**\1**", text)
|
||||
# Italic: //x// -> *x*, but leave protocol-relative URLs (://) alone.
|
||||
text = re.sub(r"(?<![:/])//(?!/)(.+?)//", r"*\1*", text)
|
||||
return text
|
||||
|
||||
def inject_documentation(merged_namespace: ET.Element, docs: DocIndex):
|
||||
glib_signal_tag = f"{{{GLIB_NAMESPACE}}}signal"
|
||||
callable_tags = {
|
||||
f"{{{CORE_NAMESPACE}}}method",
|
||||
f"{{{CORE_NAMESPACE}}}constructor",
|
||||
f"{{{CORE_NAMESPACE}}}function",
|
||||
f"{{{CORE_NAMESPACE}}}virtual-method",
|
||||
glib_signal_tag,
|
||||
}
|
||||
property_tag = f"{{{CORE_NAMESPACE}}}property"
|
||||
member_tag = f"{{{CORE_NAMESPACE}}}member"
|
||||
doc_tag = f"{{{CORE_NAMESPACE}}}doc"
|
||||
|
||||
# Build a symbol table so {@link ...} can be turned into real gi-docgen
|
||||
# cross-references. Keys use Vala-style names (underscores); values carry the
|
||||
# gi-docgen link kind and the GIR name (dashes for properties/signals).
|
||||
type_kinds = {} # type_name -> gi-docgen kind ("class"/"iface"/"enum"/"error")
|
||||
member_kinds = {} # (type_name, vala_member) -> (kind, gir_name)
|
||||
for type_elem in list(merged_namespace):
|
||||
type_name = type_elem.get("name")
|
||||
if type_name is None:
|
||||
continue
|
||||
tag = type_elem.tag.split("}")[-1]
|
||||
if tag == "class":
|
||||
type_kinds[type_name] = "class"
|
||||
elif tag == "interface":
|
||||
type_kinds[type_name] = "iface"
|
||||
elif tag == "enumeration":
|
||||
type_kinds[type_name] = "error" \
|
||||
if type_elem.get(f"{{{GLIB_NAMESPACE}}}error-domain") is not None \
|
||||
else "enum"
|
||||
for child in list(type_elem):
|
||||
cname = child.get("name")
|
||||
if cname is None:
|
||||
continue
|
||||
if child.tag == f"{{{CORE_NAMESPACE}}}method":
|
||||
member_kinds[(type_name, cname)] = ("method", cname)
|
||||
elif child.tag == f"{{{CORE_NAMESPACE}}}constructor":
|
||||
member_kinds[(type_name, cname)] = ("ctor", cname)
|
||||
elif child.tag == property_tag:
|
||||
member_kinds[(type_name, cname.replace("-", "_"))] = ("property", cname)
|
||||
elif child.tag == glib_signal_tag:
|
||||
member_kinds[(type_name, cname.replace("-", "_"))] = ("signal", cname)
|
||||
|
||||
def resolve_links(text: str) -> str:
|
||||
def repl(match):
|
||||
target = re.sub(r"^Frida\.", "", match.group(1).strip())
|
||||
parts = target.split(".")
|
||||
if len(parts) == 1:
|
||||
kind = type_kinds.get(parts[0])
|
||||
if kind is not None:
|
||||
return f"[{kind}@Frida.{parts[0]}]"
|
||||
elif len(parts) == 2:
|
||||
info = member_kinds.get((parts[0], parts[1]))
|
||||
if info is not None:
|
||||
kind, gir_name = info
|
||||
if kind == "method":
|
||||
return f"[method@Frida.{parts[0]}.{gir_name}]"
|
||||
if kind == "ctor":
|
||||
return f"[ctor@Frida.{parts[0]}.{gir_name}]"
|
||||
if kind == "property":
|
||||
return f"[property@Frida.{parts[0]}:{gir_name}]"
|
||||
if kind == "signal":
|
||||
return f"[signal@Frida.{parts[0]}::{gir_name}]"
|
||||
return "`" + target + "`"
|
||||
return re.sub(r"\{@link\s+([^}]+)\}", repl, text)
|
||||
|
||||
def set_doc(elem: ET.Element, text: str, filename: str = "<generated>",
|
||||
line: int = 0):
|
||||
if not text:
|
||||
return
|
||||
if elem.find(doc_tag) is not None:
|
||||
return
|
||||
doc = ET.Element(doc_tag)
|
||||
doc.set("xml:space", "preserve")
|
||||
# gi-docgen accesses filename/line unconditionally, so always emit them,
|
||||
# mirroring what g-ir-scanner produces for hand-written C.
|
||||
doc.set("filename", filename)
|
||||
doc.set("line", str(line))
|
||||
doc.text = resolve_links(text)
|
||||
elem.insert(0, doc)
|
||||
|
||||
def member_doc(type_name: str, name: str):
|
||||
comment = docs.members.get((type_name, name))
|
||||
if comment is None:
|
||||
for suffix in ("_finish", "_sync"):
|
||||
if name.endswith(suffix):
|
||||
comment = docs.members.get((type_name, name[: -len(suffix)]))
|
||||
if comment is not None:
|
||||
break
|
||||
return comment
|
||||
|
||||
def apply_callable(elem: ET.Element, comment: DocComment):
|
||||
set_doc(elem, comment.body, comment.filename, comment.line)
|
||||
if comment.returns:
|
||||
rv = elem.find(f"{{{CORE_NAMESPACE}}}return-value")
|
||||
if rv is not None:
|
||||
set_doc(rv, comment.returns, comment.filename, comment.line)
|
||||
params_elem = elem.find(f"{{{CORE_NAMESPACE}}}parameters")
|
||||
if params_elem is not None and comment.params:
|
||||
for param in params_elem.findall(f"{{{CORE_NAMESPACE}}}parameter"):
|
||||
text = comment.params.get(param.get("name"))
|
||||
if text:
|
||||
set_doc(param, text, comment.filename, comment.line)
|
||||
|
||||
for type_elem in list(merged_namespace):
|
||||
type_name = type_elem.get("name")
|
||||
if type_name is None:
|
||||
continue
|
||||
tag = type_elem.tag.split("}")[-1]
|
||||
|
||||
type_comment = docs.types.get(type_name)
|
||||
if type_comment is not None and tag in ("class", "interface", "enumeration"):
|
||||
set_doc(type_elem, type_comment.body, type_comment.filename,
|
||||
type_comment.line)
|
||||
|
||||
for child in list(type_elem):
|
||||
child_name = child.get("name")
|
||||
if child_name is None:
|
||||
continue
|
||||
if child.tag in callable_tags:
|
||||
lookup = child_name.replace("-", "_") if child.tag == glib_signal_tag \
|
||||
else child_name
|
||||
comment = member_doc(type_name, lookup)
|
||||
if comment is not None:
|
||||
apply_callable(child, comment)
|
||||
elif child.tag == f"{{{CORE_NAMESPACE}}}constructor" \
|
||||
and child_name == "new":
|
||||
# Vala's implicit default constructor; give it a sensible
|
||||
# description rather than leaving it bare.
|
||||
set_doc(child, f"Creates a new [class@Frida.{type_name}].")
|
||||
elif child.tag == property_tag:
|
||||
vala_name = child_name.replace("-", "_")
|
||||
comment = docs.members.get((type_name, vala_name))
|
||||
if comment is not None:
|
||||
set_doc(child, comment.body, comment.filename, comment.line)
|
||||
# The C API also exposes the property through getter/setter
|
||||
# methods; give them the same description.
|
||||
accessors = {"get_" + vala_name, "set_" + vala_name}
|
||||
for sibling in type_elem:
|
||||
if sibling.tag == f"{{{CORE_NAMESPACE}}}method" \
|
||||
and sibling.get("name") in accessors:
|
||||
set_doc(sibling, comment.body, comment.filename,
|
||||
comment.line)
|
||||
elif child.tag == member_tag:
|
||||
comment = docs.enum_members.get((type_name, child_name.upper()))
|
||||
if comment is not None:
|
||||
set_doc(child, comment.body, comment.filename, comment.line)
|
||||
|
||||
def emit_vapi(api, output_dir):
|
||||
with OutputFile(output_dir / f"frida-core-{api.version}.vapi") as output_vapi_file:
|
||||
output_vapi_file.write("[CCode (cheader_filename = \"frida-core.h\", cprefix = \"Frida\", lower_case_cprefix = \"frida_\")]")
|
||||
output_vapi_file.write("\nnamespace Frida {")
|
||||
output_vapi_file.write("\n\tpublic static void init ();")
|
||||
output_vapi_file.write("\n\tpublic static void init_with_runtime (Frida.Runtime runtime);")
|
||||
output_vapi_file.write("\n\tpublic static void shutdown ();")
|
||||
output_vapi_file.write("\n\tpublic static void deinit ();")
|
||||
output_vapi_file.write("\n\tpublic static unowned GLib.MainContext get_main_context ();")
|
||||
|
||||
for delegate in referenced_delegates(api):
|
||||
output_vapi_file.write("\n\t" + delegate)
|
||||
|
||||
for object_type in api.object_types:
|
||||
output_vapi_file.write("\n\n\t%s" % object_type.vapi_declaration)
|
||||
sections = []
|
||||
@@ -669,46 +303,6 @@ def emit_vapi(api, output_dir):
|
||||
output_deps_file.write("glib-2.0\n")
|
||||
output_deps_file.write("gobject-2.0\n")
|
||||
output_deps_file.write("gio-2.0\n")
|
||||
output_deps_file.write("json-glib-1.0\n")
|
||||
|
||||
def referenced_delegates(api) -> List[str]:
|
||||
members = []
|
||||
for object_type in api.object_types:
|
||||
members.extend(object_type.vapi_properties)
|
||||
members.extend(object_type.vapi_methods)
|
||||
members.extend(object_type.vapi_signals)
|
||||
if object_type.vapi_constructor is not None:
|
||||
members.append(object_type.vapi_constructor)
|
||||
for func in api.functions:
|
||||
members.append(func.vapi_declaration)
|
||||
text = "\n".join(members)
|
||||
|
||||
return [declaration for name, declaration in api.delegates
|
||||
if re.search(r"\bFrida\." + name + r"\b", text) is not None]
|
||||
|
||||
def strip_internal_interfaces(declaration: str) -> str:
|
||||
head, sep, rest = declaration.partition(" : ")
|
||||
if not sep:
|
||||
return declaration
|
||||
|
||||
bases_part, brace_sep, tail = rest.partition("{")
|
||||
|
||||
kept = [b.strip() for b in bases_part.split(",") if b.strip() not in INTERNAL_INTERFACES]
|
||||
if not kept:
|
||||
return f"{head} {brace_sep}{tail}"
|
||||
|
||||
return f"{head} : {', '.join(kept)} {brace_sep}{tail}"
|
||||
|
||||
def emit_symbol_maps_from_source(output_dir: Path):
|
||||
with OutputFile(output_dir / 'frida-core.version') as f:
|
||||
f.write("{\n")
|
||||
f.write(" global:\n")
|
||||
f.write(" frida_*;\n")
|
||||
f.write(" _frida_*;\n")
|
||||
f.write("\n")
|
||||
f.write(" local:\n")
|
||||
f.write(" *;\n")
|
||||
f.write("};\n")
|
||||
|
||||
def parse_api(frida_version, frida_version_components, api_version, toplevel_code, core_header, core_vapi, base_header, base_vapi):
|
||||
all_headers = core_header + "\n" + base_header
|
||||
@@ -717,7 +311,6 @@ def parse_api(frida_version, frida_version_components, api_version, toplevel_cod
|
||||
enum_types = []
|
||||
|
||||
base_public_types = {
|
||||
"SpawnGatingOptions": "ProcessMatchOptions",
|
||||
"FrontmostQueryOptions": "SpawnOptions",
|
||||
"ApplicationQueryOptions": "FrontmostQueryOptions",
|
||||
"ProcessQueryOptions": "ApplicationQueryOptions",
|
||||
@@ -732,9 +325,6 @@ def parse_api(frida_version, frida_version_components, api_version, toplevel_cod
|
||||
"EndpointParameters": "PortalService",
|
||||
"AuthenticationService": "EndpointParameters",
|
||||
"StaticAuthenticationService": "AuthenticationService",
|
||||
"WebRequestHandler": "StaticAuthenticationService",
|
||||
"WebRequest": "WebRequestHandler",
|
||||
"WebResponse": "WebRequest",
|
||||
}
|
||||
internal_type_prefixes = [
|
||||
"AgentMessageKind",
|
||||
@@ -829,7 +419,7 @@ def parse_api(frida_version, frida_version_components, api_version, toplevel_cod
|
||||
object_type.c_method_prototypes.append(method_cprototype)
|
||||
elif method_name == 'get_type':
|
||||
object_type.c_get_type = method_cprototype.replace("G_GNUC_CONST ;", "G_GNUC_CONST;")
|
||||
for d in re.finditer(r"^typedef.+?\(\*(" + object_type.c_name + r".+?)\) \(.+\);$", all_headers, re.MULTILINE):
|
||||
for d in re.finditer(r"^typedef.+?\(\*(" + object_type.c_name + r".+?)\) \(.+\);$", core_header, re.MULTILINE):
|
||||
delegate_cname = d.group(1)
|
||||
if delegate_cname not in seen_cdelegates:
|
||||
seen_cdelegates.add(delegate_cname)
|
||||
@@ -856,7 +446,8 @@ def parse_api(frida_version, frida_version_components, api_version, toplevel_cod
|
||||
if stripped_line == "}":
|
||||
ignoring = False
|
||||
else:
|
||||
if stripped_line.startswith("public class Promise") \
|
||||
if stripped_line.startswith("public abstract") \
|
||||
or stripped_line.startswith("public class Promise") \
|
||||
or stripped_line.startswith("public interface Future") \
|
||||
or stripped_line.startswith("public class CF"):
|
||||
ignoring = True
|
||||
@@ -876,7 +467,7 @@ def parse_api(frida_version, frida_version_components, api_version, toplevel_cod
|
||||
ignoring = True
|
||||
else:
|
||||
current_object_type = object_type_by_name[name]
|
||||
current_object_type.vapi_declaration = strip_internal_interfaces(stripped_line)
|
||||
current_object_type.vapi_declaration = stripped_line
|
||||
elif stripped_line == "}":
|
||||
current_enum = None
|
||||
current_object_type = None
|
||||
@@ -905,31 +496,20 @@ def parse_api(frida_version, frida_version_components, api_version, toplevel_cod
|
||||
enum.vapi_declaration = m.group(1)
|
||||
enum.vapi_members.extend([line.lstrip() for line in m.group(2).strip().split("\n")])
|
||||
|
||||
functions = [f for f in parse_vapi_functions(core_vapi + base_vapi) if function_is_public(f.name)]
|
||||
functions = [f for f in parse_vapi_functions(base_vapi) if function_is_public(f.name)]
|
||||
for f in functions:
|
||||
m = re.search(r"^(?:VALA_EXTERN )?[\w\*]+ frida_{}.+?;".format(f.name), all_headers, re.MULTILINE | re.DOTALL)
|
||||
prototype = beautify_cprototype(m.group(0))
|
||||
if prototype.startswith("VALA_EXTERN "):
|
||||
prototype = prototype[12:]
|
||||
f.c_prototype = prototype
|
||||
m = re.search(r"^[\w\*]+ frida_{}.+?;".format(f.name), all_headers, re.MULTILINE | re.DOTALL)
|
||||
f.c_prototype = beautify_cprototype(m.group(0))
|
||||
|
||||
delegates = [(m.group(1), m.group(0).strip())
|
||||
for m in re.finditer(r"^\tpublic delegate .+?\b(\w+) \(.*\);$", core_vapi + base_vapi, re.MULTILINE)]
|
||||
|
||||
return ApiSpec(frida_version, frida_version_components, api_version, object_types, functions, enum_types, error_types,
|
||||
delegates)
|
||||
return ApiSpec(frida_version, frida_version_components, api_version, object_types, functions, enum_types, error_types)
|
||||
|
||||
def function_is_public(name):
|
||||
return not name.startswith("_") and \
|
||||
not name.startswith("throw_") and \
|
||||
name not in MANUALLY_DECLARED_FUNCTIONS and \
|
||||
name not in {
|
||||
"on_pending_garbage",
|
||||
"generate_certificate",
|
||||
"get_dbus_context",
|
||||
"invalidate_dbus_context",
|
||||
"make_json_reader",
|
||||
"make_json_reader_taking_node",
|
||||
"make_parameters_dict",
|
||||
"compute_system_parameters",
|
||||
"parse_control_address",
|
||||
@@ -939,23 +519,10 @@ def function_is_public(name):
|
||||
"check_kernel_version",
|
||||
"get_syscall_signatures",
|
||||
"get_compat32_syscall_signatures",
|
||||
"get_xnu_mach_traps",
|
||||
"get_xnu_bsd_syscalls",
|
||||
"make_stdio_pipes",
|
||||
"make_stdio_pipe",
|
||||
}
|
||||
|
||||
MANUALLY_DECLARED_FUNCTIONS = {
|
||||
"init",
|
||||
"init_with_runtime",
|
||||
"shutdown",
|
||||
"deinit",
|
||||
"get_main_context",
|
||||
"unref",
|
||||
"version",
|
||||
"version_string",
|
||||
}
|
||||
|
||||
def parse_vala_object_types(source) -> List[ApiObjectType]:
|
||||
return [ApiObjectType(m.group(3), m.group(2)) for m in OBJECT_TYPE_PATTERN.finditer(source, re.MULTILINE)]
|
||||
|
||||
@@ -971,7 +538,6 @@ class ApiSpec:
|
||||
functions: List[ApiFunction]
|
||||
enum_types: List[ApiEnum]
|
||||
error_types: List[ApiEnum]
|
||||
delegates: List[tuple]
|
||||
|
||||
class ApiEnum:
|
||||
def __init__(self, name):
|
||||
|
||||
+39
-82
@@ -3,7 +3,6 @@ fs = import('fs')
|
||||
generate_api = [python, files('generate.py')]
|
||||
|
||||
generate_api_args = [
|
||||
meson.current_build_dir(),
|
||||
frida_version,
|
||||
frida_major_version.to_string(),
|
||||
frida_minor_version.to_string(),
|
||||
@@ -16,6 +15,7 @@ generate_api_args = [
|
||||
base_build_dir / 'frida-base.h',
|
||||
base_build_dir / base_gir_name,
|
||||
base_build_dir / f'frida-base-@[email protected]',
|
||||
meson.current_build_dir(),
|
||||
]
|
||||
|
||||
core_api = custom_target('frida-core-api',
|
||||
@@ -44,24 +44,6 @@ glib_gir = fs.copyfile('GLib-2.0.gir', install: install_glib_girs, install_dir:
|
||||
gobject_gir = fs.copyfile('GObject-2.0.gir', install: install_glib_girs, install_dir: girdir)
|
||||
gio_gir = fs.copyfile('Gio-2.0.gir', install: install_glib_girs, install_dir: girdir)
|
||||
|
||||
g_ir_compiler = find_program('g-ir-compiler', required: false)
|
||||
if g_ir_compiler.found()
|
||||
custom_target('frida-core-typelib',
|
||||
command: [
|
||||
g_ir_compiler,
|
||||
'--output', '@OUTPUT@',
|
||||
'--includedir=' + girdir,
|
||||
'--includedir=' + meson.current_source_dir(),
|
||||
'@INPUT@',
|
||||
],
|
||||
input: core_public_gir,
|
||||
output: f'Frida-@[email protected]',
|
||||
depends: core,
|
||||
install: true,
|
||||
install_dir: typelibdir,
|
||||
)
|
||||
endif
|
||||
|
||||
core_public_vapi_stamp = custom_target('frida-core-vapi-stamp',
|
||||
input: core_public_vapi,
|
||||
output: f'frida-core-@[email protected]',
|
||||
@@ -72,26 +54,22 @@ core_public_vapi_stamp = custom_target('frida-core-vapi-stamp',
|
||||
],
|
||||
)
|
||||
|
||||
if is_shared
|
||||
core_public_lib = core
|
||||
else
|
||||
core_public_lib = custom_target('frida-core-library',
|
||||
input: [core] + internal_libs,
|
||||
output: f'libfrida-core-@[email protected]',
|
||||
command: [
|
||||
python,
|
||||
files('merge.py'),
|
||||
lib,
|
||||
libtool,
|
||||
ar,
|
||||
meson.current_build_dir(),
|
||||
'@OUTPUT@',
|
||||
'@INPUT@'
|
||||
],
|
||||
install: true,
|
||||
install_dir: get_option('libdir'),
|
||||
)
|
||||
endif
|
||||
core_public_lib = custom_target('frida-core-library',
|
||||
input: [core] + internal_libs,
|
||||
output: f'libfrida-core-@[email protected]',
|
||||
command: [
|
||||
python,
|
||||
files('merge.py'),
|
||||
lib,
|
||||
libtool,
|
||||
ar,
|
||||
meson.current_build_dir(),
|
||||
'@OUTPUT@',
|
||||
'@INPUT@'
|
||||
],
|
||||
install: true,
|
||||
install_dir: get_option('libdir'),
|
||||
)
|
||||
|
||||
core_public_extra_headers = []
|
||||
if host_os == 'android'
|
||||
@@ -118,50 +96,29 @@ installed_variables = {
|
||||
'frida_vapidir': vapidir,
|
||||
}
|
||||
|
||||
core_public_dep_kwargs = {
|
||||
'sources': [core_public_h, core_public_gir, glib_gir, gobject_gir, gio_gir, core_public_vapi_stamp] + core_public_extra_headers,
|
||||
'include_directories': include_directories('.'),
|
||||
'link_with': core_public_lib,
|
||||
'dependencies': core_deps,
|
||||
'variables': uninstalled_variables,
|
||||
}
|
||||
if not is_shared
|
||||
core_public_dep_kwargs += {
|
||||
'link_args': backend_libs_private,
|
||||
}
|
||||
endif
|
||||
core_public_dep = declare_dependency(kwargs: core_public_dep_kwargs)
|
||||
|
||||
core_public_reqs = ['glib-2.0', 'gobject-2.0', 'gio-2.0', 'json-glib-1.0']
|
||||
if host_os_family == 'windows'
|
||||
core_public_reqs += 'gio-windows-2.0'
|
||||
else
|
||||
core_public_reqs += 'gio-unix-2.0'
|
||||
endif
|
||||
core_public_dep = declare_dependency(
|
||||
sources: [core_public_h, core_public_gir, glib_gir, gobject_gir, gio_gir, core_public_vapi_stamp, core_public_extra_headers],
|
||||
include_directories: include_directories('.'),
|
||||
link_args: backend_libs_private,
|
||||
link_with: core_public_lib,
|
||||
dependencies: core_deps,
|
||||
variables: uninstalled_variables,
|
||||
)
|
||||
|
||||
pkg = import('pkgconfig')
|
||||
pkg_kwargs = {
|
||||
'filebase': f'frida-core-@api_version@',
|
||||
'name': 'Frida Core Library',
|
||||
'version': frida_version,
|
||||
'description': 'Instrumentation toolkit for developers, reverse-engineers, and security researchers',
|
||||
'requires': core_public_reqs,
|
||||
'subdirs': f'frida-@api_version@',
|
||||
'extra_cflags': ['-I${frida_includedir}'],
|
||||
'variables': installed_variables,
|
||||
'uninstalled_variables': uninstalled_variables,
|
||||
}
|
||||
if is_shared
|
||||
pkg_kwargs += {
|
||||
'libraries': ['-L${libdir}', f'-lfrida-core-@api_version@'],
|
||||
}
|
||||
else
|
||||
pkg_kwargs += {
|
||||
'libraries': core_public_lib,
|
||||
'requires_private': ['gmodule-2.0', 'gee-0.8', 'libsoup-3.0', 'frida-gum-1.0', 'frida-gumjs-inspector-1.0', 'libbrotlidec'] + backend_reqs_private,
|
||||
'libraries_private': backend_libs_private,
|
||||
}
|
||||
endif
|
||||
pkg.generate(kwargs: pkg_kwargs)
|
||||
pkg.generate(
|
||||
filebase: f'frida-core-@api_version@',
|
||||
name: 'Frida Core Library',
|
||||
version: frida_version,
|
||||
description: 'Instrumentation toolkit for developers, reverse-engineers, and security researchers',
|
||||
requires: ['glib-2.0', 'gobject-2.0', 'gio-2.0', 'json-glib-1.0'],
|
||||
requires_private: ['gmodule-2.0', 'gee-0.8', 'libsoup-3.0', 'frida-gum-1.0', 'frida-gumjs-inspector-1.0', 'libbrotlidec'] + backend_reqs_private,
|
||||
subdirs: f'frida-@api_version@',
|
||||
libraries: core_public_lib,
|
||||
libraries_private: backend_libs_private,
|
||||
extra_cflags: ['-I${frida_includedir}'],
|
||||
variables: installed_variables,
|
||||
uninstalled_variables: uninstalled_variables,
|
||||
)
|
||||
|
||||
meson.override_dependency(f'frida-core-@api_version@', core_public_dep)
|
||||
+198
-1160
File diff suppressed because it is too large.
Load diff
Generated
+4
-4
@@ -13,9 +13,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "bindgen"
|
||||
version = "0.72.1"
|
||||
version = "0.72.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "993776b509cfb49c750f11b8f07a46fa23e0a1386ffc01fb1e7d343efc387895"
|
||||
checksum = "4f72209734318d0b619a5e0f5129918b848c416e122a3c4ce054e03cb87b726f"
|
||||
dependencies = [
|
||||
"bitflags",
|
||||
"cexpr",
|
||||
@@ -63,9 +63,9 @@ checksum = "9555578bc9e57714c812a1f84e4fc5b4d21fcb063490c624de019f7464c91268"
|
||||
|
||||
[[package]]
|
||||
name = "clang-sys"
|
||||
version = "1.9.1"
|
||||
version = "1.8.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "157a8ba7b480713b56f4c09fd13fc3e0a22a5dfab8097ba61cbc5feef950788a"
|
||||
checksum = "0b023947811758c97c59bf9d1c188fd619ad4718dcaa767947df1cadb14f39f4"
|
||||
dependencies = [
|
||||
"glob",
|
||||
"libc",
|
||||
|
||||
@@ -4,31 +4,6 @@ version = "1.0.0"
|
||||
edition = "2024"
|
||||
build = "build.rs"
|
||||
|
||||
[lib]
|
||||
name = "frida_barebone_agent"
|
||||
path = "src/lib.rs"
|
||||
crate-type = ["rlib", "staticlib"]
|
||||
|
||||
# The XNU flavour is a freestanding executable the host injects and calls into.
|
||||
# The Linux flavour is the staticlib above, linked into a .ko by linux/Kbuild.
|
||||
[[bin]]
|
||||
name = "frida-barebone-agent"
|
||||
path = "src/main.rs"
|
||||
required-features = ["blob"]
|
||||
|
||||
[features]
|
||||
# Flavors the host injects and calls into, as opposed to the module Linux loads.
|
||||
blob = []
|
||||
# The XNU flavour itself, and the two ways it is packaged: a blob the host injects
|
||||
# into a running kernel, and a kext that kernel loads.
|
||||
xnu-core = []
|
||||
xnu = ["xnu-core", "blob"]
|
||||
xnu-kext = ["xnu-core"]
|
||||
win9x = ["blob"]
|
||||
winnt = ["blob"]
|
||||
linux = []
|
||||
linux-injected = ["blob"]
|
||||
|
||||
[profile.release]
|
||||
panic = "abort"
|
||||
opt-level = "z"
|
||||
|
||||
@@ -1,81 +1,30 @@
|
||||
## Getting the SDK and the devkit
|
||||
## Getting the C toolchain
|
||||
|
||||
The agent is built against the bare soft-float SDK, which carries picolibc and the
|
||||
compiler runtime, and against a GumJS devkit built for the same flavor. Which flavor
|
||||
is the target's, listed under Targets below; this walks through the XNU one. No
|
||||
prebuilt bundles are published for these, so build both:
|
||||
npm install -g xpm
|
||||
xpm install
|
||||
export PATH=$PWD/xpacks/.bin:$PATH
|
||||
|
||||
machine=none-arm64-softfloat_nopic
|
||||
## How to build Gum
|
||||
|
||||
releng/deps.py build --bundle=sdk --host=$machine
|
||||
mkdir -p ~/sdk-$machine
|
||||
tar -C ~/sdk-$machine -xf deps/sdk-$machine.tar.xz
|
||||
|
||||
gum=~/src/frida-gum
|
||||
mkdir -p $gum/build/$machine
|
||||
(cd $gum/build/$machine \
|
||||
&& FRIDA_DEPS=$HOME/src/frida-core/deps CC=clang CXX=clang++ AR=llvm-ar \
|
||||
RANLIB=llvm-ranlib NM=llvm-nm STRIP=llvm-strip \
|
||||
../../configure --host=$machine --enable-gumjs \
|
||||
--with-devkits=gumjs \
|
||||
&& python3 ../../releng/meson/meson.py configure -Ddevkit_symbol_scope=original \
|
||||
&& ninja)
|
||||
./configure \
|
||||
--host=aarch64-none-elf \
|
||||
--enable-gumjs \
|
||||
--with-devkits=gum,gumjs \
|
||||
--with-devkit-symbol-scope=original
|
||||
make
|
||||
export GUMJS_DEVKIT_DIR=$PWD/build/bindings/gumjs/devkit
|
||||
|
||||
## Building
|
||||
|
||||
sdk=~/sdk-$machine
|
||||
export GUMJS_DEVKIT_DIR=$gum/build/$machine/bindings/gumjs/devkit
|
||||
export CC="clang -I$sdk/include -I$sdk/include/glib-2.0 -I$sdk/lib/glib-2.0/include \
|
||||
-I$sdk/include/capstone -I$sdk/include/json-glib-1.0"
|
||||
export RUSTFLAGS="-L native=$sdk/lib"
|
||||
|
||||
RUSTC_BOOTSTRAP=1 cargo build --release --features xnu \
|
||||
--target aarch64-unknown-none-softfloat --target-dir target-xnu \
|
||||
-Z build-std=core,alloc,compiler_builtins
|
||||
|
||||
Rust names no bare-metal target for the Windows guests, so the agent spells them
|
||||
out and they are asked for by path:
|
||||
|
||||
RUSTC_BOOTSTRAP=1 cargo build --release --features win9x \
|
||||
--target ./i686-unknown-none-pic.json -Z json-target-spec \
|
||||
--target-dir target-win9x -Z build-std=core,alloc,compiler_builtins
|
||||
|
||||
## Targets
|
||||
|
||||
The agent supports four kernels. One of them has to be picked; none is a default,
|
||||
since none follows from the host you build on:
|
||||
|
||||
- `xnu` — a freestanding ELF executable that the Barebone backend
|
||||
injects into a running kernel from the outside, over a remote stub.
|
||||
- `win9x` — the same, for a 32-bit Windows 9x guest.
|
||||
- `winnt` — the same, for a Windows NT guest, either word size, on x86 or arm64.
|
||||
- `linux` — a static library that becomes a kernel module, loaded from the
|
||||
inside. See `linux/README.md`.
|
||||
|
||||
Each flavor has an SDK and a devkit of its own, since the addressing differs: an
|
||||
image the host places goes in position-independent, a Linux module is absolute,
|
||||
and NT's 64-bit half is called in the Microsoft ABI.
|
||||
|
||||
| Flavor | Machine | Rust target |
|
||||
|---------|-----------------------------------|----------------------------------|
|
||||
| `xnu` | `none-arm64-softfloat_nopic` | `aarch64-unknown-none-softfloat` |
|
||||
| `win9x` | `none-x86-softfloat_pic` | `i686-unknown-none-pic.json` |
|
||||
| `winnt` | `none-x86-softfloat_pic` | `i686-unknown-none-pic.json` |
|
||||
| `winnt` | `none-x86_64-softfloat_pic_msabi` | `x86_64-unknown-none-pic.json` |
|
||||
| `winnt` | `none-arm64-softfloat_pic` | `aarch64-unknown-none-pic.json` |
|
||||
| `linux` | `none-<arch>-softfloat_nopic` | see `linux/README.md` |
|
||||
|
||||
Everything above the `kernel` module is shared; each backend supplies the same
|
||||
set of primitives (logging, allocation, threads, waiting, time, symbols) plus its
|
||||
half of Gum's platform backend (`gum_xnu.rs` / `gum_windows.rs` / `gum_linux.rs`).
|
||||
export PATH=$PWD/xpacks/.bin:$PATH
|
||||
export CC_aarch64_unknown_none=aarch64-none-elf-gcc
|
||||
export AR_aarch64_unknown_none=aarch64-none-elf-ar
|
||||
export RANLIB_aarch64_unknown_none=aarch64-none-elf-ranlib
|
||||
|
||||
## Development loop
|
||||
|
||||
export FRIDA_BAREBONE_CONFIG=$PWD/etc/xnu.json
|
||||
cargo build --release --features xnu --target aarch64-unknown-none-softfloat \
|
||||
&& make -C ~/src/frida-python \
|
||||
&& killall -9 qemu-system-aarch64 && sleep 2 \
|
||||
&& frida -D barebone -p 0
|
||||
cargo build --release && make -C ~/src/frida-python && killall -9 qemu-system-aarch64 && sleep 2 && frida -D barebone -p 0
|
||||
|
||||
## Speeding up loop
|
||||
|
||||
@@ -83,7 +32,6 @@ half of Gum's platform backend (`gum_xnu.rs` / `gum_windows.rs` / `gum_linux.rs`
|
||||
-- \
|
||||
-Dfrida-core:compat=disabled \
|
||||
-Dfrida-core:local_backend=disabled \
|
||||
-Dfrida-core:simmy_backend=disabled \
|
||||
-Dfrida-core:fruity_backend=disabled \
|
||||
-Dfrida-core:droidy_backend=disabled \
|
||||
-Dfrida-core:socket_backend=disabled \
|
||||
|
||||
@@ -1,21 +0,0 @@
|
||||
{
|
||||
"abi": "softfloat",
|
||||
"arch": "aarch64",
|
||||
"crt-objects-fallback": "false",
|
||||
"data-layout": "e-m:e-p270:32:32-p271:32:32-p272:64:64-i8:8:32-i16:16:32-i64:64-i128:128-n32:64-S128-Fn32",
|
||||
"disable-redzone": true,
|
||||
"features": "+v8a,+strict-align,-neon,+reserve-x18",
|
||||
"linker": "rust-lld",
|
||||
"linker-flavor": "gnu-lld",
|
||||
"llvm-target": "aarch64-unknown-none",
|
||||
"max-atomic-width": 128,
|
||||
"panic-strategy": "abort",
|
||||
"plt-by-default": false,
|
||||
"position-independent-executables": true,
|
||||
"relocation-model": "pic",
|
||||
"rustc-abi": "softfloat",
|
||||
"stack-probes": {
|
||||
"kind": "inline"
|
||||
},
|
||||
"target-pointer-width": 64
|
||||
}
|
||||
@@ -1,150 +0,0 @@
|
||||
SECTIONS {
|
||||
.text : {
|
||||
*(.text.entrypoint)
|
||||
*(.text*)
|
||||
}
|
||||
.rel.dyn : {
|
||||
_agent_relocs_start = .;
|
||||
*(.rel.dyn)
|
||||
_agent_relocs_end = .;
|
||||
}
|
||||
.rodata : {
|
||||
*(.rodata*)
|
||||
}
|
||||
.kernel_addrs : ALIGN(4) {
|
||||
. = ALIGN(4);
|
||||
__printk = .; . += 4;
|
||||
_printk = .; . += 4;
|
||||
_panic = .; . += 4;
|
||||
_kthread_create_on_node = .; . += 4;
|
||||
_wake_up_process = .; . += 4;
|
||||
_fget = .; . += 4;
|
||||
_kernel_read = .; . += 4;
|
||||
_filp_open = .; . += 4;
|
||||
_kernel_write = .; . += 4;
|
||||
___kmalloc_noprof = .; . += 4;
|
||||
_kmalloc = .; . += 4;
|
||||
___kmalloc = .; . += 4;
|
||||
_kfree = .; . += 4;
|
||||
_vmalloc = .; . += 4;
|
||||
_execmem_alloc = .; . += 4;
|
||||
_set_memory_rw = .; . += 4;
|
||||
_set_memory_ro = .; . += 4;
|
||||
_set_memory_x = .; . += 4;
|
||||
_set_memory_nx = .; . += 4;
|
||||
_modules = .; . += 4;
|
||||
_register_module_notifier = .; . += 4;
|
||||
_unregister_module_notifier = .; . += 4;
|
||||
_execmem_free = .; . += 4;
|
||||
_module_alloc = .; . += 4;
|
||||
_module_memfree = .; . += 4;
|
||||
___init_waitqueue_head = .; . += 4;
|
||||
_prepare_to_wait_event = .; . += 4;
|
||||
_finish_wait = .; . += 4;
|
||||
___wake_up = .; . += 4;
|
||||
_autoremove_wake_function = .; . += 4;
|
||||
_schedule_hrtimeout_range = .; . += 4;
|
||||
_pci_get_domain_bus_and_slot = .; . += 4;
|
||||
_pci_irq_vector = .; . += 4;
|
||||
_of_irq_parse_and_map_pci = .; . += 4;
|
||||
_pci_dev_put = .; . += 4;
|
||||
_schedule = .; . += 4;
|
||||
_ktime_get_mono_fast_ns = .; . += 4;
|
||||
_ktime_get_real_ts64 = .; . += 4;
|
||||
_getnstimeofday64 = .; . += 4;
|
||||
_send_sig = .; . += 4;
|
||||
_free_irq = .; . += 4;
|
||||
_request_threaded_irq = .; . += 4;
|
||||
_vmap = .; . += 4;
|
||||
___pv_offset = .; . += 4;
|
||||
_pgprot_kernel = .; . += 4;
|
||||
_ioremap = .; . += 4;
|
||||
_of_find_node_opts_by_path = .; . += 4;
|
||||
_of_irq_get = .; . += 4;
|
||||
_of_node_put = .; . += 4;
|
||||
_init_task = .; . += 4;
|
||||
_tasklist_lock = .; . += 4;
|
||||
__raw_read_lock = .; . += 4;
|
||||
__raw_read_unlock = .; . += 4;
|
||||
__raw_read_lock_irqsave = .; . += 4;
|
||||
__raw_read_unlock_irqrestore = .; . += 4;
|
||||
__raw_write_lock = .; . += 4;
|
||||
__raw_write_unlock = .; . += 4;
|
||||
__raw_write_lock_irqsave = .; . += 4;
|
||||
__raw_write_unlock_irqrestore = .; . += 4;
|
||||
_detach_pid = .; . += 4;
|
||||
_free_pids = .; . += 4;
|
||||
_get_task_exe_file = .; . += 4;
|
||||
_file_path = .; . += 4;
|
||||
_fput = .; . += 4;
|
||||
_copy_from_kernel_nofault = .; . += 4;
|
||||
_get_task_mm = .; . += 4;
|
||||
_kthread_use_mm = .; . += 4;
|
||||
_kthread_unuse_mm = .; . += 4;
|
||||
_mmput = .; . += 4;
|
||||
_vm_mmap = .; . += 4;
|
||||
_vm_munmap = .; . += 4;
|
||||
_tracepoint_probe_register = .; . += 4;
|
||||
_tracepoint_probe_unregister = .; . += 4;
|
||||
___tracepoint_sched_process_fork = .; . += 4;
|
||||
___tracepoint_sched_process_exit = .; . += 4;
|
||||
___tracepoint_sched_process_exec = .; . += 4;
|
||||
___tracepoint_task_rename = .; . += 4;
|
||||
___set_task_comm = .; . += 4;
|
||||
_vunmap = .; . += 4;
|
||||
_arm_copy_to_user = .; . += 4;
|
||||
_down_read = .; . += 4;
|
||||
_up_read = .; . += 4;
|
||||
_get_user_pages_unlocked = .; . += 4;
|
||||
_get_user_pages_remote = .; . += 4;
|
||||
_user_mode_thread = .; . += 4;
|
||||
_fget_task = .; . += 4;
|
||||
_find_task_by_vpid = .; . += 4;
|
||||
___start_BTF = .; . += 4;
|
||||
___stop_BTF = .; . += 4;
|
||||
_call_usermodehelper_setup = .; . += 4;
|
||||
_call_usermodehelper_exec = .; . += 4;
|
||||
_arm_copy_from_user = .; . += 4;
|
||||
_fixup_exception = .; . += 4;
|
||||
_init_net = .; . += 4;
|
||||
_sock_create_kern = .; . += 4;
|
||||
_kernel_connect = .; . += 4;
|
||||
_kernel_sendmsg = .; . += 4;
|
||||
_kernel_recvmsg = .; . += 4;
|
||||
_sock_release = .; . += 4;
|
||||
_patch_text = .; . += 4;
|
||||
}
|
||||
/* Everything above is only ever read, so a process being instrumented can be shown the very
|
||||
same pages; everything below it each copy needs its own of. */
|
||||
. = ALIGN(4096);
|
||||
_agent_private_start = .;
|
||||
.data.rel.ro : {
|
||||
*(.data.rel.ro*)
|
||||
}
|
||||
.got : {
|
||||
*(.got*)
|
||||
}
|
||||
.init_array : {
|
||||
_agent_init_start = .;
|
||||
*(.init_array*)
|
||||
_agent_init_end = .;
|
||||
}
|
||||
.data : {
|
||||
*(.data*)
|
||||
}
|
||||
.bss : {
|
||||
*(.bss*)
|
||||
}
|
||||
. = ALIGN(4);
|
||||
_heap_start = .;
|
||||
}
|
||||
|
||||
VERSION {
|
||||
{
|
||||
global:
|
||||
_start;
|
||||
|
||||
local:
|
||||
*;
|
||||
};
|
||||
}
|
||||
@@ -1,156 +0,0 @@
|
||||
SECTIONS {
|
||||
.text : {
|
||||
*(.text.entrypoint)
|
||||
*(.text*)
|
||||
}
|
||||
.rela.dyn : {
|
||||
_agent_relocs_start = .;
|
||||
*(.rela.dyn)
|
||||
_agent_relocs_end = .;
|
||||
}
|
||||
.rodata : {
|
||||
*(.rodata*)
|
||||
}
|
||||
.kernel_addrs : ALIGN(8) {
|
||||
. = ALIGN(8);
|
||||
__printk = .; . += 8;
|
||||
_printk = .; . += 8;
|
||||
_panic = .; . += 8;
|
||||
_kthread_create_on_node = .; . += 8;
|
||||
_wake_up_process = .; . += 8;
|
||||
_fget = .; . += 8;
|
||||
_kernel_read = .; . += 8;
|
||||
_filp_open = .; . += 8;
|
||||
_kernel_write = .; . += 8;
|
||||
___kmalloc_noprof = .; . += 8;
|
||||
_kmalloc = .; . += 8;
|
||||
___kmalloc = .; . += 8;
|
||||
_kfree = .; . += 8;
|
||||
_vmalloc = .; . += 8;
|
||||
_execmem_alloc = .; . += 8;
|
||||
_set_memory_rw = .; . += 8;
|
||||
_set_memory_ro = .; . += 8;
|
||||
_set_memory_x = .; . += 8;
|
||||
_set_memory_nx = .; . += 8;
|
||||
_modules = .; . += 8;
|
||||
_register_module_notifier = .; . += 8;
|
||||
_unregister_module_notifier = .; . += 8;
|
||||
_execmem_free = .; . += 8;
|
||||
_module_alloc = .; . += 8;
|
||||
_module_memfree = .; . += 8;
|
||||
___init_waitqueue_head = .; . += 8;
|
||||
_prepare_to_wait_event = .; . += 8;
|
||||
_finish_wait = .; . += 8;
|
||||
___wake_up = .; . += 8;
|
||||
_autoremove_wake_function = .; . += 8;
|
||||
_schedule_hrtimeout_range = .; . += 8;
|
||||
_pci_get_domain_bus_and_slot = .; . += 8;
|
||||
_pci_irq_vector = .; . += 8;
|
||||
_of_irq_parse_and_map_pci = .; . += 8;
|
||||
_pci_dev_put = .; . += 8;
|
||||
_schedule = .; . += 8;
|
||||
_ktime_get_mono_fast_ns = .; . += 8;
|
||||
_ktime_get_real_ts64 = .; . += 8;
|
||||
_getnstimeofday64 = .; . += 8;
|
||||
_send_sig = .; . += 8;
|
||||
_free_irq = .; . += 8;
|
||||
_request_threaded_irq = .; . += 8;
|
||||
_generic_ioremap_prot = .; . += 8;
|
||||
___ioremap = .; . += 8;
|
||||
_vmap = .; . += 8;
|
||||
_memstart_addr = .; . += 8;
|
||||
_init_task = .; . += 8;
|
||||
_tasklist_lock = .; . += 8;
|
||||
__raw_read_lock = .; . += 8;
|
||||
__raw_read_unlock = .; . += 8;
|
||||
__raw_read_lock_irqsave = .; . += 8;
|
||||
__raw_read_unlock_irqrestore = .; . += 8;
|
||||
__raw_write_lock = .; . += 8;
|
||||
__raw_write_unlock = .; . += 8;
|
||||
__raw_write_lock_irqsave = .; . += 8;
|
||||
__raw_write_unlock_irqrestore = .; . += 8;
|
||||
_detach_pid = .; . += 8;
|
||||
_free_pids = .; . += 8;
|
||||
_get_task_exe_file = .; . += 8;
|
||||
_file_path = .; . += 8;
|
||||
_fput = .; . += 8;
|
||||
_copy_from_kernel_nofault = .; . += 8;
|
||||
_get_task_mm = .; . += 8;
|
||||
_kthread_use_mm = .; . += 8;
|
||||
_kthread_unuse_mm = .; . += 8;
|
||||
_mmput = .; . += 8;
|
||||
_vm_mmap = .; . += 8;
|
||||
_vm_munmap = .; . += 8;
|
||||
_tracepoint_probe_register = .; . += 8;
|
||||
_tracepoint_probe_unregister = .; . += 8;
|
||||
___tracepoint_sched_process_fork = .; . += 8;
|
||||
___tracepoint_sched_process_exit = .; . += 8;
|
||||
___tracepoint_sched_process_exec = .; . += 8;
|
||||
___tracepoint_task_rename = .; . += 8;
|
||||
___set_task_comm = .; . += 8;
|
||||
_vunmap = .; . += 8;
|
||||
___arch_copy_to_user = .; . += 8;
|
||||
_down_read = .; . += 8;
|
||||
_up_read = .; . += 8;
|
||||
_get_user_pages_unlocked = .; . += 8;
|
||||
_get_user_pages_remote = .; . += 8;
|
||||
___arch_copy_from_user = .; . += 8;
|
||||
_do_futex = .; . += 8;
|
||||
_user_mode_thread = .; . += 8;
|
||||
_apply_to_existing_page_range = .; . += 8;
|
||||
_caches_clean_inval_pou = .; . += 8;
|
||||
_do_madvise = .; . += 8;
|
||||
_fget_task = .; . += 8;
|
||||
_find_task_by_vpid = .; . += 8;
|
||||
___start_BTF = .; . += 8;
|
||||
___stop_BTF = .; . += 8;
|
||||
_call_usermodehelper_setup = .; . += 8;
|
||||
_call_usermodehelper_exec = .; . += 8;
|
||||
_access_process_vm = .; . += 8;
|
||||
_fixup_exception = .; . += 8;
|
||||
_aarch64_insn_patch_text_nosync = .; . += 8;
|
||||
_aarch64_insn_patch_text = .; . += 8;
|
||||
_kthread_worker_fn = .; . += 8;
|
||||
_vring_interrupt = .; . += 8;
|
||||
_init_net = .; . += 8;
|
||||
_sock_create_kern = .; . += 8;
|
||||
_kernel_connect = .; . += 8;
|
||||
_kernel_sendmsg = .; . += 8;
|
||||
_kernel_recvmsg = .; . += 8;
|
||||
_sock_release = .; . += 8;
|
||||
_sock_def_readable = .; . += 8;
|
||||
}
|
||||
/* Everything above is only ever read, so a process being instrumented can be shown the very
|
||||
same pages; everything below it each copy needs its own of. */
|
||||
. = ALIGN(4096);
|
||||
_agent_private_start = .;
|
||||
.data.rel.ro : {
|
||||
*(.data.rel.ro*)
|
||||
}
|
||||
.got : {
|
||||
*(.got*)
|
||||
}
|
||||
.init_array : {
|
||||
_agent_init_start = .;
|
||||
*(.init_array*)
|
||||
_agent_init_end = .;
|
||||
}
|
||||
.data : {
|
||||
*(.data*)
|
||||
}
|
||||
.bss : {
|
||||
*(.bss*)
|
||||
}
|
||||
. = ALIGN(8);
|
||||
_heap_start = .;
|
||||
}
|
||||
|
||||
VERSION {
|
||||
{
|
||||
global:
|
||||
_start;
|
||||
|
||||
local:
|
||||
*;
|
||||
};
|
||||
}
|
||||
@@ -1,146 +0,0 @@
|
||||
SECTIONS {
|
||||
.text : {
|
||||
*(.text.entrypoint)
|
||||
*(.text*)
|
||||
}
|
||||
.rel.dyn : {
|
||||
_agent_relocs_start = .;
|
||||
*(.rel.dyn)
|
||||
_agent_relocs_end = .;
|
||||
}
|
||||
.rodata : {
|
||||
*(.rodata*)
|
||||
}
|
||||
.kernel_addrs : ALIGN(4) {
|
||||
. = ALIGN(4);
|
||||
__printk = .; . += 4;
|
||||
_printk = .; . += 4;
|
||||
_panic = .; . += 4;
|
||||
_kthread_create_on_node = .; . += 4;
|
||||
_wake_up_process = .; . += 4;
|
||||
_fget = .; . += 4;
|
||||
_kernel_read = .; . += 4;
|
||||
_filp_open = .; . += 4;
|
||||
_kernel_write = .; . += 4;
|
||||
___kmalloc_noprof = .; . += 4;
|
||||
_kmalloc = .; . += 4;
|
||||
_kfree = .; . += 4;
|
||||
_vmalloc = .; . += 4;
|
||||
_execmem_alloc = .; . += 4;
|
||||
_set_memory_rw = .; . += 4;
|
||||
_set_memory_ro = .; . += 4;
|
||||
_set_memory_x = .; . += 4;
|
||||
_set_memory_nx = .; . += 4;
|
||||
_modules = .; . += 4;
|
||||
_register_module_notifier = .; . += 4;
|
||||
_unregister_module_notifier = .; . += 4;
|
||||
_text_poke_kgdb = .; . += 4;
|
||||
_execmem_free = .; . += 4;
|
||||
_module_alloc = .; . += 4;
|
||||
_module_memfree = .; . += 4;
|
||||
___init_waitqueue_head = .; . += 4;
|
||||
_prepare_to_wait_event = .; . += 4;
|
||||
_finish_wait = .; . += 4;
|
||||
___wake_up = .; . += 4;
|
||||
_autoremove_wake_function = .; . += 4;
|
||||
_schedule_hrtimeout_range = .; . += 4;
|
||||
_pci_get_domain_bus_and_slot = .; . += 4;
|
||||
_pci_irq_vector = .; . += 4;
|
||||
_pci_dev_put = .; . += 4;
|
||||
_schedule = .; . += 4;
|
||||
_ktime_get_mono_fast_ns = .; . += 4;
|
||||
_ktime_get_real_ts64 = .; . += 4;
|
||||
_send_sig = .; . += 4;
|
||||
_free_irq = .; . += 4;
|
||||
_request_threaded_irq = .; . += 4;
|
||||
_vmap = .; . += 4;
|
||||
_current_task = .; . += 4;
|
||||
_ioremap = .; . += 4;
|
||||
_ioremap_nocache = .; . += 4;
|
||||
___default_kernel_pte_mask = .; . += 4;
|
||||
_init_task = .; . += 4;
|
||||
_tasklist_lock = .; . += 4;
|
||||
__raw_read_lock = .; . += 4;
|
||||
__raw_read_unlock = .; . += 4;
|
||||
__raw_read_lock_irqsave = .; . += 4;
|
||||
__raw_read_unlock_irqrestore = .; . += 4;
|
||||
__raw_write_lock = .; . += 4;
|
||||
__raw_write_unlock = .; . += 4;
|
||||
__raw_write_lock_irqsave = .; . += 4;
|
||||
__raw_write_unlock_irqrestore = .; . += 4;
|
||||
_detach_pid = .; . += 4;
|
||||
_free_pids = .; . += 4;
|
||||
_get_task_exe_file = .; . += 4;
|
||||
_file_path = .; . += 4;
|
||||
_fput = .; . += 4;
|
||||
_copy_from_kernel_nofault = .; . += 4;
|
||||
_get_task_mm = .; . += 4;
|
||||
_kthread_use_mm = .; . += 4;
|
||||
_kthread_unuse_mm = .; . += 4;
|
||||
_mmput = .; . += 4;
|
||||
_vm_mmap = .; . += 4;
|
||||
_vm_munmap = .; . += 4;
|
||||
_tracepoint_probe_register = .; . += 4;
|
||||
_tracepoint_probe_unregister = .; . += 4;
|
||||
___tracepoint_sched_process_fork = .; . += 4;
|
||||
___tracepoint_sched_process_exit = .; . += 4;
|
||||
___tracepoint_sched_process_exec = .; . += 4;
|
||||
_vunmap = .; . += 4;
|
||||
__copy_to_user = .; . += 4;
|
||||
_down_read = .; . += 4;
|
||||
_up_read = .; . += 4;
|
||||
_get_user_pages_unlocked = .; . += 4;
|
||||
_get_user_pages_remote = .; . += 4;
|
||||
_do_futex = .; . += 4;
|
||||
_user_mode_thread = .; . += 4;
|
||||
___start_BTF = .; . += 4;
|
||||
___stop_BTF = .; . += 4;
|
||||
_call_usermodehelper_setup = .; . += 4;
|
||||
_call_usermodehelper_exec = .; . += 4;
|
||||
__copy_from_user = .; . += 4;
|
||||
_access_process_vm = .; . += 4;
|
||||
_fget_task = .; . += 4;
|
||||
_find_task_by_vpid = .; . += 4;
|
||||
_init_net = .; . += 4;
|
||||
_sock_create_kern = .; . += 4;
|
||||
_kernel_connect = .; . += 4;
|
||||
_kernel_sendmsg = .; . += 4;
|
||||
_kernel_recvmsg = .; . += 4;
|
||||
_sock_release = .; . += 4;
|
||||
_register_die_notifier = .; . += 4;
|
||||
_unregister_die_notifier = .; . += 4;
|
||||
}
|
||||
/* Everything above is only ever read, so a process being instrumented can be shown the very
|
||||
same pages; everything below it each copy needs its own of. */
|
||||
. = ALIGN(4096);
|
||||
_agent_private_start = .;
|
||||
.data.rel.ro : {
|
||||
*(.data.rel.ro*)
|
||||
}
|
||||
.got : {
|
||||
*(.got*)
|
||||
}
|
||||
.init_array : {
|
||||
_agent_init_start = .;
|
||||
*(.init_array*)
|
||||
_agent_init_end = .;
|
||||
}
|
||||
.data : {
|
||||
*(.data*)
|
||||
}
|
||||
.bss : {
|
||||
*(.bss*)
|
||||
}
|
||||
. = ALIGN(4);
|
||||
_heap_start = .;
|
||||
}
|
||||
|
||||
VERSION {
|
||||
{
|
||||
global:
|
||||
_start;
|
||||
|
||||
local:
|
||||
*;
|
||||
};
|
||||
}
|
||||
@@ -1,154 +0,0 @@
|
||||
SECTIONS {
|
||||
.text : {
|
||||
*(.text.entrypoint)
|
||||
*(.text*)
|
||||
}
|
||||
.rela.dyn : {
|
||||
_agent_relocs_start = .;
|
||||
*(.rela.dyn)
|
||||
_agent_relocs_end = .;
|
||||
}
|
||||
.rodata : {
|
||||
*(.rodata*)
|
||||
}
|
||||
.kernel_addrs : ALIGN(8) {
|
||||
. = ALIGN(8);
|
||||
__printk = .; . += 8;
|
||||
_printk = .; . += 8;
|
||||
_panic = .; . += 8;
|
||||
_kthread_create_on_node = .; . += 8;
|
||||
_wake_up_process = .; . += 8;
|
||||
_fget = .; . += 8;
|
||||
_kernel_read = .; . += 8;
|
||||
_filp_open = .; . += 8;
|
||||
_kernel_write = .; . += 8;
|
||||
___kmalloc_noprof = .; . += 8;
|
||||
_kmalloc = .; . += 8;
|
||||
___kmalloc = .; . += 8;
|
||||
_kfree = .; . += 8;
|
||||
_vmalloc = .; . += 8;
|
||||
_execmem_alloc = .; . += 8;
|
||||
_set_memory_rw = .; . += 8;
|
||||
_set_memory_ro = .; . += 8;
|
||||
_set_memory_x = .; . += 8;
|
||||
_set_memory_nx = .; . += 8;
|
||||
_modules = .; . += 8;
|
||||
_register_module_notifier = .; . += 8;
|
||||
_unregister_module_notifier = .; . += 8;
|
||||
_text_poke_kgdb = .; . += 8;
|
||||
_execmem_free = .; . += 8;
|
||||
_module_alloc = .; . += 8;
|
||||
_module_memfree = .; . += 8;
|
||||
___init_waitqueue_head = .; . += 8;
|
||||
_prepare_to_wait_event = .; . += 8;
|
||||
_finish_wait = .; . += 8;
|
||||
___wake_up = .; . += 8;
|
||||
_autoremove_wake_function = .; . += 8;
|
||||
_schedule_hrtimeout_range = .; . += 8;
|
||||
_pci_get_domain_bus_and_slot = .; . += 8;
|
||||
_pci_irq_vector = .; . += 8;
|
||||
_pci_dev_put = .; . += 8;
|
||||
_schedule = .; . += 8;
|
||||
_ktime_get_mono_fast_ns = .; . += 8;
|
||||
_ktime_get_real_ts64 = .; . += 8;
|
||||
_getnstimeofday64 = .; . += 8;
|
||||
_send_sig = .; . += 8;
|
||||
_free_irq = .; . += 8;
|
||||
_request_threaded_irq = .; . += 8;
|
||||
_vmap = .; . += 8;
|
||||
_page_offset_base = .; . += 8;
|
||||
_current_task = .; . += 8;
|
||||
_cpu_current_top_of_stack = .; . += 8;
|
||||
_register_die_notifier = .; . += 8;
|
||||
_unregister_die_notifier = .; . += 8;
|
||||
_ioremap = .; . += 8;
|
||||
_ioremap_nocache = .; . += 8;
|
||||
___default_kernel_pte_mask = .; . += 8;
|
||||
_init_task = .; . += 8;
|
||||
_tasklist_lock = .; . += 8;
|
||||
__raw_read_lock = .; . += 8;
|
||||
__raw_read_unlock = .; . += 8;
|
||||
__raw_read_lock_irqsave = .; . += 8;
|
||||
__raw_read_unlock_irqrestore = .; . += 8;
|
||||
__raw_write_lock = .; . += 8;
|
||||
__raw_write_unlock = .; . += 8;
|
||||
__raw_write_lock_irqsave = .; . += 8;
|
||||
__raw_write_unlock_irqrestore = .; . += 8;
|
||||
_detach_pid = .; . += 8;
|
||||
_free_pids = .; . += 8;
|
||||
_get_task_exe_file = .; . += 8;
|
||||
_file_path = .; . += 8;
|
||||
_fput = .; . += 8;
|
||||
_copy_from_kernel_nofault = .; . += 8;
|
||||
_get_task_mm = .; . += 8;
|
||||
_kthread_use_mm = .; . += 8;
|
||||
_kthread_unuse_mm = .; . += 8;
|
||||
_mmput = .; . += 8;
|
||||
_vm_mmap = .; . += 8;
|
||||
_vm_munmap = .; . += 8;
|
||||
_tracepoint_probe_register = .; . += 8;
|
||||
_tracepoint_probe_unregister = .; . += 8;
|
||||
___tracepoint_sched_process_fork = .; . += 8;
|
||||
___tracepoint_sched_process_exit = .; . += 8;
|
||||
___tracepoint_sched_process_exec = .; . += 8;
|
||||
___tracepoint_task_rename = .; . += 8;
|
||||
___set_task_comm = .; . += 8;
|
||||
_vunmap = .; . += 8;
|
||||
__copy_to_user = .; . += 8;
|
||||
_down_read = .; . += 8;
|
||||
_up_read = .; . += 8;
|
||||
_get_user_pages_unlocked = .; . += 8;
|
||||
_get_user_pages_remote = .; . += 8;
|
||||
_do_futex = .; . += 8;
|
||||
_user_mode_thread = .; . += 8;
|
||||
___start_BTF = .; . += 8;
|
||||
___stop_BTF = .; . += 8;
|
||||
_call_usermodehelper_setup = .; . += 8;
|
||||
_call_usermodehelper_exec = .; . += 8;
|
||||
__copy_from_user = .; . += 8;
|
||||
_access_process_vm = .; . += 8;
|
||||
_fget_task = .; . += 8;
|
||||
_find_task_by_vpid = .; . += 8;
|
||||
_init_net = .; . += 8;
|
||||
_sock_create_kern = .; . += 8;
|
||||
_kernel_connect = .; . += 8;
|
||||
_kernel_sendmsg = .; . += 8;
|
||||
_kernel_recvmsg = .; . += 8;
|
||||
_sock_release = .; . += 8;
|
||||
_sock_def_readable = .; . += 8;
|
||||
_of_irq_parse_and_map_pci = .; . += 8;
|
||||
}
|
||||
/* Everything above is only ever read, so a process being instrumented can be shown the very
|
||||
same pages; everything below it each copy needs its own of. */
|
||||
. = ALIGN(4096);
|
||||
_agent_private_start = .;
|
||||
.data.rel.ro : {
|
||||
*(.data.rel.ro*)
|
||||
}
|
||||
.got : {
|
||||
*(.got*)
|
||||
}
|
||||
.init_array : {
|
||||
_agent_init_start = .;
|
||||
*(.init_array*)
|
||||
_agent_init_end = .;
|
||||
}
|
||||
.data : {
|
||||
*(.data*)
|
||||
}
|
||||
.bss : {
|
||||
*(.bss*)
|
||||
}
|
||||
. = ALIGN(8);
|
||||
_heap_start = .;
|
||||
}
|
||||
|
||||
VERSION {
|
||||
{
|
||||
global:
|
||||
_start;
|
||||
|
||||
local:
|
||||
*;
|
||||
};
|
||||
}
|
||||
@@ -1,97 +0,0 @@
|
||||
SECTIONS {
|
||||
.text : {
|
||||
*(.text.entrypoint)
|
||||
*(.text*)
|
||||
}
|
||||
.rel.dyn : {
|
||||
_agent_relocs_start = .;
|
||||
*(.rel.dyn)
|
||||
_agent_relocs_end = .;
|
||||
}
|
||||
.rodata : {
|
||||
*(.rodata*)
|
||||
}
|
||||
.kernel_addrs : ALIGN(4) {
|
||||
. = ALIGN(4);
|
||||
_Get_Cur_VM_Handle = .; . += 4;
|
||||
_Get_Sys_VM_Handle = .; . += 4;
|
||||
_Schedule_Global_Event = .; . += 4;
|
||||
_Create_Semaphore = .; . += 4;
|
||||
_Wait_Semaphore = .; . += 4;
|
||||
_Signal_Semaphore = .; . += 4;
|
||||
_Get_Next_VM_Handle = .; . += 4;
|
||||
_Release_Time_Slice = .; . += 4;
|
||||
_Set_Global_Time_Out = .; . += 4;
|
||||
_Cancel_Time_Out = .; . += 4;
|
||||
_Get_System_Time = .; . += 4;
|
||||
__HeapAllocate = .; . += 4;
|
||||
__HeapFree = .; . += 4;
|
||||
__PageAllocate = .; . += 4;
|
||||
__PageFree = .; . += 4;
|
||||
__CopyPageTable = .; . += 4;
|
||||
__MapPhysToLinear = .; . += 4;
|
||||
_VMM_Add_DDB = .; . += 4;
|
||||
_VMM_Remove_DDB = .; . += 4;
|
||||
__RegOpenKey = .; . += 4;
|
||||
__RegCloseKey = .; . += 4;
|
||||
__RegEnumKey = .; . += 4;
|
||||
__RegQueryValueEx = .; . += 4;
|
||||
__PageReserve = .; . += 4;
|
||||
__PageCommit = .; . += 4;
|
||||
_Hook_VMM_Fault = .; . += 4;
|
||||
_Unhook_VMM_Fault = .; . += 4;
|
||||
_Fatal_Error_Handler = .; . += 4;
|
||||
_Get_Cur_Thread_Handle = .; . += 4;
|
||||
|
||||
_Get_Initial_Thread_Handle = .; . += 4;
|
||||
_Get_Next_Thread_Handle = .; . += 4;
|
||||
__Debug_Printf_Service = .; . += 4;
|
||||
__ContextSwitch = .; . += 4;
|
||||
__PageModifyPermissions = .; . += 4;
|
||||
__GetCurrentContext = .; . += 4;
|
||||
_VPICD_Virtualize_IRQ = .; . += 4;
|
||||
_VPICD_Force_Default_Behavior = .; . += 4;
|
||||
_VPICD_Phys_EOI = .; . += 4;
|
||||
_VPICD_Physically_Unmask = .; . += 4;
|
||||
__VWIN32_QueueUserApc = .; . += 4;
|
||||
__VWIN32_Get_Thread_Context = .; . += 4;
|
||||
__VWIN32_Set_Thread_Context = .; . += 4;
|
||||
__VWIN32_CreateRing0Thread = .; . += 4;
|
||||
_IFSMgr_Ring0_FileIO = .; . += 4;
|
||||
_KERNEL32_Base = .; . += 4;
|
||||
_KERNEL32_ProcessIdObfuscator = .; . += 4;
|
||||
_KERNEL32_ModuleTable = .; . += 4;
|
||||
__PageCommitPhys = .; . += 4;
|
||||
}
|
||||
/* Everything above is only ever read, so a process being instrumented can be shown the very
|
||||
same pages; everything below it each copy needs its own of. */
|
||||
. = ALIGN(4096);
|
||||
_agent_private_start = .;
|
||||
.data.rel.ro : {
|
||||
*(.data.rel.ro*)
|
||||
}
|
||||
.got : {
|
||||
*(.got*)
|
||||
}
|
||||
.init_array : {
|
||||
_agent_init_start = .;
|
||||
*(.init_array*)
|
||||
_agent_init_end = .;
|
||||
}
|
||||
.bss : {
|
||||
*(.bss*)
|
||||
}
|
||||
. = ALIGN(4);
|
||||
_heap_start = .;
|
||||
}
|
||||
|
||||
VERSION {
|
||||
{
|
||||
global:
|
||||
_start;
|
||||
frida_win9x_user_main;
|
||||
|
||||
local:
|
||||
*;
|
||||
};
|
||||
}
|
||||
@@ -1,112 +0,0 @@
|
||||
SECTIONS {
|
||||
.text : {
|
||||
*(.text.entrypoint)
|
||||
*(.text*)
|
||||
}
|
||||
.rela.dyn : {
|
||||
_agent_relocs_start = .;
|
||||
*(.rela.dyn)
|
||||
_agent_relocs_end = .;
|
||||
}
|
||||
.rodata : {
|
||||
*(.rodata*)
|
||||
}
|
||||
.kernel_addrs : ALIGN(8) {
|
||||
. = ALIGN(8);
|
||||
_ExAllocatePoolWithTag = .; . += 8;
|
||||
_ExFreePoolWithTag = .; . += 8;
|
||||
_PsCreateSystemThread = .; . += 8;
|
||||
_PsGetCurrentThreadId = .; . += 8;
|
||||
_KeInitializeEvent = .; . += 8;
|
||||
_KeWaitForSingleObject = .; . += 8;
|
||||
_KeSetEvent = .; . += 8;
|
||||
_KeInitializeDpc = .; . += 8;
|
||||
_PsSetCreateThreadNotifyRoutine = .; . += 8;
|
||||
_PsRemoveCreateThreadNotifyRoutine = .; . += 8;
|
||||
_KeInsertQueueDpc = .; . += 8;
|
||||
_ZwYieldExecution = .; . += 8;
|
||||
_KeExpandKernelStackAndCalloutEx = .; . += 8;
|
||||
_KeBugCheckEx = .; . += 8;
|
||||
_DbgPrint = .; . += 8;
|
||||
_MmGetVirtualForPhysical = .; . += 8;
|
||||
_MmMapIoSpace = .; . += 8;
|
||||
_MmGetPhysicalAddress = .; . += 8;
|
||||
_HalGetInterruptVector = .; . += 8;
|
||||
_IoConnectInterrupt = .; . += 8;
|
||||
_IoDisconnectInterrupt = .; . += 8;
|
||||
_PsActiveProcessHead = .; . += 8;
|
||||
_PsInitialSystemProcess = .; . += 8;
|
||||
_PsGetProcessId = .; . += 8;
|
||||
_PsGetProcessImageFileName = .; . += 8;
|
||||
_PsGetProcessPeb = .; . += 8;
|
||||
_PsGetCurrentThread = .; . += 8;
|
||||
_PsGetThreadProcess = .; . += 8;
|
||||
_PsGetThreadId = .; . += 8;
|
||||
_PsGetThreadTeb = .; . += 8;
|
||||
_PsGetContextThread = .; . += 8;
|
||||
_PsSetContextThread = .; . += 8;
|
||||
_KeStackAttachProcess = .; . += 8;
|
||||
_KeUnstackDetachProcess = .; . += 8;
|
||||
_ZwCreateFile = .; . += 8;
|
||||
_ZwOpenKey = .; . += 8;
|
||||
_ZwEnumerateKey = .; . += 8;
|
||||
_ZwQueryValueKey = .; . += 8;
|
||||
_ZwReadFile = .; . += 8;
|
||||
_ZwWriteFile = .; . += 8;
|
||||
_ZwEnumerateValueKey = .; . += 8;
|
||||
_ZwDeviceIoControlFile = .; . += 8;
|
||||
_ZwClose = .; . += 8;
|
||||
_ZwCreateEvent = .; . += 8;
|
||||
_ExAllocatePool2 = .; . += 8;
|
||||
_MmCopyVirtualMemory = .; . += 8;
|
||||
_KeIpiGenericCall = .; . += 8;
|
||||
_MmIsAddressValid = .; . += 8;
|
||||
_ZwClearEvent = .; . += 8;
|
||||
_ZwWaitForSingleObject = .; . += 8;
|
||||
_ZwAllocateVirtualMemory = .; . += 8;
|
||||
_ZwFreeVirtualMemory = .; . += 8;
|
||||
_ZwCreateThread = .; . += 8;
|
||||
_PsProcessType = .; . += 8;
|
||||
_ObReferenceObjectByHandle = .; . += 8;
|
||||
_ObOpenObjectByPointer = .; . += 8;
|
||||
_ExEventObjectType = .; . += 8;
|
||||
_IoAllocateMdl = .; . += 8;
|
||||
_IoFreeMdl = .; . += 8;
|
||||
_MmBuildMdlForNonPagedPool = .; . += 8;
|
||||
_MmMapLockedPagesSpecifyCache = .; . += 8;
|
||||
_MmUnmapLockedPages = .; . += 8;
|
||||
}
|
||||
. = ALIGN(4096);
|
||||
_agent_private_start = .;
|
||||
.data.rel.ro : {
|
||||
*(.data.rel.ro*)
|
||||
}
|
||||
.got : {
|
||||
*(.got*)
|
||||
}
|
||||
.init_array : {
|
||||
_agent_init_start = .;
|
||||
*(.init_array*)
|
||||
_agent_init_end = .;
|
||||
}
|
||||
.data : {
|
||||
*(.data*)
|
||||
}
|
||||
.bss : {
|
||||
*(.bss*)
|
||||
}
|
||||
. = ALIGN(8);
|
||||
_heap_start = .;
|
||||
}
|
||||
|
||||
VERSION {
|
||||
{
|
||||
global:
|
||||
_start;
|
||||
frida_winnt_user_main;
|
||||
frida_winnt_user_bootstrap;
|
||||
|
||||
local:
|
||||
*;
|
||||
};
|
||||
}
|
||||
@@ -1,111 +0,0 @@
|
||||
SECTIONS {
|
||||
.text : {
|
||||
*(.text.entrypoint)
|
||||
*(.text*)
|
||||
}
|
||||
.rel.dyn : {
|
||||
_agent_relocs_start = .;
|
||||
*(.rel.dyn)
|
||||
_agent_relocs_end = .;
|
||||
}
|
||||
.rodata : {
|
||||
*(.rodata*)
|
||||
}
|
||||
.kernel_addrs : ALIGN(4) {
|
||||
. = ALIGN(4);
|
||||
_ExAllocatePoolWithTag = .; . += 4;
|
||||
_ExFreePoolWithTag = .; . += 4;
|
||||
_PsCreateSystemThread = .; . += 4;
|
||||
_PsGetCurrentThreadId = .; . += 4;
|
||||
_KeInitializeEvent = .; . += 4;
|
||||
_KeWaitForSingleObject = .; . += 4;
|
||||
_KeSetEvent = .; . += 4;
|
||||
_KeInitializeDpc = .; . += 4;
|
||||
_PsSetCreateThreadNotifyRoutine = .; . += 4;
|
||||
_PsRemoveCreateThreadNotifyRoutine = .; . += 4;
|
||||
_KeInsertQueueDpc = .; . += 4;
|
||||
_ZwYieldExecution = .; . += 4;
|
||||
_KeExpandKernelStackAndCalloutEx = .; . += 4;
|
||||
_KeBugCheckEx = .; . += 4;
|
||||
_DbgPrint = .; . += 4;
|
||||
_MmGetVirtualForPhysical = .; . += 4;
|
||||
_MmMapIoSpace = .; . += 4;
|
||||
_MmGetPhysicalAddress = .; . += 4;
|
||||
_HalGetInterruptVector = .; . += 4;
|
||||
_IoConnectInterrupt = .; . += 4;
|
||||
_IoDisconnectInterrupt = .; . += 4;
|
||||
_PsActiveProcessHead = .; . += 4;
|
||||
_PsInitialSystemProcess = .; . += 4;
|
||||
_PsGetProcessId = .; . += 4;
|
||||
_PsGetProcessImageFileName = .; . += 4;
|
||||
_PsGetProcessPeb = .; . += 4;
|
||||
_PsGetCurrentThread = .; . += 4;
|
||||
_PsGetThreadProcess = .; . += 4;
|
||||
_PsGetThreadId = .; . += 4;
|
||||
_PsGetThreadTeb = .; . += 4;
|
||||
_PsGetContextThread = .; . += 4;
|
||||
_PsSetContextThread = .; . += 4;
|
||||
_KeStackAttachProcess = .; . += 4;
|
||||
_KeUnstackDetachProcess = .; . += 4;
|
||||
_ZwCreateFile = .; . += 4;
|
||||
_ZwOpenKey = .; . += 4;
|
||||
_ZwEnumerateKey = .; . += 4;
|
||||
_ZwQueryValueKey = .; . += 4;
|
||||
_ZwReadFile = .; . += 4;
|
||||
_ZwWriteFile = .; . += 4;
|
||||
_ZwEnumerateValueKey = .; . += 4;
|
||||
_ZwDeviceIoControlFile = .; . += 4;
|
||||
_ZwClose = .; . += 4;
|
||||
_ZwCreateEvent = .; . += 4;
|
||||
_ExAllocatePool2 = .; . += 4;
|
||||
_MmCopyVirtualMemory = .; . += 4;
|
||||
_KeIpiGenericCall = .; . += 4;
|
||||
_MmIsAddressValid = .; . += 4;
|
||||
_ZwClearEvent = .; . += 4;
|
||||
_ZwWaitForSingleObject = .; . += 4;
|
||||
_ZwAllocateVirtualMemory = .; . += 4;
|
||||
_ZwFreeVirtualMemory = .; . += 4;
|
||||
_ZwCreateThread = .; . += 4;
|
||||
_PsProcessType = .; . += 4;
|
||||
_ObReferenceObjectByHandle = .; . += 4;
|
||||
_ObOpenObjectByPointer = .; . += 4;
|
||||
_ExEventObjectType = .; . += 4;
|
||||
_IoAllocateMdl = .; . += 4;
|
||||
_IoFreeMdl = .; . += 4;
|
||||
_MmBuildMdlForNonPagedPool = .; . += 4;
|
||||
_MmMapLockedPagesSpecifyCache = .; . += 4;
|
||||
_MmUnmapLockedPages = .; . += 4;
|
||||
}
|
||||
/* Everything above is only ever read, so a process being instrumented can be shown the very
|
||||
same pages; everything below it each copy needs its own of. */
|
||||
. = ALIGN(4096);
|
||||
_agent_private_start = .;
|
||||
.data.rel.ro : {
|
||||
*(.data.rel.ro*)
|
||||
}
|
||||
.got : {
|
||||
*(.got*)
|
||||
}
|
||||
.init_array : {
|
||||
_agent_init_start = .;
|
||||
*(.init_array*)
|
||||
_agent_init_end = .;
|
||||
}
|
||||
.bss : {
|
||||
*(.bss*)
|
||||
}
|
||||
. = ALIGN(4);
|
||||
_heap_start = .;
|
||||
}
|
||||
|
||||
VERSION {
|
||||
{
|
||||
global:
|
||||
_start;
|
||||
frida_winnt_user_main;
|
||||
frida_winnt_user_bootstrap;
|
||||
|
||||
local:
|
||||
*;
|
||||
};
|
||||
}
|
||||
@@ -1,121 +0,0 @@
|
||||
SECTIONS {
|
||||
/* The large code model gives every section an l-prefixed name of its own, so that
|
||||
the compiler can reach it with a 64-bit displacement rather than assume 2GB. */
|
||||
.text : {
|
||||
*(.text.entrypoint)
|
||||
*(.ltext.entrypoint)
|
||||
*(.text*)
|
||||
*(.ltext*)
|
||||
}
|
||||
.rela.dyn : {
|
||||
_agent_relocs_start = .;
|
||||
*(.rela.dyn)
|
||||
_agent_relocs_end = .;
|
||||
}
|
||||
.rodata : {
|
||||
*(.rodata*)
|
||||
*(.lrodata*)
|
||||
}
|
||||
.kernel_addrs : ALIGN(8) {
|
||||
. = ALIGN(8);
|
||||
_ExAllocatePoolWithTag = .; . += 8;
|
||||
_ExFreePoolWithTag = .; . += 8;
|
||||
_PsCreateSystemThread = .; . += 8;
|
||||
_PsGetCurrentThreadId = .; . += 8;
|
||||
_KeInitializeEvent = .; . += 8;
|
||||
_KeWaitForSingleObject = .; . += 8;
|
||||
_KeSetEvent = .; . += 8;
|
||||
_KeInitializeDpc = .; . += 8;
|
||||
_PsSetCreateThreadNotifyRoutine = .; . += 8;
|
||||
_PsRemoveCreateThreadNotifyRoutine = .; . += 8;
|
||||
_KeInsertQueueDpc = .; . += 8;
|
||||
_ZwYieldExecution = .; . += 8;
|
||||
_KeExpandKernelStackAndCalloutEx = .; . += 8;
|
||||
_KeBugCheckEx = .; . += 8;
|
||||
_DbgPrint = .; . += 8;
|
||||
_MmGetVirtualForPhysical = .; . += 8;
|
||||
_MmMapIoSpace = .; . += 8;
|
||||
_MmGetPhysicalAddress = .; . += 8;
|
||||
_HalGetInterruptVector = .; . += 8;
|
||||
_IoConnectInterrupt = .; . += 8;
|
||||
_IoDisconnectInterrupt = .; . += 8;
|
||||
_PsActiveProcessHead = .; . += 8;
|
||||
_PsInitialSystemProcess = .; . += 8;
|
||||
_PsGetProcessId = .; . += 8;
|
||||
_PsGetProcessImageFileName = .; . += 8;
|
||||
_PsGetProcessPeb = .; . += 8;
|
||||
_PsGetCurrentThread = .; . += 8;
|
||||
_PsGetThreadProcess = .; . += 8;
|
||||
_PsGetThreadId = .; . += 8;
|
||||
_PsGetThreadTeb = .; . += 8;
|
||||
_PsGetContextThread = .; . += 8;
|
||||
_PsSetContextThread = .; . += 8;
|
||||
_KeStackAttachProcess = .; . += 8;
|
||||
_KeUnstackDetachProcess = .; . += 8;
|
||||
_ZwCreateFile = .; . += 8;
|
||||
_ZwOpenKey = .; . += 8;
|
||||
_ZwEnumerateKey = .; . += 8;
|
||||
_ZwQueryValueKey = .; . += 8;
|
||||
_ZwReadFile = .; . += 8;
|
||||
_ZwWriteFile = .; . += 8;
|
||||
_ZwEnumerateValueKey = .; . += 8;
|
||||
_ZwDeviceIoControlFile = .; . += 8;
|
||||
_ZwClose = .; . += 8;
|
||||
_ZwCreateEvent = .; . += 8;
|
||||
_ExAllocatePool2 = .; . += 8;
|
||||
_MmCopyVirtualMemory = .; . += 8;
|
||||
_KeIpiGenericCall = .; . += 8;
|
||||
_MmIsAddressValid = .; . += 8;
|
||||
_ZwClearEvent = .; . += 8;
|
||||
_ZwWaitForSingleObject = .; . += 8;
|
||||
_ZwAllocateVirtualMemory = .; . += 8;
|
||||
_ZwFreeVirtualMemory = .; . += 8;
|
||||
_ZwCreateThread = .; . += 8;
|
||||
_PsProcessType = .; . += 8;
|
||||
_ObReferenceObjectByHandle = .; . += 8;
|
||||
_ObOpenObjectByPointer = .; . += 8;
|
||||
_ExEventObjectType = .; . += 8;
|
||||
_IoAllocateMdl = .; . += 8;
|
||||
_IoFreeMdl = .; . += 8;
|
||||
_MmBuildMdlForNonPagedPool = .; . += 8;
|
||||
_MmMapLockedPagesSpecifyCache = .; . += 8;
|
||||
_MmUnmapLockedPages = .; . += 8;
|
||||
}
|
||||
/* Everything above is only ever read, so a process being instrumented can be shown the very
|
||||
same pages; everything below it each copy needs its own of. */
|
||||
. = ALIGN(4096);
|
||||
_agent_private_start = .;
|
||||
.data.rel.ro : {
|
||||
*(.data.rel.ro*)
|
||||
}
|
||||
.got : {
|
||||
*(.got*)
|
||||
}
|
||||
.init_array : {
|
||||
_agent_init_start = .;
|
||||
*(.init_array*)
|
||||
_agent_init_end = .;
|
||||
}
|
||||
.data : {
|
||||
*(.data*)
|
||||
*(.ldata*)
|
||||
}
|
||||
.bss : {
|
||||
*(.bss*)
|
||||
*(.lbss*)
|
||||
}
|
||||
. = ALIGN(8);
|
||||
_heap_start = .;
|
||||
}
|
||||
|
||||
VERSION {
|
||||
{
|
||||
global:
|
||||
_start;
|
||||
frida_winnt_user_main;
|
||||
frida_winnt_user_bootstrap;
|
||||
|
||||
local:
|
||||
*;
|
||||
};
|
||||
}
|
||||
@@ -1,112 +0,0 @@
|
||||
SECTIONS {
|
||||
.text : {
|
||||
*(.text.entrypoint)
|
||||
*(.text*)
|
||||
}
|
||||
.rela.dyn : {
|
||||
_agent_relocs_start = .;
|
||||
*(.rela.dyn)
|
||||
_agent_relocs_end = .;
|
||||
}
|
||||
.rodata : {
|
||||
*(.rodata*)
|
||||
}
|
||||
.kernel_addrs : ALIGN(8) {
|
||||
. = ALIGN(8);
|
||||
_panic = .; . += 8;
|
||||
_IOLog = .; . += 8;
|
||||
_kalloc = .; . += 8;
|
||||
_proc_iterate = .; . += 8;
|
||||
_proc_find = .; . += 8;
|
||||
_proc_rele = .; . += 8;
|
||||
_proc_pid = .; . += 8;
|
||||
_proc_best_name = .; . += 8;
|
||||
_proc_task = .; . += 8;
|
||||
_current_task = .; . += 8;
|
||||
_current_thread = .; . += 8;
|
||||
_get_task_map = .; . += 8;
|
||||
_mach_vm_allocate = .; . += 8;
|
||||
_mach_vm_deallocate = .; . += 8;
|
||||
_mach_vm_protect = .; . += 8;
|
||||
_mach_vm_remap = .; . += 8;
|
||||
_vm_map_copyin = .; . += 8;
|
||||
_vm_map_copyout = .; . += 8;
|
||||
_thread_create = .; . += 8;
|
||||
_thread_set_state = .; . += 8;
|
||||
_thread_resume = .; . += 8;
|
||||
_thread_terminate = .; . += 8;
|
||||
_task_suspend = .; . += 8;
|
||||
_task_resume = .; . += 8;
|
||||
_task_clear_return_wait = .; . += 8;
|
||||
_get_bsdtask_info = .; . += 8;
|
||||
_thread_suspend = .; . += 8;
|
||||
_kfree = .; . += 8;
|
||||
_kernel_thread_start = .; . += 8;
|
||||
_assert_wait = .; . += 8;
|
||||
_assert_wait_timeout = .; . += 8;
|
||||
_thread_block = .; . += 8;
|
||||
_thread_wakeup = .; . += 8;
|
||||
_thread_wakeup_prim = .; . += 8;
|
||||
_mach_absolute_time = .; . += 8;
|
||||
_absolutetime_to_nanoseconds = .; . += 8;
|
||||
_clock_get_calendar_microtime = .; . += 8;
|
||||
_ml_io_map = .; . += 8;
|
||||
_ml_vtophys = .; . += 8;
|
||||
_ml_static_vtop = .; . += 8;
|
||||
__ZN9IOService11getPlatformEv = .; . += 8;
|
||||
__ZN9IOServiceC2Ev = .; . += 8;
|
||||
__ZN8OSSymbol17withCStringNoCopyEPKc = .; . += 8;
|
||||
__ZN6OSData9withBytesEPKvj = .; . += 8;
|
||||
_kalloc_data = .; . += 8;
|
||||
_kfree_data = .; . += 8;
|
||||
_wakeup = .; . += 8;
|
||||
_sock_socket = .; . += 8;
|
||||
_sock_connect = .; . += 8;
|
||||
_sock_send = .; . += 8;
|
||||
_sock_receive = .; . += 8;
|
||||
_sock_close = .; . += 8;
|
||||
_sysent = .; . += 8;
|
||||
_task_restartable_ranges_register = .; . += 8;
|
||||
_task_threads = .; . += 8;
|
||||
_mach_vm_region = .; . += 8;
|
||||
_mach_vm_region_recurse = .; . += 8;
|
||||
_copyin = .; . += 8;
|
||||
_copyout = .; . += 8;
|
||||
_ulock_wake = .; . += 8;
|
||||
_task_info = .; . += 8;
|
||||
_convert_port_to_thread = .; . += 8;
|
||||
_convert_port_to_thread_read = .; . += 8;
|
||||
_convert_port_to_thread_inspect = .; . += 8;
|
||||
}
|
||||
. = ALIGN(16384);
|
||||
_agent_private_start = .;
|
||||
.data.rel.ro : {
|
||||
*(.data.rel.ro*)
|
||||
}
|
||||
.got : {
|
||||
*(.got*)
|
||||
}
|
||||
.init_array : {
|
||||
_agent_init_start = .;
|
||||
*(.init_array*)
|
||||
_agent_init_end = .;
|
||||
}
|
||||
.data : {
|
||||
*(.data*)
|
||||
}
|
||||
.bss : {
|
||||
*(.bss*)
|
||||
}
|
||||
. = ALIGN(8);
|
||||
_heap_start = .;
|
||||
}
|
||||
|
||||
VERSION {
|
||||
{
|
||||
global:
|
||||
_start;
|
||||
|
||||
local:
|
||||
*;
|
||||
};
|
||||
}
|
||||
@@ -0,0 +1,51 @@
|
||||
SECTIONS {
|
||||
.text : {
|
||||
*(.text.entrypoint)
|
||||
*(.text*)
|
||||
}
|
||||
.rodata : {
|
||||
*(.rodata*)
|
||||
}
|
||||
.kernel_addrs : ALIGN(8) {
|
||||
. = ALIGN(8);
|
||||
_panic = .; . += 8;
|
||||
_IOLog = .; . += 8;
|
||||
_kalloc = .; . += 8;
|
||||
_kfree = .; . += 8;
|
||||
_kernel_thread_start = .; . += 8;
|
||||
_assert_wait = .; . += 8;
|
||||
_assert_wait_timeout = .; . += 8;
|
||||
_thread_block = .; . += 8;
|
||||
_thread_wakeup = .; . += 8;
|
||||
_mach_absolute_time = .; . += 8;
|
||||
_absolutetime_to_nanoseconds = .; . += 8;
|
||||
_clock_get_calendar_microtime = .; . += 8;
|
||||
_ml_io_map = .; . += 8;
|
||||
_ml_vtophys = .; . += 8;
|
||||
__ZN9IOService11getPlatformEv = .; . += 8;
|
||||
__ZN9IOServiceC2Ev = .; . += 8;
|
||||
__ZN8OSSymbol17withCStringNoCopyEPKc = .; . += 8;
|
||||
__ZN6OSData9withBytesEPKvj = .; . += 8;
|
||||
}
|
||||
.data.rel.ro : {
|
||||
*(.data.rel.ro*)
|
||||
}
|
||||
.got : {
|
||||
*(.got*)
|
||||
}
|
||||
.bss : {
|
||||
*(.bss*)
|
||||
}
|
||||
. = ALIGN(8);
|
||||
_heap_start = .;
|
||||
}
|
||||
|
||||
VERSION {
|
||||
{
|
||||
global:
|
||||
_start;
|
||||
|
||||
local:
|
||||
*;
|
||||
};
|
||||
}
|
||||
@@ -1,17 +0,0 @@
|
||||
{
|
||||
"abi": "eabi",
|
||||
"arch": "arm",
|
||||
"crt-objects-fallback": "false",
|
||||
"data-layout": "e-m:e-p:32:32-Fi8-i64:64-v128:64:128-a:0:32-n32-S64",
|
||||
"features": "+v7,+thumb2,+thumb-mode,+soft-float,+strict-align,-neon",
|
||||
"linker": "rust-lld",
|
||||
"linker-flavor": "gnu-lld",
|
||||
"llvm-floatabi": "soft",
|
||||
"llvm-target": "armv7a-none-eabi",
|
||||
"max-atomic-width": 64,
|
||||
"panic-strategy": "abort",
|
||||
"plt-by-default": false,
|
||||
"position-independent-executables": true,
|
||||
"relocation-model": "pic",
|
||||
"target-pointer-width": 32
|
||||
}
|
||||
+23
-148
@@ -8,17 +8,12 @@ fn main() {
|
||||
let out_dir = PathBuf::from(env::var("OUT_DIR").unwrap());
|
||||
let devkit_dir = PathBuf::from(env::var("GUMJS_DEVKIT_DIR").unwrap());
|
||||
|
||||
let target = env::var("TARGET").unwrap();
|
||||
let cc_str = env::var(format!("CC_{}", target.replace('-', "_")))
|
||||
let cc_str = env::var("CC_aarch64_unknown_none")
|
||||
.or_else(|_| env::var("CC"))
|
||||
.unwrap_or_else(|_| "cc".to_string());
|
||||
// Same convention as cc-rs: the variable may carry flags, and a bare-metal
|
||||
// compiler needs them to find its libc at all.
|
||||
let mut cc_argv = cc_str.split_whitespace();
|
||||
let cc = Path::new(cc_argv.next().unwrap());
|
||||
let cc_args: Vec<&str> = cc_argv.collect();
|
||||
let cc_include_paths = detect_gcc_include_paths(cc, &cc_args);
|
||||
let cc_library_paths = detect_gcc_library_paths(cc, &cc_args);
|
||||
let cc = Path::new(&cc_str);
|
||||
let cc_include_paths = detect_gcc_include_paths(cc);
|
||||
let cc_library_paths = detect_gcc_library_paths(cc);
|
||||
|
||||
let cc_clang_args: Vec<String> = cc_include_paths
|
||||
.iter()
|
||||
@@ -30,15 +25,9 @@ fn main() {
|
||||
.header(devkit_dir.join("frida-gumjs.h").to_str().unwrap())
|
||||
.clang_arg("-nostdinc")
|
||||
.clang_arg("-target")
|
||||
.clang_arg(format!("{}-none-elf", target.split('-').next().unwrap()))
|
||||
.clang_arg("aarch64-none-elf")
|
||||
.clang_args(cc_clang_args)
|
||||
.clang_arg(format!("-I{}", devkit_dir.to_str().unwrap()))
|
||||
.clang_arg("-include")
|
||||
.clang_arg("stddef.h")
|
||||
.clang_arg("-include")
|
||||
.clang_arg("stdint.h")
|
||||
.blocklist_type("max_align_t")
|
||||
.blocklist_function("memcpy|memmove|memset|memcmp|bcmp|strlen")
|
||||
.merge_extern_blocks(true)
|
||||
.generate()
|
||||
.expect("Unable to generate bindings");
|
||||
@@ -47,131 +36,25 @@ fn main() {
|
||||
.write_to_file(out_dir.join("bindings.rs"))
|
||||
.expect("Couldn't write bindings");
|
||||
|
||||
// The Linux flavour is a staticlib: kbuild owns the final link, so it — not
|
||||
// us — decides where the devkit and libc archives come from.
|
||||
if env::var("CARGO_FEATURE_BLOB").is_ok() {
|
||||
println!(
|
||||
"cargo:rustc-link-search=native={}",
|
||||
devkit_dir.to_str().unwrap()
|
||||
);
|
||||
println!("cargo:rustc-link-lib=static=frida-gumjs");
|
||||
for path in cc_library_paths {
|
||||
println!("cargo:rustc-link-search=native={}", path.to_string_lossy());
|
||||
}
|
||||
for arg in &cc_args {
|
||||
if let Some(path) = arg.strip_prefix("-L") {
|
||||
println!("cargo:rustc-link-search=native={path}");
|
||||
}
|
||||
}
|
||||
println!("cargo:rustc-link-lib=static=c");
|
||||
println!("cargo:rustc-link-lib=static=m");
|
||||
println!("cargo:rustc-link-arg=--export-dynamic");
|
||||
println!("cargo:rustc-link-arg=--emit-relocs");
|
||||
let flavor = if env::var("CARGO_FEATURE_WIN9X").is_ok() {
|
||||
"win9x"
|
||||
} else if env::var("CARGO_FEATURE_WINNT").is_ok() {
|
||||
"winnt"
|
||||
} else if env::var("CARGO_FEATURE_LINUX_INJECTED").is_ok() {
|
||||
"linux"
|
||||
} else {
|
||||
"xnu"
|
||||
};
|
||||
let arch = match target.split('-').next().unwrap() {
|
||||
"i686" => "x86",
|
||||
"armv7a" => "arm",
|
||||
"aarch64" => "arm64",
|
||||
other => other,
|
||||
};
|
||||
let script = format!("agent-{flavor}-{arch}.lds");
|
||||
println!("cargo:rustc-link-arg=--script={script}");
|
||||
println!("cargo:rustc-link-arg=--gc-sections");
|
||||
// All of the agent lives in the library crate, so nothing in the binary
|
||||
// references the entrypoint the host calls; keep the linker from
|
||||
// dropping it along with the rest of the unreferenced archive members.
|
||||
println!("cargo:rustc-link-arg=--undefined=_start");
|
||||
|
||||
let note = compile_version_note(&out_dir, cc, &cc_args, arch);
|
||||
println!("cargo:rustc-link-arg={}", note.to_string_lossy());
|
||||
}
|
||||
|
||||
if target.starts_with("i686") && env::var("CARGO_FEATURE_LINUX_INJECTED").is_ok() {
|
||||
let shim = out_dir.join("regparm.o");
|
||||
let status = Command::new(cc)
|
||||
.args(&cc_args)
|
||||
.args(["-m32", "-c", "-O2", "-fPIC", "-ffreestanding", "-o"])
|
||||
.arg(&shim)
|
||||
.arg("src/linux/regparm.c")
|
||||
.status()
|
||||
.expect("Couldn't run the compiler");
|
||||
assert!(status.success(), "Couldn't compile the kernel-call shim");
|
||||
|
||||
println!("cargo:rustc-link-arg={}", shim.to_string_lossy());
|
||||
println!("cargo:rerun-if-changed=src/linux/regparm.c");
|
||||
}
|
||||
|
||||
println!("cargo:rerun-if-changed=build.rs");
|
||||
println!("cargo:rerun-if-env-changed=GUMJS_DEVKIT_DIR");
|
||||
println!("cargo:rerun-if-env-changed=FRIDA_VERSION");
|
||||
println!("cargo:rerun-if-changed={}", devkit_dir.join("frida-gumjs.h").display());
|
||||
}
|
||||
|
||||
fn compile_version_note(out_dir: &Path, cc: &Path, cc_args: &[&str], arch: &str) -> PathBuf {
|
||||
let version = env::var("FRIDA_VERSION")
|
||||
.ok()
|
||||
.filter(|v| !v.is_empty())
|
||||
.unwrap_or_else(|| "0.0.0".to_string());
|
||||
let payload = format!(
|
||||
"{{\"type\":\"frida\",\"name\":\"frida-barebone-agent\",\
|
||||
\"version\":\"{version}\",\"architecture\":\"{arch}\"}}"
|
||||
println!(
|
||||
"cargo:rustc-link-search=native={}",
|
||||
devkit_dir.to_str().unwrap()
|
||||
);
|
||||
|
||||
let source = out_dir.join("version-note.S");
|
||||
fs::write(
|
||||
&source,
|
||||
format!(
|
||||
".section .note.package,\"\",%note\n\
|
||||
.balign 4\n\
|
||||
.long 2f - 1f\n\
|
||||
.long 4f - 3f\n\
|
||||
.long 0xcafe1a7e\n\
|
||||
1: .asciz \"FDO\"\n\
|
||||
2: .balign 4\n\
|
||||
3: .asciz {payload:?}\n\
|
||||
4: .balign 4\n"
|
||||
),
|
||||
)
|
||||
.expect("Couldn't write the version note");
|
||||
|
||||
let object = out_dir.join("version-note.o");
|
||||
let status = Command::new(cc)
|
||||
.args(cc_args)
|
||||
.args(["-target", &llvm_target(), "-c", "-o"])
|
||||
.arg(&object)
|
||||
.arg(&source)
|
||||
.status()
|
||||
.expect("Couldn't run the compiler");
|
||||
assert!(status.success(), "Couldn't assemble the version note");
|
||||
|
||||
object
|
||||
println!("cargo:rustc-link-lib=static=frida-gumjs");
|
||||
for path in cc_library_paths {
|
||||
println!("cargo:rustc-link-search=native={}", path.to_string_lossy());
|
||||
}
|
||||
println!("cargo:rustc-link-lib=static=c");
|
||||
println!("cargo:rustc-link-lib=static=m");
|
||||
println!("cargo:rustc-link-arg=--export-dynamic");
|
||||
println!("cargo:rustc-link-arg=--emit-relocs");
|
||||
println!("cargo:rustc-link-arg=--script=agent.lds");
|
||||
println!("cargo:rustc-link-arg=--gc-sections");
|
||||
println!("cargo:rerun-if-changed=build.rs");
|
||||
}
|
||||
|
||||
fn llvm_target() -> String {
|
||||
let target = env::var("TARGET").unwrap();
|
||||
let spec = Path::new(&env::var("CARGO_MANIFEST_DIR").unwrap()).join(format!("{target}.json"));
|
||||
let text = fs::read_to_string(&spec).expect("Couldn't read the target specification");
|
||||
|
||||
let key = "\"llvm-target\"";
|
||||
let at = text.find(key).expect("Target specification names no LLVM target");
|
||||
let rest = &text[at + key.len()..];
|
||||
let open = rest.find('"').unwrap() + 1;
|
||||
let close = open + rest[open..].find('"').unwrap();
|
||||
|
||||
rest[open..close].to_string()
|
||||
}
|
||||
|
||||
pub fn detect_gcc_include_paths(gcc: &Path, args: &[&str]) -> Vec<PathBuf> {
|
||||
pub fn detect_gcc_include_paths(gcc: &Path) -> Vec<PathBuf> {
|
||||
let out = Command::new(gcc)
|
||||
.args(args)
|
||||
.args(["-xc", "-E", "-v", "-"])
|
||||
.stdin(Stdio::null())
|
||||
.output()
|
||||
@@ -201,7 +84,7 @@ pub fn detect_gcc_include_paths(gcc: &Path, args: &[&str]) -> Vec<PathBuf> {
|
||||
|
||||
let p = Path::new(raw);
|
||||
if p.exists() {
|
||||
let canonical = without_extended_length_prefix(fs::canonicalize(p).expect("Failed to canonicalize include path"));
|
||||
let canonical = fs::canonicalize(p).expect("Failed to canonicalize include path");
|
||||
if !paths.contains(&canonical) {
|
||||
paths.push(canonical);
|
||||
}
|
||||
@@ -211,16 +94,8 @@ pub fn detect_gcc_include_paths(gcc: &Path, args: &[&str]) -> Vec<PathBuf> {
|
||||
paths
|
||||
}
|
||||
|
||||
fn without_extended_length_prefix(path: PathBuf) -> PathBuf {
|
||||
let text = path.to_string_lossy();
|
||||
match text.strip_prefix(r"\\?\") {
|
||||
Some(rest) => PathBuf::from(rest),
|
||||
None => path,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn detect_gcc_library_paths(gcc: &Path, args: &[&str]) -> Vec<PathBuf> {
|
||||
let out = Command::new(gcc).args(args).arg("-print-search-dirs").output()
|
||||
pub fn detect_gcc_library_paths(gcc: &Path) -> Vec<PathBuf> {
|
||||
let out = Command::new(gcc).arg("-print-search-dirs").output()
|
||||
.expect("Failed to execute GCC to detect library paths");
|
||||
|
||||
let stdout = String::from_utf8_lossy(&out.stdout);
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
export FRIDA_BAREBONE_CONFIG=$PWD/etc/xnu.json
|
||||
export PYTHONPATH=$HOME/src/frida-python
|
||||
|
||||
sdk=$HOME/src/frida-core/deps/sdk-none-arm64-softfloat_pic
|
||||
export CC="clang --target=aarch64-none-elf -ffixed-x18 -I$sdk/include -I$sdk/include/glib-2.0 -I$sdk/lib/glib-2.0/include \
|
||||
-I$sdk/include/capstone -I$sdk/include/json-glib-1.0"
|
||||
export RUSTFLAGS="-L native=$sdk/lib"
|
||||
export GUMJS_DEVKIT_DIR=$HOME/src/frida-gum/build/none-arm64-softfloat_pic/bindings/gumjs/devkit
|
||||
export PATH=$PWD/xpacks/.bin:$PATH
|
||||
export CC_aarch64_unknown_none=aarch64-none-elf-gcc
|
||||
export AR_aarch64_unknown_none=aarch64-none-elf-ar
|
||||
export RANLIB_aarch64_unknown_none=aarch64-none-elf-ranlib
|
||||
export GUMJS_DEVKIT_DIR=/home/oleavr/src/frida-gum/build/bindings/gumjs/devkit
|
||||
@@ -1,8 +0,0 @@
|
||||
{
|
||||
"agent": {
|
||||
"transport": {
|
||||
"type": "socket",
|
||||
"path": "/tmp/frida-guest.sock"
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,8 +0,0 @@
|
||||
{
|
||||
"agent": {
|
||||
"transport": {
|
||||
"type": "device",
|
||||
"path": "/dev/frida"
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,51 +0,0 @@
|
||||
{
|
||||
"connection": {
|
||||
"host": "127.0.0.1",
|
||||
"port": 52494,
|
||||
"flavor": "vz",
|
||||
"pid": 49248
|
||||
},
|
||||
"allocator": {
|
||||
"mode": "target-functions",
|
||||
"alloc_function": "0xfffffe0007ab6cdc",
|
||||
"free_function": "0xfffffe0007ab74a8",
|
||||
"alloc_flags": 512
|
||||
},
|
||||
"agent": {
|
||||
"path": "/Users/oleavr/src/frida-core/src/barebone/agent/target/aarch64-unknown-none/release/frida-barebone-agent",
|
||||
"transport": {
|
||||
"type": "vsock",
|
||||
"socket_path": "/tmp/claude-501/vphone-frida-21528.sock",
|
||||
"port": 1339
|
||||
}
|
||||
},
|
||||
"image": {
|
||||
"type": "xnu-kernelcache",
|
||||
"file": "/Users/oleavr/src/vphone-cli/vm/iPhone17,3_26.1_23B85_Restore/kernelcache.research.vresearch101",
|
||||
"symbols": {
|
||||
"panic": "0x12a2814",
|
||||
"IOLog": "0xac44cc",
|
||||
"thread_block": "0xad3dac",
|
||||
"assert_wait": "0xacf1f8",
|
||||
"assert_wait_timeout": "0xacf3a0",
|
||||
"thread_wakeup": "0xad24e0",
|
||||
"kalloc_data": "0xab2cdc",
|
||||
"kfree_data": "0xab34a8",
|
||||
"sock_socket": "0x1006c88",
|
||||
"sock_connect": "0x1005714",
|
||||
"sock_send": "0x1006708",
|
||||
"sock_receive": "0x100669c",
|
||||
"sock_close": "0x1006de8",
|
||||
"mach_absolute_time": "0xc0548c",
|
||||
"absolutetime_to_nanoseconds": "0xc05a34",
|
||||
"clock_get_calendar_microtime": "0xa996c0",
|
||||
"kernel_thread_start": "0xafb660",
|
||||
"sb_evaluate_internal": "0x214dc00",
|
||||
"hook_cred_label_update_execve": "0x2156004",
|
||||
"hook_vnode_check_create": "0x213cf48",
|
||||
"hook_policy_syscall": "0x21443bc",
|
||||
"gLoadedKextSummaries": "0x24ec160",
|
||||
"proc_pid": "0xf65e5c"
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,15 +0,0 @@
|
||||
{
|
||||
"connection": {
|
||||
"host": "127.0.0.1",
|
||||
"port": 1234
|
||||
},
|
||||
"kernel": "win9x",
|
||||
"agent": {
|
||||
"path": "/home/oleavr/src/frida-core/src/barebone/agent/target-win9x/i686-unknown-none-pic/release/frida-barebone-agent",
|
||||
"transport": {
|
||||
"type": "hostlink",
|
||||
"qmp": "unix:/tmp/claude-1000/-home-oleavr-src-frida-core/0f3e358c-8f66-4246-b793-deb2cd3727f3/scratchpad/qmp.sock",
|
||||
"bus": "frida-vserial.0"
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,15 +0,0 @@
|
||||
{
|
||||
"connection": {
|
||||
"host": "127.0.0.1",
|
||||
"port": 1234
|
||||
},
|
||||
"kernel": "winnt",
|
||||
"agent": {
|
||||
"path": "/home/oleavr/src/frida-core/src/barebone/agent/target-winnt/i686-unknown-none-pic/release/frida-barebone-agent",
|
||||
"transport": {
|
||||
"type": "hostlink",
|
||||
"qmp": "unix:/tmp/qmp.sock",
|
||||
"bus": "frida-vserial.0"
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -16,7 +16,6 @@
|
||||
}
|
||||
},
|
||||
"image": {
|
||||
"type": "xnu-kernelcache",
|
||||
"file": "/Users/oleavr/src/frida-barebone-ios/iPhone11_8_iPhone12_1_14.0_18A5351d_Restore/kernelcache.research.iphone12b",
|
||||
"base": "0xfffffff007004000",
|
||||
"symbols": {
|
||||
|
||||
Loaded 100 of 466 files, more files were not shown because too many files have changed in this diff.
Show more
Reference in new issue
Block a user