基于缓冲区溢出的攻击.docx

上传人:b****5 文档编号:6019468 上传时间:2023-01-03 格式:DOCX 页数:17 大小:1.31MB
下载 相关 举报
基于缓冲区溢出的攻击.docx_第1页
第1页 / 共17页
基于缓冲区溢出的攻击.docx_第2页
第2页 / 共17页
基于缓冲区溢出的攻击.docx_第3页
第3页 / 共17页
基于缓冲区溢出的攻击.docx_第4页
第4页 / 共17页
基于缓冲区溢出的攻击.docx_第5页
第5页 / 共17页
点击查看更多>>
下载资源
资源描述

基于缓冲区溢出的攻击.docx

《基于缓冲区溢出的攻击.docx》由会员分享,可在线阅读,更多相关《基于缓冲区溢出的攻击.docx(17页珍藏版)》请在冰豆网上搜索。

基于缓冲区溢出的攻击.docx

基于缓冲区溢出的攻击

实验题目:

基于缓冲区溢出的攻击

实验目的:

1.掌握缓冲区溢出的原理;2.理解汇编语言,通过汇编语言防范缓冲区溢出的漏洞。

实验环境:

个人电脑、linux发行版本、ubuntu环境

实验内容及操作步骤:

1.开始时对于本次实验的内容并不清楚,通过查找资料了解,这个实验主要是模拟缓冲区溢出。

实验中涉及到3个可执行的二进制文件bufbomb,hex2raw,makecookie。

bufbomb是进行缓冲区实验的目标程序,既然是缓冲区溢出实验,肯定得有一个导致缓冲区溢出的条件,这个实验是通过类似于c语言中的gets函数的Gets读取一行数据到固定大小的缓冲区,而当我们的输入超过了缓冲区的大小时,Gets没有任何的边界检查,超过缓冲区的数据就会覆盖内存中用作其它用途的数据,从而改变程序的行为,而如果gets从终端读取时,无法输入一些不可打印的数据,比如想输入控制字符0x09,于是就有了hex2raw这个程序,这个程序将16进制表示的字节转换成二进制字节数据。

makecookie主要是为了防止学生直接copy别人答案用的,每个学生有一个唯一的提交作业的userid,makecookie为不同的userid计算出不同的cookie值。

userid要通过命令行参数传给bufbomb,实验中我们在内存某个区域中用自己的cookie值覆盖原来的数据,bufbomb中会有一个validate函数的调用来比对传入的cookie值与命令行传入的userid计算得出的cookie是否相等,如果相等,作业是有效的,否则作业是无效的。

 

