Hack Like a Pro: How to Build Your Own Exploits, Part 2 (Writing a Simple Buffer Overflow in C)
Welcome back, my amateur hackers!
Over the course of the next year, we will be developing our own zero-day exploits. In my first article in this series, I introduced you to buffer overflows, which are the source of some of the most lethal exploits, particularly the "remote code execution," so we are focusing our exploit development here on a buffer overflow.
Developing your own exploits requires considerable knowledge and skill, so this series will toggle between providing you background material and information and labs to test and expand your skills.
In this tutorial, we will build a simple buffer overflow to demonstrate how a buffer overflow can work. We will build a short, simple program in C, compile it, run it successfully, and then attempt to overflow its buffer and get our own code to run. Although it is far from a sophisticated exploit, I think it demonstrates well what we are trying to achieve in developing our buffer overflow exploit.
First, fire up Kali and open a text editor for entering our code. In my case, I'll be using Leafpad, but you can use any text editor you want. To open Leafpad, go to Applications -> Accessories -> Leafpad.
I have developed a small bit of code that will enable us to overflow a memory buffer and run our own commands on the system. It is not meant to be used as an exploit, but rather to simply demonstrate the principle of buffer overflows that we will be building into our zero-day exploit.
Now, enter the following code as shown below.
In the screenshot below, I have highlighted our two variables we will be using in this code;
We have declared them below both "char" or character type variables.
Next, we have allocated memory for each variable using the malloc (memory allocation) command.
After the memory allocation, we have two "printf" statements that print the memory locations of the two variables. The third printf below then calculates the number of bytes between the two memory locations of our variables.
The fourth printf then asks the user "Where is the best place to learn hacking on the web?" followed by the "gets" function that puts the users response into the variable "place."
This is then followed by another printf function that prints the statement "The best place to learn hacking on the web is" followed by the user's response. Of course, the user will respond with "Null Byte"... what else?
Finally, the last line executes whatever is in the "systemcommand" variable. If the variable is empty, then no command is executed.
Finally, let's save this file as bufferoverflow.c.
The next step is to compile our new program. Compiling is the process of converting our source code, in this case C, into machine code. It's required whenever we write code in a compiled language, unlike say, Python, that is an interpreted language (interpreted languages are converted to machine language on the fly at run-time, line by line, and are thereby slower).
We need to use the GNU C Compiler (gcc) on the file bufferoverflow.c and output (-o) the compiled to a new file named "bufferoverflow" or whatever you choose to call it.
kali> gcc bufferoverflow.c -o bufferoverflow
This may produce a few errors, but you can largely ignore those.
Now, let's run our little "bufferoverflow" program.
kali > ./bufferoverflow
Notice that it first responded with the memory location of our variable "place," and then the memory location of our variable "systemcommand," and third it calculates that there are 16 bytes between these two memory locations. It then prompts the user for "the best place on the web to learn hacking" and, of course, the user responds "Null Byte." Finally, our little program responds with the obvious truth "The best place to learn hacking is Null Byte."
Now, let's run this program and try to overflow the memory area for the variable "place" into the memory area for "systemcommand." If we can overflow that memory area into the variable "systemcommand," we should be able to execute any system command on the system. For instance, we might be able to execute a command shell or display the contents of the /etc/shadow file.
We know from the third printf statement, the space between the "place" variable and the "systemcommand" variable is 16 bytes. This means that if we enter more than 16 ASCII characters (each ASCII character is one byte) when prompted, starting with the 17th character, whatever we input will move into the next variable, in this case, "systemcommand."
Let's now enter the following when prompted:
kali> nnnnnnnnnnnnnnnncat /etc/shadow
When we do this, the first 16 characters will go into the "place" variable and the 17th character and everything after will overflow into the "systemcommand" variable. The final line of our code will then execute the system command variable.
Notice that that we have been able to overflow the "place" variable into the "systemcommand" variable and have been able to "cat" the contents of the /etc/shadow file thereby showing us all the users and their hashed passwords. Congratulations! You have successfully overflowed the buffer and run your own code.
Over the course of this year, 2015, we will work step by step toward developing our own zero-day exploit in this series, so keep coming back, my novice hackers!