4.3 r2mcp自建工具流


4.3 r2mcp自建工具流

本节摘要:r2ai 的会话再漂亮,关掉终端就散了。本节把过程固化成流水线。r2mcp 是 radare 社区生态里把 r2 暴露为 MCP 服务器的桥(与 r2ai 同生态,另有 r2copilot、r2agent 等同类),任何 MCP 客户端都能把 r2 命令当工具调用。本节先用它把 r2 挂上 MCP;然后设计全书反复出现的那条流水线:模型读第 2.2 节的备料 JSON 产出假设清单(每条假设附可验证的 r2 命令)——流水线逐条执行命令拿到观测——模型按观测给出裁决(支持 / 反驳 / 证据不足)——结论回填成报告 JSON 与 r2 批注。第三部分给出可跑的骨架实现 verify_hypotheses.py(模型调用为占位示意),第四部分讲回填,最后与 r2ai 分工:交互探索用 r2ai,可复现流程用流水线。

学习目标

  • 说出 r2mcp 在 MCP 架构里的位置与适用场景。
  • 画出假设-验证-回填流水线并解释每个闸门。
  • 跑通(或改造)verify_hypotheses.py 骨架脚本。
  • 把结论回填为报告 JSON 与 r2 会话批注。
  • 按任务在 r2ai 与流水线之间做出选择。

一、r2mcp:把 r2 变成 MCP 服务器

第 03 章的模式平移:GhidraMCP 把 Ghidra 变成 MCP 服务,r2mcp 把 r2 变成 MCP 服务。形态上的差别值得注意:r2 本来就是命令行工具,桥只需要把「命令字符串进、文本出」这对接口翻译成 MCP 工具即可——比 Ghidra 侧薄得多。

MCP 客户端(任意支持 MCP 的智能体) │ 工具调用:run_r2_command("aflj") 之类 ▼ r2mcp(桥进程,持有 r2 会话) │ r2 命令 ▼ r2 ──▶ 文本 / JSON 观测 ──▶ 原路返回 ​

安装与启动形态随项目演进较快(以 r2mcp 官方仓库 README 为准),生态位稳定:r2ai 深度嵌在 r2 会话里(4.1 与 4.2 节);r2mcp 让 r2 成为外部智能体可调用的工具——适合自建编排。本书取后者,因为本章要的正是「自己的流水线」。

二、流水线设计:假设、验证、回填

┌──────────────┐ 备料 JSON(第 2.2 节) ┌──────────────────────────┐ │ 模型(一次) │ ──────────────────────▶ │ 假设清单 hypotheses │ │ 只读不操作 │ │ 每条:主张 + 验证命令 │ └──────────────┘ └────────────┬─────────────┘ ▼ ┌────────────────────────────────────────────────────────────────┐ │ 循环(脚本执掌,非模型):发命令 ──▶ 截断观测 ──▶ 模型裁决 │ │ 裁决三值:支持 / 反驳 / 证据不足(不许「大概」) │ └────────────┬───────────────────────────────────────┬───────────┘ ▼ ▼ out/hypothesis_report.json 回填:报告 + r2 批注 (主张、命令、观测、裁决,全留痕) (人复核后执行) ​

设计原则三条:其一,假设必须附验证命令——模型说「该函数是异或去混淆」时必须同时给出 pdf @ fcn.00401189 这样的验证路径,没命令的假设直接退回;其二,循环由脚本执掌,模型只在两端出现(出假设、下裁决),中段执行不给模型自由度——这是对 4.2 节预算问题的结构性解法;其三,裁决三值制,逼模型承认「证据不足」而不是硬选边。

三、实现:验证循环骨架

以下骨架可直接对 demo_stripped 跑通(模型调用为占位;接真实模型的方式随所用 SDK 而异):