(参考资料:

2.

因为对缓冲区溢出不了解上网查找资料。

首先要介绍函数调用过程及栈的相关操作。

我们称调用其他函数的函数为Caller,被调用的函数为Callee。

图中紫色部分为Caller的栈区,浅蓝色部分为Callee的栈区。

A和B两个函数,A调用B,那么A就是Caller,B就是Callee。

图中紫色部分即为A的栈区, A在调用B之前,需要将参数和返回地址压栈,图中“Arguments”对应的就是2(因为i=2);“Returnaddress”是函数B运行之后的返回地址,即调用函数B后执行的下一条指令,这里应当是printf("thisisfunca.\n")这条指令的地址。

浅蓝色部分是B的栈区,字符串s就在“Localvariables”中维护,因为s是函数B的局部变量。

缓冲区溢出就是说输入的s过长,长度超出了s本身的容量,覆盖掉了“Returnaddress”,导致程序不能正常执行,甚至转为执行其他命令。

3.通过函数名以及阅读buflab.pdf文件,此次试验过程类似于LAB3的拆弹过程。

在命令终端窗口查看汇编代码并进行输入等处理不方便,使用objdump–dbufbomb>2.txt将汇编代码输出到当前文件夹中一个自动生成的2.txt的文件中。

(此方法借鉴了LAB3中的方法)

4.开始“拆弹”:

(根据buflab.pdf文件提示和网上资料

Level0:

Level0是要让getbuf函数完成后直接进入smoke函数,而由实验原理可知我们只要输入44字节的无用字符再在最后输入smoke的入口地址就可以了,

运用gdb反汇编查看编代码,我们可以看到smoke的入口地址为0x08048e0a

(由于服务器系统是小端规则我们输入的顺序为0b8e0408)

注:

0a是回车,我们输入这个字符不会得到正确的结果)

建立文档lijia.txt,所以输入的字符串是:

00000000000000000000

00000000000000000000

00000000000000000000

00000000000000000000

00000000

0b8e0408

输入命令./hex2raw

结果如图:

测试通过!

在这一关中if(val==cookie)的语句在调用getbuf函数的后面,因此实际上没有用到我们的userid来计算cookie比对。

Level1:

本关要求我们进入函数fizz。

通过makecookie计算出userid的cookie值.

cookie值为4169155f。

查看fizz的代码

在这一关中通过getbuf函数输入参数val,参数val应当与cookie相同,然后传递给fizz函数。

由fizz的汇编代码可得,push%ebp之后,%esp与%ebp指向同一个位置,而此时用%ebp+8表示输入的参数。

而我们由上面fizz函数的代码可得,要使cookie值等于参数值。

在调用fizz函数后,开辟一个新的栈,此时参数位置距离fizz函数首地址还有一个空,需要用00000000来覆盖,将cookie值付给参数。

除了要将这个值用相同的方式输入到getbuf函数中返回地址处外,还应将cookie值0x1005b2b7输入到在fizz函数中fizz函数返回地址的上一个4字节处即第一个参数处。

getbuf函数输入时fizz函数的地址值和cookie值是不变的,(不能输入0a),共需要输入56(0x28+0x4+0x4+0x4+0x4)个字节,其中前44个可以任意输入.

getbuf返回地址处输入应为0x08048daf(小端法:

af8d0408)

fizz返回地址处可以随意,故输入00000000

第1个参数处为cookie值0x4169155f(小端法:

5f156941)。

所以,新建文本文档level1.txt输入以下内容:

输入命令./hex2raw

测试成功。

Level2:

bufbomb函数中有一个函数bang,其c语言代码如下:

根据bufbomb.pdf文件,本关任务是调用getbuf函数后不返回到test,而是执行bang函数,但是之前要修改global_value的值为cookie值。

而global_value是一个全局变量,全局变量没有存储在栈里面,在程序运行期间要修改全局变量的值,我们只能通过执行赋值指令方式改变global_value的值。

由以上代码可以知道如果我们想要得到正确的输出,我们就要执行global_value==cookie分支,global_value是一个全局变量,初始值为0,我们需要将它的值改为cookie值才能得到正确结果。

修改全局变量:

1.首先要我们要查到全局变量的地址:

我们需要写一个代码将全局变量赋值,然后将指令对应的字号作为我们输入的字符。

然后在命令之后的返回地址我们设置为bang的入口地址,然后填充无用字符,将最终的返回地址设为输入字符串的起始地址

运用dgb查看bang函数,其首地址为0x0804d10c

通过上面汇编代码知道global_value的地址为0x0804d10c,开始时对于0x0804d10c这个地址所存是否为global_value不确定,通过查看地址所存内容确定。

建立level2.S文件进行汇编。

将cookie值存入eax寄存器,再将global_value的地址存入ecx寄存器,cookie值存到了global_value中,通过ret调用改变eip转到bang函数中。

编译level2_lijia.s,然后通过反汇编得到汇编代码

查看level2_lijia.d文件中的汇编代码,如下:

getbuf函数执行完后的返回地址改成buf的首地址,上一个栈的4字节改成bang函数的地址,这样当在getbuf中调用ret返回时程序会跳转到buf处报告上面的指令,出现ret时会跳转到bang函数中执行。

getbuf中的buf位于栈中,我们通过gdb来查看buf的地址值,利用gdb设置断点调试:

由此可得buf运行时首地址为0x556839f8。

建立level2.txt文档输入:

B85f156941690cd104088901c3

00000000000000000000

00000000000000000000

00000000000000000000

005f156941//cookie的值

528d0408首地址

前13个字节是level2-lijia.s文件生成的汇编代码,后面的31个是无关内容的,最后的8个字节分别是cookie的值h和bang首地址,运用小端法输入

运行结果如下:

测试成功。

Level3;

返回到test,改变返回值为cookie的值.

这个实验要求程序要正常返回到test执行,并且改变返回值为cookie的值,且不能破坏test函数的栈状态。

我们在执行时要把破坏的栈恢复过来,并直接返回到test。

在getbuf返回地址中填充buf的首地址,当getbuf函数碰到返回指令ret时,将跳转到buf处执行,此时esp寄存器指向getbuf返回地址的高一个字节。

通过最后一条语句可知getbuf调用后一条指令的地址为8048e50

编写level3_lijia.s文档

movl$0x4169155f,%eax//将getbuf返回值置为cookie值

pushl$0x8048e50//将返回地址置为正确返回地址0x08048e50

ret

接下来的操作与Level2一致然后通过反编译level3_lijia.s,然后通过反汇编得到汇编代码level3_lijia.d

查看level3_lijia.d文件

查找%ebp的值

然后设值断点进行查找

可以看到%ebp的值为0x55683a50

将赋值代码的字号和找到的%ebp的值写到攻击文件相应的位置

字符串初始地址为0x556839f8)

