Level description

#include <stdlib.h> #include <unistd.h> #include <stdio.h> #include <string.h> void vuln(char *string) { volatile int target; char buffer[64]; target = 0; sprintf(buffer, string); if(target == 0xdeadbeef) { printf("you have hit the target correctly :)

"); } } int main(int argc, char **argv) { vuln(argv[1]); }

Intro

This is just an introductory level for format string vulnerabilities. Before this level, I knew very little about this type of vulnerabilities and the PDF document linked in the level description was of great help.

Solution

This level can be solved using simple buffer overflow techniques as seen in the previous level, but because of the <10 bytes input restriction given in level description, we need to find another way of solving this, hence the need to learn about the new type of vulnerabilities.

As I want for this blog post to be as informative as possible, I will show you how the execution looks on the stack. Before the call to fprintf(), the stack looks as follows:

Only interesting thing to note here is the way how buffer and target are stored in memory, one on top of the other. Next, we need to analyze how will the stack look after fprintf()‘s call. Interesting thing here is that if we check the definition of fprintf() function, we can see that it receives variable number of arguments (2 or more), first one being the buffer to write to, next is the format string and everything after that is used for the replacement of the format character inside the given format string. If we start the program with “Rick and Morty” string as user input and after we enter the fprintf() function, the stack will look like this:

To be exact, the picture above shows how the stack will look like before the fprintf() function returns. We gave the function only 2 parameters which are pushed onto the stack in reverse order: the user supplied “Rick and Morty” string (sent as an argument when starting the program from the console) and the address of the buffer where user supplied data needs to be stored.

This is the normal scenario with no format parameters in the user supplied string, but what would happen if we put format parameters inside our string but without supplying the additional arguments to fprintf() that this format parameters would expect? This is exactly what this vulnerability is about. As previously linked PDF states, fprintf() function has its own pointer to keep track of arguments that need to be put at the place of format parameters. I’ll go straight to the exploit, if we supply something like: “%64d\xef\xbe\xad\xde” as our argument string, but without additional argument to fill the place of “%64d“, the fprintf() function will look at location of its format string argument’s pointer (the location fprintf() would expect the first format parameter to be) and use whatever it finds at that location as the format argument and put it inside the string. In this case, the location of the parameter would be expected to be immediately after the user supplied format string (“%64d\xef\xbe\xad\xde“), towards higher memory addresses, because function arguments are passed in reverse order onto the stack before calling the function itself. In this case, our stack will look like this:

When the fprintf() function gets executed, and the format string gets parsed, the first thing it will see is the %64d format parameter which means: “take the first argument from where the internal pointer is pointing at and put it in the place of the format parameter, using minimum of 64 spaces”, after that, it needs to write further the remaining bytes (“\xef\xbe\xad\xde“) but the buffer is out of space (remember we are writing the new expanded string into our buffer) , and this is where the buffer overflow occurs, overwriting the target variable with bytes we needed to overwrite it with. Notice that the internal pointer doesn’t know where it is pointed to, it just points to the place it would expect the format argument to be, and if the format argument isn’t there, the function will read whatever it finds at that place, giving us a way to exploit this simple program.

Thanks for reading!