ARTICLE · 1153980
REA:让 AI 沿着证据逆向软件
大家好,这里是叮当岛。
拿到一个已经发布的软件,我们能观察它的功能,却未必知道内部是怎样实现的。代码可能被压缩进 JavaScript 包,也可能只剩可执行文件。要回答“这次复制操作把数据交给了谁”,往往需要在多个文件、进程和分析工具之间来回查找。这种从软件成品追查实现的过程,就是逆向分析。
REA 把这些调查能力接到了 AI Agent 上。它通过 MCP 这类工具调用接口,把本地分析能力交给 Agent,也可以直接从命令行使用。原生二进制分析会借助 Hopper、Ghidra 或 IDA;JavaScript、Electron 等目标则有相应的静态分析和运行时观察路径。[3]
我觉得它值得关注的地方,是对调查结果的组织方式:保留文件、位置、内容摘要和限制,让下一次追问有具体依据。它能帮助我们理解某段实现,是否解释正确、重写后的代码是否符合目标,仍需要继续验证。[7]

图 1|REA 官方调查流程。Agent 围绕本地目标提问,REA 调用分析工具并返回代码、引用与未知项,再由 Agent 解释、实现和测试;后续追问可以重新进入调查。[32]
从一次复制操作开始
假设我们正在做一个本地笔记应用,想理解桌面软件复制富文本的实现。文字可以复制过去,表格和块结构为什么也能保留下来?网页里的复制动作,又是怎样进入操作系统剪贴板的?
这是一个适合逆向调查的问题。只看界面,无法解释数据怎样流动;把整个应用包交给模型,也很难确定应该先读哪里。
REA 官方的 Notion 案例提供了一个具体入口。案例用 REA 4.1.0 分析 Notion Desktop 7.6.1 的一段 preload 文件,定位到对页面暴露的 __electronApi,以及一处 ipcRenderer.invoke 调用,并给出压缩代码中的源码位置。[15]
在 Electron 应用里,页面和主进程承担不同职责,preload 是页面与桌面能力之间的桥接层;IPC 是进程之间传递请求的机制。沿着这层桥接继续读代码,案例连接出了页面剪贴板 API、preload 包装函数、主进程接收函数和 Electron 剪贴板写入调用。[22]
但完整调用链并不是 REA 自动匹配出来的。案例记录显示,那次分析中的 IPC 通道仍是动态表达式;用具体剪贴板通道做功能追踪也没有得到图匹配。后续关系来自对包装函数和接收端源码的进一步阅读。关于块结构保留的部分,则来自另一份缓存的网页代码和单独的模块探针,不能合并成同版本桌面应用的完整实测。[15]
这个例子更接近 REA 的实际用途:先指出值得打开的代码位置,再让 Agent 或研究者继续追踪。它缩小了阅读范围,同时留下还没有解决的问题。
它怎样把应用拆成可追问的线索
REA 的全名是 Reverse Engineer Anything。名字覆盖面很大,理解它时仍要回到目标类型:原生程序、JavaScript 应用和运行中的网页,需要的分析能力并不相同。[3]
以 JavaScript/Electron 为例,REA 可以读取指定的应用目录或 ASAR。ASAR 是 Electron 常见的应用归档格式。静态分析路径先盘点文件并计算摘要,再把源码当作文本解析,恢复模块、导入关系、入口和 Electron 进程边界,最后形成应用图与语义关系图。[6][17]
应用图用节点表示模块、preload、IPC 通道、原生扩展等对象,用带证据的边表示它们之间的关系。语义关系图进一步保留变量、属性、调用、参数和返回值之间可静态恢复的联系。Agent 可以从一个 API、通道名、模块或字符串出发,查询相关路径,而不必每次从全部材料重新开始。[7][8]
这条流程在源码里有明确入口。JavaScriptApplicationService 校验输入,调用重建服务,校验输出,再生成 Evidence。重建服务负责文件盘点、读取、解析和图构建;它并不启动被分析的应用。[16][17]
Evidence 可以理解为一次分析的记录包:保存分析对象的内容摘要、工具身份与版本、操作参数、结果和限制。这样,后续查询能知道自己接着哪次分析往下走,避免混淆不同目标和工具的结果。这些记录有助于核对调查过程,不保证解释一定正确。[20]
相关测试还设置了一个会在执行时修改全局变量的样本,随后断言静态重建没有触发这个副作用。这个测试所检查的是“不执行目标代码也能恢复结构”,并不证明任何真实应用都能完整还原。[24]
如果调查进入 .node 原生扩展,JavaScript 图能保留请求的绑定和对应文件线索,但原生导出是否存在、函数内部如何工作,仍属于原生分析工具的职责。REA 在这里负责衔接调查,不替代底层逆向引擎。[6][8]
证据里也要写清楚“不知道”
AI 很容易把一条合理的解释写得像已经发生过。逆向分析尤其需要防止这种跳跃。
REA 的图模型区分观测、推断、未知和不可用,并保留证据来源、位置、置信度及覆盖范围。代码里出现一处 IPC 调用,是静态观测;把它与某个接收函数配对,是关系推断;运行时捕获到了某个脚本,又是另一类证据。[7]
这些区别会影响结果。静态 IPC 配对要求明确的字面通道和唯一的兼容接收候选。动态通道或多个接收候选不会被强行连接。找到一条静态路径,也不能说明某次点击一定走过它。[6]
同样,一个应用包缺少解包后的原生伴随文件,结果应该记录对应字节不可用,不能直接写成“没有原生依赖”。分析覆盖不完整时,在版本比较中找不到某个模块,也不能直接判定它被删除。相关测试明确要求这类单边缺失保留为 unknown。[6][25]
REA 还可以把已有静态结果与运行时观察进行关联。捕获的源码摘要与位置提供匹配依据;如果路径相同、内容摘要却不同,结果会报告不一致,不让文件名压过字节证据。相应测试也检查了这个情况。[9][26]
即便匹配成功,观察到脚本加载仍不足以证明功能执行或因果关系。这个边界对阅读结果很重要:证据格式可以帮助审查,不能替我们保证最终解释正确。[9]
从解释到重写,验证仍是单独的一步
理解一个功能以后,Agent 可以据此写实现。接下来要回答的问题变了:新实现是否复现了需要的行为?
REA 官方展示的 DX-Ball 声像计算案例说明了这段工作如何展开:声像计算决定声音在左右声道间的分配。案例使用保存的 REA 4.1.0 分析结果。最初的反编译伪代码没有完整表达输入和算术过程,调查继续读取指令、调用方和二进制中的常量,再由重建项目写出 C 函数。[23][31]
案例报告,这一个函数通过了 3,205 个与原始 x86 代码的行为对照用例,并在固定编译工具链和已审查重定位条件下匹配了完整的 63 字节函数代码。这是一个具体函数的验证结果,不能扩大成“REA 可以完整克隆软件”或一般性的成功率。[31]

