ARTICLE · 1181238
爆火的 REA:给 AI 装上逆向工具,它怎么读懂软件的实现?
看到一个软件里的功能,想知道它怎么做的,手头却只有安装包,这个场景很多开发者都遇到过。截图能看出交互,抓包能看到请求,但一个按钮背后的计算、桌面应用里的进程通信、游戏里的某个算法,还得继续往程序里面找。
最近研究了一个叫 REA 的 GitHub 项目,全名 Reverse Engineer Anything。它给 Coding Agent 接上一组逆向分析工具,让 AI 能查应用包、读汇编、看反编译结果,再沿着证据追踪具体功能。我更关心的,是这一套工具怎么接起来,以及 AI 的解释能不能落到可检查的位置。
一套 MCP,连接几条不同的分析路线
REA 主要提供 CLI 和 MCP 两个入口。你可以在终端跑一条分析命令,也可以把它注册给支持本地 MCP 的 Agent,让 Agent 负责规划调查、调用工具、解释结果,以及编写和测试新的实现。REA 自己承担的是工具和证据这一侧的工作。CLI 与 MCP 分工
目前可分析的目标已经比较广。把主要路线压缩成一张表,比较容易看出依赖在哪里:
Android 设备、固件、WASM 等也有独立工具路径。支持一个目标类别,只能说明仓库提供了对应入口;主机平台、工具安装、具体格式和操作仍有条件。尤其是原生深度分析,要准备分析引擎;静态 JavaScript 和 .NET 分析可以直接读取提供的文件。目标与依赖说明

图:REA 的主要调用分工,AI 生成示意图。底层分析在本地完成;模型服务取决于 Agent 的配置。依据:仓库架构。
代码里,MCP 请求如何变成分析结果
从目录结构看,REA 把入口、工作流和底层工具适配分开了。src/server/ 接收 MCP 请求,src/application/ 编排分析工作,src/domain/ 保存证据和图模型,src/composition/ 负责把具体能力组装起来。CLI 也调用应用层,因此两种入口可以共用分析逻辑。服务注册代码
这里的 provider,就是“实际执行分析的工具后端”。原生目标会经过 AnalysisProviderRegistry 和 SessionProviderRouter 选择一个深度分析引擎,辅助能力则走独立路由。成功打开目标后,深度引擎绑定保持固定;运行失败时返回具体问题,保留所选引擎的身份。路由代码、会话契约
这个选择影响结果的可比较性。同一个函数,Hopper 和 Ghidra 可能给出不同的伪代码、函数边界或类型判断。保留引擎身份和分析配置,后续才知道差异来自程序版本,还是来自工具的解释。
原生分析的桥接也很直接。Hopper 侧有运行在其内部的 Python bridge,调用文档、过程和反编译 API;Ghidra 侧有 Java bridge,访问程序、反编译器和引用等 API,再通过本地通信把结果交回 REA。Hopper 桥接、Ghidra 桥接
REA 在这里承担三项工作:适配分析工具,编排跨文件或跨边界的调查,把结果整理成有身份和限制的证据。AI 再把这些结果放回当前问题中,决定下一步查哪个函数、哪条引用、哪个数据位置。下面两个案例,分别展示应用包和原生二进制里的调查过程。

