返回博客列表

REA:让 AI Agent 逆向任何东西,从网站一路分析到二进制

2026-10-15T23:10:00+08:00
REAMCPAI Agent逆向工程静态分析固件

REA:让 AI Agent 逆向任何东西,从网站一路分析到二进制

看懂一个网页只要按 F12,看懂一个没有源码的二进制呢?

上一篇聊了 REA 的定位:它把 Hopper、Ghidra、IDA 这些专业逆向引擎包装成 MCP 接口,交给 Claude Code、Codex、Cursor 这样的 AI Agent 驱动。它自己不做引擎,只做一件事:让 Agent 能自主调用现成的分析工具,并把结果组织成可信的证据。三个 showcase(DX-Ball 音效算法重建、Notion 剪贴板桥接追踪、TH04 子弹环恢复)证明了这条路能走通。

这一篇换个拆法。把 REA 能分析的目标从浅到深排成一条线:网站、JavaScript/Electron、.NET、Android APK、原生二进制、EVM 字节码、固件,看看每一层它到底返回什么、依赖什么;然后把"发现 + 证据链"这个设计掰开,说说为什么一个 MCP 工具坚持不下结论,反而是对的。

仓库数据先摆在这里:作者 morluto,2026 年 4 月 14 日创建,TypeScript,MIT 协议,截至 10 月 15 日 254,259 Star、63,880 Fork(GitHub API 实测),官网 rea.tools。项目刚好满半年。

本文提纲

  1. 一条纵深线:23 类目标,从网站排到固件
  2. 静态分析的底气:不运行程序也能读出这么多
  3. 发现 + 证据链:把下结论的权力留给 Agent
  4. 两个最硬的终点:EVM 字节码与固件
  5. 边界依旧清晰

一、一条纵深线:从网站排到固件

REA 文档的 "What you can analyze" 一节列了 23 类目标。散着看容易眼晕,按"离源码多远"排一遍就清楚了:每一层是一类信息载体,REA 对每层返回的东西、要求的装备都不一样。

纵深 目标 REA 返回 依赖
网站 网页与站点 页面结构、脚本、网络观察、按需截图 一个 Chrome 系浏览器
应用壳 JavaScript / Electron 模块、导入、source maps、路由、IPC、原生插件关系 Node.js 和 npm
应用壳 .NET 程序集 元数据、CIL 指令、声明的原生依赖、构建对比 无(纯静态)
应用壳 Android APK Manifest 声明、类、反编译方法与引用 无头 JADX + 完整 JDK
应用壳 Flutter 应用 Dart 快照哈希、per-ABI 库摘要、引擎构建来源 无(静态解析 APK)
出厂信息 Go 二进制 内嵌编译器版本、模块、替换项、构建设置 无(内置 ELF/PE/Mach-O 解析)
出厂信息 Rust 二进制 cargo-auditable 的 crate 名、版本、来源、依赖边 无(同上)
原生 原生二进制 伪代码、汇编、字符串、符号、调用与引用 Hopper、Ghidra 或 IDA
特殊载体 EVM 字节码 分发选择器、字节偏移、推断参数、可变性 本地 raw/hex 载体(Linux x64)
特殊载体 固件 区域、提取结果、到原生分析的交接 Binwalk 或 Unblob(Linux)
运行时 进程行为 终端输出、交互、退出码与文件系统观察 Linux/macOS 原生 PTY

表格之外还有十几类长尾目标在册:SQLite 数据库(本地快照)、HAR 与 Fiddler SAZ 抓包、pcap 摘要(TShark 4.x)、sigrok 逻辑信号、Linux 崩溃记录(pwntools)、WASM 工件(WABT)、ADB 连接的真机或模拟器、JEB 项目、Apktool 资源、Apple 应用包解剖。

把"依赖"这一列单独拎出来,规律很清楚:越靠近网站和托管语言,装备越轻;越往二进制深处走,装备越重。

  • 网站层只要一个浏览器。
  • JavaScript、.NET、Flutter 的静态分析零引擎依赖,.NET 和 Flutter 两行的依赖栏干脆写着 None。
  • 真正的重装备只出现在三个深水区:原生二进制要 Hopper/Ghidra/IDA 之一,APK 要 JADX 加 JDK,固件要 Binwalk 或 Unblob。

二、静态分析的底气:不运行,也能读出这么多

零依赖不是魔法。编译和打包的时候,大量结构化信息本来就写进了文件里,REA 做的是把这些信息读出来、整理好,全程不运行目标程序。README 的原话是:静态 JavaScript 和 .NET 检查"读取你提供的文件,不运行应用"。

几类载体的"出厂信息"尤其丰富:

  • .NET 程序集自带完整的元数据表,REA 直接读出 CIL 指令和声明的原生依赖,还能做构建对比;
  • Go 链接器会把编译器版本、模块列表、替换项和构建设置嵌进二进制,REA 内置了 ELF/PE/Mach-O 解析,不装 Go 也能读;
  • Rust 生态有 cargo-auditable 约定,把 crate 名、版本、来源和依赖边写进产物,REA 同样内置解析;
  • Flutter 的 Dart 快照带哈希,REA 能给出 per-ABI 库摘要和引擎构建来源;
  • JS/Electron 应用里躺着 source maps 和模块声明,路由、IPC 边界、原生插件关系都能静态还原。

