$npx -y skills add gadievron/raptor --skill fridaDynamic instrumentation via Frida - attach to or spawn a process, load a JS hook script, capture send() events into a lifecycle-managed run directory. Supports local, USB-attached, and remote frida-server targets.
| 1 | # Frida - dynamic instrumentation (alpha) |
| 2 | |
| 3 | Hook a target at runtime to confirm LLM-flagged sinks actually execute, trace API calls, bypass SSL pinning, scan memory for secrets. |
| 4 | |
| 5 | ## When to use |
| 6 | |
| 7 | - `/scan` or `/agentic` flagged a sink and you want to confirm it fires at runtime before treating it as exploitable. |
| 8 | - A binary or mobile app is doing something opaque and a few minutes of API-trace would reveal the shape. |
| 9 | - A pinned mobile app is blocking your MITM proxy. |
| 10 | - A crash you can't `rr`-record (macOS) needs a function-call trace. |
| 11 | |
| 12 | ## Install |
| 13 | |
| 14 | ```bash |
| 15 | pipx install frida-tools # host CLI + python bindings |
| 16 | raptor doctor # confirms frida is detected |
| 17 | ``` |
| 18 | |
| 19 | For remote / mobile targets, install the matching `frida-server` on the target side. See `docs/frida/SETUP_MACOS.md`, `SETUP_LINUX.md`. Note: most `frida-server` binaries bind to `127.0.0.1` by default - start with `-l 0.0.0.0:27042` or SSH-forward port 27042. |
| 20 | |
| 21 | ## Invocation |
| 22 | |
| 23 | The slash command surfaces the libexec wrapper; run it as Bash. Lifecycle (output dir, run state) is handled by the wrapper. |
| 24 | |
| 25 | ``` |
| 26 | libexec/raptor-frida --target <pid|name|bundle-id|binary> |
| 27 | (--template <name> | --script <path>) |
| 28 | [--host HOST[:PORT]] [--usb] |
| 29 | [--duration N] [--spawn] [--unsafe-attach] |
| 30 | ``` |
| 31 | |
| 32 | Equivalent CLI without a Claude session: `raptor frida ...`. |
| 33 | |
| 34 | ## Templates |
| 35 | |
| 36 | ```bash |
| 37 | raptor frida --list-templates |
| 38 | ``` |
| 39 | |
| 40 | | Name | Purpose | |
| 41 | |------|---------| |
| 42 | | `api-trace` | Hooks `open`/`read`/`write`/`connect`/`fork`/`execve` etc. Most useful default. | |
| 43 | | `ssl-unpin` | Bypasses iOS/macOS Security.framework, OpenSSL `SSL_get_verify_result`, and Android `X509TrustManager`. | |
| 44 | |
| 45 | Operator-supplied scripts via `--script ./hook.js` - same `send(...)` capture path. |
| 46 | |
| 47 | ## Examples |
| 48 | |
| 49 | ```bash |
| 50 | # Trace API calls in a local PID for 30s |
| 51 | raptor frida --target 1234 --template api-trace --duration 30 |
| 52 | |
| 53 | # Spawn a binary and watch its first minute |
| 54 | raptor frida --target ./victim --template api-trace --duration 60 |
| 55 | |
| 56 | # Bypass SSL pinning on a USB-attached mobile target. Spawn by bundle id (frida resolves bundle ids for spawn); attach-by-name needs the running process's name, not the bundle id, so --spawn is the reliable form. |
| 57 | raptor frida --target com.example.app --template ssl-unpin --usb --spawn --duration 120 |
| 58 | |
| 59 | # Connect to remote frida-server |
| 60 | raptor frida --target target-proc --host 10.10.20.1 --template api-trace |
| 61 | |
| 62 | # Operator-supplied hook |
| 63 | raptor frida --target Safari --script ./my-hook.js --duration 30 |
| 64 | ``` |
| 65 | |
| 66 | ## Output layout |
| 67 | |
| 68 | ``` |
| 69 | <run-dir>/ |
| 70 | events.jsonl # one JSON object per send() from the script |
| 71 | metadata.json # target, host info, timings, errors |
| 72 | script.js # copy of the script that ran |
| 73 | frida-report.md # short human-readable summary |
| 74 | ``` |
| 75 | |
| 76 | `<run-dir>` is resolved by `libexec/raptor-run-lifecycle`: |
| 77 | - Active `/project`: `out/projects/<name>/frida-<timestamp>/` |
| 78 | - Otherwise: `out/frida_<timestamp>/` |
| 79 | |
| 80 | ## Failure modes (read `metadata.json` first) |
| 81 | |
| 82 | | Error fragment | Likely cause | |
| 83 | |---|---| |
| 84 | | `ptrace denied` | Linux `kernel.yama.ptrace_scope` ≥ 1. Lower it or spawn-and-attach. | |
| 85 | | `task_for_pid` | macOS hardened-runtime target or system process - needs SIP-disabled or signed-with-`get-task-allow`. | |
| 86 | | `unable to connect to remote frida-server` | Target not running, or bound to localhost only. SSH-forward 27042 or rebind. | |
| 87 | | `frida-python not installed` | `pipx install frida-tools`. | |
| 88 | |
| 89 | ## Threat model |
| 90 | |
| 91 | Frida-instrumented targets are **untrusted** - that's the whole point. The runner is wrapped in `core.sandbox.run()` with the `frida` profile (ptrace allowed, `skip_pid_ns=True` for `/proc` access, `restrict_reads=True`, `fake_home=True`): |
| 92 | |
| 93 | - **Spawn mode** (`--target ./binary`): `block_network=True` — the target can't reach out. |
| 94 | - **Attach mode** (`--target <pid|name>`): network untouched — the process is already running with whatever connectivity it needs. |
| 95 | - **`--unsafe-attach`**: sandbox bypassed entirely (system processes, SIP targets). Logged in `metadata.json`. |
| 96 | |
| 97 | ## Pipeline integration |
| 98 | |
| 99 | Frida output is automatically consumed by downstream pipelines when evidence exists in the run directory: |
| 100 | |
| 101 | | Consumer | What it reads | What it produces | |
| 102 | |----------|--------------|-----------------| |
| 103 | | `/agentic` reachability prepass | `events.jsonl` function names | `metadata.frida_runtime_trace` on inventory items; promotes `FRIDA_RUNTIME_TRACE` witness (SOUND) | |
| 104 | | `/validate` Stage B | `events.jsonl` function names | `runtime_evidence` annotations on attack path steps; proximity floor at 6 | |
| 105 | | `/understand --map` context bridge | `events.jsonl` file operations | `ObserveProfile` merged into context map (read/write/stat/connect paths) | |
| 106 | | Cove |