pwndbg mmap 命令详解:在调试会话中直接调用 mmap 系统调用映射内存
【免费下载链接】pwndbgExploit Development and Reverse Engineering with GDB & LLDB Made Easy项目地址: https://gitcode.com/GitHub_Trending/pw/pwndbg
本篇技术指南以 pwndbg 仓库中的 mmap 命令文档 为主体,结合 mmap 命令实现、参数解析模块 与 集成测试 等源码证据,完整讲解 pwndbgmmap命令的语法、全部参数、底层执行原理与安全机制。读者读完可以掌握:如何在 GDB/LLDB 调试会话中为被调试进程动态分配 RWX 内存、映射指定文件描述符、借助地址对齐检查与冲突检测安全使用MAP_FIXED,并能读懂 syscall 返回值与失败原因。
命令定位:为什么调试时需要手动 mmap
在利用开发(exploit development)与逆向调试场景中,经常需要为被调试进程(inferior)临时分配可执行或可读写的内存,例如:
- 为注入的 shellcode 准备 RWX 内存区域;
- 映射进程已打开的文件描述符,便于检查文件内容;
- 在特定地址附近固定分配页面,为后续 ROP/堆利用步骤做准备。
pwndbg 的mmap命令正是为此设计:它在被调试进程的上下文中直接发起mmap系统调用,并将系统调用返回的映射地址打印出来。它属于 pwndbg 的CommandCategory.MEMORY分类(见 mmap 命令注册代码),与 mprotect 命令文档(修改映射权限)构成内存操作的两大利器。
命令语法与全部参数
mmap命令的完整用法如下:
usage: mmap [-h] [--quiet] [--force] addr length [prot] [flags] [fd] [offset]位置参数
| 位置参数 | 说明 |
|---|---|
addr | 传递给 mmap 的地址提示(address hint)。内核不保证使用该地址,且会自动按页对齐。 |
length | 映射长度,单位字节,必须大于零。 |
prot | 内存保护属性,可以是枚举字符串或整数(同mmap(2))。例如"PROT_READ|PROT_EXEC"或7(即 RWX)。默认值7。 |
flags | 映射标志,可以是枚举字符串或整数(同mmap(2))。例如"MAP_PRIVATE|MAP_ANONYMOUS"或0x22。默认值34(即0x22)。 |
fd | 待映射文件的文件描述符;使用MAP_ANONYMOUS时传-1。默认值-1。 |
offset | 基于文件映射时的文件内偏移,单位字节。默认值0。 |
可选参数
| 短选项 | 长选项 | 说明 |
|---|---|---|
-h | --help | 显示帮助信息并退出 |
-q | --quiet | 关闭地址有效性警告与提示 |
-f | --force | 强制执行潜在不安全的操作 |
保护属性(PROT)与映射标志(MAP)取值
命令文档明确列出了支持的取值:
- PROT 值:
NONE (0)、READ (1)、WRITE (2)、EXEC (4)。默认组合7即PROT_READ|PROT_WRITE|PROT_EXEC(RWX)。 - MAP 值:
SHARED (1)、PRIVATE (2)、SHARED_VALIDATE (3)、FIXED (0x10)、ANONYMOUS (0x20)。默认组合34(0x22)即MAP_PRIVATE|MAP_ANONYMOUS。
上述常量与 pwndbg/lib/mmap.py 中的PROT_DICT、FLAG_DICT一一对应,是底层参数解析的权威来源。
参数解析的底层实现:字符串、简写与整数三合一
文档说明"flags 和 protection 值既可以是包含名称的字符串,也可以是按位或后的单一数字"。其实现位于 pwndbg/lib/mmap.py,支持三种输入格式,且大小写不敏感(输入会先.upper()):
- 带
PROT/MAP前缀的枚举名:如PROT_READ|PROT_WRITE、MAP_PRIVATE|MAP_ANONYMOUS,按|分隔的名字依次进行按位或。 - 简写权限字母(仅 PROT 支持):
r、w、x的组合,如rx。见 pwndbg/lib/mmap.py 的PROT_SHORT_DICT。 - 整数:支持十进制与
0x前缀的十六进制,如7、0x22,通过int(s, 0)解析。
单元测试 tests/unit_tests/test_mmap.py 覆盖了多种格式组合,例如"Rx"解析为PROT_READ|PROT_EXEC、"3"解析为PROT_READ|PROT_WRITE、"prot_read|PROT_WRITE"的大小写混合写法,以及"MAP_PRIVATE|MAP_FIXED"的组合解析,验证了这些解析规则的行为。
底层执行原理:注入 shellcode 发起系统调用
mmap命令并非通过 GDB 的call表达式调用 libc 函数,而是直接在被调试进程中注入一小段机器码执行mmap系统调用。完整调用链如下(见 mmap 命令实现):
- 地址对齐:用户传入的
addr首先经pwndbg.lib.memory.page_align()按页对齐。 - 构造 syscall 机器码:exec_syscall 使用
pwnlib.shellcraft.syscall("SYS_mmap", arg0, ..., arg5)生成汇编,再通过 pwndbg 的汇编器编译为机器码。 - 注入并执行:exec_shellcode 将机器码临时写入当前 PC 之后的空间(代码上下文管理),把 PC 跳到该处执行,并在执行期间挂起所有调试事件;执行完成后恢复原始指令与全部寄存器(寄存器上下文管理),保证被调试进程可无中断地继续运行。
- 读取返回值:从体系结构规定的返回值寄存器中读取 syscall 结果。
- 错误解码:
pwndbg.lib.errnum.handle_syscall_ret()(见 errnum 模块)判断返回值是否为错误码:若是错误,打印形如mmap syscall failed with EINVAL ('Invalid argument')的消息;否则打印mmap syscall returned 0x7f...的映射地址。
需要特别注意的是,文档提醒:mmap系统调用可能因多种原因失败(参见man mmap),失败时其返回值不是有效指针,切勿当作映射地址使用。
安全机制:地址对齐检查与 MAP_FIXED 冲突检测
源码中对"危险操作"有两道保护(见 mmap 命令实现):
1. 非 MAP_FIXED 时的对齐警告:若传入地址未按页对齐,内核会自动将其改为对齐地址。此时 pwndbg 会打印警告,提示内核可能修改该地址,并给出建议使用的对齐地址。--quiet可关闭此类提示。
2. MAP_FIXED 时的严格检查:MAP_FIXED会强制在内核指定的地址精确建立映射,可能覆盖并删除该地址范围内已存在的映射,是破坏性操作。因此:
- 地址未对齐时打印警告(
MAP_FIXED配合未对齐地址几乎必然失败); - 默认执行冲突检测:遍历当前 vmmap 列表,找出与目标范围重叠的所有现有映射;若存在冲突,打印冲突映射列表与"该操作是破坏性的、将删除上述映射"的警告,并中止命令,除非用户再次使用
--force强制执行; --force跳过冲突检测,适用于用户确认自己清楚后果的场景,同时也能显著提速(源码注释指出冲突检测在大映射数量下开销可观)。
该保护逻辑有集成测试支撑:tests/library/dbg/tests/test_mmap.py 中先查找空闲地址再以MAP_FIXED|MAP_ANONYMOUS|MAP_PRIVATE映射,断言返回地址与目标地址一致,验证了固定映射的正确路径。
实战示例
示例一:映射匿名 RWX 页面
mmap 0x0 4096 PROT_READ|PROT_WRITE|PROT_EXEC MAP_PRIVATE|MAP_ANONYMOUS -1 0在由内核决定的位置新建一个 4096 字节的私有匿名页面,权限为可读可写可执行,fd=-1、offset=0。这也是mmap 0x0 4096简写形式(使用默认参数)的完整展开,常用于为注入 shellcode 腾出可执行空间。
示例二:映射文件描述符
mmap 0x0 4096 PROT_READ MAP_PRIVATE 10 0将文件描述符10所指文件的 4096 字节以只读权限映射到内核选择的地址。集成测试 tests/library/dbg/tests/test_mmap.py 展示了真实用法:先在use-fds.native.c的断点处取出文件描述符,再执行mmap 0x0 16 PROT_READ MAP_PRIVATE {fd} 0,最后对比映射内容与进程内read()读入的缓冲区内容一致,同时校验映射权限确为只读。
示例三:带地址提示的简写
mmap 0xdeadbeef 0x1000以0xdeadbeef作为地址提示,映射一个默认的私有匿名 RWX 页面。内核会在0xdeadbeef附近的页边界处选择实际地址(未对齐时会给出对齐警告)。
映射后的联动操作
执行成功后,若 vmmap 缓存处于开启状态,命令会提示运行vmmap --refresh以在vmmap输出中看到新映射(见 mmap 命令实现)。之后可以用 vmmap 命令文档 查看映射布局,或用 mprotect 命令文档(同样基于exec_syscall注入机制)进一步调整该区域的执行权限。
小结
pwndbg 的mmap命令把操作系统的虚拟内存映射能力完整地带入了调试会话:它支持枚举字符串、简写字母与整数三种参数格式(解析实现),通过注入 shellcode 的方式在原进程上下文中执行真实系统调用(执行框架),并对错误返回值、地址对齐、MAP_FIXED破坏性覆盖提供逐层防护。其行为由 单元测试 与 集成测试 双重验证,是调试与利用开发中"动态造内存"的可靠手段。
【免费下载链接】pwndbgExploit Development and Reverse Engineering with GDB & LLDB Made Easy项目地址: https://gitcode.com/GitHub_Trending/pw/pwndbg
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考