# verify_hypotheses.py —— 假设-验证-回填流水线骨架(LLM 调用为示意占位) import json import r2pipe TARGET = "bin/demo_stripped" REPORT = "out/hypothesis_report.json" MAX_OBS = 2000 # 每条观测的截断上限(字符,示意) HYPOTHESES = [ { "id": "H1", "claim": "主函数对输入做条件校验后分支到成功与失败两条路径", "cmd": "pdf @ main", }, { "id": "H2", "claim": "存在异或去混淆函数,常量为 0x5a", "cmd": "pdf @ fcn.00401189", }, { "id": "H3", "claim": "期望密钥为去混淆结果 license", "cmd": "px 16 @ 0x00402008", }, ] def llm_judge(claim: str, observation: str) -> tuple: # 示意占位:把主张与观测交给模型,要求三值裁决并给一句理由 # 真实实现:调用你所选模型的 SDK,系统提示词固定「只准三值」 return "证据不足", "占位实现,接模型后生效" r2 = r2pipe.open(TARGET, flags=["-A", "-q"]) results = [] for item in HYPOTHESES: observation = (r2.cmd(item["cmd"]) or "").strip() verdict, reason = llm_judge(item["claim"], observation) results.append({ "id": item["id"], "claim": item["claim"], "cmd": item["cmd"], "observation": observation[:MAX_OBS], "truncated": len(observation) > MAX_OBS, "verdict": verdict, "reason": reason, }) r2.quit() with open(REPORT, "w", encoding="utf-8") as fh: json.dump(results, fh, ensure_ascii=False, indent=2) print("verified %d hypotheses -> %s" % (len(results), REPORT)) ​

假设清单这里手工给出,真实使用由模型从备料 JSON 生成——生成端同样要求结构化输出(id、claim、cmd 三字段),退回不合规格的输出。H3 的字节观测(36 33 39 3f 34 29 3f)与前两章的结论再次互证:流水线没有引入新事实,只是把验证过程程序化了。

四、回填:把结论写成批注与报告

报告 JSON 是机器友好的;人友好与工具友好的回填做两件事:

  • 报告侧:每条「支持」的假设升级为结论条目,带证据(命令 + 观测节选);「反驳」的记下反证;「证据不足」的进待办。这就是第 11 章《工程化与合规》(后续批次)证据链的最小雏形。
  • 工程侧:人复核后,把确认的名字与批注写回工具——r2 会话里 CC 注释文本 @ 地址 加批注,Ghidra 侧沿用第 3.3 节的回写脚本。规则同前:先人核,后落库。

五、与 r2ai 的分工

维度 r2ai(4.1 / 4.2 节) 本节流水线
交互形态 会话内,即时往复 脚本批处理,一次成型
模型自由度 ReAct 自主发命令 只在两端:出假设、下裁决
可复现性 依赖会话留痕 命令与观测全在报告 JSON
适用 探索期:不知道该问什么 收敛期:知道要验证什么

经验用法:先用 r2ai 角色与自动模式探索,形成候选假设;再把假设倒进流水线做正式验证与落盘。探索要自由,验证要约束——两种形态各得其所。

本节要点回顾

  • r2mcp 把 r2 变成 MCP 工具,比 Ghidra 侧的桥更薄:命令进、文本出。
  • 流水线三原则:假设必须附验证命令、循环由脚本执掌、裁决三值制。
  • verify_hypotheses.py 是可跑骨架:r2pipe 执行、截断观测、JSON 留痕。
  • 回填双轨:报告 JSON 给机器,人核后的批注给工程。
  • r2ai 管探索,流水线管验证——自由与约束分工明确。

至此,Ghidra 与 r2 两条工具流都已接上模型。下一章把它们再抬高一层:REA 聚合层——一个入口聚合多引擎与多对象类型,代价是要学会审视它的热度与证据。


作者与出处
原作者: 灏天文库
整理: 灏天文库整理
本站整理收录,版权归原作者/开源协议所有;欢迎通过原文链接访问源仓库。
发布者: 作者: 灏天文库 转发
评论区 (0)
U