图:官方仓库提供的真实 Hopper 截图,分析目标为 /usr/bin/true 的 Mach-O ARM64 文件,下方可见 bridge bootstrap 执行信息。来源:REA 仓库图片。本图并非本次调研运行截图。
Electron:从应用包追到系统 API
JavaScript 路线更能说明 REA 自己做了什么。Electron 安装包里的 app.asar 通常还保留着打包后的 JavaScript,虽然变量被压缩、模块被合并,程序结构仍然可以继续分析。
JavaScriptArtifactReconstruction.ts 的流程是:建立文件清单和样本身份,读取选定源码,交给静态分析进程,再构建应用图、Electron 边界摘要和 Evidence。它解析目标代码,整个静态分析过程不执行目标应用。分析服务实现
源码选择也有一个实用区别。指定 source_paths 可以把解析重点缩到已知入口文件,未选中的文件仍保留清单身份,其关系标为未知;请求 summary 则主要减少返回内容。两种做法分别控制分析范围与交付体积,使用时要分清。源码选择说明
静态分析使用 AST,也就是代码的语法树,由语法结构提取模块、导入和 Electron 调用线索。Node.js 下的独立分析进程设有堆内存和超时限制;资源耗尽时,结果保留已完成的事实及未完成范围,Bun 下部分限制的实现和可用性另有区别。静态分析进程、运行时差异
这些结果进入 JavaScript Application Graph。图里可以表达 main、preload、renderer、contextBridge、IPC channel、native add-on 等实体,也可以表达加载、暴露、调用和处理等关系。每条观察或关系还带着来源、位置、认知状态和覆盖范围。应用图模型
这对 Electron 很有用。页面里看到的方法名可能只是一层包装器,点击后先进入 preload,再通过 IPC 到主进程,才触达系统 API。能沿着这些边界继续查,才有机会把“界面上发生了什么”连接到“程序里执行了什么”。
官方 Notion 案例展示了这个过程。针对 Notion Desktop 7.6.1 的 tab preload,案例使用 REA 4.1.0 定位到 __electronApi 暴露位置和 ipcRenderer.invoke 调用;Agent 再阅读包装器,找到 notion:clipboard:write,去主进程追接收端,接着发现发送方检查和 Electron 的 clipboard.write(data)。Notion 案例

图:官方案例的源码链路整理,AI 生成示意图。REA 定位 API 与 invoke,Agent 阅读包装器后连接后续步骤;本图未展示桌面运行验证。依据:Notion 证据范围说明。
案例里保留的限制同样有价值:API 被标为 dynamic,invoke 的通道表达式仍然是变量,自动图没有恢复完整剪贴板链路。上图的四步路径由进一步阅读应用包源码连接起来,不能算成一次完整自动推断,更不能当作同版本桌面运行验证。案例底稿
这也是静态分析的现实边界。看到明确调用可以继续追;遇到动态属性、包装器或不唯一的 IPC 匹配,工具应该把未解析项留下来。REA 的图模型允许表达 unknown 和 unavailable,给后续调查留出位置。
原生二进制:伪代码漏掉的内容,继续查汇编
原生程序没有这层可直接阅读的 JavaScript。REA 会交给反编译器,还原出伪代码、汇编和引用等线索。编译优化、间接调用、缺失符号和不完整的类型信息都会影响结果,恢复出来的伪代码只是工具对机器码的解释。Ghidra 语义边界
官方 DX-Ball 案例选了一个很小的目标:老游戏把砖块的横向位置转成左右声像值的函数。案例记录使用 REA 4.1.0 与 Ghidra 12.1.4;首次反编译结果只露出 __ftol 转换调用,参数和前面的浮点计算没有完整显示,这时就得继续查底层指令。案例分析版本
Agent 通过 REA 读取汇编,找到从 [EBP+8] 取入的整数参数,再追调用方,确认传入值来自砖块横坐标。随后读取常量所在地址,恢复乘以 1.5625、减去 500.0、再乘声像缩放值的计算。DX-Ball 调查过程
用便于阅读的形式表达,这段核心关系是:
声像值 = 向零截断((横向位置 × 1.5625 − 500.0) × 缩放值)这里有三个不同动作:REA 提供原始指令和常量,Agent 解释其意义,重建项目再写 C 实现并验证。项目记录显示,该函数通过 3,205 组原始 x86 对照用例;在指定历史编译器与重定位检查条件下,完整函数的 63 个字节匹配。这是重建项目对这个函数的验证记录,本次调研未独立复跑,也不能扩展为整款游戏已完成复刻。函数证据与验证范围、重建项目记录
这个案例说明了 REA 的价值:AI 拿到初步解释后,还能继续找证据补上遗漏。要恢复算法,调用方、数据常量和机器指令往往需要一起看;一句“反编译成功”不足以回答逻辑是否恢复准确。
Evidence:让每次分析都能回查
把大量代码塞进模型上下文,会遇到两个问题:结果太大,读者又难以知道某句话从哪里来。REA 用 Evidence 记录把样本、操作、结果和限制放在一起,让调查过程留下可追踪的依据。
在 src/domain/evidence.ts 里,可以看到几个关键字段:normalized_result 是整理后的操作结果,raw_result 保存不同于整理结果的原始表示,没有时允许为空;analysis_profile 保存分析配置,也允许为空。证据还记录样本摘要、工具身份、参数、位置和限制。Evidence 数据模型
evidence_id 由记录的语义内容计算得来。会话里的 EvidenceLedger 保留不可变记录,对重复记录去重,对同一 ID 下内容冲突的记录报错。这样可以检查某份结果是否对应同一份证据,但哈希本身不能保证反编译器的判断正确。证据账本实现

