文档库 最新最全的文档下载
当前位置:文档库 › 实验4缓冲区溢出攻击实验

实验4缓冲区溢出攻击实验

实验4缓冲区溢出攻击实验
实验4缓冲区溢出攻击实验

深圳大学实验报告课程名称:计算机系统(2)

实验项目名称:缓冲区溢出攻击实验

学院:计算机与软件学院

专业:

指导教师:罗秋明

报告人:学号:班级:

实验时间:2017年5月12日

实验报告提交时间:2017年5月31日

教务处制

一、实验目标:

1.理解程序函数调用中参数传递机制;

2.掌握缓冲区溢出攻击方法;

3.进一步熟练掌握GDB调试工具和objdump反汇编工具。

二、实验环境:

1.计算机(Intel CPU)

2.Linux32位操作系统(Ubuntu 16.04)

3.GDB调试工具

4.objdump反汇编工具

三、实验内容

本实验设计为一个黑客利用缓冲区溢出技术进行攻击的游戏。我们仅给黑客(同学)提供一个二进制可执行文件bufbomb和部分函数的C代码,不提供每个关卡的源代码。程序运行中有3个关卡,每个关卡需要用户输入正确的缓冲区内容,否则无法通过管卡!

要求同学查看各关卡的要求,运用GDB调试工具和objdump反汇编工具,通过分析汇编代码和相应的栈帧结构,通过缓冲区溢出办法在执行了getbuf()函数返回时作攻击,使之返回到各关卡要求的指定函数中。第一关只需要返回到指定函数,第二关不仅返回到指定函数还需要为该指定函数准备好参数,最后一关要求在返回到指定函数之前执行一段汇编代码完成全局变量的修改。

实验代码bufbomb和相关工具(sendstring/makecookie)的更详细内容请参考“实验四缓冲区溢出攻击实验.pptx”。

本实验要求解决关卡1、2、3,给出实验思路,通过截图把实验过程和结果写在实验报告上。

四、实验步骤和结果

首先是makecookie:

步骤1 返回到smoke()

1.1解题思路

步骤1是要修改getbuf()的返回地址,在执行完getbuf()后不是返回到原来的调用者test(),而是跳到一个叫做smoke()的函数里。

只需构造一段字符串让Gets()全部拷贝到buf数组了,从而造成缓冲区溢出。同时最重要的一点是:将smoke()函数的初始地址也放到构造的字符串内,使其恰好覆盖到getbuf()的return address位置。

1.2解题过程

首先要知道smoke()的初始地址,用objdump查看符号表

smoke的初始地址是0x08048eb0。buf第一个元素的地址是-0x18,而return address 第一个字节的地址是0x04,两个位置的相差换算成十进制就是0x04 - (-0x18) = 4 + 24 = 28。也就是说我们要构造28个字符,然后加上smoke()的地址就能准确覆盖到return address了。

1.3 最终结果截图

步骤2 返回到fizz()并准备相应参数

2.1 解题思路

通过objdump -t查看符号表中fizz()函数的初始地址。拿到了地址0x08048e60,只要用它替换掉之前exploit.raw中smoke()的地址就能让getbuf()执行完毕后返回到fizz()中。然后用makecookie生成我的用户名ylb。以getbuf()调用Gets()为例,看一下调用者的代码和对应的栈。

2.2 解题过程

先分析出从getbuf()函数结束后,到调用fizz()函数前栈的情况:

0x0c 即将是fizz()栈区

0x08 即将是fizz()栈区

0x04 getbuf()的返回地址(即fizz()的地址)<- %esp

0x00 getbuf()中%ebp的保存值

得知,在返回并调用fizz()前,栈指针指向0x04处(相对getbuf()中的%ebp为0x00),随后fizz()调用时,会把fizz()的%ebp值压入栈中,

8048e66:8b 45 08 mov 0x8(%ebp),%eax

8048e69:3b 05 d4 a1 04 08 cmp 0x804a1d4,%eax

再结合这两行代码得知,fizz()函数的传入参数是应该存放在0x8(%ebp)处的,栈的情况应变为:

0x0c fizz的传入参数

