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蜜罐, 云资产清单, 无后门, 进程注入, 逆向工具, 逆向工程