frida_mcp
by 276793422
README.md
# frida_mcp
A [Model Context Protocol](https://modelcontextprotocol.io) server for
[Frida](https://frida.re), built on the official MCP Python SDK (FastMCP).
It exposes Frida's dynamic-instrumentation capabilities as MCP tools so an AI
agent (or any MCP client) can enumerate devices/processes, attach, inject
JavaScript, hook functions, read memory, and collect results.
## Features
- Full device & process management (list / spawn / attach / resume / kill)
- Persistent sessions and per-script lifecycle (load / unload individual scripts)
- Arbitrary JavaScript execution:
- `load_script` — persistent (hooks / interceptors), messages captured
- `exec_script` — one-shot, returns the evaluated value + console.log synchronously
- `rpc_call` — invoke `rpc.exports` on a persistent script
- Per-(session, script) message queues with binary `data` support
- Convenience tools: `read_memory`, `list_modules`, `list_exports`, `find_export`, `scan_memory`
- Robust error handling (tools return `{status: "error"}` instead of throwing)
- Binary-data cap to keep large dumps from flooding the channel
## Tools
### Device / process
- `list_devices()` — local, USB, remote
- `list_processes(device_id?)` / `find_process(name, device_id?)`
- `spawn_process(program, device_id?, paused=true)` — suspended by default so you can hook before resume
- `resume_process(pid, device_id?)` / `kill_process(pid, device_id?)`
### Session
- `attach_to_process(pid, device_id?, name?)` → `session_id`
- `list_sessions()` — pids, scripts, pending message counts, detached state
- `detach_session(session_id)` — unload all scripts + detach
### Script
- `load_script(session_id, source, name?, runtime?)` → `script_id` — persistent; messages captured
- `unload_script(session_id, script_id)`
- `exec_script(session_id, source, timeout?)` — one-shot, returns value + logs
- `rpc_call(session_id, script_id, method, args?, timeout?)` — call `rpc.exports`
### Messages
- `get_messages(session_id, script_id?, clear?, limit?, include_data?)` — retrieve `send()` output; binary `data` base64-inlined up to a cap
### Convenience
- `read_memory(session_id, address, size)` → hex + base64
- `list_modules(session_id)`
- `list_exports(session_id, module, kind?)`
- `find_export(session_id, module, export_name)`
- `scan_memory(session_id, pattern, module?, max_hits?)`
### Resources
- `frida://version` — Frida binding version
- `frida://sessions` — JSON snapshot of active sessions
## Install
```bash
pip install -e E:/Tools/Frida/frida_mcp
# also need the frida runtime on the host
pip install frida
```
Requires Python 3.8+, Frida 16+, and a reachable `frida-server` (or gadget) on the target.
## Configure (`.mcp.json`)
```json
{
"mcpServers": {
"frida_mcp": {
"command": "frida_mcp"
}
}
}
```
## Typical workflow: hook before the target loads
```text
spawn_process("com.example.app") # -> pid (suspended)
attach_to_process(pid) # -> session_id
load_script(session_id, "<hook JS>") # -> script_id (keep-alive)
resume_process(pid) # app runs; hook fires
get_messages(session_id) # collect send() output
unload_script(session_id, script_id) # or detach_session(session_id)
```
## Example: dump every Lua chunk that the Lua VM compiles
Bypasses any AssetBundle encryption entirely — by the time the Lua VM sees the
source, it's already decrypted. The script writes each chunk to the device
filesystem and only reports small metadata back (so the MCP channel never sees
the full payload):
```js
// load_script(source=...)
var DUMP = "/sdcard/lua_dump/";
var counter = 0;
Interceptor.attach(Module.findExportByName("libxlua.so", "luaL_loadbuffer"), {
onEnter: function (args) {
try {
var buf = args[1];
var len = args[2].toInt32();
var bytes = Memory.readByteArray(buf, len);
var path = DUMP + Date.now() + "_" + (counter++) + ".lua";
var f = new File(path, "wb");
f.write(bytes);
f.flush(); f.close();
send({ type: "lua_chunk", path: path, size: len, head: hexdump(bytes, { length: 32 }) });
} catch (e) { send({ type: "err", err: e.toString() }); }
}
});
```
> The exact chunk-name argument to `luaL_loadbuffer` depends on the build; tune per target. Then `adb pull /sdcard/lua_dump` and you have the plaintext Lua.
## Notes & limits
- Tools return `{status: "error", error: "..."}` (or `status: "timeout"`) instead of throwing.
- Binary `data` larger than 64 KiB is reported by size only — write to a device file and `adb pull`.
- Anti-Frida defences in the target are the environment's concern — confirm you can attach first.
## License
MIT
This server cannot be deployed
Maintenance
ActivityMaintained
ResponsivenessNo issues