A format string attack exploits code that passes attacker-controlled input directly as a format string argument, rather than as a data argument.
sprintf(buffer, sizeof_buffer, input);
input is interpreted as a format string. An attacker who controls input can read from or write to the stack.
Reading from the Stack
An attacker enters %x%x%x as input:
sprintf(buffer, sizeof_buffer, "%x%x%x");
Each %x fetches the next value from the stack as if it were an argument, printing 3 hex values that were never intended as output.
Writing to the Stack
The %n conversion stores the number of characters printed so far into the memory location of its corresponding argument.
printf("Testing%n", &test);
Loads the number 7, the length of "Testing", into the memory location of test. An attacker who controls the format string can target a chosen memory location and write an attacker-chosen value into it.