ImageVerifierCode 换一换
格式:DOCX , 页数:12 ,大小:418.56KB ,
资源ID:3545298      下载积分:3 金币
快捷下载
登录下载
邮箱/手机:
温馨提示:
快捷下载时,用户名和密码都是您填写的邮箱或者手机号,方便查询和重复下载(系统自动生成)。 如填写123,账号就是123,密码也是123。
特别说明:
请自助下载,系统不会自动发送文件的哦; 如果您已付费,想二次下载,请登录后访问:我的下载记录
支付方式: 支付宝    微信支付   
验证码:   换一换

加入VIP,免费下载
 

温馨提示:由于个人手机设置不同,如果发现不能下载,请复制以下地址【https://www.bdocx.com/down/3545298.html】到电脑端继续下载(重复下载不扣费)。

已注册用户请登录:
账号:
密码:
验证码:   换一换
  忘记密码?
三方登录: 微信登录   QQ登录  

下载须知

1: 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。
2: 试题试卷类文档,如果标题没有明确说明有答案则都视为没有答案,请知晓。
3: 文件的所有权益归上传用户所有。
4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
5. 本站仅提供交流平台,并不能对任何下载内容负责。
6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。

版权提示 | 免责声明

本文(Bufbomb内存炸弹.docx)为本站会员(b****5)主动上传,冰豆网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对上载内容本身不做任何修改或编辑。 若此文所含内容侵犯了您的版权或隐私,请立即通知冰豆网(发送邮件至service@bdocx.com或直接QQ联系客服),我们立即给予删除!

Bufbomb内存炸弹.docx

1、Bufbomb内存炸弹what process_keys34 does:首先来看接下来的代码,显然可以看出来,我们要让程序进入并执行 msg2 = extract_message2(start, stride);也就是下面的第二个if循环:那么可以考虑能不能让msg1=0,很显然,第一个循环里process_key34函数不可能直接来改变msg1的值,message是全局变量( msg1的实际指向),key3是局部变量,而且,是在执行了process_key34函数之后才执行msg1赋值的,那么要保证执行第二个if语句,也可以考虑能否让process_key34函数在返回的时候直接跳转到目标代

2、码呢?如果要这么做,我们就需要修改程序在运行过程中的栈帧结构中的存储数据了。现在让我们来分析一下程序在调用 process_keys34之前的栈帧结构:从汇编码中我们可以看到在调用之前整个栈帧结构中数据的存储细节:首先是将参数 key3、 key4压入栈中保存,然后再传入这些参数(实际上是传递地址)。所以可以在 process_keys34中可以通过&key3的相对定位来改动调用者的栈帧数据。来看看调用时的栈帧结构: 很显然key3下面就是返回地址,在地址上ret=&key3-1(这里减1就是地址上减4,因为int型占4字节)。那么key3就求出来了,key3 = -1,接下来就是通过地址相差

3、的值求key4了,还是看下汇编语言吧:原函数执行完后返回地址为第一行也就是:0040138E,我们想要它变成的返回地址为最后一行也就是004013BB,从process_keys34函数(*(int *)&key3) + *key3) += *key4;)可以看出:原值加上key4的值就是修改后的值,那么key4 = 0x004013BB 0x0040138E = 0x2D,转化为十进制就是45,即key4 = 45.describing the line of source code that is executed when the first call to process_keys34

4、 returns.解析过程上面已经说过,第一次调用process_keys34函数后,将返回到上面截图中的最后一行代码msg2 = extract_message2(start, stride)中执行。(原因见上一小题解析)。The meaning of the third and fourth keys in terms of variables and addresses in the decoder program.详细解析上面解释了。-Swap开始-NextNext- 在调用swap1函数时,调用函数将形参b、a的值压入栈中,然后再调用函数。在进入被调用函数时,会自动保存返回的地址,即

