By playing various wargames I noticed that I kept on getting stuck on format strings vulnerabilities, so I decided to step back and relearn them from scratch. In the process I realized that I couldn't explain to myself why we can read / write to arbitrary locations by providing a valid address.
According to my understanding of format strings, this function call is supposed to simply print
AAAA + stack value + stack value and nothing else. Instead, it leaks two addresses starting by the provided address
The format function now parses the format string ‘A’, by reading a character a time. If it is not ‘%’, the character is copied to the output. In case it is, the character behind the ‘%’ specifies the type of parameter that should be evaluated. The string “%%” has a special meaning, it is used to print the escape character ‘%’ itself. Every other parameter relates to data, which is located on the stack
If the above statement is true, and
\x41\x41\x41\x41_%08x_%08x is the only argument of printf() allocated on the stack, then how can we explain reading / writing from/to memory locations ?
This answer does indeed specify that we can leak whatever address we want, but it doesn't go over how to start leaking from an arbitrary memory location.
So you're asking how printf can find the string because there is a different parameter count than the % signs say? Two thought problems here: a) Before printf can count the % at all, it has to find the string. Wrong string content can't prevent finding this string. b) Without attacks: printf supports variable parameter counts, and it always can find the string. Last parameter etc. doesn't matter.
For some reason the OP assumes that the 'AAAA' part is an actual address.