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 Olivier Arteau
Format String
- 1,330