For a long time, i never understood buffer overflows, they seemed to be so complicated. There are some really good resources out there to study this particular vulnerability. But i always found them to not be enough. Some were too basic while others were too complicated. So i decided to make my own blog post on the infamous buffer overflow.

What are Buffer Overflows? (basic concept)

A buffer overflow occurs when a program or process attempts to write more data to a fixed length of memory, than the buffer is allocated to hold. this fixed length of memory is called the buffer. By sending specific characters as input to a program, a hacker can cause the program to execute arbitrary code and most likely will be able to take over the system.

Putting it on basic terms, a buffer is a temporary area for data storage. When more data gets placed by a program, than was originally allocated to be stored, the extra data overflows. It causes some of that data to leak out into other buffers, which can corrupt or overwrite whatever data they were holding.

A basic example

This is a basic C program.

int main(int argc, char *argv[]) 
{ 
       char buffer[5];  

       if (argc < 2) 
       { 
              printf("strcpy() NOT executed....\n"); 
              printf("Syntax: %s <characters>\n", argv[0]); 
              exit(0); 
       } 
  
       // copy the user input to mybuffer, without any 
       // bound checking a secure version is srtcpy_s() 
       strcpy(buffer, argv[1]); 
       printf("buffer content= %s\n", buffer); 
  
       // you may want to try strcpy_s() 
       printf("strcpy() executed...\n"); 
  
       return 0; 
} 

The way this program works is, we have reserved 5 bytes of memory in the buffer, including the terminating NULL. To overflow the buffer we need more than 8 bytes of data. The vulnerability exists because the buffer could be overflowed if the user input (argv[1]) bigger than 8 bytes. For 32 bit (4 bytes) system, we must fill up a double word (32 bits) memory. Character (char) size is 1 byte, so if we request buffer with 5 bytes, the system will allocate 2 double words (8 bytes). That is why when you input more than 8 bytes, then mybuffer will be over flowed.

How does buffer overflow work?

When a binary application is executed, it allocates memory in a very specific way within the memory boundaries used by modern computers. The lowest memory address (0x00000000) and the highest memory address
(0x7FFFFFFF) used by applications.

ram-1

The top of the memory is the kernel area, which contains the command-line parameters that are passed to the program and the environment variables. Also the heap grows up (from low to higher memory) when more memory is required by an application and the stack grows downwards (from high to lower memory). The only thing which we should be concerned about is the stack. That’s where all the magic happens.

Now let us try and understand the stack

The stack is a LIFO data structure extensively used by computers in memory management. There are a few of registers present in the memory among which we shall only be concerned about EIP, EBP, ESP.

The buffer moves downwards, as more characters are added, an overflow of characters looks like this

Exploit writing tutorial part 1 : Stack Based Overflows | Corelan Team
  • EBP: It’s a stack pointer which points to the base of the stack.
  • ESP: It’s a stack pointer which points to the top of the stack.
  • EIP: It contains the address of the next instruction to be executed.

Here is another diagram:

After an overflow:

The space between the ESP and EBP is the buffer. Controlling EIP is the first step in creating a successful buffer overflow

Another Example

This is a basic C program.

#include <stdio.h>
#include <string.h>
int main(int argc, char *argv[])
{
char buffer[64];
if (argc < 2)
{
printf("Error - You must supply at least one argument\n");
return 1;
}
strcpy(buffer, argv[1]);
return 0;
}

In this case, the main function first defines a character array named buffer that can fit up to 64 characters. Since this variable is defined within a function, the C compiler will treat it as a local variable and will reserve space (64 bytes) for it on the stack. Specifically, this memory space will
be reserved within the main function stack frame during its execution when the program runs.

The program then proceeds to copy (strcpy) the content of the given command-line argument (argv[1]) into the buffer character array. Note that the C language does not support strings as a data type. At a low level, a string is a sequence of characters terminated by a null character (‘\0’), or put another way, a one-dimensional array of characters. Finally, the program terminates its execution and returns a zero (standard success exit code) to the operating system. When we call this program, we will pass command-line arguments to it. The main function processes these arguments with the help of the two parameters, argc and argv, which represent the number of the arguments passed to the program (passed as an integer) and an array of pointers to the argument “strings” themselves, respectively. If the argument passed to the main function is 64 characters or less, this program will work as expected and will exit normally. However, since there are no checks on the size of the input, if the argument is longer, say 80 bytes, part of the stack adjacent to the target buffer will be overwritten by the remaining 16 characters, overflowing the array boundaries.

You can see how that works in the diagram below.

How to conduct as successful buffer overflow?

  1. Spiking
  2. Fuzzing
  3. Finding the offset
  4. Overwriting the EIP
  5. Finding bad characters
  6. Finding the right module
  7. Generating shell code
  8. Getting Root
Tools to Download

I would suggest that you try and set up the tools above. At first i thought i would explain those whole process using videos. But then The Cyber Mentor on YouTube has a really good playlist on how to do so. I will be attaching each video below.

For Spiking click here

For Fuzzing click here

For Offset discovery click here

For overwriting EIP click here

Finding Bad characters click here

Finding Right module click here

Generating Shell code click here