b85f156941//mov$0x4174d6a6,%eax

68508e0408//push$0x8048e50

c3//ret

3030303030

3030303030

3030303030

3030303030

3030303030

30303030

503a6855//%ebp的值

f8396855//字符串初始地址

测试成功

Level4

本次实验中,我们给bufbomb加-n选项,main中调用testn而不是test,在testn在调用getbufn,这时栈底是不固定的,会在一定范围内变化,完成上一个实验相同的任务,但是这个实验中会调用testn五次,每次调用时栈指针都不同。

函数testn中调用getbufn时前的代码

返回地址指向testn中的getbufn调用后一条指令8048ce2.。

保存的ebp的值就是testn函数中值,当执行完ret后,通过执行 lea0x28(%esp),%ebp 恢复ebp内容 :

建立level4_lijia.o文件

编译level2_lijia.s,然后通过反汇编得,得到可执行文件和level4_lijia.s的汇编代码,如下:

由于栈空间的地址是随机分配的所以每次调用getbufn都会有一个不同的buf地址。

通过gdb工具来查看每次的buf地址

可以看到5次的buf地址分别为0x55683188,0x556837a8,0x55683888,0x55683808,0x556837f8

尽可能增大nop填充区,尽可能使有效机器代码段往后挪。

考虑将最高的buf地址0x55683888作为跳转地址,将有效机器代码置于跳转地址之前,并将其它所有字符都用作nop指令,此时所有五个buf地址的写入都能满足跳转到地址0x55683920后顺利到达有效机器代码。

(这部分内容来源于http:

//blog.youlingman.info/csapp-bufbomb-lab-solve/)”

新建文件level4.txt:

90共505个字节,即机器指令空操作nop,紧跟着15字节指令,4字节填充,也可以直接在前面用509个空指令,15字节指令后移4字节,然后是指向buf中某个字节的地址,要保证总是指向buf到15字节之间(包括边界),第520~524置为任意字符,最后为buf最大的那个地址0x55683888

(小端法输入)

输入命令catlevel4–lijia..txt|./hex2raw–n|./bufbomb–n–ulijia

测试正确。

 

收获与体会:

本次实验在读懂题意和操作过程中都有很大难度。

弄懂题主要是通过网上查找和询问同学,在操作过程很容易出现错误。

我是在一边做一边建立文档,但是建立完成后却无法打开。

在重新ls一次buflab-handout之后便可以找到新建文档。

如果删除这个文档之后,再建一个同名文档的时候,必须要删干净,回收站中也要删去。

还有注意新建文档的格式,必须加后缀名。

在.txt中输入文档的时候,经常马虎输入错误,导致实验花费了很多不必要的时间。

这次实验也加深了自己对栈的理解与掌握。

验成绩

展开阅读全文
相关资源
猜你喜欢
相关搜索

当前位置:首页 > 求职职场 > 简历

copyright@ 2008-2022 冰豆网网站版权所有

经营许可证编号:鄂ICP备2022015515号-1