Fuzzing in action

Let's take a basic code written in C, that takes a user input and displays it on the terminal:

#include <stdio.h>
#include <unistd.h>

int vuln() {

char arr[400];
int return_status;

printf("What's your name? ");
return_status = read(0, arr, 400);

printf("Hello %s", arr);

return 0;
}

int main(int argc, char *argv[]) {
vuln();
return 0;
}
ssize_t read(int fildes, void *buf, size_t nbytes);

The following table explains the fields used in the preceding code block:

Field Description
int fildes The file descriptor of where to read the input. You can either use a file descriptor obtained from the open (http://codewiki.wikidot.com/c:system-calls:open) system call, or you can use 0, 1, or 2, to refer to standard input, standard output, or standard error, respectively.
const void *buf A character array where the read content is stored.
size_t nbytes The number of bytes to read before truncating the data. If the data to be read is smaller than n bytes, all data is saved in the buffer.
return value Returns the number of bytes that were read. If the value is negative, then the system call returns an error.

 

We can see that this simple program attempts to read from the console (specified by the 0 value of the file descriptor), and whatever it reads from the console window, it attempts to place in the locally created array variable called arr. Now arr acts as a buffer in this code with a maximum size of 400. We know that a character datatype in C can hold 1 byte, which means that as long as our input is <=400 characters, the code should work fine, but if the input given is more than 400 characters, we may encounter an overflow or a segmentation fault, as we would be attempting to save more than the buffer arr can potentially hold. Looking at the preceding code, we can see straight away that more than 400 bytes of input will break the code.

Imagine that we didn't have access to the source code of the application. Then, for us to figure out the size of the buffer, we have the following three options:

  • The first option is to reverse engineer it to see the mnemonics or assembly level code of the application. Who wants to do that!
  • Many modern day decompilers also give us a source code equivalent of the original application. For a small example like ours, this would be a good choice, but if the executable in question is thousands of lines of code, we might want to avoid this option as well.
  • The third and generally preferred approach is to take the application as a black box and identify the places where it expects the user to specify an input. These would be our injection points in which we would specify strings of varying lengths to see if the program crashes and, if it does, where this would happen.

Let's compile our source code to generate the object file of C that we shall run and fuzz as a black box.

By default, Linux systems are safe and they come with all sort of protection against buffer overflows. For this reason, while compiling the source code, we will disable the inbuilt protections as shown here:
gcc -fno-stack-protector -z execstack -o buff buff.c

The preceding command would produce the following screenshot:

Let's run our object file in a single line by piping the output of echo command to it. This will be automated using Python and fuzzing:

We know that ./buff is our out-file that can be executed as an executable. Let's assume that we know the actual source code of the file to see how we can use Python to fuzz the file. Let's create a basic Python-fuzzing script:

Let's run the preceding Python code to see how and what effects fuzzing has and how would it break the application to get us close to the crash point:

As can be seen from the previous output, the point where the application crashes is somewhere between 400 and 500 bytes, which is where the actual crash lies. To be more precise, we can use a smaller step size for i and arrive at the following with a step size=10:

The preceding screenshot gives us more granular information and tells us that the application crashes at an input length between 411 and 421.

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset
18.188.20.56