如何逆向分析一个 Mach-O?REA 原生二进制分析与控制流重建实战指南
【免费下载链接】reaReverse engineer anything with agents, from app behavior down to native binaries.项目地址: https://gitcode.com/GitHub_Trending/rea2/rea
逆向Mach-O、找符号、读 switch 分支、追数据流——Mach-O 逆向的痛点在于:每一步都得在 Hopper 或 Ghidra 里手工点。REA(Reverse Engineer Anything)通过一条 MCP 总线把 Hopper、Ghidra 等引擎接入你的 AI Agent,让 REA 原生二进制分析从「打开文件」到「重建控制流」全程自动化,每条结论都带上可核查的Evidence(证据)。
App 真正执行的是编译后的原生二进制(macOS/iOS 上是Mach-O,Windows 是 PE,Linux 是 ELF)。本文只回答一个问题:如何逆向分析 Mach-O?下面按「你想问二进制的问题」来切分——里面有什么、某个函数在做什么、数据与控制流怎么流动——每节都遵循同一个节奏:目标 → 命令 → 产出(含证据与未知项)。
能力全景:10 秒看懂 REA 能做什么
| REA 能力 | 对应命令 | 产出 |
|---|---|---|
| 确认本机可用的分析引擎 | rea providers --json/rea capabilities --json | Provider 列表、能力集合 |
| 建立分析会话 | rea analyze <目标> --provider <引擎> --json | 目标身份、反汇编、分析 pass 快照 |
| 全文搜索 | rea search <目标> "关键词" --json | 字符串/符号命中列表 |
| 查询交叉引用 | rea xrefs <目标> <地址> --json | 该地址被谁引用 |
| 读取函数档案 | rea function <目标> <函数名> --json | 入口、参数、调用关系、反汇编事实 |
| 获取伪代码 | rea decompile <目标> <地址> --json | 反编译伪代码 |
| 有界调用跟踪 | rea trace | 类型化调用引用,按类型分别标注 |
| 值依赖跟踪 | rea trace-native-values | 值依赖图(数据流) |
| 运行时断点观测 | rea observe-native-calls | 寄存器实参记录 |
| 证据存档与版本对比 | rea evidence-export/rea compare | 规范证据包、行为差异 |
跑通任何一条命令前,只需 Node.js(22.19+)和 npm,执行一次:
npx rea-agents setupsetup 会注册 REA 的 MCP 服务、安装配套的工作流说明,并可选地配置 Hopper 或 Ghidra——所有变更都会先展示计划、经你确认后才写入,完整安装与 Provider 配置见 installation 文档。
Provider 的选择是确定性且显式的:多个引擎都能分析同一目标时,必须用--provider明确指定,REA 永远不会在 Hopper 与 Ghidra 之间静默回退。引擎适配层源码在 src/hopper/ 与 src/ghidra/,该决策有专门的设计文档记录。
分目标实战:把每个问题单独问
这个 Mach-O 里到底有什么?——身份、入口与分析快照
目标。第一次接触这个二进制,想知道:它是什么(Loader、架构、调用约定)、代码在哪、引擎做了哪些分析。
操作。用rea analyze指向 Mach-O 可执行文件的绝对路径——也可以直接传一个 macOS 的.app包:
rea analyze /absolute/path/to/program --provider ghidra --json产出。选定的引擎会完成加载镜像、反汇编__TEXT段、识别函数入口与 prologue、数据流分析和调用参考恢复。结果包含三类可核查的证据:
- 目标身份:File Information 中 Loader 为
Mach-O、CPUARM64、调用约定AAPCS——这是后续一切逆向结论的「身份证」; - 入口与段信息:
__TEXT段被反汇编出EntryPoint,指令级注释标出段范围与文件偏移; - 分析 pass 记录:日志从
Analysis pass 6/11逐轮输出到11/11(反汇编各代码段、数据流分析、prologue 搜索),后台分析耗时 0ms 完成。
下图是 REA 通过 Python 引导脚本在 Hopper 内部完成一次 Mach-O 分析的现场:
会话建立后,Provider 与分析配置会绑定到该目标,直到你显式切换或关闭才解除,会话实现见 BinarySession.ts。
想读懂某个函数的逻辑?——从搜索到伪代码
目标。从一堆符号里缩小范围到具体某个函数,并看懂它做了什么。
操作。推荐阅读顺序:search→xrefs→function→decompile——用字符串或符号缩小范围,看谁在调用它,再读伪代码。各对应一条命令(完整清单见 cli 文档):
rea search /path/to/program "关键词" --provider ghidra --json:全文搜索rea xrefs /path/to/program 0x1000 --provider ghidra --json:交叉引用rea function /path/to/program main --provider ghidra --json:函数档案rea decompile /path/to/program 0x1000 --provider ghidra --json:反编译伪代码
产出。function返回dossier(函数档案):入口、参数、调用关系与反汇编事实;decompile给出伪代码。两者的差别在于:dossier 是一组可逐条核查的事实,而不只是一块伪代码——Agent 在后续追问时可以引用其中任何一条。
数据和控制流是怎么流动的?——跳转表与 def-use
目标。从「函数在做什么」再深入一层:还原 switch 分支的真实形态,跟踪调用与数据依赖,逼近「重建算法」。细节见 native-investigation 文档。
操作与产出由三个工具承担,各自有明确边界:
- switch / 跳转表重建。跳转表是 switch 依赖的「case 值 → 目标地址」查表结构。对反编译器恢复的 switch,REA 把
mappings(数值映射)、default_targets(默认分支)、data_sources(底层数据来源)三者分开呈现;一个 null 的 case 值只表示「未解析」,绝不会被误报为已知默认分支。对 AArch64,还会从寄存器定义、表加载和分支基址逐字节验证跳转表形式。 - 有界静态跟踪
rea trace。从一个 selector、符号或函数地址出发,沿类型化调用引用走有限深度。直接引用、间接解析、歧义候选、无引用调用点会被分开标注,而不是混成一团。 - 值依赖跟踪
rea trace-native-values。基于 Ghidra 的高 p-code,跨静态解析调用合成def-use图(def-use 即「定义-使用」配对:哪个指令写入值、哪个指令读取它),常量、运算、LOAD/STORE 与分支操作数都内联进来——这是从「重建控制流」走向「重建算法」的关键一步。
边界。静态跟踪路线不等于运行时可达性证明。REA 会把这类限制显式写进结果,而不是让你误读。
边界与进阶 ⚠️:静态分析不够时,还有运行时
上面反复出现的「边界」不是缺陷,而是 REA 的设计原则:每个结果都带证据,每个「不知道」都明确写成「不知道」——null 的 case、歧义候选、静态路线的局限,全部被显式标注。这正是它区别于「只看伪代码」脚本类工具的地方。静态不够或想反复迭代时,还有三种扩展能力:
- 运行时观测:
rea observe-native-calls用 LLDB 以你拥有进程的方式启动 Mach-O,在指定函数或 Objective-C 方法(按 selector)处设断点并记录寄存器实参,全程不 attach 非自有进程。 - 快照复用:加上
--snapshot /path/to/analysis.json后,当目标字节、操作、参数、Provider 与设置完全一致时,相同查询直接命中本地缓存、秒级返回——适合对同一二进制反复迭代。 - 证据导出与对比:
rea evidence-export把分析证据打包成规范形式存档;rea compare对比两个版本间的行为差异。
场景速查 🧭:遇到什么情况就跑什么
| 你的处境 | 先跑什么 | 你会拿到 |
|---|---|---|
| 首次安装,确认本机装了哪些引擎 | rea providers --json、rea capabilities --json | 可用 Provider 与能力集合 |
第一次打开.app或 Mach-O 可执行文件 | rea analyze <路径> --provider ghidra --json | 目标身份、__TEXT反汇编、11 轮 pass 快照 |
| 拿到一个可疑字符串,想找对应代码 | rea search <路径> "str" --json,接着rea xrefs | 命中列表与引用点 |
| 要弄清某个函数全貌和它的伪代码 | rea function接rea decompile | dossier 与伪代码 |
| switch 结构对不上反编译器的说法 | 跳转表重建(mappings / default_targets / data_sources) | 三要素分开呈现,null 明确标为未解析 |
| 想还原某段算法的数据路径 | rea trace-native-values | def-use 数据流图 |
| 想看断点处的真实寄存器实参 | rea observe-native-calls | 运行时寄存器记录 |
| 下一版本要回归对比行为 | rea evidence-export+rea compare | 证据存档与版本差异 |
你的下一步动作:挑一个手头最小的二进制,跑一遍rea analyze,然后让 Agent 基于返回的证据回答「这个功能是怎么实现的」——这是验证 REA 是否适合你目标的最快方式。
【免费下载链接】reaReverse engineer anything with agents, from app behavior down to native binaries.项目地址: https://gitcode.com/GitHub_Trending/rea2/rea
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考