最近 REA 火得离谱。媒体口径:10 月 6 号还不到 1 万星,10 月 12 号已经 11 万,6 天涨了 10 万。我写这篇文章时已经超过了20万 星。
火成这样,总得有人认真测一测。我把源码(git clone,3722 个文件)翻了一遍(借助AI分析),又用 npm 上发布的 6.4.0 版本跑了一堆真实样本,下面所有数字都是本机跑出来的。
环境说明:Windows + Node 24,电脑没装 ilspycmd / dnSpy 这种反编译工具,所以它的 .NET 分析结果全部由它自己产出,顺便验证了"不依赖 .NET 工具链"这个声明。
结论先行
一句话:REA 是一个值得用的工具,但它的名字是一个营销选择。
"Reverse Engineer Anything" 里的 "Anything",指的是目标种类的宽度,不是分析的深度。这两件事在 README 里被同一张表格并列呈现,深度差异被抹平了。下面是REA项目中写的,提取了部分:
| 目标 |
REA 返回的内容 |
要求与指南 |
| 原生二进制文件 |
伪代码、汇编、字符串、符号、调用和引用 |
Hopper、Ghidra 或 IDA;原生分析 |
| JavaScript / Electron |
模块、导入、source map、路由、IPC 和原生扩展关系 |
Node.js 和 npm;应用分析 |
| .NET 程序集 |
元数据、CIL 指令、声明的原生依赖和构建对比 |
静态检查;托管代码指南 |
| Android APK |
清单声明、类、反编译的方法和引用 |
Linux/macOS/Windows x64 上的无界面 JADX 和完整 JDK;Android 指南 |
把其中的解析代码量化一下:它的 JavaScript/Electron 语义引擎有 4万行自研代码,而 Go 二进制解析只有 112 行。112 行能干嘛?读一下二进制里内嵌的 buildinfo 字符串而已。这叫"识别",不叫"逆向"。
「一切」的水分在哪
坑一:.NET 分析有一堵约 2000 方法的墙
这是最大的坑,因为它非常容易就会被触发。
我用它的工具扫了约 200 个 .NET Framework 标准程序集,边界非常清晰:
- System.Web.Extensions.Design.dll(1701 个方法)→ 完整解出
- System.DirectoryServices.dll(2094 个方法)→ 直接失效,0 个方法
- System.Core.dll,系统基础库,才 1.48 MB → 失效
原因写在源码里,ManagedDecodeBudget.ts:7:
const MAX_METADATA_REPRESENTATION_BYTES = 64 * 1024 * 1024;
注意这 64MB 不是文件大小,是它自己构造的 JSON 中间表示的估算预算。超过之后不是降级,是整个功能返回 0 个方法。
更迷惑的是,同一个文件,它家两个命令会给出自相矛盾的判断。拿 System.Activities.dll(9857 个方法)实测:inspect-managed-artifact 说 metadata.status = "complete",能读出全部方法名;inspect-managed-members 说 coverage.state = "unavailable",0 个方法。任何基于前者结果决定"要不要继续深入"的自动化流程,都会在下一步撞墙。
main 分支文档倒是给了应对方案:rea inspect-managed-members xxx.dll --type SomeType,先选类型再解。可惜 npm 6.4.0 上实测直接报 Unknown flag: --type。文档描述的解决路径,在用户实际装的版本上不存在。
坑二:Windows 上 44% 能力不可用
rea capabilities 实测,18 项操作里 10 项 unsupported_host,全是 macOS 专属(检查 Mach-O、Swift demangle、plist、签名等)。另外固件分析要 Binwalk、抓包要 tshark、逻辑信号要 sigrok,都是 Linux 的活。
所以"逆向一切"的真实含义是:在特定平台上,逆向特定类型的一个子集。README 表格里其实有 Requirements 一列,但"一切"这个词把限定条件全盖过去了。
真正的干货:web/JavaScript 栈
喷完了,说好话。REA 全部自研能力里,web/JS/Electron 这一块含金量最高,也是 dnSpy / ILSpy / Ghidra / IDA 这些工具生态里没有对标物的原创东西。
整个 web 栈 8万多行,占全部代码 29%。核心是 domain/javascript 下 3万多行的静态语义分析引擎:用 @babel/parser 做 AST,但语义层全是自研——追踪值怎么流动、对象怎么被改、IPC 消息怎么传、Promise 怎么链。
AI构造了一个 Electron 风格的测试应用:main.js 里开 BrowserWindow、注册 ipcMain.handle("store:get" / "store:set"),有个文件 require 了原生 .node 插件,还有一个条件分支的动态 require。跑它的 analyze-javascript-application,引擎产出 24 个语义节点 + 33 条关系边,该推出来的全推出来了:
- ipcMain.handle("store:get") → 生成 ipc-channel 和 ipc-handler 节点,handler --handles--> channel,高置信度
- native/bindings.node 判为 native-addon,require 解析出 native-export
- package.json 的 main 字段 → electron-main → 映射到 main.js;win.loadURL 识别出渲染入口
- new BrowserWindow 精确定位到源码区间 BrowserWindow@7:12-7:58
做的最好的地方是它不去猜测。我把一个 require 写成 process.env.NODE_ENV === "dev" ? "./dev-driver" : "./prod-driver" 这种静态推不出的形式,引擎如实标成 unknown,不猜。每条边都带 authority(ast-static-analysis / static-relationship-inference / artifact-bytes)和 confidence,每份报告都写死一句:values were recovered from inert syntax only;no JavaScript was executed。
不把推断伪装成事实,这在逆向工具里是稀缺品质。
两个大家最关心的问题
能破 JSVMP 吗?
不能,而且是设计层面就够不到,不是"还没优化"。
JSVMP 的本质是把代码转成自定义字节码,由一个 JS 解释器在运行时逐条执行,关键逻辑不再以可读源码存在。破它必须执行——要么跑那个 VM,要么动态 hook 看 dispatch。而 REA 的设计前提是"从不执行目标代码",这在 .NET 那边是合规优点,在 JSVMP 这边就是硬伤:静态分析器穿透不了"代码运行时才生成"的 VM。
这不是我的推测,它 CONTRIBUTING.md 写得明明白白,"defeat commercial packing or code-virtualization protections" 这类工作流不集成。JSVMP 正是 code-virtualization 的 JS 形态,正好落在拒绝清单里。
要破 JSVMP,老老实实走动态 hook + 针对具体混淆器的去混淆脚本那条路。
能分析 JS 病毒吗?
它是个很好的"静态结构剖析器",但不是反病毒引擎。
能干的:npm 供应链投毒、Electron 木马基本都是多文件 + package.json,REA 几秒就能画出"谁依赖谁"的图,并标出可疑点——IPC 通道、.node 原生插件(很多 JS 病毒把恶意 C 代码藏在里面绕纯 JS 沙箱)、动态 require。那个被标成 unknown 的动态 require,本身就是信号:正常应用不会那么写。
做不到的:它不执行,看不到"解密后再 eval"里的东西;没有 YARA、没有行为打分、没有恶意判定,是不是病毒得你自己下结论。
.NET 那边同理:它能看懂混淆程序集的骨架——字符串解密函数的完整 CIL、字段访问关系、P/Invoke CreateFileW 都能给你,但 FieldRVA 字节数组的内容它读不出来,而载荷恰恰就在那个数组里。全仓库搜 de4dot / Confuser / anti-debug 全是 0 命中,反混淆能力为零,而且是主动划进产品边界的"不做"。
我的实战建议:REA 负责静态摸底,沙箱负责动态验证。先用它快速理清样本结构和可疑点,再针对这些点在隔离环境里动态跑。分析和处置病毒务必在 VM / 沙箱里做。
它没吹牛的地方
一篇讲道理的帖子不能只列缺点。这几项我专门做了对抗性验证:
1. 不执行目标代码,是真的。 我构造了一个 Trap.dll,静态构造函数里写 File.WriteAllText("PWNED.txt")。REA 完整解出了 4 个方法和字符串锚点,而 PWNED.txt 没有被创建。源码里 capability 声明也全是 false:launchesProcess、mayWriteFilesystem、mayAccessNetwork……七项副作用开关全部显式列出,对需要证明"我没跑过样本"的合规场景很友好。
2. 证据链是下了功夫的。 它给每个 CIL 方法算两个哈希:原始字节一个、规范化 [opcode, operand_kind, operand] 一个。文档给的测试向量我手算复核过,一致。而且文档主动声明这个指纹的局限——不含 switch 目标、折叠不同 NaN 编码。不夸大自己的指纹,这是成熟工程。
3. 资源不够时如实降级。 超预算的程序集返回 partial + resource-limit issue,并明确写 "omitted facts are unknown"。省略的事实保持未知,没变成空。fail-closed,正确的做法。
4. 不是 Ghidra 的壳。 我对全部 1,408 个非测试 TS 文件逐文件判定(判据:是否直接 import node:child_process),98.2% 的代码不启动任何外部进程;真正的第三方引擎适配层(Ghidra / IDA / Hopper / JADX 等)只有 12.6%。核心领域层 domain/ 有 9 万多行,纯内存计算。
5. 跨版本比对逻辑严谨。 我编译了两个只差一个常量的程序集,它能精确定位到唯一变更的那个方法。契约里还写死了一条:"名字永远不作为匹配依据,签名没解出来的成员宁可标 unknown 也不猜增删"。这种保守在混淆样本上才有价值。
关于 21 万星
得泼盆冷水:这波热度反映的是"AI + 逆向"整个浪潮的关注度,不完全等于这个项目的技术领先度。
同期的一些事实:《Practical Reverse Engineering》合著者、前 Hex-Rays 的 Elias Bachaalany 转发推介时只评了一个词——"炒作";x64dbg 作者用 IDA Pro MCP(不是 REA)约一小时解完 Flare-On 全部题目;让老游戏跑进浏览器那个最出圈的案例,用的是 Hex-Rays 官方 MCP;GhidraMCP、IDA Pro MCP 这些同类 2025 年就存在了。
REA 的真实贡献是降低门槛:npx rea-agents setup 一行命令,把"会装 IDA、会配插件、知道该问什么"变成说一句话。这个贡献是真实的,它爆红的真实原因也在这里。
另外提一句工程上的坑:172 个工具的定义体约 496KB、12 万 token,直接挂全量工具会挤爆 Agent 上下文,官方文档自己都承认会 autocompact thrashing。记得用 compact 模式或裁剪。
选型建议
适合:
- 批量分诊(是不是托管程序集、什么运行时、有没有 P/Invoke)——跨平台无依赖,可脚本化
- 给 Agent 喂结构化事实——原生 MCP,结论带 digest 和 provenance
- CI 里做跨版本回归(比对 CIL 是否变更)——两个 il 哈希可以直接断言
- 合规场景需要证明"未执行代码、未改文件"
- JavaScript/Electron 应用的静态语义分析——这可能是全项目最强项
- 1500 个方法以内的 .NET 程序集分析
不适合:
- 动态调试、改程序集 → dnSpy / ILSpy
- 反混淆 .NET 病毒、提取加密载荷 → de4dot + 自己写解密脚本
- 大于 2000 方法的 .NET 程序集 → 同上
- Windows 上分析 Apple 应用 → 直接 unsupported_host
- 破 JSVMP → 动态 hook + 专门去混淆工具链
一句话收尾:把它当"给 Agent 用的逆向工具接口层",它做得很扎实;把它当"逆向一切",你会在 2000 个方法的地方踩坑,会在 npm 版上发现 8 种格式不存在,会在 Windows 上发现一半能力不可用。真实边界它的文档里其实都写了——夸大的部分,在标题里。