$ cat writeup.md…
$ cat writeup.md…
umasscybersec
Task: a 32-bit service printed user input directly with printf and exposed two format-string sinks in a loop. Solution: leak puts from the GOT to recover libc, overwrite printf@got with system, then trigger the second sink with `cat flag.txt`.
$ cat /etc/rate-limit
Rate limit reached (20 reads/hour per IP). Showing preview only — full content returns at the next hour roll-over.
"We're using a new %format for the TPS reports. Did you get my memo?"
English summary: the service asks for an office design string and later asks whether you want to redesign. User-controlled data is printed with printf without a format string, giving a format string vulnerability that can be used to leak libc and overwrite the GOT.
Service:
nc brick-city-office-space.pwn.ctf.umasscybersec.org 45001
The binary is a 32-bit ELF (i386), dynamically linked, and not stripped.
checksec showed:
RELRO: No RELRO Stack: No canary found NX: NX enabled PIE: No PIE
These properties are ideal for a classic GOT overwrite:
Important addresses from the binary:
vuln = 0x80491d6 main = 0x80493db puts@got = 0x804bbbc printf@got = 0x804bbb0
Important offsets from the provided libc.so.6:
puts = 0x732a0 system = 0x48170
The stack offset for our format string was 4. A probe such as AAAA.%1$p.%2$p.%3$p.%4$p revealed 0x41414141 at %4$p, so attacker-controlled bytes placed at the start of the input are read as the 4th format argument.
The real bug is a format string vulnerability: user input is passed directly to printf.
There are two useful printf(user_input) paths inside vuln():
y or n, it enters a This is what you said: branch and prints that invalid response with printf(buffer).That gives two separate stages in one execution:
...
$ grep --similar