IDA Domain MCP: no GUI, no binary preloading, multi IDB analysis

要让 AI Agent 有逆向分析能力,就得给它 IDA tools。

背景

ida-pro-mcp 是目前比较常用的 ida MCP 服务器工具,它可以用GUI 界面、headless 模式两种方式启动。主要原理为,

  • 通过 Plugin 提供 JSON-RPC 接口,调用 IDA 的各种功能;
  • 通过 FastMCP 接收 MCP 客户端(AI Agent 或其它)的请求,调用对应的 Plugin 接口来完成任务。

但是无论在 GUI 还是 headless 模式下,MCP server 的启动都需要人工预先加载好一个二进制文件,才能进行后续的分析工作。当出现如下场景的时候,使用 ida-pro-mcp 就会比较麻烦:

  • AI Agent 需要根据 thinking 的结果,动态选择需要加载的二进制文件进行分析的时候;
  • 需要对多个二进制文件进行分析,甚至需要同时进行关联分析的时候。

针对上述场景,我们开发了一个新的 ida MCP 工具 ida-domain-mcp,它可以实现:

  • 无需 GUI 界面,完全 headless 运行;
  • 无需人工预加载二进制文件,AI Agent 可以动态指定需要分析的二进制文件路径;
  • 可以同时对多个 IDB 文件进行分析,方便 AI Agent 使用进行跨 IDB 关联分析。

为什么 ida-pro-mcp 的实现必须要预加载二进制文件?

IDA 是一个静态 / 交互式反汇编器/反编译器。其基本工作流程是:加载一个二进制,将其内容映射 / 解析 / 建立交叉引用 / 构造函数 / 数据类型 / 符号表 / 代码&数据区。也就是说,IDA 的各种分析功能,都是基于当前已经加载的二进制文件(或 IDB)来进行的。
如图1所示,所有基于 IDB 分析的 core API,都是在加载了二进制文件之后,与对应的 IDB 强绑定的。而需要调用这些 core API 的 IDA 插件,比如 ida-pro-mcp plugin,因此在加载二进制文件之后才能正常工作。


flowchart LR
    subgraph s1["IDA pro 启动"]
        n1["加载 Binary / IDB, 建立 Database Context"]
        n2["IDA core API(反汇编/反编译/符号/类型/xref 等)关联到具体 IDB"]
        n1 --> n2
    end
    subgraph s2["IDA 插件注入"]
        n3["ida-pro-mcp plugin 调用 IDA core API"]
        n4["MCP server"]
        n3 <--JSON-RPC--> n4
    end
    n2 --> n3
    n4 <--FastMCP--> n5["MCP client(AI Agent、VS code插件等)"]

图1: ida-pro-mcp :插件必须在加载二进制后才能工作

为了让 MCP tools 本身具有管理 loader / database 的能力,不能仅从插件入手,还需要对 IDA 的启动流程进行定制化开发。我们希望 MCP tools 与 IDA 的关系应该是如图2所示:


