系统级编程-lab5_第1页
系统级编程-lab5_第2页
系统级编程-lab5_第3页
系统级编程-lab5_第4页
系统级编程-lab5_第5页
已阅读5页,还剩2页未读 继续免费阅读

下载本文档

版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领

文档简介

1、Practice1 上周做了,复制过来。前面得key1=3、key2=777下面我们继续往后面看代码,并且通过提示我们了解到我们需要想办法使程序进入并执行msg2 = extract_message2(start, stride);但是从正常的程序逻辑上看,我们无法使msg1为空而顺利进入到条件码中。那么我们需要考虑应该在process_keys34中做出调整。我们能否在执行完process_keys34后偷偷的改变msg1的值呢?在看了这段函数的代码后,我们发现这个函数中两个变量的范围相差太大了,一个是全局变量message(msg1的实际指向),一个是局部变量key3。那么我们需要换一个思

2、路,能否让函数在返回的时候直接跳转到目标代码呢?如果要这么做,我们就需要修改程序在运行过程中的栈帧结构中的存储数据了。现在让我们来分析一下程序在调用process_keys34之前的栈帧结构:从汇编码中我们可以看到在调用之前整个栈帧结构中数据的存储细节。首先是将参数key3、key4压入栈中保存,然后在传入这些参数。然而这些参数的传递都是传地址的,所以我们在process_keys34中可以通过&key3的相对定位来改动调用者的栈帧数据。在这之前让我们来想想调用时的栈帧结构:我们可以看到,如果我们能够修改返回地址使它返回到我们期望的位置就可以了。那么我们现在需要确定这个返回地址相对于k

3、ey3的距离是多少,通过图我们可以看到这个地址就在key3的下面,只需要在key3基础上减一(这个减一是在int下的,实际上在地址层面应该是-4)就好了。所以我们得到了key3的值-1.另外我们需要感谢出题者,他一直给我们提供充足的相对数据。在这里我们只需要在原返回地址上面加上一个合适的值就好了。从上图中,我们可以看到原先的返回地址和我们需要抵达的返回地址0040138e是原先保存在栈帧中的返回地址,而我们期望程序返回时直接到达0x004013bb。这样我们就得到了key4的具体值:Key4=(0x004013bb-0040138e)/4=45。所以key1234分别就是 3 777 -1 4

4、5。Practice200951850 push ebp将ebp压入栈顶位置。EIP跳到00951851。栈顶ESP变为0091FD6800951851 movebp,esp将ESP的值赋值给EBP,栈底EBP变为0091FD6800951853 sub esp,0D8h将ESP的值减小0D8h,变为00D2FBF800951859 push ebx0095185A push esi0095185B push edi将当前的EBX,ESI,EDI值逐个压入到栈里。得到ESP为00D2FBECMain()0095185C lea edi,ebp-0D8hEDI=EBP-0D8h为与栈底相隔0D8

5、hbytes的位置00951862 mov ecx,36h将ECX赋值为36h.00951867 mov eax,0CCCCCCCCh将EAX赋值为0CCCCCCCCh0095186C rep stosdwordptres:edi从EDI的位置开始赋值,每次EDI+4,ECX-1,直到ECX为0为止。执行完后EDI=00D2FCD0、EFL=000002120095186E movdwordptr a,1将1赋值给a的位置00951875 movdwordptr b,2将2赋值给b的位置0095187C moveax,dwordptr b将(b位置中的)2赋值给EAX=000000020095

6、187F push eax将EAX放入栈中, ESP变为00D2FBE800951880 movecx,dwordptr a将(a位置中的)1赋值给ECX=0000000100951883 push ecx将ecx压入栈顶,ESP变为00D2FBE400951884 call swap1 (0951307h)执行swap1函数00951889 add esp,8ESP加8,ESP变为00D2FBEC0095188C moveax,dwordptr b将(b位置中的)2赋值给EAX=000000020095188F push eax将eax压入栈顶,esp变为00D2FBE800951890 m

7、ovecx,dwordptr a将(a位置中的)1赋值给ECX=0000000100951893 push ecx将ecx压入栈顶,esp变为00D2FBE400951894 push 956B30h00951899 call _printf (0951325h)调用printf()函数EAX = 00000015 EBX = 7ED8F000 ECX = 0D0AE50D EDX = 5447181C ESI = 00951046 EDI = 00D2FCD0 EIP

8、60;= 0095189E ESP = 00D2FBE0 EBP = 00D2FCD0 EFL = 000002440095189E add esp,0Ch栈顶ESP置为ESP+0Ch,清除之前放入的形参009518A1 lea eax,bEax = b(00D2FCBC)009518A4 push eax将eax压入栈顶,esp变为00D2FBE8009518A5 lea ecx,aEcx=a(00D2FCC8)009518A8 push ecx将ecx压入栈顶,esp变为00D2FBE4009518A9 call swa

9、p2 (0951339h) 跳转执行swap2函数009518AE add esp,8 栈顶ESP置为ESP+8,清除之前放入的形参009518B1 moveax,dwordptr b将(b位置中的)1赋值给EAX=00000001009518B4 push eax将eax压入栈顶,esp变为00D2FBE8009518B5 movecx,dwordptr a将(a位置中的)2赋值给ECX=00000002009518B8 push ecx将ecx压入栈顶,esp变为00D2FBE4009518B9 push 956B30h 009518BE call _printf (0951325h)调用

10、printf()函数EAX = 00000015 EBX = 7ED8F000 ECX = 0D0AE50D EDX = 5447181C ESI = 00951046 EDI = 00D2FCD0 EIP = 009518C3 ESP = 00D2FBE0 EBP = 00D2FCD0 EFL = 00000244009518C3 add esp,0Ch栈顶ESP置为ESP+0Ch,清除之前放入

11、的形参009518D7 pop eax009518D8 pop edx009518D9 pop edi009518DA pop esi009518DB pop ebx栈压出EDI,ESI,EBX以前的值放入EDI,ESI,EBX中009518DC add esp,0D8h ESP = ESP+0D8h 009518E2 cmpebp,esp比较EBP和ESP009518E4 call _RTC_CheckEsp (0951113h)检查函数有没有出错009518E9 movesp,ebpESP = EBP009518EB pop ebpEBP = 栈顶压出的值009518EC ret跳转执行栈

12、顶压出的值指向的代码Practice3  题目中已经说了,“分析这个程序,可以得知,正常情况下,这个函数会在getbuf中,调入getxs函数读入数字对,然后不管任何情况下,都会对test函数返回0x1,”那我们该怎么办了?我们马上可以想到在getbuf这个函数里定义的char buf16上做手脚,可以看到在getxs函数里的while循环,结束条件只是以回车或者是eof结束符为判断标准,所以,根本没对char输入的数量做判断!这样的话,我们可以输入多于16个的数,从而缓冲区溢出!   在这里还是提一下帧栈结构,如下:+-+高地址|函数参数 n 个 &#

13、160;   |+-+|函数参数第 n-1 个   |+-+|     .     |     .      |     .     |+-+|函数参数第1个    |+-+|return 返回地址  

14、0;  |+-+|ebp指针入栈      | +-+|local var(局部变量)   |+-+|        others |+-+低地址   按照上面说的函数栈的存放情况,在getbuf这个函数里,函数参数没有,我们不管,然后就是return返回地址,然后就是ebp指针,然后就是char buf16。+-+低地址|return 返回地址  

15、;    |+-+|ebp指针入栈       | +-+|    buf15     |+-+|    buf14      |+-+      :      :    

16、0; :+-+|     buf0     |+-+|    others |+-+高地址  如果我们对buf溢出,能改写ebp和return地址!下面看看,ebp是多少,return地址是多少。  要知道这里的%ebp存的是test函数的%ebp,因而我们在调试的时候就可以在test函数得到%ebp的值,它应该是我们写入的buf16-buf19的值,而且它要保持原来的值,不然返回之后就乱套了,在我机器上是0x0040100f。这个很容易,解决了第一步。

17、下面我们再来看返回地址,先看一段汇编码(不同的机器有所不同):   在getbuf()返回后,肯定会接着执行0040126a,我们能让它从这执行吗?当然不行!不然就要push eax,那是我们不想看到的,因为eax的值就是1。因而我们会想到能不能跳过这?当然能,改返回地址啊!顺水推舟,我们通过buf数组来覆盖返回地址。此时,我们想要它直接跳到00401271处,因而可以通过设置buf19-buf22的值来覆盖返回地址。  到了考虑如何加进deadbeef了,在返回后,将直接执行push  offset string "getbuf returned 0x%xn" (0042301c),没eax怎么行了?不然printf函数就少了参数。再回到帧栈结构一下,printf在调用之前,要压入参数,先压入val,再压入offset string "getbuf returned 0x%xn",也就是说参数val(等同那个eax)在offset string "getbuf returned 0x%xn“之上,而且紧挨着。此时我们可以想到,既然返回之后(返回地址及其以下的元素都已弹出,返回地址的上一个字节成了栈顶)就执行push  offset s

温馨提示

  • 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
  • 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
  • 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
  • 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
  • 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
  • 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
  • 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。

评论

0/150

提交评论