From a book I’m reading called Hacking: The Art of Exploitation, I recently learned what a buffer overflow is, and how it can be used to make a program do something totally separate from what it was designed to do (such as run code that spawns, for example, a shell prompt with root privileges). A buffer overflow is the result of a character buffer in C being filled with more bytes of data than were allotted to it. C doesn’t have any measures in place to stop the programmer from accidentally (or purposefully) overflowing a character buffer, which means that if you put ten bytes (characters) into an 8-byte buffer, you’ll see the entered values actually overflowing into variables that are next to the buffer in memory. Example:
Let’s say you declare two 8-byte buffers, one after another, at the top of your main function, like this:
char buffer_one[8], buffer_two[8];
What is this line of code actually doing? It allocates memory that will be used to store two buffers. The buffers are actually located right next to each other in memory. buffer_two might be located at 0xbffff29c, and buffer_one might be located at 0xbffff2a4. The reason that the second buffer is at a lower memory address is that the stack structure in memory that contains a function’s variables grows up toward lower addresses, rather than down toward the higher ones. You’ll notice that the two example memory addresses I just gave are exactly 8 bytes apart (a4-9c), which is due to the declaration of buffer_two as one that would be used to hold up to 8 bytes of data (buffer_one is also 8-bytes long, with the allocated memory ending at 0xbffff2bb). This is fine if nothing longer than 8 bytes ever gets copied to these buffers, but in the event that it does, it will cause a buffer overflow.
Say that we used strcpy() to copy a command-line argument into the space allocated for buffer_two like this:
strcpy(buffer_two, argv[1]);
We could run the example with different values for buffer_two just by adding them at the command line. Something like
./a.out AAAAAAAAAAAAAAAAAAAAAA
where the long string of A’s is the set of characters that will be copied into buffer_two. Remember that since the second character buffer is located at a memory address lower than that of the first one, any characters beyond the eighth in buffer_two will overflow into the next memory addresses, which happen to belong to buffer_one. If, after copying the argument to the buffer, you were to print the contents of each buffer with
printf("buffer_two is at %p and contains \'%s\'\n", buffer_two, buffer_two);
printf("buffer_one is at %p and contains \'%s\'\n", buffer_one, buffer_one);
you’d see that both buffers contained some part of the argument string. buffer_two, located before buffer_one in memory, has overflowed into buffer_one. We only ever assigned the argument to the second buffer, yet part of it appears when we print the first buffer. This is the basic idea of a buffer overflow.
Check back for more in the next few days. I’m going to explain some more, including how to use a buffer overflow to divert the control flow of a program to different sections of the existing code. Thanks for reading!
