广东东软学院
学生实验报告
实验课程名称:计算机系统基础
实验项目名称:缓冲区溢出攻击实验
实验类型: 设计性
指导教师:
实验日期:
学生姓名
宋晓燕
学号
1210121125
班级
11 班
专业名称
软件工程
实验组
其他成员
实验地点
实验成绩
(教师签名)
无
F408
实验目的与要求
实验目的:加深对 IA-32 函数调用规则和栈帧结构的理解。
实验目标:通过构造并输入相应的攻击字符串,破坏程序的原始执行流程,并
影响程序功能,是程序执行按设计所要求的代码部分。
实验要求:尽可能多的完成所有难度等级的缓冲区溢出攻击。
实验原理与内容
对目标程序实施缓冲区溢出攻击(buffer overflow attacks)。通过造成缓冲
区溢出来破坏目标程序的栈帧结构,继而执行一些原来程序中没有的行为。。
每个阶段考察要求对栈帧结构的理解及使用方式的难度递增:
5 个难度等级:(15 难度递增)
1.Smoke
2.Fizz
3.Bang
4.Boom
5.Nitro
实验环境
Linux
实践技能
Linux 基本命令
IA32 汇编程序
gdb 调试
Objdump 反汇编
gcc
可以简单分析一下 bufbomb.c(但这不重要),可以看到 bufbomb 中函数之间
的调用关系:
main 函数里 launcher 函数被调用 cnt 次,但除了最后 Nitro 阶段,cnt 都只是
1。testn、getbufn 仅在 Nitro 阶段被调用,其余阶段均调用 test、getbuf。正常
情况下,如果你的操作不符合预期,会看到信息“Better luck next time”,这时
你就要继续尝试了。
目标程序分析:
本实验从分析 test 函数开始。
test 函数调用了 getbuf 函数, getbuf 函数的功能是从标准输入(stdin)读
入一个字符串。
getbuf 函数源程序(bufbomb.c 里没有,根据反汇编逆向)
int getbuf()
{
}
char buf[32]; //32 字节字符数组
Gets(buf);
//从标准输入流输入字符串,gets 存在缓冲区溢出漏洞
return 1;
//当输入字符串超过 32 字节即可破坏栈帧结构
缓冲区攻击从 getbuf 函数入手
函数 Gets()不判断 buf 大小,字符串超长,缓冲区溢出。
实验任务:
构造 5 个攻击字符串,对目标程序实施缓冲区溢出攻击。
5 次攻击难度递增,分别命名为
1. Smoke
(让目标程序调用 smoke 函数)
2. Fizz
3. Bang
4. Boom
(让目标程序使用特定参数调用 Fizz 函数)
让目标程序调用 Bang 函数,并篡改一个全局变量)
(让目标程序感知不到攻击,并传递有效返回值)
5. Nitro
(在栈帧地址变化的情况下实施多次有效攻击)
需要调用的函数均在目标程序中存在。输入数据时使用所得到文件中的
hex2raw 程序进行转换并输入。
例:
注:可以根据个人习惯使用自己所熟悉的调试工具,如 DDD,IDA,edb-debugger
或 gdb 等。
实验设备与软件环境
1. 操作系统:Windows 8.1 专业版
2. 硬件平台:vmware 虚拟机上的 Ubntu
3. 调试软件:gdb
实验过程与结果(可贴图)
实验步骤:
一、将 bufbomb 反编译到 bufbomb.txt 文档中
编译代码:objdump -d bufbomb > bufbomb.txt,效果如图所示:
二、本次试验共要构造五个攻击字符串,对目标程序实施缓冲区溢出攻击,攻
击成功结果如图所示
三、本次 lab 利用 getbuf()方程不检查读取 string 长度的漏洞破坏该方程的
return address 从而达到对主程序造成破坏的目的。从 getbuf() 的 assembly code
我们可以看到:
位于<0x80490a3> 地址处代码为预读的 string 在 stack 创建了 0x28(也就是 40)个 Byte 的空
间。具体位置可以通过 gdb 在下一行设置 breakpoint 查找 %eax 的值得到,如下所示:
通过 gdb 调试得到,getbuf()申请的 40 字节缓冲区首地址为<0x55683858>,这个地址后面会用
到。
四、第一关 Smoke
smoke 的开始地址是<0x08048c28>,由三中的 getbuf()可知 buf 缓冲区的大小是 0x28(40 个
字节)。
攻击字符串的功能是用来覆盖 getbuf 函数内的数组 buf(缓冲区),进而溢出并覆
盖 ebp 和 ebp 上面的返回地址,所以攻击字符串的大小应该是 0x28+4+4=48 个字节。
并且其最后 4 个字节应是 smoke 函数的地址,正好覆盖 ebp 上方的正常返回地址。
这样再从 getbuf 返回时,取出的根据攻击字符串设置的地址,就可实现控制转移。
所以,这样的攻击字符串为:
执行语句:cat smoke_25.txt |./hex2raw |.bufbomb -u 25,显示结果如下
五、第二关 Fizz
fizz()函数的起始地址为<0x08048c52>
构造攻击文件 fizz_25.txt 如下:
其中,<0x08048c52>为 fizz 函数起始地址,0x51098e02 为自己的 cookie,通过参数传递给 fizz。
执行语句:cat fizz_25.txt |./hex2raw |./bufbomb -u 25
最后执行测试结果如下:
六、第三关 Bang
我们还需要执行一些自行设计的指令,因为该任务我们需要将 global_value 的值改成我们的
cookie,通过 objdump -D bufbomb | less (注意 D 要大写我们才能看到 header 的代码, -d 不会
显示):
通过 objdump -D 反汇编可以看到: