发信人: 3509(〖~@~〗) 
整理人: starseacn(2002-01-17 16:47:11), 站内信件
 | 
 
 
声明:文中的大部分演示程序来自qera [email protected],感谢qera为  
 我们精心构造这些很能说明的演示程序。  
 
 有些程序可能有不只一种的利用方法,而文中又没有提到的。如果您有好的idea,记得mail to <href="mailto:[email protected]">mailto:[email protected]
 ,不正确或者不当之处还请斧正。  
 
 ★★ 一 高级缓冲区溢出篇  
 
 ★ 1.1 演示一----盲目服从(blind obedience)  
 
 定义的buf太小,需要copy的数据不足以容纳下。  
 
 
 /* abo1.c                          *  
 * specially crafted to feed your brain by [email protected] */  
 
 /* Dumb example to let you get introduced...        */  
 
 int main(int argc,char **argv) {  
   char buf[256];  
 
   strcpy(buf,argv[1]);  
 }  
 
 
 这是个很好的例子程序,很能说明问题:该程序将拷贝argv[1]到buf中,使用了strcpy函数,没有做任何的边界检查。这就给了我们一个机会,传一个超长的argv[1]进去,覆盖到堆栈中buf后面的数据。你需要利用所有的工具来查看 buf后面到底是什么重要的东西,然后才能构造出那些exploit需要的摸板。  
 
 
 ★ 1.2 演示二----执行流程(execution flow)  
 
 在来看看这个程序  
 
 /* abo2.c                          *  
 * specially crafted to feed your brain by [email protected] */  
 
 /* This is a tricky example to make you think        *  
 * and give you some help on the next one          */  
 
 int main(int argv,char **argc) {  
   char buf[256];  
 
   strcpy(buf,argc[1]);  
   exit(1);  
 }  
 
 
 
 正如我们看的那样,在这个例子中,加了个exit(). 发现了不同了吗?一般利用覆盖main的返回地址的方法已经行不通了。在这个例子中,windows下利用windows的异常机制可以成功的溢出这个程序,而在unix下就没有这种特性,暂时还不知道如何溢出这个程序?或者就根本不能利用。欢迎讨论,请mail to <href="mailto:[email protected]">mailto:[email protected];) 
 
 
 ★ 1.3 演示三----覆盖函数指针  
 
 
 /* abo3.c                          *  
 * specially crafted to feed your brain by [email protected] */  
 
 /* This'll prepare you for The Next Step           */  
 
 int main(int argv,char **argc) {  
   extern system,puts;  
   void (*fn)(char*)=(void(*)(char*))&system;  
   char buf[256];  
 
   fn=(void(*)(char*))&puts;  
   strcpy(buf,argc[1]);  
   fn(argc[2]);  
   exit(1);  
 }  
 
 
 可利用缓冲区溢出覆盖fn函数指针,达到攻击目的。  
 
 
 ★ 1.4 演示四----覆盖指针,导致任意地址的覆盖  
 
 /* abo4.c                          *  
 * specially crafted to feed your brain by [email protected] */  
 
 /* After this one, the next is just an Eureka! away     */  
 
 extern system,puts;  
 void (*fn)(char*)=(void(*)(char*))&system;  
 
 int main(int argv,char **argc) {  
   char *pbuf=malloc(strlen(argc[2])+1);  
   char buf[256];  
 
   fn=(void(*)(char*))&puts;  
   strcpy(buf,argc[1]);  
   strcpy(pbuf,argc[2]);  
   fn(argc[3]);  
   while(1);  
 }  
 
 第一个strcpy时候,可覆盖到pbuf指针,可使pbuf指向fn地址,所以第二次  
 strcpy的时候就会覆盖到fn指针,结果运行fn()函数的时候就可以执行任意  
 函数调用,比如system();  
 
 
 
 ★ 1.5 演示五----ch-ch-ch-changes  
 
 
 /* abo5.c                          *  
 * specially crafted to feed your brain by [email protected] */  
 
 /* You take the blue pill, you wake up in your bed,     *  
 *   and you believe what you want to believe       *  
 * You take the red pill,                  *  
 *   and I'll show you how deep goes the rabbit hole    */  
 
 int main(int argv,char **argc) {  
   char *pbuf=malloc(strlen(argc[2])+1);  
   char buf[256];  
 
   strcpy(buf,argc[1]);  
   for (;*pbuf++=*(argc[2]++););  
   exit(1);  
 }  
 
 
 第一个strcpy时候,可覆盖到pbuf指针,可使pbuf指向exit的GOT或者.dotrs地址+4, 从而可以覆盖到那些部分,获得控制权。  
 
 
 ★ 1.6 演示六  
 
 /* abo6.c                          *  
 /* specially crafted to feed your brain by [email protected] */  
 
 /* wwwhat'u talkin' about? */  
 
 int main(int argv,char **argc) {  
   char *pbuf=malloc(strlen(argc[2])+1);  
   char buf[256];  
 
   strcpy(buf,argc[1]);  
   strcpy(pbuf,argc[2]);  
   while(1);  
 }  
 
 第一个strcpy时候,可覆盖到pbuf指针,可使pbuf指向第二个strcpy函数的返回地址,从而可以覆盖到该地址,第二个strcpy一返回就可以获得控制权。  
 
 
 ★ 1.7 演示七  
 
 /* abo7.c                          *  
 * specially crafted to feed your brain by [email protected] */  
 
 /* sometimes you can,    *  
 * sometimes you don't   *  
 * that's what life's about */  
 
 char buf[256]={1};  
 
 int main(int argv,char **argc) {  
   strcpy(buf,argc[1]);  
 }  
 [alert7@redhat]$ gcc -o test test.c -g  
 [alert7@redhat]$ gdb test -q  
 (gdb) l  
 1    char buf[256]={1};  
 2  
 3    int main(int argv,char **argc) {  
 4        strcpy(buf,argc[1]);  
 5    }  
 (gdb) b 4  
 Breakpoint 1 at 0x80483cb: file test.c, line 4.  
 (gdb) r 999  
 The program being debugged has been started already.  
 Start it from the beginning? (y or n) y  
 Starting program: /home/alert7/test 999  
 
 Breakpoint 1, main (argv=2, argc=0xbffffbc4) at test.c:4  
 4        strcpy(buf,argc[1]);  
 (gdb) p &buf  
 $1 = (char (*)[256]) 0x8049460  
 
 buf的地址为0x8049460,也就是说如果0x8049460地址后有什么重要的话我们  
 可以得到控制权的数据的话,那么我们就可以溢出成功。在这里:  
 [alert7@redhat]$ objdump -s -j .dtors test  
 
 test:   file format elf32-i386  
 
 Contents of section .dtors:  
 804956c ffffffff 00000000          ........  
 我们可以覆盖.dtors,达到获得控制权的目的。  
 
 
 ★ 1.8 演示八  
 
 Don't stay static  
 
 
 /* abo8.c                          *  
 * specially crafted to feed your brain by [email protected] */  
 
 /* spot the difference */  
 
 
 
 char buf[256];  
 
 int main(int argv,char **argc) {  
   strcpy(buf,argc[1]);  
 }  
 
 
 [alert7@redhat]$ gcc -o test test.c -g  
 [alert7@redhat]$ objdump --dynamic-reloc test  
 
 test:   file format elf32-i386  
 
 DYNAMIC RELOCATION RECORDS  
 OFFSET  TYPE       VALUE  
 0804947c R_386_GLOB_DAT  __gmon_start__  
 0804946c R_386_JUMP_SLOT  __register_frame_info  
 08049470 R_386_JUMP_SLOT  __deregister_frame_info  
 08049474 R_386_JUMP_SLOT  __libc_start_main  
 08049478 R_386_JUMP_SLOT  strcpy  
 [alert7@redhat]$ gdb test -q  
 (gdb) l  
 1  
 2    char buf[256];  
 3  
 4    int main(int argv,char **argc) {  
 5        strcpy(buf,argc[1]);  
 6    }  
 7  
 (gdb) b 5  
 Breakpoint 1 at 0x80483cb: file test.c, line 5.  
 (gdb) r 11  
 Starting program: /home/alert7/test 11  
 
 Breakpoint 1, main (argv=2, argc=0xbffffbc4) at test.c:5  
 5        strcpy(buf,argc[1]);  
 (gdb) p & buf  
 $1 = (char (*)[256]) 0x8049540  
 (gdb) q  
 The program is running. Exit anyway? (y or n) y  
 [alert7@redhat]$ objdump -s -j .dtors test  
 
 test:   file format elf32-i386  
 
 Contents of section .dtors:  
 8049458 ffffffff 00000000          ........  
 [alert7@redhat]$ gcc -o test test.c -g -static  
 [alert7@redhat]$ gdb test -q  
 (gdb) l  
 1  
 2    char buf[256];  
 3  
 4    int main(int argv,char **argc) {  
 5        strcpy(buf,argc[1]);  
 6    }  
 7  
 (gdb) b 5  
 Breakpoint 1 at 0x804819b: file test.c, line 5.  
 (gdb) r 11  
 Starting program: /home/alert7/test 11  
 
 Breakpoint 1, main (argv=2, argc=0xbffffc14) at test.c:5  
 5        strcpy(buf,argc[1]);  
 (gdb) p &buf  
 $1 = (char (*)[256]) 0x807bb60  
 (gdb) p __exit_funcs  
 $2 = (struct exit_function_list *) 0x807b160  
 [alert7@redhat62 alert7]$ objdump -s -j .dtors test  
 
 test:   file format elf32-i386  
 
 Contents of section .dtors:  
 807b100 ffffffff 00000000          ........  
 buf的地址都比其他的地址要大,所以覆盖不到他们。  
 这个例子还不知道如何得到控制权呢?用超长字符串覆盖main函数的  
 返回地址是不现实的,并且在还没有覆盖到main函数返回地址之前就会  
 Segmentation fault,原因是访问了一个没有映射的地址(地址  
 映射是不连续的) 。  
 这个演示程序让我郁闷了好久,在我的linux上还真的无法成功溢出这个  
 程序,还是qera又一次专门为windows设计的!?(如果您有好的idea,  
 记得mail to <href="mailto:[email protected]">mailto:[email protected]
 ,在windows下成功溢出这个演示程序是没有问题的。  
 
 
 ★ 1.9 演示九----两次free技术  
 
 /* abo9.c                         *  
 * specially crafted to feed your brain by [email protected] */  
 
 /* free(your mind) */  
 
 /* I'm not sure in what operating systems it can be done */  
 
 int main(int argv,char **argc) {  
   char *pbuf1=(char*)malloc(256);  
   char *pbuf2=(char*)malloc(256);  
 
   gets(pbuf1);  
   free(pbuf2);  
   free(pbuf1);  
 }  
 请参考<<一种新的Heap区溢出技术分析>>  
 那片文章上已经讲的很明白了,不想多说:)  
 
 ★ 1.10 演示十----一次free技术  
 
 /* abo10.c                         *  
 * specially crafted to feed your brain by [email protected] */  
 
 /* Deja-vu*/  
 
 char buf[256];  
 
 int main(int argv,char **argc) {  
   char *pbuf=(char*)malloc(256);  
 
   gets(buf);  
   free(pbuf);  
 }  
 [alert7@redhat]$ gcc -o test test.c -g  
 /tmp/ccO6gW96.o: In function `main':  
 /home/alert7/test.c:6: the `gets' function is dangerous and should not be used.  
 [alert7@redhat]$ gdb test -q  
 (gdb) l  
 1    char buf[256];  
 2  
 3    int main(int argv,char **argc) {  
 4        char *pbuf=(char*)malloc(256);  
 5  
 6        gets(buf);  
 7        free(pbuf);  
 8    }  
 (gdb) b 6  
 Breakpoint 1 at 0x8048440: file test.c, line 6.  
 (gdb) r  
 Starting program: /home/alert7/test  
 
 Breakpoint 1, main (argv=1, argc=0xbffffbc4) at test.c:6  
 6        gets(buf);  
 (gdb) p &buf  
 $1 = (char (*)[256]) 0x80495c0  
 (gdb) p pbuf  
 $2 = 0x80496c8 ""  
 可覆盖到pbuf的chunk块,利用一次free技术也可覆盖到.dotrs,main的返回地址等等。  
 演示九和演示十都是由于缓冲区溢出而导致的内存管理函数处理出错,从而利用内存管理函数中的写操作,覆盖到自己想要覆盖的任何地址空间。  
 
   
 mail to<href="mailto:[email protected]">mailto:[email protected]
 
 
  ---- r-Wu#show processes cpu
 CPU utilization for five seconds: 1%/1%; one minute: 1%; five minutes: 2%
  PID Runtime(ms)   Invoked      uSecs   5Sec   1Min   5Min TTY Process 
    1         112     38427          2  0.00%  0.00%  0.00%   0 Load Meter       
    2         320       123       2601  0.16%  0.35%  0.09% 130 Virtual Exec     
    3           0      1602          0  0.00%  0.00%  0.00%   0 DHCPD Timer      
    4       57296     19523       2934  0.00%  0.02%  0.00%   0 Check heaps      
    5           0         1          0  0.00%  0.00%  0.00%   0 Chunk Manager    
    6          36        66        545  0.00%  0.00%  0.00%   0 Pool Manager     
    7           0         2          0  0.00%  0.00%  0.00%   0 Timers           
    8           0         2          0  0.00%  0.00%  0.00%   0 Serial Backgroun 
    9          96     38400          2  0.00%  0.00%  0.00%   0 ALARM_TRIGGER_SC 
   10           0         1          0  0.00%  0.00%  0.00%   0 OIR Handler      
  | 
 
 
 |