pwndbg r2 命令实战:在 GDB 会话中无缝启动 radare2 协同分析
【免费下载链接】pwndbgExploit Development and Reverse Engineering with GDB & LLDB Made Easy项目地址: https://gitcode.com/GitHub_Trending/pw/pwndbg
本文围绕 pwndbg 的r2(别名radare2)命令展开,讲解如何在 pwndbg 调试会话中一键拉起 radare2、把当前进程的 ELF 文件与基址自动传递给 radare2,从而在 GDB 与 radare2 之间无缝切换进行反汇编、分析(-AA)与协同逆向。读完本文,你将掌握r2命令的全部参数语义(--no-seek、--no-rebase、arguments)、底层命令构造逻辑,以及配套的r2pipe状态化管道用法,可以直接在真实调试会话中复现。
一、命令总览
r2是 pwndbg 集成 radare2 的入口命令,其功能一句话即可概括:在 pwndbg 会话中启动一个 radare2 实例,并把当前正在调试的可执行文件交给它。该命令定义在 pwndbg/commands/radare2.py,分类属于CommandCategory.INTEGRATIONS(集成类命令),并注册了别名radare2,即r2与radare2完全等价。
在 docs/commands/index.md 的命令索引中,它被归入 integrations 分区:
r2— Launches radare2(启动 radare2)r2pipe— Execute stateful radare2 commands through r2pipe(通过 r2pipe 执行有状态的 radare2 命令)
1. 完整用法
usage: r2 [-h] [--no-seek] [--no-rebase] [arguments ...]2. 参数一览
| 位置参数 | 说明 |
|---|---|
arguments | 传给 radare2 的命令行参数 |
| 可选参数 | 说明 |
|---|---|
-h,--help | 显示帮助信息并退出 |
--no-seek | 不把 radare2 的光标 seek 到当前 PC(程序计数器)位置 |
--no-rebase | 不为 PIE(位置无关可执行文件)根据当前映射设置基址 |
3. 官方示例
pwndbg> r2 -- -S -AA WARN: Relocs has not been applied. Please use `-e bin.relocs.apply=true` or `-e bin.cache=true` next time INFO: Analyze all flags starting with sym. and entry0 (aa) [...] INFO: Debugger commands disabled in sandbox mode [0x0001d3d0]> help Welcome to radare2! [...]注意示例中的关键细节:
--是 argparse 的位置参数分隔符,它之后的-S -AA才会被当作arguments原样透传给 radare2(否则 radare2 自己的-S、-AA会被 pwndbg 的参数解析器拦截)。- 命令执行后 pwndbg 终端直接转入 radare2 交互界面(提示符形如
[0x0001d3d0]>),意味着这是阻塞式调用——radare2 退出后才返回 pwndbg 命令行。 - 示例中的
WARN: Relocs has not been applied. Please use -e bin.relocs.apply=true or -e bin.cache=true是 radare2 加载 ELF 重定位时的提示,与 pwndbg 传入的io.cache=true相关(详见下文实现剖析)。
二、源码实现剖析:pwndbg 到底把什么传给了 radare2
r2命令的实现位于 pwndbg/commands/radare2.py,核心逻辑分为“取目标文件”“构造参数”“执行子进程”三步。
1. 目标文件来源
filename = pwndbg.aglib.file.get_proc_exe_file()命令装饰了@pwndbg.commands.OnlyWithFile,即只有在当前会话已经确定目标文件(如加载了可执行文件)时才可用,随后通过get_proc_exe_file()拿到正在被调试的进程对应的可执行文件路径。
2. 构造 radare2 命令行
cmd = ["radare2"] flags = ["-e", "io.cache=true"] exe = pwndbg.aglib.elf.exe() if pwndbg.aglib.proc.alive() and exe is not None: addr = pwndbg.aglib.regs.pc if pwndbg.aglib.elf.get_elf_info(filename).is_pie: if no_rebase: addr -= exe.address else: flags.extend(["-B", hex(exe.address)]) if not no_seek: cmd.extend(["-s", hex(addr)]) cmd.extend(flags) cmd += arguments cmd.extend([filename])从源码可以还原出 pwndbg 最终拼出的完整命令形态:
radare2 [-s <当前PC地址>] -e io.cache=true [-B <PIE基址>] [arguments...] <目标文件>关键决策点逐一说明:
-e io.cache=true:pwndbg 始终会为 radare2 启用 IO 缓存,这是示例中那条 “Relocs has not been applied” WARN 出现的直接背景。- PIE 处理:当被调试文件是 PIE 且进程存活时,默认做法是给 radare2 传入
-B hex(exe.address),即用当前内存映射中的实际加载基址重设 radare2 的 bin 基址,让 radare2 中的地址与 pwndbg/GDB 中的运行时地址对齐;若指定--no-rebase,则改为把 PC 减去exe.address(即还原成文件偏移),radare2 将按静态文件布局工作。 - seek 处理:默认(不传
--no-seek)会用-s hex(addr)让 radare2 一启动就把光标定位到当前 PC 处,与 GDB 正在执行的位置保持同步;--no-seek则关闭该行为,radare2 停在默认的入口点。 arguments透传:用户输入的所有额外参数原样追加到命令行末尾、目标文件之前,这也是示例中-S -AA(跳过调试器 attach、执行完整分析)能够生效的原因。
3. 异常兜底
try: subprocess.call(cmd) except Exception: print("Could not run radare2. Please ensure it's installed and in $PATH.")命令以subprocess.call阻塞执行;一旦 radare2 不在$PATH或启动失败,pwndbg 会打印提示,要求确保 radare2 已安装且可执行。
三、两个开关参数的实际使用场景
--no-seek:摆脱“光标跟随”
默认情况下 r2 会把 radare2 光标 seek 到当前 PC。当你并不关心当前执行位置,而是想从入口点或自定义地址开始分析时,可以关闭跟随:
pwndbg> r2 --no-seek -- -AA此时 radare2 将从文件的入口点(entry0)开始展示。
--no-rebase:回到静态文件视角
当目标是 PIE 程序时,默认的-B重基址会让 radare2 中的地址呈现为运行时地址(如0x55...高位基址)。如果你更习惯以文件偏移/静态地址(如0x1d3d0)进行分析——例如与未运行时提取的二进制对比、或使用基于文件偏移的工具链——可以用--no-rebase:
pwndbg> r2 --no-rebase -- -S -AA两个开关可以组合使用,r2 --no-seek --no-rebase -- <参数>会得到一个完全“静态视角”且不跟随 PC 的 radare2 会话。
四、进阶联动:r2pipe命令保持状态复用
在同一源码文件 pwndbg/commands/radare2.py 中,还定义了同主题的r2pipe命令(独立文档见 docs/commands/integrations/r2pipe.md),用于在 pwndbg 内直接执行有状态的 radare2 命令,而不需要离开 GDB:
usage: r2pipe [-h] arguments [arguments ...]pwndbg> r2pipe pdf @ sym.main ; ICOD XREF from entry0 @ 0x1d3e8(r) ┌ 6786: int main (uint32_t argc, char **argv, char **envp); │ `- args(rdi, rsi, rdx) vars(21:sp[0x40..0x18c]) │ 0x0001b920 f30f1efa endbr64 │ 0x0001b924 4157 push r15 [...]两者构成完整的 radare2 协作方案:
r2:交互式拉起完整 radare2 终端(适合深度手工分析);r2pipe:把 radare2 的命令字符串直接交给后台管道执行并把结果打印回 pwndbg(适合脚本化、状态化地连续调用,如反复pdf @ sym.main、s、afl)。
r2pipe的底层逻辑
r2pipe最终调用pwndbg.aglib.radare2.r2cmd()(见 pwndbg/aglib/radare2.py),其上游r2pipe()工厂函数有若干值得注意的实现事实:
- 句柄缓存:r2pipe 句柄被
cache_until("start", "objfile")缓存,即同一个目标文件、同一轮调试内多次r2pipe调用复用同一个 radare2 会话,保证“有状态”。 - 依赖检查:需要本机同时安装 radare2 与 Python 的 r2pipe 库,缺失时返回带错误码的失败状态(
ErrorCode.NO_IMPORT)。 - PIE 自动基址:与
r2命令一样,对 PIE 文件会自动追加-B hex(exe.address)重基址。 - r2ghidra 插件要求:会执行
LD检查支持的伪代码命令列表,若输出中不含pdg,则返回失败,提示 “radare2 plugin r2ghidra must be installed and available from r2”——也就是说r2pipe pdc/pdg反编译能力依赖 r2ghidra 插件。 - 内核调试适配:从源码结构看,在 QEMU 内核调试(
is_qemu_kernel())场景下会改用bin.cache=true、bin.relocs.apply=true并依据内核基址设置bin.baddr。
五、环境前提与常见问题
- radare2 必须安装:
r2命令通过subprocess.call执行radare2,需要该可执行文件位于$PATH;未安装或不在路径中时,pwndbg 会打印Could not run radare2. Please ensure it's installed and in $PATH.。 - 必须有目标文件:
r2与r2pipe都带OnlyWithFile装饰器,在未确定目标文件时不可用。 --分隔符:向 radare2 传递以-开头的选项时,务必先用--与 pwndbg 自身的参数解析隔离开。- WARN 提示的处理:若在 radare2 内看到 “Relocs has not been applied”,可按提示在 radare2 侧执行
-e bin.relocs.apply=true或-e bin.cache=true后重新加载。
六、相关资源
- 命令文档:docs/commands/integrations/r2.md、docs/commands/integrations/r2pipe.md
- 命令实现:pwndbg/commands/radare2.py
- r2pipe 底层封装:pwndbg/aglib/radare2.py
- 命令索引:docs/commands/index.md
- 同类集成:Rizin 生态对应命令
rz/rzpipe(见 docs/commands/integrations/rz.md、docs/commands/integrations/rzpipe.md 与 pwndbg/commands/rizin.py)
【免费下载链接】pwndbgExploit Development and Reverse Engineering with GDB & LLDB Made Easy项目地址: https://gitcode.com/GitHub_Trending/pw/pwndbg
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考