图:证据记录与后续追问的关系,AI 生成示意图。Evidence、未知项和分析视图共同服务于回查;结论正确性仍需额外验证。依据:证据模型、MCP 契约。
对大结果,REA 还处理了传输边界。完整 Evidence 若超过 MCP 响应预算,工具可以报告 transport resource constraint,把证据保留在当前会话里,再提供引用。Agent 可以用 inspect_analysis_view 请求摘要、选定模块或分页内容,也可以导出整个证据包。结果交付实现
这个设计有意义,因为“分析覆盖完整”和“这次返回多少内容”是两件事。缩小读取视图,可以分批理解已保存的结果;分析本身因资源或工具限制没有覆盖的部分,则仍需保留其未知状态。不能把返回的短摘要当成整个目标已被完整理解。
接入与试用入口
想体验 Agent 工作流,可以按照官方安装说明运行下面的命令,查看 setup 提出的配置修改、外部工具需求和备份计划,确认后再执行。Setup 会注册 MCP,并安装匹配版本的工作流说明,完成后需要重启 Agent。安装说明
npx rea-agents@latest setup本次核查版本支持 Node.js 22.x(至少 22.19)、24.x(至少 24.11)或 26 及以上。原生目标另需准备相应分析引擎,Hopper 和 IDA 的授权条件也要单独处理;REA 自身的 MIT 许可只覆盖它的项目代码。运行版本、项目许可
原生分析还要区分“服务连上了”和“引擎准备好了”。以 Ghidra 为例,MCP 初始化完成后,首次实际查询仍需等待导入、自动分析和桥接就绪;客户端请求超时可能早于引擎启动期限。大样本第一次查询的等待,不能直接当成 MCP 配置失败。启动与恢复说明
如果先从静态 JavaScript 分析入手,可以对自己有权检查的 ASAR 或解包目录执行一条独立 CLI 命令。下面固定到本文核查的发布版本,便于明确结果对应哪个工具版本;路径需替换成本地样本绝对路径。
npx -y rea-agents@6.4.0 analyze-javascript-application /absolute/path/to/app.asar --json给 Agent 的问题也尽量收窄。例如:“追踪这个应用的 CSV 导出,从页面入口到实际写文件的位置;列出源码位置和未解析项,再为我的项目实现同样的转义规则,并用逗号、双引号、换行和中文四类输入验证。”比起要求一次恢复整个应用,明确输入、行为和验收条件,更容易判断调查是否完成。
几种路径可以这样选:
看完 REA,我最认可的是它让 AI 有条件持续回答“这段解释依据什么”。工具给出位置和限制,Agent 才能把下一步调查落到具体材料上;重写出来的代码,再用原程序的输入输出或其他明确规则验证。
如果要开始,挑一个你有权研究的软件,选一个小功能,列出几个边界输入。能找到证据、解释限制、通过验证,这一轮调查才算交付了有用的结果。
项目地址:morluto/rea。官网:rea.tools。















































