5、地址 0x00401413。这个可以通过esp的改变看出,进入函数时,esp改变小,说明栈压入了新的值,而根据这个值我们可以看到,它是一个地址,而这个地址正是我们的返回地址:0x00401413。压入旧的ebp,esp减小。主要是为了保存主函数的ebp,在被调用函数返回时可以找到它将esp的值赋给ebp由于被调用函数和调用函数的分配空间是紧邻的,所以调用函数的栈顶就是被调用函数的栈底给被调用函数分配44h大小的空间(这个空间大小是随机的),esp变为:0012fea0将x的值赋给temp,我们可以观察temp的地址,它是在esp和edp之间的某个地址,也就是当前帧栈的某个空间。调用函数结束,做

6、一些例行操作之后,将ebp的值赋给esp,即将栈底改为栈顶,为回到调用函数做准备。之后压出一个值,将这个值赋给ebp,还记得调用时压入的那个旧的ebp吗?就是将这个值还原给ebp。现在要做的就是回到以前的执行地址也就是最开始保存的返回地址0x00401413,而ret就是这个作用。sp和ebp都回到了被调用前的值我们可以看到,调用swap1后,a、b的值并没有交换,跟据上面的分析可以知道,其实主函数中的a,b与swap1中的a,b其实是不同的,他们分别保存在不同的地址,所以主函数中a、b的值并不会被调换。现在我们开始来看调用swap2的过程。前期准备和后期处理都一样这里不再赘述。但swap2中

7、压入的是变量b和a的地址。现在进入被调用函数swap2。同样的分配44h的空间,同样的改变esp和ebp。对比swap1和swap2的汇编代码会发现不同之处,swap2是通过地址的方式来改变变量的值,而这个地址和主函数中a、b的地址相同,所以这个地址里面的值已经被改变。所以当swap2结束后,变量a、b的值已经交换。个人总结:函数调用都会在栈中形成独立的栈帧,值传递的函数中,形参会在被调用函数中声明,但它的生存期也就仅仅存在于调用函数的生存期,而地址传递引用的是相同的地址空间。-Bufbomb理解题目意思:看源程序可以发现,好像无论输入什么数据,其返回结果都是1,因为在getbuf()函数中最

8、后一行就是return 1,也就是函数按照正常来说会返回1,所以理论上无论输入是什么打印出来的都是0x1。看起来要达到预期目标:让程序返回0xdeadbeef。我们首先想到的方法肯定是把return语句改成return deadbeef,但是不允许修改源码,所以仔细分析程序的编译、链接、执行的过程即可知道,我们又有一个思路了:由函数栈帧调用过程可以知道,过程调用时要将参数和返回地址压入栈中,然后进入被调过程执行,待从被调过程返回时,弹出返回地址,将该地址存入%eip寄存器,并转到该地址开始执行。入栈和出栈均是对%esp指向的内存操作,其基地址为%ebp。假设,如果我们输入的是机器码,存放于该缓

9、冲区中,注意到程序中的缓冲区只有16字节,利用缓冲区溢出,将本应存放test调用getbuf的返回地址的内存单元修改为存放可执行的机器码的地址,而这个地址就是我们的缓冲区地址,那么在调用完getbuf后会返回到缓冲区地址处执行我们输入的机器码,在机器码中让程序输出oxdeadbeef,并正确返回继续执行。这样会不会达到目标?直白一点说吧:简单来讲,就是输入的时候会超过16字节(缓冲区大小),输入内容覆盖掉ebp(test程序调用getbuf后会把自己的ebp压入栈)与返回地址(getbuf的返回地址)。想法是将存放test调用getbuf的返回地址的内存单元的内容修改为buf缓冲区的地址。在缓

10、冲区执行代码:第一、给eax寄存器赋值deadbeef,也就是更改返回值;第二、实现ret语句,这一句的作用是保证程序正常运行,不会报错,但是在这之前我们已经改变了返回值!在编译之前我们来看下test调用getbuf的栈帧结构:栈底部-高地址 = Main函数的栈帧部分 =Test函数栈帧基址ebp 1 - Test函数栈帧基址 - +4 retAddr(实际上就是test函数中printf语句地址) =Getbuf函数栈帧基址 ebp- ebp 1(作用是保存test函数基址) - Getbuf函数的栈帧 | Buf | | Bufaddr -Getbuf的栈顶esp - retAddr1

