Data Leak

Using format string exploitation is possible to read arbitrary value into the stack.

Reading values

As explained here, if there is more placeholders than arguments when calling the printf function, it will use the next values into the stack as arguments.

$ ./chall
Enter the password: %x.%x.%x.%x.%x
permission denied using password :
ffd98b6c.f.9c2e1a0.f7f3b000.f7f77230

It's possible to use any type specifier to leak as needed type, for example with the %d :

$ ./chall
Enter the password: %d.%d.%d.%d.%d
permission denied using password :
-2766116.15.154689952.-134955008.-134708688

Offsets

In most of binaries, the user input has a length limitation, so how to do if the needed value is the 5th stack value and the input limit is 2 ?

$ ./chall
Enter the password: %5$x
permission denied using password :
f7f77230

Arbitrary data read

When the %s placeholder is used, the formatted parameter need to be a pointer to the string value. So it's possible to inject an arbitrary pointer address into the user input and then read this value as previously show.

Thus, the payload must be [targeted address]%[offset]$s

Retrieving user input offset

To retrieve the user input offset, send 4 well known bytes such as "0x41414141" (which is 4 'A') followed by the format string "%1$x" and increase the value till retrieve the 4 bytes.

This technique is commonly call "Fuzzing"

Here is a python script to do that :

Read arbitrary value

For this example let's assume that there is a global declared variable called "secret" and PIE isn't set.

The first condition to read an arbitrary value is to know its address. In the example, the target is a global variable and as a global variable, it's within the binary itself. The location can be using readelf to check for symbols.

Thus, the payload must be [targeted address]%[offset]$s --> \x2c\xc0\x04\x08$7$s

Here is a python script to do that :

Last updated