Format Stringz
How to pwn a printf
fgets(hello, 256, stdin);
printf(hello);
fgets(hello, 256, stdin);
printf(hello);
NOPE
Fonctionnement de printf
- Format String
- Structure de la stack
Format String
- %x : Print first argument as hex
- %08x : Pad hex with 0
- %3$x : Print third argument as hex
- %s : Print string at memory location from argument
- %n : Write string length into the memory location from argument as an `int`
- %hhn : Like %n, but store value as a 8 bit char
Regular printf call
fn(){
int a = 42;
char* b = "Hello world";
printf("%s and %x", b, a);
}
Regular printf

Expected result:
"Hello world and 42"
Printf exploited
void fn(char* input){
int password = 0x12345678;
printf(input);
}
Printf exploited

Given input = "%x\n%x\n%x"
Expected output:
<top_secret>
<fn's ebp>
<fn's return>
Print all the thing
void fn(){
char buffer[1024];
gets(buffer);
printf(buffer);
}
Print all the things

Buffer = "\x12\x34\x56\x78 %3$s"
Print string located at 0x78563412
Write all the thing
- Insert target address in format string (Like the "Read all the thing")
- Pad string with %NNx
- Write length of the string with %hhn
- 1 byte at a time
- eg: To write 0x44 at 0x12345678
- "\x78\x56\x34\x12%40x%7$hhn
- \x78\x56\x34\x12
- Target address
- %40x
- Add an additional 0x40 bytes to the output string
- %7$hhn
- Write output length (0x44)
Write all the thing
- Can write many bytes in the same format string:
- Example for a 32 bits integer:
- <addr><addr+1><addr+2><addr+3>
- <pad1>%<N>$hhn
- <pad2>%<n+1>$hhn
- <pad3>%<n+1>$hhn
- <pad4>%<n+1>$hhn
- Remember that the written value is the output string length. If the first byte is 0xf0, and the second byte is 0x10, <pad2> should be %20x.
Limitation
- Format string are used by all printf family function and often by logging function
- To read and write everywhere, an attacker must control a value on the stack to put the target address. For this reason, a format string in the Heap might be harder to exploit.
Exploit through .GOT
- Global Offset Table
- Located at the end of the program
- Address known
- Table mapping imported function to their real address
- Ex: exit(0)
- A stub function is called
- Lookup the exit GOT entry
- Jump to exit location
- Rewrite printf() address to system()?
Format String
By Israel Hallé
Format String
- 2,369