11、getbuf返回地址 = Getxs的栈帧 =地地址 栈顶 -(基本的注明上面都已经标出来了,就说下=是栈帧分隔线)分析:我们输入的数据存放在buf指向的一段内存中,且数据由低地址到高地址存放(图中向上箭头所示)。如果输入的数据不覆盖ebp+4指向的内存,即buf不溢出,getbuf将永远返回1。如果输入的数据覆盖ebp+4指向的内存呢?也就是覆盖retAddr,但考虑到程序正常运行,不能覆盖ebp指向的内存(意思是可以覆盖,只要不改变值就行),即其中的ebp1不能被修改,如果被修改,程序将不能正确返回出现错误。如果ebp+4指向的内存被修改为新地址,即retAddr被覆盖而存入新地址,则te

12、st调用getbuf后将返回到新地址中执行,这个新地址就可以存放一段可执行的代码,做一些我们想要发生的事了!。接下来要考虑,从程序来看,新地址只有可能是buf了(16字节长)。如果新填入ebp+4的新地址是buf缓冲区的起始地址,而且地址中已经输入了一些我们想要执行的代码,嘿嘿,接下来就有戏了!即test调用getbuf后将返回到buf的起始地址处执行我们想要执行的代码,并且“正常”返回,嘿嘿。分析完之后我们就可以确定输入了:可执行机器码Ebp1新地址好了,可以解释下了:其中ebp1必须还是存放在ebp指向的内存中,这样才能保证程序不会出错,新地址存放在%ebp+4指向的内存中,而且新地址=b

13、uf的地址。还有就是输入数据的长度:16B+4B+4B(我们期望执行的机器码不够16字节就补0)。目标明确后就开始找值了,首先得确定机器码,到底是啥?首先,我们应该确定可执行机器码的功能:让程序返回0xdeadbeef返回到%ebp+4指向的返回地址retAddr处继续执行。我们看下源程序的返回:我们要写改的是36下面那条语句,我们要执行的返回语句写成汇编语句就是:Mov eax,0xdeadbeef第一点完成了,第二点,要返回到%ebp+4指向的返回地址retAddr处继续执行,看下test函数对应的汇编代码:可以看出,实际上返回地址就是44那条printf语句,也就是0040126A(上面

14、那条汇编代码)所以昨晚第一步我们只要让程序返回到0040126A继续执行就ok了,就是要将该地址压入栈中,当遇到ret指令时,再将retAddr=0x0040126A从栈中弹出,并跳转到0x0040126A处继续执行,就能保证程序正确返回到test中,并继续执行。而从getbuf中返回时,返回值在eax中,其值就是0xdeadbeef。保证机器码执行后返回到retAddr=0x0040126A处继续执行的机器码对应的汇编代码为:Push 0x0040126ARet到此为止,我们已经得到了想要执行的汇编代码,转化为机器码就行了,至于怎么变为机器码VC反汇编里直接可以看到:Mov eax,0xde

15、adbeefPush 0x0040126ARet -转化为机器码- b8 ef be ad de 68 6A 12 40 00 C3 00 00 00 00 00(补齐16字节)接下来就是确定ebp1和buf地址了:我们在getbuf函数入口设一个端点:也就是当程序执行到text函数将要调用getbuf函数时看下ebp值:0018FEAC从下图也可以看到,调用getbuf函数时首先会保存text函数的基址:从第一句就可以看到,push ebp(保存text栈帧基址),此时ebp寄存器的只看下就知道了:0018FEAC,所以很显然我们得到了ebp1的值了,接下来最后一步,看buf的地址了:Buf地址为0018FE44。到此为止,我们已得到了全部要输入的内容:b8 ef be ad de 68 6A 12 40 00 C3 00 00 00 00 000x0018FEAC0x0018FE44考虑到后面两个地址在计算机中是按小端存储的,所以我们的最终输入信息为:b8 ef be ad de 68 6A 12 40 00 C3 00 00 00 00 00 AC FE 18 00 44 FE 18 00程序运行结果截图如下:Wonderful!

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

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