wklwkl115/ida-pilot
GitHub: wklwkl115/ida-pilot
将 IDA Pro 的反编译与反汇编能力封装为 MCP 工具供 AI agent 调用的无头分析服务器,专为降低逆向分析中的 token 成本和交互轮次而设计。
Stars: 1 | Forks: 0
# IDA Pilot
[](https://github.com/wklwkl115/ida-pilot/actions/workflows/verify.yml)
[](LICENSE)





无头 (Headless) IDA Pro 分析服务器,提供 MCP 工具(启用 `py_eval` 时为 28 个,未启用时为 27 个)。专为 AI agent 设计 —— 分层工具加载、多层缓存、批量操作以及紧凑的有效载荷 (payload),旨在最小化每轮对话的 token 成本。
由 Go 负责编排会话和缓存。Python worker 通过 idalib 运行 IDA。通信采用基于 TCP 的 Connect RPC。
## 为什么选择 IDA Pilot?
- **专为 agent 而非人类设计。** 每次响应都是紧凑的 —— 十六进制地址、稀疏字段、`[address, type]` 交叉引用 (xref) 元组、使用 `"ok"` 代替 `{"success": true}` —— 以实现每轮对话消耗最少的 token。
- **一次调用胜过十次。** 像 `survey_binary` 和 `analyze_function` 这样的复合工具能在一次往返中返回反编译代码 + 元数据 + 交叉引用 + 注释;`analyze_functions` 支持一次批量处理多达 10 个函数。
- **在处理庞大二进制文件时依然保持响应。** 加载和自动分析以独立进程运行,并带有实时进度心跳,因此即使是 200 MB 的二进制文件也不会卡死或导致你的 MCP 客户端超时 —— 你只需轮询直到 `ready=true` 即可继续工作。
- **分层工具呈现。** Agent 启动时仅有 3 个工具;随着工作流的推进,读取/分析和写入工具会逐步解锁,从而保持每轮对话的 schema 精简。
- **多二进制文件支持。** 可以同时打开多个数据库,并通过 `cross_reference` / `cross_search` 在它们之间进行交叉检索。
- **默认安全。** 仅绑定本地回环 (Loopback)、默认关闭 `py_eval`、带有 `Origin`/`Host` 校验、支持可选的路径白名单(详情见下文)。
## ⚠️ 安全模型 —— 暴露端口前必读
IDA Pilot **没有内置身份验证**。默认配置专为同一台机器上受信任的单一 MCP 客户端调优:
- **默认绑定到 `127.0.0.1`。** 只有本地主机上的调用者才能访问。仅当你在其前方部署了已通过身份验证的反向代理时,才应使用 `--bind 0.0.0.0`(或 `IDA_PILOT_BIND`)进行覆盖。
- 每次请求都会进行 **`Origin` / `Host` 验证**(当绑定到本地回环时)—— 这可以阻止 DNS 重绑定攻击和浏览器跨域攻击。
- **`py_eval` 默认关闭。** 它会在 IDA worker 内部运行任意 Python 代码(拥有完整的主机文件系统和网络访问权限)。必须使用 `--enable-py-eval`(或 `IDA_PILOT_ENABLE_PY_EVAL=1`)显式开启,并将由此产生的 endpoint 视为一个 RCE 原语 —— 任何能访问该端口的人都可以执行代码。
- **文件系统白名单(可选开启)。** 默认情况下,客户端可以打开服务器用户有权限读取的任何文件(`open_binary`, `import_metadata`)。设置 `--allowed-roots`(或 `IDA_PILOT_ALLOWED_ROOTS`)可将这些路径限制在特定目录中 —— 只要暴露端口就强烈建议这样做。路径在进行检查前会进行符号链接解析,因此根目录内的链接无法逃逸出去。
截断输出的缓存(`get_cached_output`)在进程全局范围内共享,没有基于会话的 ACL —— 因为服务器没有可绑定条目的客户端身份 —— 所以其访问安全性依赖于不可预测的 128 位缓存 ID 以及上述的本地回环/Origin 防护,而不是基于会话所有权。
简而言之:**新启动的 `./bin/ida-pilot` 运行时保持默认配置是安全的;向网络开放端口或启用 `py_eval` 是你明确的选择,保护它是你的责任。**
## 架构
```
MCP Client (Claude, Cursor, etc.)
│
│ Streamable HTTP / SSE
▼
Go Server (:17300)
│ session registry, tool tiers, caching, output pagination
│
│ Connect RPC (TCP)
▼
Python Worker (one per binary)
│ idalib + Hex-Rays decompiler
▼
IDA database (.i64)
```
## 快速开始
### 前置条件
- **IDA Pro 9.0+** 且已激活 idalib([文档](https://docs.hex-rays.com/user-guide/idalib))
- **Go 1.25+**
- **Python 3.10+**(支持的最低版本;CI 和 `mise` 固定使用 3.12)
### 构建
```
git clone https://github.com/wklwkl115/ida-pilot.git
cd ida-pilot
pip install -r python/requirements.txt
go build -o bin/ida-pilot ./cmd/ida-pilot
```
### 运行
```
./bin/ida-pilot --debug
```
服务器将监听 `http://localhost:17300/`(Streamable HTTP)和 `http://localhost:17300/sse`(SSE 备用)。
### 连接 MCP 客户端
添加至你的 MCP 客户端配置中:
```
{
"mcpServers": {
"ida-pilot": {
"type": "http",
"url": "http://127.0.0.1:17300/"
}
}
}
```
**Claude Desktop:** `~/Library/Application Support/Claude/claude_desktop_config.json` (macOS) 或 `%APPDATA%\Claude\claude_desktop_config.json` (Windows)
**Claude Code:** 项目根目录下的 `.mcp.json` 或 `~/.claude/settings.json`
**Cursor:** 项目根目录下的 `.cursor/mcp.json`
## 针对 Agent 的优化设计
IDA Pilot 是为 agent 而非人类构建的。每一项设计决策都旨在降低 token 成本和减少往返次数。
### 分层工具加载
Agent 启动时仅拥有 3 个工具。随着需求增加,会解锁更多工具 —— 从而保持每次对话的 schema 有效载荷精简。
| 层级 | 触发条件 | 工具数 | 用途 |
|------|---------|-------|---------|
| 0 | 服务器启动 | 3 | `open_binary`, `list_sessions`, `get_cached_output` |
| 1 | 二进制文件已打开 | +19 = 22 | 读取、查询、复合、分析、上下文及跨会话工具 |
| 2 | 首次分析 | +5 = 27 | 写入、注释及导入工具 |
当最后一个会话关闭时,工具会降级回 Tier 0。添加 `--enable-py-eval` 会额外注册一个 Tier-1 工具,使完整的工具集达到 28 个。
### 复合工具
一次调用替代多次。这些是进行分析的主要入口:
- **`survey_binary`** —— 区段、函数/导入/导出/字符串计数及其头部条目、入口点、反编译器状态。一次调用即可掌握全貌。
- **`analyze_function`** —— 获取单个函数的伪代码 + 元数据 + 交叉引用 + 注释。全部已被缓存。
- **`analyze_functions`** —— 并行批量分析最多 10 个函数。
- **`annotate_function`** —— 针对每个函数,在一次调用中批量进行重命名、重新定义类型和添加注释。
### 多层缓存
| 缓存 | 作用域 | 容量 | 失效条件 |
|-------|-------|----------|--------------|
| 列表 (函数, 导入, 导出, 字符串) | 会话 | 无限制 | rename / make_function |
| 反编译 (伪代码) | 单函数 | 200 条 | 定向失效:函数重命名仅使该函数失效;数据标签重命名会搜索并仅驱逐包含旧名称的条目;局部变量(lvar)/注释会使该函数失效 |
| 交叉引用 (源 + 目标) | 单地址 | 无限制 | make_function |
| 区段 | 会话 | 静态 | 永不失效 |
| 输出 (被截断的响应) | 全局 | 200 条, 1小时 TTL | FIFO 驱逐 |
| 分析上下文 (已访问 + 备注) | 会话 | 无限制 | 永不失效 |
当打开二进制文件时,后台缓存预热会自动开始 —— `survey_binary` 在首次调用时能瞬间返回。
### 紧凑的有效载荷
- 输入和输出中的地址均为十六进制 (`0x...`),因此 agent 可以原样粘贴在反汇编/列表中看到的内容(输入时也接受十进制)
- 稀疏字段:省略零值/假值/空值
- 交叉引用使用 `[address, type]` 元组而不是对象
- 写入操作返回 `"ok"` 而不是 `{"success": true}`
- 超过 8KB 的响应会自动截断,并可通过 `get_cached_output` 进行分页处理
- 当仅有一个活动会话时,自动检测会话 ID
### 分析上下文
Agent 在长对话中容易丢失上下文。IDA Pilot 会在服务器端进行跟踪:
- **`set_analysis_note`** —— 在分析过程中将备注附加到地址上
- **`get_analysis_context`** —— 检索所有已访问的函数和备注,以恢复状态
## 工具参考
工具集设计得刻意精简:相关操作被整合在少数几个调度工具背后,这些工具通过一个区分字段(`category`, `mode`, `action`, `target`, `format`)来执行操作。跨越三个层级的 28 个工具。
### 会话与生命周期 (Tier 0–1)
| 工具 | 描述 |
|------|-------------|
| `open_binary` | 打开二进制文件。立即返回;加载和自动分析在后台运行 |
| `close_binary` | 关闭会话并保存数据库 |
| `save_database` | 保存但不关闭 |
| `list_sessions` | 列出活动会话 |
| `get_session_progress` | 加载/分析进度及就绪状态 —— 轮询直到 `ready=true` |
| `get_cached_output` | 通过其 `_cache_id` 对截断的响应进行分页 |
`open_binary` 不会阻塞:加载和自动分析在后台 worker 线程中运行,因此调用会立即返回(大型二进制文件分析可能需要几分钟)。在发出分析工具指令之前轮询 `get_session_progress` 直到 `ready=true` —— 在此之前它们会受到限制并返回 `not ready` 错误。状态 RPC 始终保持响应,因为 worker 会在单线程上串行化对 IDA 的访问,同时根据缓存状态响应进度查询。
### 复合工具 (Tier 1)
| 工具 | 描述 |
|------|-------------|
| `survey_binary` | 一次调用获取完整的二进制概览 |
| `analyze_function` | 针对单个函数的反编译 + 元数据 + 交叉引用 + 注释 |
| `analyze_functions` | 批量分析最多 10 个函数;包含单项错误反馈,因此一个错误的地址不会导致整个批次失败 |
### 读取与查询 (Tier 1)
| 工具 | 描述 |
|------|-------------|
| `query` | 按 `category` 浏览:functions, imports, exports, strings, globals, segments, structs, enums, entry_point。支持正则表达式、分页和类别过滤器 (`named_only`, `module`, `name`) |
| `get_references` | 交叉引用。`mode`=code (`direction`=to/from/both), data, 或 string |
| `search` | `mode`=text (`needle`) 或 binary (IDA `pattern`),限定在 `start`/`end` 范围内 |
| `inspect` | 获取地址上的名称 + 类型 + 注释 + 函数边界 + 指令长度 |
| `get_disasm` | 获取地址处的反汇编,或整个函数的 |
| `read_memory` | 原始内存:`format`=bytes/dword/qword/byte/string |
### 跨会话 (Tier 1)
| 工具 | 描述 |
|------|-------------|
| `cross_reference` | 从一个二进制文件 (`source_session_id` + `address`) 中查找符号,并找出它在另一个文件 (`target_session_id`) 中出现的位置 —— 搜索导入、导出、函数名和字符串 |
| `cross_search` | 一次跨多个会话进行搜索。`mode`=functions/imports/exports/strings,支持正则表达式或精确匹配。省略 `session_ids` 以搜索所有活动会话 |
### 分析控制与上下文 (Tier 1)
| 工具 | 描述 |
|------|-------------|
| `run_auto_analysis` | 触发 IDA 自动分析(适用于使用 `skip_analysis` 打开的二进制文件)。在分析完成后返回,或者 如果分析时间超过调用时长 —— 迅速返回并带有 `status:"analyzing"`,同时继续在后台运行;轮询 `get_session_progress` 直到 `ready=true` |
| `watch_auto_analysis` | 观察 (watch) 自动分析进度(不会驱动或取消它) |
| `set_analysis_note` / `get_analysis_context` | 用于状态恢复的服务器端上下文跟踪 |
| `prune_context` | 清除缓存的输出和已标记函数的缓存以释放内存 |
| `py_eval` *(可选开启)* | 在 IDA 中执行 Python —— 仅在使用 `--enable-py-eval` 时注册。每次调用后会使缓存失效(使用 `read_only=true` 可保持缓存)。参见 [安全模型](#%EF%B8%8F-security-model--read-before-exposing-the-port)。 |
### 写入与导入 (Tier 2)
| 工具 | 描述 |
|------|-------------|
| `annotate_function` | 针对函数批量重命名 + 重定义类型 + 加注释 → 返回更新后的伪代码 |
| `set_metadata` | `action`=set_name, delete_name, 或 set_comment (`scope`=address/function/decompiler) |
| `set_type` | `target`=function (prototype), global (C type), 或 lvar (C type + `function_address` + `lvar_name`) |
| `make_function` | 在指定地址创建函数 |
| `import_metadata` | `format`=il2cpp (script.json + il2cpp.h) 或 flutter (flutter_meta.json) |
## 配置
### 命令行参数
```
--bind Bind interface (default 127.0.0.1; use 0.0.0.0 only behind an auth proxy)
--port HTTP port (default: from config.json)
--config Config file path (default: config.json)
--worker Python worker script path
--max-sessions Max concurrent sessions
--session-timeout Session idle timeout (e.g. 4h)
--debug Verbose logging
--enable-py-eval Register the py_eval tool (arbitrary Python in the IDA worker — RCE primitive)
--allowed-roots Restrict agent-supplied paths to these dirs (OS-path-list separated; empty = unrestricted)
```
### 环境变量
```
IDA_PILOT_BIND=127.0.0.1
IDA_PILOT_PORT=17300
IDA_PILOT_SESSION_TIMEOUT_MIN=240
IDA_PILOT_MAX_SESSIONS=10
IDA_PILOT_WORKER=/path/to/worker.py
IDA_PILOT_DEBUG=1
IDA_PILOT_ENABLE_PY_EVAL=0
IDA_PILOT_ALLOWED_ROOTS=/srv/samples:/data/binaries # OS-path-list separated; empty = unrestricted
```
### config.json
```
{
"bind": "127.0.0.1",
"port": 17300,
"session_timeout_minutes": 240,
"max_concurrent_sessions": 4,
"database_directory": "./databases",
"python_worker_path": "python/worker/server.py",
"debug": false,
"enable_py_eval": false,
"allowed_roots": []
}
```
## 开发
```
make build # Build server
make test # Run tests
make proto # Regenerate protobuf (requires protoc)
make clean # Clean artifacts
make inspector # Launch MCP Inspector at localhost:5173
```
### 项目结构
```
ida-pilot/
├── cmd/ida-pilot/ # Server entry point
├── internal/
│ ├── server/ # MCP tool handlers, caching, tiers
│ ├── session/ # Session registry + persistence
│ └── worker/ # Python worker process manager
├── proto/ # Protobuf service definitions
└── python/worker/ # idalib wrapper + Connect RPC server
```
## 贡献
欢迎提交贡献 —— 有关环境设置、本地测试门槛及规范,请参阅 [CONTRIBUTING.md](CONTRIBUTING.md)。
如需私下报告安全问题,请参阅
[SECURITY.md](SECURITY.md)。
## 许可证
MIT
标签:EVTX分析, Go, IDA Pro, MCP, Python, Ruby工具, 云资产清单, 无后门, 日志审计, 服务端, 逆向分析辅助, 逆向工具, 逆向工程