In languages such as C and C++, the printf-style-statements are often vulnerable to an issue called Format String Attacks. Functions such as printf, sprint, fprintf and so on are called Format functions. The behavior of these functions is defined by the format string. Format string vulnerability arises when the user-supplied input is evaluated as part of a command. For example, the attacker may supply characters such as %x as part of input data, and when it is parsed by the Format Function, the conversion happens as specified. However, the Format function expects arguments corresponding to this, but when they are not supplied, it reads from the stack. Thus by sending crafted input vectors, an attacker can exploit this issue to read values from the stack, write values to stack, read memory address values and so on. As part of this lab exercise, we will have an example C program which is vulnerable to Format Strings attack and how it can be exploited to view the stack values, write values to the stack and so on.

Virtual Machines Needed: Kali Linux VM.

Step 1: Creating Example.c file

From your Kali Linux VM, open up a terminal and type the below command:

This would open a text editor. Now enter the C source code below and save the file in any location (say desktop)
with .c as an extension.

#include <stdio.h>

#include <string.h>

int main(int argc, char *argv[])

{

char ex[1024];

strcpy(ex,argv[1]);

printf(“You wrote:”);

printf(ex);

printf(“\n”);

}

The above program simply reads an input string and displays it back to the user. While running the program supply any random value as argument.

Step 2: Compile the Run the program

To compile and run the C program use below commands as shown in the following screenshot:

This command will invoke the GNU C compiler to compile the file Example.c and output (-o) the result to an executable called Example.

Step 3: Exploiting Format String

  • To view the stack: Format parameter “%x” can be used to read data from the stack. When this is provided as input the program rather than displaying it, will execute it and display the value from the stack as shown in the following screenshot.

  • To view addresses on the stack: It’s important here to note that printf takes a variable number of arguments. To determine the number of arguments it uses format strings. By taking advantage of this an attacker can pass “%p %p %p %p %p %p %p %p %p %p” and fool the compiler into thinking that it has ten arguments. In this case, it would simply print the next ten addresses on the stack, assuming they are its arguments as shown below:

  • To write values to a particular memory location: Enter AAAA followed by any number of %x as input and observe the response.

Please note that 41414141 is the hex representation of AAAA. Observe that this value is shown after eight addresses on the stack. Thus, in this case, we have passed an arbitrary value (41414141) as input. To simplify it further we can take advantage of another notation used in C.

For example, we can do printf(“%<any number>$x”)¬†to select an arbitrary argument to¬†printf.

Now instead of reading, we can write the values to a location, just by replacing $x in the above place with $n. In other words, If we were to pass the string AAAA%2$n, we would write the value to the 2nd address. We can give any arbitrary input and write it to a selected location. Please note that the value that is going to be written would be the number of characters entered so far. For example, as shown in the below screenshot, by varying the input length observe that the value in 2nd address also varies.

In other words, we can write arbitrary values to arbitrary memory locations. This is extremely dangerous as it allows an attacker to overwrite important flags that may control the access privilege. Attackers may also overwrite return addresses, function pointers, etc. using this technique.

Ethical Hacking Training – Resources (InfoSec)

  • To change values of variables: This can be accomplished with the use of “%n” directive. This directive allows you to write values into the memory. The number of characters written so far is stored into the integer indicated by the int * (or variant) pointer argument. For the sake of understanding this, create a program Example.c with below C code:

    #include <stdio.h>

    #include <string.h>

    int main(int argc, char *argv[])

    {

    int b;

    char ex[1024];

    strcpy(ex,argv[1]);

    printf(“%s%n\n”, ex, &b);

    printf(“The value of b now= %d\n”, b);

    printf(“\n”);

    }

As you can see, the variable “b” initially does not contain any value. Let’s compile and run this program to see the result:

From the above output, it’s clear that the value of b is controlled by the number of characters we enter. The printf() call displays the string “Rorot” which contains 5 characters. The next %n format writes this value to variable “b”. Thus by using the %n character an attacker can write values into the memory.

Remediation: The problem of format string vulnerability arises due to the confusion on the part of the format functions in understanding the supplied arguments. Hence it is recommended to validate the input supplied to make sure that it does not contain any arbitrary commands or characters. Also make sure to supply the exact number of argument with the argument type. To fix the issue exploited in the above examples, just add “%s” to the printf function as shown below:

#include <stdio.h>

#include <string.h>

int main(int argc, char *argv[])

{

char ex[1024];

strcpy(ex,argv[1]);

printf(“You wrote:”);

printf(“%s”, ex);

printf(“\n”);

}

Now compile and run the above code to see the result.

As shown in the above screenshot, rather than executing %08x as part of the command, it is now treated as a string and is displayed back to the user.