$ cat writeup.md…
$ cat writeup.md…
metactf
Task: a remote binary reads one line with fgets() and passes it directly to printf(), creating a format string bug in front of a final puts() call. Solution: place puts@GOT on the stack, use %8$hn to write the low two bytes of win(), and let the next puts() jump into the flag-printing routine.
$ cat /etc/rate-limit
Rate limit reached (20 reads/hour per IP). Showing preview only — full content returns at the next hour roll-over.
A server at nc.umbccd.net:8925 reads input with fgets into a 128-byte buffer and then calls printf(buffer), followed by puts("\nGoodbye!"). The provided source also contains a win() function that opens flag.txt and prints it.
We are given a small 64-bit ELF source and a remote service running it. The objective is to turn the unsafe printf(buffer) into code execution and redirect the program into win(), which prints the flag and exits.
The bug is a classic format string vulnerability:
fgets(buffer, sizeof(buffer), stdin); printf(buffer); puts("\nGoodbye!");
Because our input becomes the format string itself, we control both reads from the stack (%p, %x, positional arguments) and writes through %n-style specifiers. That makes the immediately following puts() call the perfect control-flow target: if we overwrite puts@GOT with win, the next call transfers execution straight into the flag routine.
The useful addresses were:
puts@got = 0x404000win = 0x401196Only the low 16 bits needed to change. Writing 0x1196 into puts@GOT with %hn was enough because the higher bytes already matched the same binary/PLT region.
The key reconnaissance step was finding where an appended pointer appears in printf's argument list. By padding the format string portion to 16 bytes and then appending an 8-byte address, the controlled qword became reachable as positional argument 8.
That gives a stable primitive of the form:
%<count>c%8$hn + <8-byte destination address>
Since win = 0x401196, we need printf to have emitted 0x1196 = 4502 characters before %8$hn executes. Therefore the final write count is produced with %4502c.
...
$ grep --similar