rapid1337.com

Format Strings — The Bug That Writes Anywhere

2026-07-04 · [ security ] · by staff · C

printf(user_input) is not a typo — it's an arbitrary read/write primitive.

<-- newest | [ Security ]

[ read in diskmag ]


The mistake looks harmless:

printf(user_input);        // should have been printf("%s", user_input)

If user_input reaches the format argument, the attacker controls the format string — and printf will happily walk the stack for conversions that were never supplied.

Read

Feed it %p %p %p %p and each specifier pops the next stack slot, leaking pointers, canaries, and saved return addresses. %s dereferences a slot as a char *, so with a controlled pointer on the stack you get an arbitrary read.

Write

%n writes the number of bytes printed so far to the pointed-at address. Pair it with width specifiers to set the count precisely and you have an arbitrary 4-byte write — enough to overwrite a GOT entry, a return address, or a function pointer. %hn / %hhn narrow it to 2 or 1 bytes for surgical edits.

Why it still matters

Modern -Wformat-security and FORTIFY catch the obvious cases, but they only fire when the compiler can see the literal. Wrap the call behind a logging helper, or build the format string at runtime, and the check goes quiet while the primitive stays live.

Rule of thumb: the format string is code. Never let the user supply it.

More PoCs and target write-ups to follow. Send yours — working code only.

#exploitation #c #primitives


<-- newest | [ Security ] | Shadow of the Beast 2 – Cracking Tutorial [French] -->