☰
GEF print-format (pf) 命令详解:将内存区段导出为多语言字节字面量的完整工作流
2026/9/25 15:05:14 网站建设 项目流程
  • 网络安全
  • 开发工具

【免费下载链接】gef

GEF (GDB Enhanced Features) - a modern experience for GDB with advanced debugging capabilities for exploit devs & reverse engineers on Linux

项目地址:https://gitcode.com/gh_mirrors/gef/gef
点击查看免费下载

在漏洞利用与逆向分析中,经常需要把目标进程某段内存(shellcode、GOT 表项、构造好的 payload 等)以可直接粘贴的代码字面量形式取出来。GEF 的print-format命令(别名pf)正是为此设计:它能按指定语言、指定位宽把任意地址开始的内存转储为 Python、C、JavaScript、汇编或十六进制字面量,还支持一键复制剪贴板,以及与patch byte命令配合的$_gefN便利变量写回工作流。读完本文,你将掌握print-format的全部参数、各输出格式的代码级生成逻辑、剪贴板与便利变量的底层实现,以及"导出—检视—写回"内存的实战用法。

1. 命令概览与参数说明

print-format的完整用法如下(与 官方命令文档 一致):

gef➤ print-format -h [+] print-format [--lang LANG] [--bitlen SIZE] [(--length,-l) LENGTH] [--clip] LOCATION --lang LANG specifies the output format for programming language (available: ['py', 'c', 'js', 'asm', 'hex'], default 'py'). --bitlen SIZE specifies size of bit (possible values: [8, 16, 32, 64], default is 8). --length LENGTH specifies length of array (default is 256). --clip The output data will be copied to clipboard LOCATION specifies where the address of bytes is stored.

各参数含义与取值:

参数别名默认值说明
--lang LANG—py输出语言格式,可选py、c、js、asm、hex,另有一个特殊值bytearray(用于生成$_gef[N]字节访问,见第 4 节)
--bitlen SIZE—见下文说明每个数组元素的位宽,可选 8 / 16 / 32 / 64
--length-l256导出的数组元素个数(不是字节数)
--clip—关闭将输出结果复制到系统剪贴板
LOCATION—$pc起始地址,支持任意 GDB 地址表达式,如$rsp、$rsp+8、0x401000

