Format String Vulnerability Basics
Hey Folks, this is an article regarding Format string vulnerability. Let's dive in !!
What causes this vulnerability?
The vulnerability is the result of functions having Variable number of arguments like printf(),sprintf (), fprintf (), and scanf ().If you have used printf() a number of times, you may notice that it is quite different from other functions: unlike most functions, which take a fixed number of arguments, pr int f () accepts any number of arguments.It is because how printf is defined(shown below)
int printf (const char *format, ... ) ;In the argument list, the function specifies one concrete argument format, followed by 3 dots ( . .. ). These dots indicate that zero or more optional arguments can be provided when the function is invoked. That is why compilers do not complain.
Now how printf() access optional parameter? Not going in much detail printf() uses stdarg macro and calls va_arg() function which in return gives the optional argument pointed to by the va_l i st pointer and advances the pointer to the next argument.see(Figure 1)
Hands on experiment on Format String Vulnerability
We will now see how we can change the data using this vulnerability.
Below is the Vulnerable program
#include <stdio.h>
void fmtstr()
{
char input [100];
int var= 0x11223344 ;
/*printout information for e xperiment purpose*/
printf ( "Target address : %x\n ", (unsigned) &var);
printf (" Data at target address : 0x%x\n ", var) ;
printf ("Please enter a string : ");
fgets (input , sizeof (input ) , stdin );
printf (input); // The vulnerable place
printf (" Data at target address : 0x%x\n ", var);
}
void main () { fmtstr (); }Program compilation and execution
Attack 1: Crash the program
To crash the program we can do the following.
When the program runs, printf() will parse the format string; for each %s encountered, it fetches a value from where va_list points to and advances va_list to the next position .
The %s format specifier in printf() takes the value pointed by va_list as a address and prints the content on the address.It may happen that the address is an invalid address hence the program gives segmentation fault i.e program has accessed an invalid address.In simple terms program crashes.
How many %s are needed to crash to program?🤔😒
It is variable sometimes you will need one or two or many this depends on the value that is taken as an address if it lies in permissible range program will not crash but as soon as the address is invalid the program will crash so it is a trial and error game.
Attack 2: Print out Data on the Stack
To print data on Stack of program we use %x foramt specifier.
Get Shweta tripathi’s stories in your inbox
Join Medium for free to get updates from this writer.
When printf () sees an %x, it prints out the integer value pointed to by the va_list pointer, and advances va_list by four bytes.
How many %x are required?🤔
We can perform trail and error or a more sophisticated method can be finding the distance between the var(variable in program) and start of va_list. We can use gdb to find the distance between the two.Here i used trail and error and got the variable value at 5th %x.
Attack 3: Change the Program’s Data in the Memory
There is a special format specifier %n which does not print any data but writes the number of characters printed so far into the memory
From how %n is used, we can tell that printf() expects an address when it sees %n . Basically, when print£ () sees %n, it gets a value pointed to by the va_list pointer, treats the value as an address, and write to the memory at that address. Therefore, if we need to write to any integer variable, the address of the memory needs to be on the stack. Even if the integer itself is on the stack, but if its address is not, we still cannot write to it. Our target vari able is var, and assume we know its address is 0xbfffecd4(refer Figure 5 ,Target address :bfffecd4 ) , so we need to get this address into the stack memory.We observe that the contents of the user input is stored on the stack, so we can include the address at the beginning of our input. Obviously, we cannot type this binary number; we can save our input to a file, and then ask the vulnerable program to get the input from our fil e. Here is how we can do it.
In the above Figure we can see that 2c in hexadecimal in replaced in place of target variable 2c is equal to 44 in decimal .
$ () around the printf command. Using $ (command) is referred to as command substitution. When used in the ba sh shell , it allows the output of a command to replace the command itself . Putting “ \ x“ before a number (e.g., 0 4) indicates that we would like to treat 0 4 as an actual number, not as two ASCII characters ‘ 0‘ and ‘ 4 ‘ . It should also be noted that our VM runs on the x86 architecture, which uses Little Endian, so the least significant byte should be placed at the lower address.
How we got 44 here?🤔
This is because 44 characters have been printed out before printf() sees %n i.e ����.64.b7f1c5a0.b7fd6990.b7fd4240.11223344. we can also se 11223344 in the stack which is just after 4 %x.
Attack 4: Change the Program’s Data to a Specific Value
To achieve this task we use width modifier.
The width modifier has the same format as precision, but without a decimal point. When applied to an integer, it controls the minimum number of digits to print. If the number of digits in the integer is smaller than the specified width, empty spaces will be placed at the beginning. For example, printf ( “ % 5d “, 10 ) will print out the number 10 with three leading spaces.
We will apply the precision modifier on the last %x (using the width modifier is similar). For this experiment purpose, we set the precision field to 100. To make the calculation simpler, we also set the precision fields of the other % x format specifiers to 8, forcing each number to be printed out in exactly 8 digits, even if the number is not large enough.
Here desired value can be printed by doing some maths and setting precision filed to desired value. I will show how we got 88.
0x88 in decimal is 136 this means 136 bytes are written before %n.
136 B = 4 B(address)+4 x 8 B (as each %x has 8 B)+100 B(specified in precision)
This is all about basics of format string vulnerability . Hope you liked and understood the article.
Thank You for reading .😊






