REA:AI 驱动的逆向工程
REA 如何把 Claude Code、Codex、Cursor 等智能体连接到真实的分析工具与证据驱动的调查流程
每个工程师迟早都会遇到没人完全理解的软件。
它可能是一个跑了十年的夜间批处理作业,作者早已离职,源代码仓库也在某次迁移中丢失了。它可能是一个团队想要复现其行为的桌面应用。也可能是一个物理规则从未被记录的老游戏,或者一个从外部看行为一目了然、但实现无从得知的网站。在所有这些场景中,根本问题是同一个:这个软件究竟在做什么?我们能证明吗?
传统上,回答这个问题需要一位专家:手持反汇编器、静态分析工具,外加极大的耐心。逆向工程意味着在陌生的二进制文件中跟踪函数、检查汇编与数据、追踪调用、验证假设,并逐步建立对程序行为的模型。这是强有力的工作,但也极其艰苦,其中大部分难度来自把零散的观察转化为可检验的结论。
REA(Reverse Engineer Anything,逆向任何东西)采取了不同的路径:把调查交给 AI 编码智能体,但让证据始终紧贴结论。
REA 是一个开源 MCP 服务器,把 Claude Code、Codex、Cursor 等智能体连接到真实的逆向与分析工具上,包括 Ghidra 和 Hopper。与其让智能体根据几段代码片段猜测程序如何工作,这套工作流可以让它检查目标、浏览其结构、追踪相关行为、收集证据、形成解释,并利用这份理解去帮助实现并测试一个类似的功能。
这个区别很重要。真正令人期待的承诺,并不只是 AI 能从一个未知的二进制文件生成代码,而是智能体能在实现之前展开调查,让它的结论扎根于真实分析工具产出的产物,而不是把逆向工程当作又一个代码生成问题。
1、核心思路:反编译、理解、重实现
描述这个方法最简单的方式,是三个层层递进的阶段。
第一个阶段是反编译。给定一个目标,REA 提取出分析所依赖的原材料:近似还原原始逻辑的伪代码、汇编指令、字符串、符号和元数据。这与人类分析师从 Ghidra 或 Hopper 这类工具中提取的材料是同一类。
第二个阶段是理解。原材料不是知识。真正的工作是把它们连起来:跟踪函数调用、构建调用图、追踪交叉引用以查看某个字符串或数值被用在哪里,并逐步弄清某个特定功能究竟如何行为。这是智能体最能节省时间的地方,因为它可以执行许多细小的调查步骤,并记住每一步展示了什么。
第三个阶段是重实现。一旦行为被理解,这些知识就可以用来在一个新项目中编写并测试实现。开发者可以请智能体弄清一个应用的离线搜索是如何工作的,展示证据,然后用 TypeScript 加 SQLite 构建一个版本。智能体不会复制那个二进制文件。它学会行为,然后写出完成同样工作的新代码。
有必要说清楚它不是什么。这个项目不声称恢复原始源代码,也不承诺自动、精确地克隆一个应用。反编译产物是一种近似,在经过验证之前,理解都是不完整的。诚实的表述是:REA 缩短了从一个谜团到一份可用的、经过验证的理解之间的路径,而不是抹掉了这条路径。
2、证据作为一等公民
REA 中最重要的设计选择,也许就是它的证据系统。当智能体调查一个目标时,一个干巴巴的答案是不够的。每条结论返回时,都带着支撑它的证据与局限性。
在实践中,这意味着智能体可以表达三件不同的事。它可以说它学到了什么。它可以说它在哪里学到的,指向支撑该结论的函数、字符串、引用或观察。它还可以说什么仍然不确定。第三点是大多数工具跳过的部分,而它至关重要。
任何让语言模型解释过一段代码的人都知道,无论答案对错,它们听起来可以多么流畅、自信。在逆向工程中,一个自信的错误答案代价高昂。一个读错的比较或误解的数据结构,可能导致一个行为几乎正确的实现——而这正是最难查找的那类 bug。通过强制让发现携带其证据与未知,REA 给了人类审查者可以核对的东西,也给了智能体可以跟进的东西。
实际的习惯很简单:要求智能体展示证据,并把任何标记为未知的内容当作一项任务,而不是一条脚注。
3、REA 能分析什么
它的范围远不止原生二进制文件。这套工具箱覆盖了多种目标,每种各有其要求。
原生二进制文件是经典场景。REA 返回伪代码、汇编、字符串、符号、调用和引用。深度原生分析使用 Hopper、Ghidra 或 IDA 之一;安装过程可以在批准后选择安装 Hopper,而 Ghidra 和 IDA 使用已有安装。Ghidra 的支持甚至延伸到 16 位 DOS 分析,Windows 上的 Ghidra 支持被列为实验性。
JavaScript 和 Electron 应用是回报特别高的目标,因为大量现代桌面程序就是这样构建的。REA 能恢复模块、导入、source map、路由、进程间通信以及原生插件的关系。它只需要 Node.js 和 npm,完全不需要原生分析引擎。
网站可以被检查页面结构、脚本、网络行为,并按需截图,使用的是 Chrome 系浏览器。保存的网络抓包——HAR 格式或 mitmproxy 原生抓包——会展露请求、响应、负载及其背后的来源位置。
.NET 程序集路径通过静态检查读取元数据、中间语言指令、声明的原生依赖,以及构建对比。Android 包会被分析 manifest 声明、类、反编译后的方法和引用,使用无头反编译器以及 Linux 或 macOS 上的完整 Java 开发套件。
固件镜像可以在 Linux 上用标准提取工具拆分为各个区域和提取结果,并可交接给原生分析。安装包与资源则产出文件清单、摘要、属性列表、Apple bundle 结构以及提取出的资源。
还有几项更专门的能力补齐了这份清单。使用 Linux 上的 pwntools,ELF 布局的离线分析会报告节、段、符号、重定位以及候选的缓解措施。EVM 字节码分析从本地载体返回分派选择器、字节偏移、推断的参数和可变性。录制的 Linux 崩溃可以被检查注记、线程寄存器、信号以及可选的映射候选。进程行为捕获则在 Linux 或 macOS 上通过原生伪终端,记录终端输出、交互、退出状态、文件系统观察,以及多次运行之间的对比。
一个关键区别贯穿这份清单。对 JavaScript 和 .NET 的静态检查只读取提供的文件,不运行应用。而运行时捕获则以用户自己的权限运行或与所选目标交互。每份运行时指南都会描述其影响,这一点值得注意,正如后面安全一节所解释的那样。
4、几分钟即可上手
安装过程刻意做得很短。装好 Node.js 和 npm 之后,一条命令开启一切:
npx rea-agents setup
安装工具会询问要配置哪些智能体,展示拟议的更改,并在触碰任何东西之前等待批准。然后它把 REA MCP 服务器注册到所选智能体上,并安装匹配的工作流指令,同时保留任何现有配置的备份。之后,智能体需要重启以加载更改。
支持的智能体包括 Claude Code、Codex、Cursor、Gemini CLI 等。任何支持本地 MCP 服务器的智能体都可以使用 REA,未被自动安装覆盖的客户端可以手动注册服务器。Node.js 版本要求是 22 系列的 22.19 及以上、24 系列的 24.11 及以上,或任何 26 及以上的版本。
智能体重启之后,使用 REA 只需要用自然语言。一个请求可能这样写:
Understand how search works in the Notes app, show me the evidence, and build a
similar feature for my project.
只需换成别的应用和功能即可。智能体决定调用哪些 REA 工具,阅读返回的结果,提出后续问题,并在证据足够有力时编写并测试一个实现。
常见问题(FAQ)回答了实际使用中的疑问。原生分析不需要手动启动 Hopper,因为 REA 会在操作需要时启动它——尽管在 macOS 上首次运行的对话框可能会询问使用演示模式还是激活许可证。对 JavaScript 和 .NET 的静态检查不需要原生引擎。可以从 skills 目录安装的技能为智能体提供调查指令,而安装命令同时会注册 MCP 服务器,所以安装命令就是完整路径。
5、直接使用终端
不使用智能体也完全可以。同样的工作流可以从命令行使用,这便于编写脚本、快速检查,以及喜欢看原始输出的开发者。检查一个解包后的 JavaScript 或 Electron 应用,或一个 ASAR 归档,大致如下:
npx -y rea-agents@latest analyze-javascript-application /absolute/path/to/app --json
结果包含模块、导入、Electron 进程边界,以及每项的证据。在 Windows 上,路径类似盘符加一个 apps 文件夹。日常使用时,全局安装这条命令让它随处可用:
npm install --global rea-agents
rea --help
原生命令首先需要配置一个 provider,也就是在 Hopper、Ghidra 或 IDA 中做出选择。CLI 与证据文档覆盖了 provider 选择、快照和脚本编写,这使得把可重复的分析步骤构建进流水线成为可能。