flowchart LR
    %% =====================
    %% 顶层结构
    %% =====================
    Client["MCP Client"]
    Server["MCP Server"]
    Worker1["Worker Process project=foo"]
    Worker2["Worker Process project=bar"]
    WorkerN["Worker Process project=xxx"]

    %% Worker 内部 IDA
    subgraph W1_IDA["IDA headless (idat/idat64)"]
        Binary1["根据 foo_path 加载 Binary 文件,建立 foo_idb"]
        CoreAPI1["IDA core API 关联到 foo_idb"]
    end

    subgraph W2_IDA["IDA headless (idat/idat64)"]
        Binary2["根据 bar_path 加载 Binary 文件,建立 bar_idb"]
        CoreAPI2["IDA core API 关联到 bar_idb"]
    end

    subgraph WN_IDA["IDA headless (idat/idat64)"]
        BinaryN["根据 xxx_path 加载 Binary 文件,建立 xxx_idb"]
        CoreAPIN["IDA core API 关联到 xxx_idb"]
    end

    %% =====================
    %% 关系与调用
    %% =====================
    %% 加载数据库
    Client -- "load_database(project=foo)" --> Server
    Client -- "load_database(project=bar)" --> Server
    Client -- "load_database(project=xxx)" --> Server

    Server -->|forks on demand| Worker1
    Server -->|forks on demand| Worker2
    Server -->|forks on demand| WorkerN

    Worker1 --> Binary1
    Binary1 --> CoreAPI1

    Worker2 --> Binary2
    Binary2 --> CoreAPI2

    WorkerN --> BinaryN
    BinaryN --> CoreAPIN

    %% 具体分析
    Client -- "list_functions(project=foo)" --> Server
    Server -- "find the worker" --> Worker1
    Worker1 -- "调用 IDA core API" --> CoreAPI1

    %% 给节点或连线定义样式
    %% classDef highlight fill:#f9f,stroke:#333,stroke-width:1px;
    %% class CoreAPI1,CoreAPI2,CoreAPIN highlight;

    %% 连线样式(注意:索引从 0 开始,按连线在上面出现的顺序计数)
    %% 12: Client -- "list_functions(project=foo)" --> Server
    %% 13: Server -- "find the worker" --> Worker1
    %% 14: Worker1 -- "调用 IDA core API" --> CoreAPI1
    linkStyle 12,13,14 stroke:#2ca02c,stroke-width:5px;

图2: ida-domain-mcp :多进程模型支持动态加载和并发分析

ida-domain-mcp 的设计思路

ida-domain-mcp 的设计目标则是:

  • 无图形界面(No GUI):运行在完全 headless 的环境中,不依赖任何 UI;
  • 无需预加载二进制(No binary preloading):二进制数据库(IDB/binary)由 Agent 动态指定加载;
  • 多 IDB 并发分析(Multi IDB analysis):每个项目拥有独立的进程上下文,可同时进行分析,互不干扰。

为了实现上述目标,我们采用了如下设计,参见图2:

  • 将 IDA 进程完全抽象为一个可控制的 worker;
  • 用 ida-domain 作为与 IDA headless runner (idat/idat64)之间的桥梁;
  • 用一个主 MCP Server 进程负责调度多个 IDA worker;
  • 用字典结构记录每个 project 与 Worker 的对应关系;
  • 用管道/IPC 实现 MCP Server 与各 Worker 之间的双向调用。

1. 无图形界面(No GUI)

idat 是 IDA 官方提供的无界面 runner,可以在 CLI 或服务端环境下稳定运行,因此整个服务流程中不再有任何图形界面被触发,适合自动化运行和容器化部署。

2. 无需预加载二进制(No binary preloading)

为了摆脱必须手动预加载二进制文件这个约束,ida-domain-mcp 以 ida-domain 作为桥梁,将数据库加载过程也纳入 MCP 可控制的生命周期来解决这一问题。

ida-domain 是 Hex-Rays 官方提供的一个 Python 库,可以用来在 headless 环境下加载二进制文件,建立 IDB 数据库,并调用 IDA core API 进行分析。通过 ida-domain,我们可以在 MCP worker 进程中动态加载指定路径的二进制文件,从而实现无需预加载二进制的目标。用法示例如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
import ida_domain
from ida_domain import Database
from ida_domain.database import IdaCommandOptions

ida_options = IdaCommandOptions(auto_analysis=True, new_database=False)
with Database.open(db_path, ida_options) as db:
# Get basic information
print(f'Address range: {hex(db.minimum_ea)} - {hex(db.maximum_ea)}')

# Get metadata
print('Database metadata:')
metadata_dict = asdict(db.metadata)
for key, value in metadata_dict.items():
print(f' {key}: {value}')

