Akhil-Chaturvedi/Frida-MCP
GitHub: Akhil-Chaturvedi/Frida-MCP
一个基于 MCP 协议的 Frida 动态插桩服务器,允许 AI 客户端在 Windows 上直接进行进程管理和底层分析。
Stars: 0 | Forks: 0
# Frida MCP Server(专注于 Windows)
一个模型上下文协议(MCP)服务器,将 Frida 的动态插桩功能作为可供 MCP 客户端使用的工具公开。此实现基于 Windows 构建和测试,采用动态调度器架构,使用 8 个主工具而非单独的工具注册。
## 要求
- Python 3.10 或更高版本
- Frida Python 绑定(`pip install frida`)
- MCP Python SDK(`pip install mcp`)
- 系统中必须安装 Frida(`frida` CLI 工具)
## 安装
```
pip install frida mcp
```
验证 Frida 是否正常工作:
```
frida --version
python -c "import frida; print(frida.__version__)"
```
## 配置
添加到您的 MCP 客户端配置中(确切路径取决于您的客户端):
```
{
"mcpServers": {
"frida": {
"command": "python",
"args": ["path\\to\\cli.py"]
}
}
}
```
将 `path\\to\\cli.py` 替换为 `cli.py` 文件的完整路径。
## 用法
该服务器公开了 8 个主工具。每个主工具接受一个 `action` 参数,用于选择特定的子操作。与将每个子操作注册为单独的工具相比,这种设计减少了 MCP 工具广播的开销。
### 主工具概述
| 工具 | 描述 |
|------|-------------|
| `frida_system(action, params)` | 设备和进程管理(23 个操作) |
| `frida_session(action, params)` | 会话和脚本管理(22 个操作) |
| `frida_inspect(pid, action, params)` | 进程内省(13 个操作) |
| `frida_memory(pid, action, params)` | 内存操作(10 个操作) |
| `frida_instrument(pid, action, params)` | 插桩(13 个操作) |
| `frida_symbol(pid, action, params)` | 符号和 API 解析(6 个操作) |
| `frida_file(pid, action, params)` | 文件操作(5 个操作) |
| `frida_help(category)` | 操作发现(1 个操作) |
总计:8 个主工具调度 93 个子操作。
### 发现可用操作
```
# 列出所有类别及其操作
frida_help()
# 获取特定类别的详细信息
frida_help(category="memory")
frida_help(category="instrument")
frida_help(category="session")
```
### 常见工作流
**列出进程并附加到其中一个:**
```
# 列出所有运行中的进程
frida_system(action="list_processes")
# 按名称查找特定进程
frida_system(action="get_process_by_name", name="notepad.exe")
# 带参数派生进程
frida_system(action="spawn", program="C:\\Windows\\System32\\notepad.exe", args=["file.txt"])
# 完全控制派生进程(env、工作目录、stdio)
frida_system(action="spawn_full", program="myapp.exe", cwd="C:\\project", env={"DEBUG": "1"})
# 恢复已派生的进程
frida_system(action="resume", pid=1234)
# 终止进程
frida_system(action="kill", pid=1234)
```
**检查进程:**
```
# 列出已加载的 DLL
frida_inspect(pid=1234, action="enumerate_modules")
# 获取特定 DLL 的详细信息
frida_inspect(pid=1234, action="get_module_by_name", module_name="kernel32.dll")
# 列出 DLL 的导出
frida_inspect(pid=1234, action="enumerate_exports", module_name="kernel32.dll")
# 列出线程
frida_inspect(pid=1234, action="enumerate_threads")
# 列出内存区域
frida_inspect(pid=1234, action="enumerate_memory_ranges", protection="rwx")
# 获取 backtrace(仅在 Interceptor 回调内部有效)
frida_inspect(pid=1234, action="get_backtrace")
```
**Hook 函数:**
```
# 按地址 hook 函数
frida_instrument(pid=1234, action="install_interceptor",
function_address="0x7ffa12345678",
on_enter="console.log('[+] Called, arg0=' + args[0]);")
# 按名称 hook 函数(使用 Module.getExportByName 自动解析)
frida_instrument(pid=1234, action="create_hook",
function_name="CreateFileW",
module_name="kernel32.dll",
log_args=True,
log_return=True)
# 替换函数实现
frida_instrument(pid=1234, action="replace_function",
function_address="0x7ffa12345678",
return_type="int",
arg_types=["pointer", "int"],
implementation_code="console.log('[+] Replaced!'); return 0;")
# 还原已替换的函数
frida_instrument(pid=1234, action="revert_function",
function_address="0x7ffa12345678")
```
**追踪函数调用:**
```
# Trace 特定导出
frida_instrument(pid=1234, action="trace",
include=["exports:kernel32.dll!CreateFile*", "exports:ntdll.dll!Nt*"])
# Trace 来自特定模块的所有导出
frida_instrument(pid=1234, action="trace",
include_modules=["kernel32.dll", "ntdll.dll"])
# Trace 特定调试符号
frida_instrument(pid=1234, action="trace",
include_symbols=["*CreateFile*", "*ReadFile*"])
```
**系统调用追踪(Windows API 名称):**
```
# Trace 所有 Windows API 调用
frida_instrument(pid=1234, action="strace")
# Trace 特定 API 调用
frida_instrument(pid=1234, action="strace",
filter=["CreateFileA", "ReadFile", "WriteFile"])
```
strace 操作会 Hook 以下 Windows API 函数:CreateFileA、ReadFile、WriteFile、CloseHandle、CreateFileMappingA、UnmapViewOfFile、CreateProcessA、GetFileAttributesA、DeviceIoControl、SetHandleInformation、connect、send、recv、socket、bind、listen、accept、select、WSAPoll。
**函数发现:**
```
# 采样函数调用 5 秒
frida_instrument(pid=1234, action="discover", duration=5)
```
**内存操作:**
```
# 读取内存(返回 hex 字符串)
frida_memory(pid=1234, action="read", address="0x7ffa00000000", size=256)
# 扫描 pattern
frida_memory(pid=1234, action="scan_sync",
address="0x7ffa00000000", size=4096, pattern="41 42 43 ?? 00")
# 对区域进行 hexdump
frida_memory(pid=1234, action="hexdump", address="0x7ffa00000000", size=128)
# 分配内存
frida_memory(pid=1234, action="alloc", size=1024)
# 更改内存保护
frida_memory(pid=1234, action="protect",
address="0x7ffa00000000", size=4096, protection="rwx")
# 安全 patch 代码(hex 字符串格式)
frida_memory(pid=1234, action="patch_code",
address="0x7ffa12345678", size=16, hex="90 90 90 90")
```
**符号解析:**
```
# 从地址解析符号
frida_symbol(pid=1234, action="from_address", address="0x7ffa12345678")
# 按名称查找函数
frida_symbol(pid=1234, action="get_function", function_name="CreateFileW")
# 枚举匹配 pattern 的 API
frida_symbol(pid=1234, action="api_resolver",
resolver_type="module", query="exports:kernel32.dll!Create*")
# 调用 native 函数
frida_symbol(pid=1234, action="call_native",
function_address="0x7ffa12345678",
return_type="int",
arg_types=["pointer", "int"],
args=["0x0", "0"])
```
**会话管理(用于持久化插桩):**
```
# 创建持久会话
frida_session(action="create", pid=1234)
# 返回:{ "session_id": "session_1234_1", ... }
# 在会话中执行 JavaScript
frida_session(action="execute",
session_id="session_1234_1",
javascript_code="var kernel32 = Process.getModuleByName('kernel32.dll'); Interceptor.attach(kernel32.getExportByName('CreateFileW'), { onEnter: function(args) { console.log('CreateFileW(' + args[0].readCString() + ')'); } });",
keep_alive=True)
# 从运行中的脚本获取异步消息
frida_session(action="get_messages", session_id="session_1234_1")
# 向运行中的脚本发送消息
frida_session(action="post_message",
session_id="session_1234_1",
message='{"cmd": "toggle_logging"}')
# 永久化脚本(在会话 detach 后依然保留)
frida_session(action="eternalize_script", session_id="session_1234_1")
# detach 会话
frida_session(action="detach", session_id="session_1234_1")
```
**目标进程内的文件操作:**
```
# 从进程视角读取文件(返回 hex 字符串)
frida_file(pid=1234, action="read_bytes", file_path="C:\\config.ini")
# 读取文本文件
frida_file(pid=1234, action="read_text", file_path="C:\\config.ini")
# 写入文件
frida_file(pid=1234, action="write_text",
file_path="C:\\output.txt", text="Hello from Frida")
# 删除文件
frida_file(pid=1234, action="remove", file_path="C:\\temp\\test.txt")
```
**远程设备管理:**
```
# 连接到远程 Frida server
frida_system(action="add_remote_device", address="192.168.1.100:27042")
# 列出所有设备
frida_system(action="enumerate_devices")
# 断开远程设备
frida_system(action="remove_remote_device", address="192.168.1.100:27042")
# 检查设备是否仍然连接
frida_system(action="is_lost")
# 获取系统信息
frida_system(action="query_system")
```
## 架构
该服务器使用动态调度器模式。它没有注册 93 个单独的 MCP 工具,而是注册了 8 个主工具。每个主工具接受一个 `action` 参数,该参数会路由到正确的处理函数。这减少了客户端的 MCP 工具广播开销。
操作注册表(`_ACTIONS` 字典)将每个类别映射到其可用的操作。`frida_help()` 工具提供了对所有可用操作及其参数的运行时发现。
## 错误处理
- 所有 Frida 操作都有 15 秒的超时时间。如果操作超过此时间,将引发 `RuntimeError`。
- JavaScript 执行错误将在响应中返回,并带有 `"status": "error"`。
- 会话操作在继续之前会验证会话 ID 是否存在。
- 如果设备丢失或会话分离,操作将返回适当的错误消息。
## 限制
### 平台限制
- 此服务器是在 Windows 上构建和测试的。某些 Frida 功能在 Windows 后端不可用:
- `get_frontmost_application` - Frida 的 Windows 后端未实现
- Spawn gating(`enable_spawn_gating`、`disable_spawn_gating`、`enumerate_pending_spawn`) - 仅限移动端/iOS
- `open_channel` 和 `open_service` - Unix D-Bus/服务概念在 Windows 上不可用
- 这 6 个操作已从服务器中移除。
- `strace` 操作会 Hook Windows API 函数(CreateFileA、ReadFile 等),而不是 Unix 系统调用。
- `discover` 操作最多 Hook 200 个导出,并在可配置的持续时间内进行采样。结果仅限于调用次数最多的前 100 个函数。
### 技术限制
- `device_input` 仅适用于派生(而非附加)的进程。在附加的进程上使用它会导致 frida-helper 死锁,并需要重启服务器。
- `get_backtrace` 仅在 Interceptor 回调内部有效。单独调用时会超时。
- 内存写入操作可能会导致目标进程崩溃。请使用 `patch_code` 进行更安全的代码修改。
- 带有 `persistent=True` 的 `trace` 操作会创建一个长时间运行的脚本。请使用 `get_messages` 检索输出,并使用 `unload_scripts` 进行清理。
- `Module.findExportByName()` 和 `Module.findBaseAddress()` 是静态方法,在 Frida 的 QuickJS eval 上下文中会失败。请改用 `Module.getExportByName()` 和 `Process.getModuleByName().base`。
- `Backtracer.ACCURATE` 是一个静态属性,在 eval 上下文中会失败。请改用其数值 `1`。
- `_execute_js_quick` 助手将代码封装在 IIFE 中并使用 `eval()`。带有顶层 `return` 语句的代码会失败并报 `SyntaxError: return not in a function`。
- `NativePointer.toString()` 在 eval 上下文中可能会失败。请改用 `String(nativePointer)`。
### 已知 Bug
- 在 Windows 上,`snapshot` 操作会失败并提示“not supported by the QuickJS runtime”。
- `enable_debugger`、`disable_debugger`、`enable_jit`、`disable_jit` 在当前的 Frida Python 绑定中不可用。它们会返回描述性错误,而不是直接崩溃。
- 如果 frida-helper 因先前的操作而处于不良状态,`call_native` 可能会超时。
- 如果查询格式不正确,`api_resolver` 可能会失败并报“invalid query”,或者完全断开连接。
## 开发
```
# Clone repository
git clone https://github.com/akhil-chaturvedi/frida-mcp.git
cd frida-mcp
# Install development dependencies
pip install -e ".[dev]"
```
## 许可证
MIT
标签:Docker支持, Frida, MCP服务器, Python, SSH蜜罐, 云资产清单, 无后门, 进程注入, 逆向工具, 逆向工程