图 2|REA 官方 DX-Ball 案例示意。图中的 3,205 个用例和 63 字节匹配,仅对应这个声像计算函数及案例规定的验证条件,不代表整个软件的重建效果。[33]
对普通开发工作,我更关心输入输出、状态变化和错误条件是否符合目标。只有在历史软件重建等特定任务里,才可能需要继续追求编译字节匹配。采用哪种验证标准,应由重建目标决定。
哪些任务值得用,哪些任务应该先收窄
如果手里已经有源码,而且问题集中在几个函数,直接读代码、搜索调用方和补测试通常更简单。REA 更适合线索分散在发布产物、压缩模块、跨进程接口和二进制里的调查任务。
例如,对有权分析的旧程序研究文件格式;检查自己发布的 Electron 应用里某个桌面功能的边界;比较两个应用版本的模块变化;追踪一个本地包怎样调用原生扩展。这些任务有具体问题,也容易定义要保留什么证据。[6][8]
开始时最好只问一个小问题,比如“这个导出动作把请求发送到了哪里”。没有明确调查目标就全量分析,可能得到大量结果,却仍不知道下一步应该读哪一段。
资源成本也需要提前考虑。源码文档说明,流式输出减少了构造整份 JSON 字符串的压力,但图本身仍要占用内存。调研时的公开 Issue 中,有用户报告 6.3.0 分析大型压缩包会中止;另一个报告涉及特定 Chromium 版本的页面地址变化导致观察失败。这些是公开报告,不是本次复现,足以提醒我们在真实目标上验证版本和环境,而不是只用小样本判断可用性。[6][27][28]
工具依赖则由目标决定。静态 JavaScript 分析不需要原生逆向引擎;深入分析原生程序,需要相应的 Hopper、Ghidra 或 IDA 环境。REA 使用 MIT 许可证,但底层工具的安装、授权和运行条件需要分别确认。[3][4][10]
最后是执行和数据边界。REA 在本地分析,不代表 Agent 工作流完全离线:工具结果会交给 Agent,模型服务的数据政策仍然适用。私有代码、应用路径和观察内容是否可以进入模型上下文,需要使用者自己判断。[3]
也别把“有脱敏处理”理解成结果已经不含秘密。浏览器 URL 的相关测试明确要求保留查询参数和片段,连示例中的 token 值也保留。因此,使用真实账户页面前,需要检查哪些数据会进入 Evidence、日志和模型上下文。[30]
静态分析与运行时捕获也不能混用安全结论。Process Capture 会以当前用户权限运行指定命令并继承宿主环境,官方文档明确说明它不是沙箱;文件观察路径只决定记录哪些变化,并不限制进程能读写哪里。[13] 项目的安全政策同样说明,本地反编译器解析陌生二进制时仍使用当前用户权限。需要分析或运行陌生目标时,应另行准备隔离环境,避免携带生产凭据和个人登录状态。[21]
我会把 REA 用在一个范围明确、素材已获授权、结果能够验证的调查任务里。先拿到具体位置和关系,再决定是否扩大分析范围。对于“一次读完整个应用,自动给出可上线替代品”这样的期待,现有案例和实现都不足以支撑。
最后
如果你也关心 AI 工具怎样进入实际开发流程,欢迎关注「叮当岛」。我们会继续分享产品解析与工程实践,也欢迎留言聊聊你的判断。
Sources
[3] https://github.com/morluto/rea/blob/74cf9e1401fcd89482fe39c27cc898f5858e9b72/README.md — REA README:定位与数据流
[4] https://github.com/morluto/rea/blob/74cf9e1401fcd89482fe39c27cc898f5858e9b72/LICENSE — MIT 许可证
[6] https://github.com/morluto/rea/blob/74cf9e1401fcd89482fe39c27cc898f5858e9b72/docs/javascript-artifact-reconstruction.md — JavaScript artifact reconstruction:静态分析与限制
[7] https://github.com/morluto/rea/blob/74cf9e1401fcd89482fe39c27cc898f5858e9b72/docs/javascript-application-graph.md — JavaScript Application Graph:证据与实体身份
[8] https://github.com/morluto/rea/blob/74cf9e1401fcd89482fe39c27cc898f5858e9b72/docs/javascript-application-workflows.md — Cross-layer JavaScript workflows:功能追踪与版本比较
[9] https://github.com/morluto/rea/blob/74cf9e1401fcd89482fe39c27cc898f5858e9b72/docs/javascript-runtime-reconciliation.md — Static/runtime reconciliation:匹配规则与局限
[10] https://github.com/morluto/rea/blob/74cf9e1401fcd89482fe39c27cc898f5858e9b72/docs/installation.md — Installation and setup:工具依赖与配置边界
[13] https://github.com/morluto/rea/blob/74cf9e1401fcd89482fe39c27cc898f5858e9b72/docs/process-capture.md — Process capture:权限与非沙箱边界
[15] https://github.com/morluto/rea/blob/74cf9e1401fcd89482fe39c27cc898f5858e9b72/website/evidence/notion-clipboard.md — Notion clipboard:案例证据与范围
[16] https://github.com/morluto/rea/blob/74cf9e1401fcd89482fe39c27cc898f5858e9b72/src/application/javascript/JavaScriptApplicationService.ts — JavaScriptApplicationService:分析入口
[17] https://github.com/morluto/rea/blob/74cf9e1401fcd89482fe39c27cc898f5858e9b72/src/application/javascript/JavaScriptArtifactReconstruction.ts — JavaScriptArtifactReconstruction:文件读取与图构建
[20] https://github.com/morluto/rea/blob/74cf9e1401fcd89482fe39c27cc898f5858e9b72/src/domain/evidence.ts — Evidence:结果封套定义
[21] https://github.com/morluto/rea/blob/74cf9e1401fcd89482fe39c27cc898f5858e9b72/SECURITY.md — Security Policy:本地分析的安全边界
[22] https://rea.tools/showcase/notion — Notion 官方案例:剪贴板调用路径
[23] https://rea.tools/showcase/dx-ball — DX-Ball 官方案例:声像计算
[24] https://github.com/morluto/rea/blob/74cf9e1401fcd89482fe39c27cc898f5858e9b72/tests/composition/javascript-applications/javascriptArtifactReconstruction.test.ts — JavaScript 重建测试:不执行样本与图结构
[25] https://github.com/morluto/rea/blob/74cf9e1401fcd89482fe39c27cc898f5858e9b72/tests/boundary/filesystem/javascriptApplicationWorkflows.test.ts — JavaScript workflow 测试:部分覆盖保留 unknown
[26] https://github.com/morluto/rea/blob/74cf9e1401fcd89482fe39c27cc898f5858e9b72/tests/composition/runtime-observation/javascriptRuntimeReconciliation.test.ts — Runtime reconciliation 测试:摘要不一致与执行边界
[27] https://github.com/morluto/rea/issues/1387 — Issue #1387:6.3.0 大型 bundle 中止报告
[28] https://github.com/morluto/rea/issues/1384 — Issue #1384:Chromium 150 页面观察报告
[30] https://github.com/morluto/rea/blob/74cf9e1401fcd89482fe39c27cc898f5858e9b72/src/domain/browserObservation.test.ts — Browser observation 测试:URL 查询参数保留
[31] https://github.com/morluto/rea/blob/74cf9e1401fcd89482fe39c27cc898f5858e9b72/website/evidence/dx-ball-sound-pan.md — DX-Ball sound-pan:分析版本与验证范围
[32] https://github.com/morluto/rea/blob/74cf9e1401fcd89482fe39c27cc898f5858e9b72/website/public/assets/figures/rea-investigation-flow.svg — REA 官方调查流程图,图 1 来源
[33] https://github.com/morluto/rea/blob/74cf9e1401fcd89482fe39c27cc898f5858e9b72/website/public/assets/figures/dx-ball-sound-pan-investigation.svg — REA 官方 DX-Ball 声像计算调查图,图 2 来源