第 37 章 radare2 / Cutter 深度使用与脚本化
第 4 章讲了 radare2 的入门工作流,本章深入:r2 命令体系的内在逻辑、r2pipe 脚本化、自定义命令与插件、Cutter(GUI)、以及与 IDA/Ghidra 的工作流衔接。CLI 工具掌握得深,才能在无 GUI 环境(服务器/CI/容器)里照样逆向。
📍 知识点地图 | 主题:radare2深度 | 前置:第4章 | 后续:— | 核心概念:命令体系、r2pipe、Cutter、自动化
37.1 r2 命令体系的内在逻辑(掌握命令规律)
r2 命令不是死记硬背,而是有一套统一语法:
[.][命令][参数][@地址] # 在指定地址执行命令
[命令][?] # 查看子命令帮助
[.] 前缀 # 静默执行(不打印)
[~] 后缀 # grep 过滤(如 afl~main)
[;] 分号 # 命令串联
[%] 前缀 # 遍历(如 %s 对所有字符串)
核心命令族速记
| 命令族 | 功能 | 例子 |
|---|---|---|
a* |
分析 | aaa / afl / afi / axt |
i* |
文件信息 | iI / iS / iz / ii / ie |
s |
跳转 | s main / s 0x401000 |
p* |
打印 | pdf / pd 20 / px 64 / psz |
d* |
调试 | db / ds / dc / dr |
w* |
写(patch) | wa nop / wx 90 |
x* |
十六进制 | x / xx |
f* |
标志 | f / f label @ addr |
e |
配置 | e asm.syntax=intel |
? |
表达式/帮助 | ? 0x10+0x20 / ?v main |
学习法:? 查看任意命令的子命令列表(如 p? 看所有打印命令),比背表快。
37.2 深度分析命令(进阶必会)
函数与交叉引用
afl # 函数列表
afi # 函数详细信息(含调用者/参数猜测)
axt <addr> # 谁引用了该地址(xref to)
axf <addr> # 该地址引用了谁(xref from)
agf # 函数图(ASCII)
字符串与数据
iz # 数据段字符串
izz # 全文件字符串(含隐藏段)
psz @ 0x405000 # 读该地址字符串
px 32 @ 0x405000 # 十六进制 32 字节
pcp <addr> <n> # 输出为 C 数组(喂 Python 脚本)
搜索
/ 41414141 # 搜字节
/x 48 89 # 搜十六进制(支持 ?? 通配)
/r 0x401000 # 搜引用该地址的指令
/v 42 # 搜立即数
逆向辅助
aan # 分析并命名自动变量
aaa # 标准分析
aaaa # 更深分析(慢)
ar # 寄存器(调试)
ao <addr> # 单条指令操作码分析
37.3 r2pipe:用 Python 驱动 r2(自动化核心)
import r2pipe
# 打开文件(只读/写模式)
r = r2pipe.open("target.exe")
# r2pipe.open("target.exe", flags=["-w"]) # 写模式
# 执行命令
print(r.cmd("aaa"))
print(r.cmd("afl"))
print(r.cmd("iz~http"))
# 获取 JSON 结构化输出
funcs = r.cmdj("aflj") # 函数列表 JSON
strings = r.cmdj("izj") # 字符串 JSON
# 循环处理
for f in funcs:
name = f["name"]
if "sub" in name:
print(name, hex(f["offset"]))
批量分析管道(r2pipe 实战)
# 自动化: 批量导入 → 提取 → 报告
import r2pipe, json
def analyze(filepath):
r = r2pipe.open(filepath)
r.cmd("aaa")
result = {
"file": filepath,
"funcs": len(r.cmdj("aflj")),
"strings": [s["string"] for s in r.cmdj("izj") if "http" in s["string"]],
"imports": r.cmdj("iij"),
}
r.quit()
return result
samples = ["a.exe", "b.exe", "c.exe"]
for s in samples:
print(json.dumps(analyze(s)))
37.4 自定义命令与脚本(r2lang)
批处理文件
# 文件 myscript.r2
aaa
afl~main
s main
pdf
q
# 执行
r2 -i myscript.r2 target.exe
自定义宏命令
(every_string, iz) # 定义宏
(every_string) # 执行宏
r2lang / R2Pipe 插件
r2 支持用 C/Vala 写核心插件,或用 r2pipe 脚本封装常用工作流
场景: 团队共享分析命令 → 封装成 r2lang 脚本 → 全员复用
37.5 Cutter(r2 的 GUI)
Cutter = r2 内核 + GUI 界面
能力: 反编译(集成 r2ghidra 插件 → Ghidra 反编译器!)
用途: 需要 GUI 时用 Cutter,服务器上用纯 r2 → 同一内核,同一心智模型
# 安装 r2ghidra(Cutter 内获取 Ghidra 反编译能力)
r2pm -ci r2ghidra
37.6 r2 与 IDA/Ghidra 的工作流衔接
快速侦察(服务器/大批量): r2 + r2pipe 脚本
深度单点分析(GUI): IDA 或 Cutter/Ghidra
脚本化批量: r2pipe(轻) vs Ghidra headless(重)
两者衔接:
r2 导出符号/注释 → IDA 导入(或反之)
r2 定位可疑地址 → IDA 打开同一文件深挖
IDA 分析完 → r2 快速 patch 验证
37.7 r2 深度工作流(综合实战)
1. rabin2 -I/-z/-i 快速侦察
2. r2 -A 打开 → afl → 定位可疑函数
3. 交叉引用链: 字符串 → axt → 函数 → 深挖
4. r2pipe 批量提取 → JSON → LLM 分类(第 29 章)
5. 需要 GUI 时 → Cutter + r2ghidra 反编译
6. 动态验证: r2 调试模式(r2 -d)或转 GDB
7. patch 验证: r2 -w + wa/wx
动手练习
- 用
?探索命令树:找出p家族全部命令,试验其中 10 个。 - 写一个 r2pipe 脚本:批量分析 3 个文件,输出每个文件的函数数+可疑字符串列表。
- 用
pcp导出一个常量数组为 C 代码,粘贴进 Python 脚本完成一次解密。 - 用 r2 的调试模式(r2 -d)下一个断点,观察寄存器变化(对比 GDB 的体验差异)。
深入阅读
- 仓库:
skills/radare2/SKILL.md(CLI 工作流与脚本) - 仓库:
skills/radare2/references/cheatsheet.md(命令速查) - 仓库:
skills/radare2/scripts/recon.ps1(侦察脚本范例) - 仓库:
skills/reverse-engineering/tools.md(r2pipe 自动化) - 仓库:
skills/reverse-engineering/patterns*.md(r2 实战案例)