其中--bitlen的默认行为值得注意:帮助文本写的是 "default is 8",但从源码看,PrintFormatCommand 在do_invoke中实际执行的是args.bitlen = args.bitlen or gef.arch.ptrsize * 2(gef.py#L5647-L5650),即默认位宽 = 指针字节数 × 2——32 位目标上是 8 位(与帮助文本一致),而 64 位目标上是 16 位。因此在 64 位环境下显式指定--bitlen通常更稳妥。

命令由@only_if_gdb_running装饰器保护,必须存在活跃的调试会话,否则返回 "not running" 错误(tests/commands/print_format.py#L16-L18 中有对应断言)。

2. 六种输出格式及其生成逻辑

源码中格式集合定义为valid_formats = ("py", "c", "js", "asm", "hex", "bytearray")(gef.py#L5603),其中前五种是常规"打印字面量"格式,bytearray是面向 GDB 便利变量的特殊模式。各格式的输出样式:

格式输出样式示例
py(默认)buf = [0x87, 0xfa, 0xa3, ...]
cunsigned char buf[N] = {0x87, 0xfa, ...};
jsvar buf = [0x87, 0xfa, ...]
asmbuf db 0x87, 0xfa, ...
hex87faa3f7ff7f000030e6(无分隔的纯 hex 串)
bytearraySaved data b'...'... in '$_gefN'(不直接打印全部数据)

生成这些字面量时,--bitlen决定了解码粒度。源码中的format_matrix属性(gef.py#L5625-L5633)把位宽映射为三样东西:

--bitlenstruct 格式符(含端序前缀)C 类型汇编指令
8<B/>B(依端序)chardb
16<H/>Hshortdw
32<I/>Iintdd
64<Q/>Qlong longdq

从源码结构看,非bytearray路径的实现是:按bitlen/8字节步进读取每个元素地址,用struct.unpack(fmt, gef.memory.read(addr, size))解码(fmt已根据gef.arch.endianness自动带<小端或>大端前缀),再把所有数值以hex()拼接;C 格式在此基础上额外套用类型名并生成unsigned <type> buf[长度] = {...};声明,asm格式则生成buf <db/dw/dd/dq> ...的 Nasm/Masm 风格伪指令。hex格式不走 struct 解码,直接对整个地址区间gef.memory.read(start, end-start).hex()(gef.py#L5675-L5692)。这一设计保证了在小端机上按 16/32/64 位读取多字节元素时得到的是按机器序解释后的值,而非错位拼接。

3. 实战示例

3.1 转储并按位宽取数 + 剪贴板复制

官方文档给出的第一个例子:从$rsp处取 10 字节并复制到剪贴板:

gef➤ print-format --lang py --bitlen 8 -l 10 --clip $rsp [+] Copied to clipboard buf = [0x87, 0xfa, 0xa3, 0xf7, 0xff, 0x7f, 0x0, 0x0, 0x30, 0xe6]

[+] Copied to clipboard由--clip触发,输出本体仍会打印在控制台,两者并不互斥。

3.2 bytearray 模式配合 patch byte 写回内存

这是该命令最有实战价值的用法,也是 官方文档 重点演示的场景——把$rsp+8的前 10 字节"搬运"到$rip处:

gef➤ print-format --lang bytearray -l 10 $rsp+8 Saved data b'\xcb\xe3\xff\xff\xff\x7f\x00\x00\x00\x00'... in '$_gef0' gef➤ display/x $_gef0[5] 4: /x $_gef0[5] = 0x7f gef➤ patch byte $rip $_gef0

流程拆解:

  1. --lang bytearray不打印完整数组,而是把原始字节存入 GDB 便利变量$_gef0,并给出前若干字节的预览(b'...'...);
  2. 之后可以随时用 GDB 原生表达式按字节下标访问,如display/x $_gef0[5];
  3. patch byte是 patch 命令族 的成员,它内置了对$_gef前缀值的特殊解析:若值以$_gef开头,会先gdb.parse_and_eval把便利变量展开成逐项字节再逐字节按端序写回(gef.py#L9747-L9755)。

官方文档对这一组合的总结是:Very handy to copy-paste-execute shellcodes/data from different memory regions(非常适合在不同内存区之间复制、粘贴、执行 shellcode 或数据)。

3.3 常用变体

# 以 32 位元素打印 8 个(适合观察 dword 序列) gef➤ pf --bitlen 32 -l 8 $rsp # C 风格 64 位数组,直接粘进 exploit 脚本 gef➤ pf --lang c --bitlen 64 -l 4 0x404000 # 纯 hex 串,便于对比/校验 gef➤ pf --lang hex -l 16 $rax

4. 源码级实现剖析

4.1 命令主体:PrintFormatCommand

命令主体位于 gef.py#L5599-L5701,关键实现点:

  • 参数解析:由 GEF 的@parse_arguments装饰器完成,location的位置参数默认$pc,--length默认 256,--bitlen默认 0 再在函数体内替换为ptrsize * 2(gef.py#L5635-L5650);
  • 校验:bitlen不在{8,16,32,64}报Size of bit must be in: ...,lang不在白名单报Language must be in: ...(gef.py#L5652-L5659);
  • 读取区间:end_addr = start_addr + length * size,其中size = bitlen / 8,注意--length的单位是"元素数",实际读到的字节数是它的 8/16/32/64 倍。

4.2 bytearray 模式与 $_gefN 便利变量

bytearray路径调用gef.memory.read拿到原始字节后交给gef_convenience()(gef.py#L4593-L4605):该函数按会话计数生成$_gef0、$_gef1…… 递增命名的 GDB 便利变量,把字节序列展开为{0xcb, 0xe3, ...}数组字面量执行set $_gefN = {...},并返回变量名。因此每个调试会话内变量名是递增不复用的,示例中的$_gef0在多次调用后会依次变为$_gef1等。

预览长度由命令自身配置项max_size_preview控制(默认 10,gef.py#L5620-L5623),可通过 GEF 的 config 命令 调整,例如把print-format.max_size_preview设得更大以看到更长的预览。

4.3 --clip 剪贴板机制

--clip最终调用copy_to_clipboard()(gef.py#L3984-L4000)。从源码看:

  • Linux:通过shutil.which查找xclip,执行xclip -selection clipboard -i;
  • macOS:使用pbcopy;
  • 其他平台:抛出NotImplementedError("copy: Unsupported OS")。

也就是说剪贴板功能有明确的外部依赖(X 环境下的xclip)与平台限制,在无图形环境时会收到 "There's a problem while copying" 的警告而非硬失败。

5. 测试用例验证

tests/commands/print_format.py 对该命令做了端到端覆盖,可作为行为基线参考:

  • 无调试会话时执行返回 inactive session 错误(L12-L18);
  • print-format $sp输出以buf = [开头;--lang js输出以var buf = [开头(L22-L26);
  • 写入p32(0x41414141)后--lang hex输出包含41414141(L28-L30);
  • 非法语言名触发Language must be in:错误(L32-L33);
  • --lang bytearray -l 4输出Saved data b'AAAA'... in '$_gefN',且随后p $_gefN可得到{0x41, 0x41, 0x41, 0x41}(L41-L50)。

6. 适用前提与限制

结合源码与文档,使用该命令时需注意:

  1. 必须有活跃调试会话(only_if_gdb_running),LOCATION默认$pc,省略位置参数即从当前指令指针开始导出;
  2. --length是元素个数,实际读取字节数 = length × bitlen/8,导出大区间时留意是否越出目标页导致MemoryError;
  3. 剪贴板仅限 Linux(xclip)与 macOS(pbcopy),且 Linux 侧要求xclip已在 PATH 中;
  4. bytearray变量按会话递增编号,配合patch byte时请使用输出中实际给出的$_gefN名称;
  5. 按 16/32/64 位解码时值按目标机器端序解释,跨端序机器直接比较字面量前需先确认gef.arch.endianness。

参考文件索引:print-format 官方命令文档、PrintFormatCommand 实现、gef_convenience 实现、copy_to_clipboard 实现、patch 命令文档、命令测试、命令配置说明。

  • 网络安全
  • 开发工具

【免费下载链接】gef

GEF (GDB Enhanced Features) - a modern experience for GDB with advanced debugging capabilities for exploit devs & reverse engineers on Linux

项目地址:https://gitcode.com/gh_mirrors/gef/gef
点击查看免费下载

相关推荐

上一篇:Windows HEIC缩略图插件完整指南:3分钟解决iPhone照片预览难题
下一篇:如何快速获取网盘真实下载链接:LinkSwift 完整使用指南

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询