本文作者:杉木@涂鸦智能安全实验室
本文档汇总 GhidraMCP 的架构原理、部署方式及与本项目相关的使用实践,便于后续复现与扩展。
一、GhidraMCP 是什么
GhidraMCP (LaurieWired/GhidraMCP)是一个基于 Model Context Protocol (MCP) 的 Ghidra 桥接方案,让支持 MCP 的客户端(如 Cursor、Claude Desktop、Cline)能够通过统一协议调用 Ghidra 的反编译、符号、重命名等能力,从而用自然语言或自动化脚本做逆向分析。
核心价值:
- 在 IDE/对话中直接"问"Ghidra:列出函数、反编译、按地址/名称重命名等。
- 可编写脚本(如从 SO 导出符号并写回 Ghidra)或由 AI 根据反编译结果做漏洞分析、生成 PoC。
二、架构与原理
2.1 整体架构
┌─────────────────────────────────────────────────────────────────┐
│ MCP 客户端(Cursor / Claude Desktop / Cline 等) │
│ - 通过 stdio 或 SSE 与 MCP Server 通信 │
│ - 展示"工具"列表并调用(如 list_methods, decompile_function) │
└────────────────────────────┬────────────────────────────────────┘
│ MCP 协议 (stdio or SSE)
▼
┌─────────────────────────────────────────────────────────────────┐
│ Python MCP Server(bridge_mcp_ghidra.py) │
│ - 使用 FastMCP 暴露一组"工具"(list_methods, decompile, rename...) │
│ - 每个工具内部通过 HTTP 请求转发到 Ghidra 端 │
└────────────────────────────┬────────────────────────────────────┘
│ HTTP (默认 http://127.0.0.1:8080/)
▼
┌─────────────────────────────────────────────────────────────────┐
│ Ghidra 插件(GhidraMCP Plugin,Java) │
│ - 在 Ghidra 进程内启动 HTTP 服务(默认 8080) │
│ - 提供 REST 风格接口:/methods, /decompile, /rename_function_ │
│ by_address, /segments 等 │
│ - 直接调用 Ghidra API 完成反编译、符号表修改等 │
└────────────────────────────┬────────────────────────────────────┘
│
▼
┌─────────────────────────────────────────────────────────────────┐
│ Ghidra 当前打开的项目 / 程序 │
│ - 当前激活的 Program 的符号、反编译、内存布局等 │
└─────────────────────────────────────────────────────────────────┘
要点:
- Ghidra 端:只负责"当前项目"的分析与数据;所有对函数、符号、反编译的读写都通过插件提供的 HTTP 接口完成。
- 桥接端:Python 脚本不实现任何逆向逻辑,只做"协议转换":MCP 工具调用 → HTTP 请求 → Ghidra 插件 → Ghidra API。
- 客户端:用户或 AI 在 Cursor 等环境中调用 MCP 工具,等价于对当前打开的 Ghidra 程序执行对应操作。
2.2 协议与传输
- MCP:Model Context Protocol,定义"工具(Tools)"的命名、参数与返回格式;客户端通过 JSON-RPC 调用这些工具。
- 传输方式 :
- stdio:子进程标准输入/输出交换 JSON,适合 Cursor、Claude Desktop 等本地单进程调用。
- SSE :桥接脚本作为 HTTP 服务暴露
/sse,客户端通过 Server-Sent Events 连接,适合 Cline 等"远程 MCP"场景。
- Ghidra 与桥接之间 :固定为 HTTP ,默认
http://127.0.0.1:8080/,由插件在 Ghidra 内提供。
2.3 典型工具与对应 HTTP 接口
| MCP 工具(示例) | 作用 | 大致对应 HTTP 行为 |
|---|---|---|
| list_methods / list_functions | 列出函数 | GET /methods 或 /list_functions |
| decompile_function(name) | 按名称反编译 | POST /decompile,body=函数名 |
| get_function_by_address | 按地址取函数信息 | GET /get_function_by_address?address= |
| rename_function_by_address | 按地址重命名函数 | POST /rename_function_by_address |
| list_segments | 列出段/内存布局 | GET /segments |
桥接脚本中通过 safe_get(endpoint, params)、safe_post(endpoint, data) 调用上述接口,并将结果返回给 MCP 客户端。
三、部署方式
3.1 前置条件
- 已安装 Ghidra(本文以 12.0.4 为例,路径可自定)。
- Python 3.10+ ,并安装依赖:
mcp、requests(见桥接脚本内 PEP 723 或requirements.txt)。 - 若需从 SO 还原符号:系统具备 nm(通常来自 binutils)。
3.2 第一步:安装 Ghidra 插件
- 从 GhidraMCP Releases 下载对应版本的 zip(如
GhidraMCP-1-4.zip)。 - 在 Ghidra 中:File → Install Extensions ,点击 +,选择该 zip。
- 重启 Ghidra。
- File → Configure → Developer 中勾选启用 GhidraMCPPlugin。
- (可选)Edit → Tool Options → GhidraMCP HTTP Server 中修改端口,默认 8080。
完成后,打开任意项目并分析,插件会在本机 8080 端口提供 HTTP 接口。
3.3 第二步:部署 Python 桥接(MCP Server)
-
将发布包中的 bridge_mcp_ghidra.py 放到本机某目录(如
Extensions/GhidraMCP-release-1-4/)。 -
安装依赖:
bashcd /path/to/GhidraMCP-release-1-4 pip install -r requirements.txt # 或 pip install mcp requests -
本地测试桥接是否连通 Ghidra:
bashpython3 bridge_mcp_ghidra.py --ghidra-server http://127.0.0.1:8080/ # 无报错即说明参数正确;实际作为 MCP 由 Cursor 启动时不会常驻前台
3.4 第三步:配置 MCP 客户端(以 Cursor 为例)
在 Cursor 中让 MCP 使用上述桥接脚本:
- 全局配置 :编辑
~/.cursor/mcp.json(若不存在则新建)。 - 项目级配置 :在项目根目录下
.cursor/mcp.json。
示例内容:
json
{
"mcpServers": {
"ghidra": {
"command": "python3",
"args": [
"/绝对路径/bridge_mcp_ghidra.py",
"--ghidra-server",
"http://127.0.0.1:8080/"
]
}
}
}
command:本机 Python 解释器(或python3)。args:桥接脚本路径 +-ghidra-server+ Ghidra HTTP 地址;若 Ghidra 改了端口,此处需一致。- 保存后重启 Cursor ,即可在对话或 MCP 面板中看到并调用
ghidra的工具。
3.5 传输方式选择
-
默认(stdio) :不写
-transport时,Cursor 通过标准输入/输出与桥接进程通信;上述配置即 stdio 模式。 -
SSE 模式(如配合 Cline 等):
bashpython3 bridge_mcp_ghidra.py --transport sse --mcp-host 127.0.0.1 --mcp-port 8081 --ghidra-server http://127.0.0.1:8080/客户端连接
http://127.0.0.1:8081/sse使用 MCP。
四、与本项目相关的使用实践
4.1 SO 文件函数名还原(apply_so_symbols.py)
问题 :strip 后的 SO 在 Ghidra 中大量显示为 FUN_xxxx,仅有动态符号表(.dynsym)中的导出符号有名字。
思路 :用系统自带的 nm -D --defined-only 从 SO 中解析出"地址 + 函数名",再通过 Ghidra 的 rename_function_by_address 接口,按"当前程序基址 + 偏移"写回 Ghidra。
要点:
- 基址 :Ghidra 中 SO 的加载基址往往不是 0(如 arm64-v8a 常见为
0x100000)。脚本通过 GET /segments 取首段起始地址作为基址,再与nm得到的偏移相加,得到 Ghidra 内真实地址。 - 仅能还原导出符号 :脚本只处理
nm -D中 type 为 T/t 的符号,数量有限(例如约 110 个);其余未导出函数仍会显示为 FUN_xxx,需 FLIRT 或带符号 SO 进一步处理。
基本用法:
bash
cd /path/to/GhidraMCP-release-1-4
. .venv/bin/activate # 若使用虚拟环境
python3 apply_so_symbols.py /path/to/libxxx.so
# 不指定 --base 时,脚本会从 Ghidra 自动读取基址
4.2 连接与连通性测试
- Ghidra 侧:确认已打开目标程序并完成分析,GhidraMCP 插件已启用,HTTP 服务监听 8080。
- 脚本测试 :可写简单脚本请求
http://127.0.0.1:8080/segments?offset=0&limit=1或http://127.0.0.1:8080/methods,返回 200 即表示 Ghidra 端正常。 - Cursor 侧:配置好 mcp.json 并重启后,在对话中通过 MCP 调用"列出函数""反编译某函数"等,能返回结果即表示端到端打通。
4.3 漏洞分析工作流示例
- 在 Ghidra 中打开目标 SO(如 libthing_security_algorithm.so),执行自动分析。
- 运行
apply_so_symbols.py还原导出函数名(注意架构与基址)。 - 在 Cursor 中通过 MCP 或直接 HTTP 调用:
list_functions/list_methods获取函数列表;decompile_function(name)或按地址反编译关键函数。
- 根据反编译结果做人工/脚本化漏洞分析,并编写 PoC 与修复方案(如本项目中的漏洞 1/2/3)。
五、常见问题与注意点
| 问题 | 可能原因 | 处理建议 |
|---|---|---|
| 函数名还原后界面上仍无变化 | 基址错误,符号写到了错误地址 | 使用脚本自动获取基址,或显式传 --base 0x100000 等正确基址 |
| Cursor 中看不到 Ghidra 工具 | mcp.json 未生效或路径错误 | 检查 command/args 路径,重启 Cursor,确认 MCP 配置已加载 |
| Ghidra HTTP 请求超时/连接拒绝 | 插件未启用或未打开项目 | 确认插件已勾选、已打开并分析目标程序,端口与配置一致 |
| 大量函数仍为 FUN_xxx | SO 已 strip,仅 .dynsym 有符号 | 属预期;可考虑 FLIRT、带符号 SO 或人工命名 |
六、参考与延伸
- 官方仓库: LaurieWired/GhidraMCP
- MCP 协议与客户端: MCP 文档
其实前面内容都是让AI生成的,在实际操作都可以让AI自己配置和操作,其中只有Ghidra中的配置需要用户自己进行配置,具体就是文档中3.2的操作流程,其他的都是AI自己配置的;
我这边测试了两个,一个是cursor(文档主要内容也是cursor生成)以VS插件的形式调用,一个是claude,以token api的形式调用;
下图左边是claude,右边是cursor,不知道是不是cursor是后台配置了主要是研发代码生成的prompt还是啥,在还原函数调用ghidra的api时候无法还原,他会先生成一个调用api的python脚本去调用,但是却还原不了,效果也不好;而cursor则全自己处理还完完成,前提都是存在符号表的;
至于在漏洞检索方面,两边各自生成了一份漏洞报告,具体结果倒是大差不差;

函数还原前;

函数还原后的效果;

| 💡
函数还原对话小技巧
在让其还原的时候,可以先让他检索代码日志、打印这块东西,然后从中结合理解函数的能力来还原,结果会更加准确。
漏洞悬赏计划:涂鸦智能安全响应中心(https://src.tuya.com)欢迎白帽子来探索。