0x08 fizz()的返回地址

0x04 fizz()中%ebp的保存值<- %esp (因为压栈,getbuf()的返回地址被替换)

0x00 getbuf()中%ebp的保存值01020304050607080910111213141516171819202122232425262728608e0408这串字符串刚覆盖到0x08,即还需要覆盖4个字节,然后传入黑客cookie值.

./makecookie ylb利用该命令获得个人黑客cookie值为0x239772d5

黑客cookie值依据小端法调整为96 3c df 30,cookie值前方还需覆盖4个字节,故得到完整字符串内容为:01020304050607080910111213141516171819202122232425262728608e040801020 304d57297230d

cat exploit2.txt | ./sendstring | ./bufbomb –t ylb

最后通过以上指令来把字符串内容构造并输入到bufbomb程序中。

2.3 最终结果截图

步骤3 返回到bang()且修改global_value

3.1解题思路

因为全局变量与代码不在一个段中,所以我们不能让缓冲区一直溢出到.bss段(因为global_value初始化为0,所以它会被放在.bss而非.data段以节省空间)覆盖global_value的值。若修改了.bss和.text之间某些只读的段会引起操作系统的“警觉”而报错。所以在进入bang()之前我们需要执行一小段我们自己的代码去修改global_value,这一段代码就叫做exploit code。

3.2解题过程

a.bang()和global_value地址

得到bang()的入口地址0x08048e10,以及global_value的地址0x0804a1c4

利用gdb调试获得buf字符数组的首地址,即是注入代码的首地址。

gdb bufbomb ;调试程序

disass getbuf ;查看getbuf的汇编代码

给getbuf()设置断点,程序把断点设置在0x8048ad6

run –t ylb ;运行程序

p $ebp-0x18 ;由lea -0x18(%ebp),%eax分析出buf地址为%ebp地址-0x18

得出buf地址,也即注入代码地址应为0xbfffb930

接下来编写注入代码(汇编代码):

.code32 ;让gcc以32位模式来编译

movl $0x333382e2, 0x0804a1c4 ; 令global_value = cookie值

pushl $0x08048e10 ; %esp -> bang入口地址

ret ; ret bang()

gcc –c exploit_code.s //编译汇编文件为可重定位文件.s -> .o objdump –d exploit_code.o //查看可重定位文件的内容

最终获得注入代码的16进制机器码,为16字节。在第1题中返回地址前有28个字节的空间,故在注入代码后面仍需补充12个字节的空间,为方便计数定为01~12,紧接着则是buf的地址,让getbuf()返回时跳转到注入代码的首地址,按照小端法,buf地址应为30 b9 ff ff,故完整字符串为:

c7 05 c4 a1 04 08 e2 82 33 33 68 10 8e 04 08 c3 01 02 03 04 05 06 07 08 09 10 11 12 30 b9 ff bf 0d

忽略空格(和下划线)后,得到exploit3.txt的内容为:

c705c4a10408e282333368108e0408c301020304050607080910111230b9ffbf0d

Linux 内存地址有随机化机制,若随机化机制打开,那么每次运行程序,%ebp的地址可能是不一样的,即buf地址无法确定(注入代码开始地址无法确定),这样的话,注入代码将无法正确编写。所以需要先关闭Linux 内存地址随机化机制,才能完成实验。

可以通过设置kernel.randomize_va_space内核参数来设置内存地址随机化的行为。

# echo 0 >/proc/sys/kernel/randomize_va_space

3.3 最终结果截图

将global_value的值设为0x333382e2

五、实验总结与体会

(1)在做第一题的时候,遇到了一个问题。

Error:Unable to send validation information to grading server.随后在网上查阅了相关的资料,明白了需要先安装sendmail。执行的命令如下:

sudo apt-get install sendmail

sudo apt-get install sendmail-cf

随后问题得以解决。

(2)而第三题,遇到了一个问题。Linux有内存地址随机化机制,因此在运行时,buf数组的首地址是不一样的,即注入代码首地址不能确定,此时,需要先关闭内存地址随机化机制,确定buf首地址后,编写注入代码,再来运行程序,才能成功。

相关文档