还有一处设计细节:caller-supplied(调用者自备)。pwntools、WABT、adb、Apktool、tshark、sigrok-cli、JEB 这些外部工具,REA 一律不捆绑、不代装,由你在自己机器上准备,它只负责调用和调度。对 GNU objdump 和 Rizin,文档的原话是 "REA does not install or update either provider"。唯一的例外是 Hopper:setup 可以在你明确批准后代装。

这个取舍有代价也有好处。好处是安装包小,不会和你机器上已经调好的工具链打架;代价是依赖矩阵碎,Linux 上还要求 PATH 里有 procps 兼容的 ps 做进程归属检查。底线要求倒是不高:Node.js 22.19+、24.11+ 或 26+,外加 npm。

三、发现 + 证据链:把下结论的权力留给 Agent

REA 的每个结果都遵循同一个约定:给发现,同时给证据和局限。README 写的是 "results include the evidence and limitations behind each conclusion",CLI 与证据指南(docs/cli.md)里专门有一节讲 Evidence limitations。

实际跑一下就能看到这个约定长什么样。用终端分析一个解包的 Electron 应用:

npx -y rea-agents@latest analyze-javascript-application /absolute/path/to/app --json

返回的 JSON 里,模块、导入、Electron 边界每一项都跟着自己的 evidence 字段。Agent 拿到结果后并不急着向你汇报"我看懂了",它基于证据决定下一步:追问、换工具,或者开始写实现。

为什么坚持这个设计?三个原因。

第一,可审查。证据链意味着你(或者另一个 Agent、一段 CI 脚本)可以沿着它复核每个结论。DX-Ball 的重建能通过 3,205 个原始 x86 用例、63 个函数字节完全一致,靠的就是每一步都有据可查。

第二,不越权。工具不替模型思考,模型也不替工具背书。反编译引擎输出的伪代码本身就不完整,如果工具层再"好心"补一个自信的结论,幻觉就被包装成了事实。

第三,迭代闭环。逆向是不断追问的过程:看到可疑函数,追调用方;看到字符串,追引用。证据链决定了 Agent 下一铲子挖哪里。

sequenceDiagram
    participant A as Agent
    participant R as REA MCP server
    participant T as Target

    A->>R: inspect(target, question)
    R->>T: static read or guided runtime capture
    T-->>R: bytes, metadata, traces
    R-->>A: findings + evidence + limitations
    Note over A: reason, then decide next step
    A->>R: follow-up inspection
    R-->>A: more evidence
    A-->>A: explain, implement, test

最后一个容易被忽略的事实:分析全部在本地跑。FAQ 里专门有一条 "Does REA upload my app?",答案是没有,REA 不上传你的目标。但 Agent 拿到工具结果后会调用模型供应商的 API,那是另一条数据链路,遵循各家的数据政策。拿它分析敏感目标之前,这条链路得自己掂量。

四、两个最硬的终点:EVM 字节码与固件

23 类目标里,EVM 字节码和固件是两个特殊终点:它们没有原生二进制那样成熟的 GUI 反编译生态,长期靠手工和零散脚本。

EVM 这条线完全离线,在 Linux x64 上吃本地 raw/hex 载体,返回分发选择器(dispatch selectors)、字节偏移、推断的函数参数和可变性(mutability)。对没有源码的链上合约,这基本是复原 ABI 和审计逻辑的第一步。

固件这条线是流水线设计:Binwalk 或 Unblob 先做区域识别和提取,REA 把结果整理成"到原生分析的交接"(native-analysis handoffs),从固件里挖出来的 ELF 再交给 Hopper、Ghidra 或 IDA 继续深挖。固件分析在这里是段前置工序,主战场在原生分析那一层。

这两类目标恰恰是 Agent 驱动最划算的场景:没有顺手的图形界面,步骤琐碎、试错频繁,正好交给会自我追问的 Agent。

五、边界依旧清晰

几个使用前该知道的事。

静态和运行时的分界线很明确:静态分析读文件,不碰目标;运行时采集(进程行为、网站交互、ADB 操作)会用你的用户权限真实运行目标,每个 runtime guide 都写明了影响范围。分析来路不明的样本,先想清楚这一层。

平台支持有偏差。不少目标类型只在 Linux 上验证过(pwntools、TShark 4.x、sigrok-cli 0.7.2),macOS 和 Windows 用户动手前先查对应 guide。

项目迭代很快,README 自己承认 "REA changes quickly"。用 rea update 或 npx rea-agents@latest setup 保持更新,遇到 bug 先升级再报 issue。

至于引擎上限、商业依赖和法律边界,上一篇的判断在这里依然成立:REA 不提升伪代码质量,授权问题得自己把关。


参考文档与链接

你手上有没有一个一直想拆开看看的 App 或二进制?让 Agent 替你挖一层试试,回来聊聊挖到了什么。


作者: itech001
来源: 公众号:AI人工智能时代(the-ai-era)
网站: https://www.theaiera.top/ 关注每日最新AI新闻和技术博客,主页有更多的文章的AI 技术参考:https://www.theaiera.top

本文首发于 AI人工智能时代,转载请注明出处。

分享给朋友