# Count functions
function_count = sum(1 for _ in db.functions)
print(f'Total functions: {function_count}')

3. 多 IDB 并发分析(Multi IDB analysis)

为了支持多目标分析(例如同时关联分析多个 IDB、或者不同二进制的对比分析),我们引入了多进程模型,用一个主 Server 进程管理多个 IDA worker 进程。

  • 每个需要分析的二进制 / IDB 都由一个独立的 IDA worker 进程负责运行;
    1
    2
    3
    4
    5
    6
    7
    8
    def _worker(child_conn: Connection):
    msg = child_conn.recv()
    func_name = msg.get("func")
    func = getattr(tools, func_name)
    args = msg.get("args", [])
    kwargs = msg.get("kwargs", {})
    result = func(*args, **kwargs)
    child_conn.send({"ok": True, "result": result})
  • 主 MCP Server 用一个字典结构来维护 project_name(创建时用户指定的标识符)与 worker 的对应关系,主 MCP Server 与每个 worker 之间是通过管道/IPC 保持通信;
    1
    2
    3
    4
    5
    6
    7
    8
    # project_name -> (Process, parent_conn)
    PROJECTS: Dict[str, Tuple[multiprocessing.Process, Connection]] = {}
    def open_database(project_name, path):
    parent_conn, child_conn = multiprocessing.Pipe()
    proc = multiprocessing.Process(target=_worker, args=(child_conn,), daemon=True)
    proc.start()
    reply = parent_conn.recv()
    PROJECTS[project_name] = (proc, parent_conn)
  • 收到客户端请求时,主 MCP Server 根据 project name 定位到对应的 worker 进程,将调用通过管道送过去,由 worker 进程调用 IDA core API 并返回结果;
    1
    2
    3
    4
    5
    def call_worker(project_name, func_name, *args, **kwargs):
    proc, parent_conn = PROJECTS[project_name]
    parent_conn.send({"func": func_name, "args": args, "kwargs": kwargs})
    reply = parent_conn.recv()
    return reply.get("result")
  • 不同 worker 进程之间互不干扰,可以同时对多个 IDB 进行分析。

如何使用 ida-domain-mcp

安装

方法一:从源码安装

1
2
git clone https://github.com/xxyyue/ida_domain_mcp.git
cd ida_domain_mcp
1
2
3
4
5
6
7
8
# With uv
uv venv
uv pip install -e .

# Or with pip/venv
python3.11 -m venv .venv
source .venv/bin/activate
pip install -e .

方法二:通过包管理器安装

1
2
3
4
5
# With uv
uv add ida-domain-mcp

# Or with pip
pip install ida-domain-mcp

安装 ida-domain-mcp 会同时安装其运行时依赖:

  • ida-domain (通过 headless IDA 控制数据库)

❗️在运行前,需要确认 IDA 的 headless 可执行文件可以被找到:

1
which idat64 || which idat

如果没有找到,请将 IDA 安装目录添加到 PATH 中,或者使用 ida-domain 提供的配置选项来指定 IDA 的安装路径。

启动

ida-domain-mcp 支持两种传输模式启动服务端:

  1. stdio(默认,适合直接与 MCP 客户端集成)
    1
    uv run ida-domain-mcp --transport stdio
  1. HTTP SSE(适合与 MCP Inspector 及远程客户端使用)
    1
    2
    uv run ida-domain-mcp --transport http://127.0.0.1:8744
    # Server prints: MCP Server available at http://127.0.0.1:8744/sse

你可以使用 MCP Inspector 进行快速尝试:

1
2
npx @modelcontextprotocol/inspector
# Point it to: http://127.0.0.1:8744/sse

具体使用示例可参考 ida-domain-mcp example


IDA Domain MCP: no GUI, no binary preloading, multi IDB analysis
https://xxyyue.pages.dev/2025/12/20/ida-domain-mcp/
作者
xxyyue
发布于
2025年12月20日
许可协议