由于 CLI 和 MCP 工具共享相同的工作流,在一种环境中产出的发现可以在另一种环境中复现。开发者可以先手动试一条命令,再让智能体大规模地使用同一个工具。
6、一次调查如何展开
调查循环很容易描述。智能体通过 MCP 调用 REA 来检查目标、追踪相关代码。REA 返回带有证据的发现。智能体利用这些发现提出后续问题、解释行为,或者编写并测试一个实现。
拿离线搜索的例子来说。智能体先识别出这个应用。然后它寻找指向该功能的字符串和函数,比如查询文本、索引文件名或数据库操作。它追踪这些函数之间的关系,跟随调用和交叉引用,看一次查询如何在程序中流动。它反编译相关函数以阅读其逻辑。它重建对该功能如何工作的理解,记下什么是已确认的、什么仍然是猜测。最后,它帮助用开发者自己的技术栈编写实现并进行测试。
智能体并非遵循固定的脚本。每个结果塑造下一个问题——这正是人类分析师的工作方式,只是更快、更少疲劳。人的角色从亲手执行每一步,转变为掌控方向、审查证据、决定该信任什么。
7、实战示例:拯救一个孤儿般的夜间作业
有一个场景比任何功能清单都更能展示整套方法的价值。想象你接手了一个源代码早已丢失的夜间批处理作业。它读取一些输入,进行转换,然后写出输出文件。所有人都同意它必须继续运行,但没人能确切说出它在做什么。业务方希望把它迁移到现代语言和现代平台上。
REA 给 Claude Code 或 Codex 这样的智能体提供了通过 Ghidra 阅读二进制文件的工具,且每项发现都有证据支撑。它可以提取出揭示文件路径、列名、查询文本和错误信息的字符串。它可以追踪解析输入、应用规则、写出输出的函数,并用平实的语言描述逻辑,附上支撑代码的引用。
然后是带来真正差异的那一步。重写需要验收测试,而仅仅读代码是不够的。REA 的进程行为捕获可以在某个场景下运行原始程序并记录发生了什么:终端输出、退出状态和文件系统变化。然后在重写版上运行同样的场景,并对比两份记录,涵盖输出和文件变化。
这种对比是比代码审查更强的验收测试。审查者无法仅凭阅读就确认一个重写的模块与反编译逻辑匹配,因为反编译逻辑本身就是近似的。行为才是 ground truth。如果原始程序产出某份特定报告、触碰某些特定文件,而重写版产出的东西不同,那么这个差异是具体的,并指向该去检查的地方。如果两者在一组足够好的场景上都吻合,信心就会以一种人可以核对的理由增长。
有几个实践要点能让这套方法运转良好。
精心选择场景。一条 happy path 是不够的。要覆盖正常输入、边界情况、空输入、格式错误的输入,以及业务最关心的那些情况。
处理非确定性。即使代码完全相同,时间戳、随机标识符和顺序在多次运行之间也可能不同。对比应该考虑这些因素,要么做归一化,要么加以控制。
针对差异迭代。每个不匹配都是一条线索。智能体可以带着一个具体问题回到二进制文件,比如某个字段为什么采用某种格式,找到答案,然后修正重写版。
安全地运行。因为运行时捕获以用户的权限运行原始程序,它应当在隔离环境中进行,使用数据副本而不是生产系统。
这个模式可以推广到批处理作业之外。任何时候只要必须保持行为——无论是迁移、移植还是替换——把原始版本录制下来并与新版本对比,都是一套强大的纪律,而 REA 让智能体也能运用它。
8、项目给出的三个案例
项目发布了一些案例研究,展示了可能性的广度。
第一个跟随经典游戏 DX Ball 中的一个声音计算。分析把一次声音调用追踪进其辅助函数——该函数把坐标转换为立体声声像值——检查指令,并把不完整的伪代码转写为 C。重建经过了严格校验:针对原始 x86 行为通过了 3,205 个测试用例,并逐字节复现了编译后函数全部 63 个字节。这种级别的验证,正是行为对比所能达到的效果的展示。
第二个研究 Notion 桌面应用。它找到渲染进程的剪贴板接口,顺着预加载脚本和进程间通信一路追进主进程,并检查富文本剪贴板格式。这是一个很好的例子,展示如何把一个 Electron 应用从界面层一路映射到内部,且每一跳都有证据支撑。
第三个考察 TH04——日本 PC-98 平台上的一个原创游戏。分析检查 16 位指令,还原固定角度与自瞄准子弹角度的计算,并把重建的 C++ 与那个年代编译器的输出做对比。它表明这套方法可以回溯到非常古老的软件——而这正是源代码丢失最常见的地方。
每个案例研究都附有问题本身、REA 如何提供帮助、以及发现了什么,项目也邀请读者以同样的形式贡献自己的案例。
9、REA 的其他用武之地
除了救援任务,还有几种日常用途值得关注。
向现有产品学习。一个团队如果欣赏某个功能的行为,可以调查它如何工作,并构建自己的版本。关键词是自己的版本——意思是实现同样行为的新代码,而不是别人作品的复制品。
理解依赖。当一个第三方库或供应商的二进制行为古怪、而文档又语焉不详时,一次调查可以揭示它究竟在做什么。
安全研究与审查。分析二进制文件的导入、字符串和结构,检查固件镜像,阅读 ELF 布局与缓解措施,研究录制的崩溃——这些都是漏洞研究与防御性审查的日常工具。
互操作性。当一个系统必须与某个协议或文件格式没有文档的程序通信时,分析该程序或其抓取的网络流量可以揭示其格式。
归档与保存。过时平台上的老软件包含着值得记录的行为——趁最后一个理解它的人还没离开。
Web 与 API 工作。检查网站的脚本与网络行为,或分析保存的抓包,有助于调试集成、理解前端如何与服务器对话。
10、隐私与数据流
逆向工程常常涉及敏感材料,所以值得把数据去向说清楚。REA 在本地分析目标。分析引擎运行在开发者的机器上,结果来自本地工具。
智能体是另一回事。智能体会收到工具结果,而智能体背后的模型供应商有其自己的数据政策。换言之,REA 本身不会上传应用,但智能体读到的任何东西都可能流向智能体背后的供应商。对机密目标而言,这个区别很重要。团队应当审阅供应商的数据处理条款,采用符合自身敏感度要求的配置,并考虑对最敏感的工作是否应当使用本地部署的模型。
11、安全、合法与责任
强大的分析工具承载着责任,有几点值得直说。
静态与运行时是两回事。静态检查只读取文件,不执行它们。运行时捕获以用户的权限运行或与目标交互。运行未知软件可能很危险,因此陌生的二进制文件应当在虚拟机等隔离环境中分析,不接触重要数据或凭据。
合法性因情境而异。逆向工程在许多情境下是合法的——例如互操作性、安全研究,以及分析自己拥有或有权拥有的软件——在另一些情境下则受限。软件许可协议和最终用户协议常常禁止它,而版权法、反规避法律和合同条款因国家而异。任何计划基于调查发现构建产品的人,都应当理解适用的规则,并在利害重大时寻求法律意见。
行为不等于代码。最健康的用法是弄懂它如何工作,然后写出原创代码。把专有程序的反编译代码复制进产品,与基于独立理解实现同样的行为,是截然不同的行为。在意这个区别的团队有时会让分析者与实现者分离,在两者之间写出一份规格说明——这种实践被称为洁净室设计(clean room design)。
尊重目标的所有者。分析竞品以复制其标志性功能,或探测自己无权测试的服务,会制造任何工具都无法解决的法律与伦理问题。
12、如何获得好结果
有几个习惯能改善结果。
提出具体的问题。请求理解某个特定功能如何工作,远比请求解释整个程序效果好得多。
要求证据。要求智能体展示每个论断背后的函数、字符串和引用,并列出仍然未知的部分。
用行为验证。只要有可能,就拿真实程序检验你的理解。吻合的输出和文件变化,胜过貌似合理的解释。
小步前进。逆向工程奖励渐进式的推进,每个发现都引导下一个问题。
保持工具链最新。REA 变化很快,版本发布包含频繁的 bug 修复。对于通过 npm 安装的命令行工具,更新命令会刷新它,并打印出刷新智能体注册的安装命令:
rea update
对于通过 npx 运行的用户,刷新智能体配置大致如下:
npx rea-agents@latest setup
审查更改后,重启智能体并重试任务。如果更新后问题仍然存在,项目希望收到一个 issue,包含 REA 版本、目标类型、复现步骤和错误输出。
13、写在最后
REA 让逆向工程更贴近日常编码工作流,办法是把专家们依赖多年的工具交给 AI 智能体。通过 MCP,智能体可以与 Ghidra、Hopper 及其他分析器协作,调查原生二进制文件、JavaScript 与 Electron 应用、.NET 程序集、Android 包、固件、网站、网络抓包,以及实时进程行为。反编译、理解、重实现、测试的工作流给调查赋予了清晰的结构,而证据系统增添了一条重要的纪律:每个结论背后都应该有支撑,不确定性应当显形而非被隐藏。
但最有价值的想法也许是最简单的那一个:行为是终极测试。阅读一个反编译函数可以提示程序在做什么。把原始程序和重实现放在同样的输入下运行,比较它们的输出、副作用和文件变化,能提供强得多的证据,证明行为确实被理解了。
当源代码已经消失、而软件仍必须继续工作时,这个区别就至关重要。REA 并没有让逆向工程变得毫不费力,也没有让智能体的结论自动正确。它所做的,是在一个不透明的程序、一个有证据支撑的假设、和一份可用的实现之间,缩短距离。
在隔离环境中负责任地使用、守住适当的法律边界、坚持原创实现而非复制代码、对每一条论断保持健康的怀疑——如此使用 REA,它为一个古老的工程问题提供了实用的新路径:这东西究竟是怎么工作的?
原文链接:Reverse Engineering With an AI Agent: From Binary to Understanding
汇智网翻译整理,转载请标明出处