Thursday, March 7, 2013

Buffer Overflows : overwriting eip with strcpy()

Buffer overflows is one of the very common vulnerabilities found out there. Many of the exploit codes existing today take advantage of this particular vulnerability. Therefore, skills of overflowing the buffer is an indispensable tool in any hacker's arsenal. I struggled to understand and exploit this vulnerability a few years back. I hope I'll make it easy for you through this post. I shall only cover overwriting the eip stored on a stack frame which is relatively easy but important step to launch a buffer overflow exploit.

Before proceeding ahead, I recommend that you have knowledge of CPU registers and stack from computer organization and architecture class, memory address space of a process and working with gcc.

Here is a diagram of a stack frame for quick reference-

Let's consider a piece of code-
//strcopy.c
#include<string.h>
int main()
{
char string[10];
strcpy(string,"ZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZ");
return 0;
}
Here we are declaring a string of 10 characters and trying to store around 40 Z's in that with the strcpy function which does not perform bounds checking. What happens when we compile and try to run it? Let's find out-
vipulc@ubuntu:~/Desktop$ gcc -ggdb -mpreferred-stack-boundary=2 -fno-stack-protector -o strcopy strcopy.c
vipulc@ubuntu:~/Desktop$ ./strcopy
Segmentation fault (core dumped)
vipulc@ubuntu:~/Desktop$ 
Here I am using gcc on ubuntu 12.
The -ggdb parameter enables debugging of the program. 
-mpreferred-stack-boundary=2 keeps the stack boundary aligned to 2^2. We will not go into details of this.
-fno-stack-protector disables stack protection to help us learn about the exploit. 

Now here since we got a segmentation fault, we'll try to find out using gdb.
We will run the program in gdb and then see the values of registers to see what went wrong.
First we run the program with the "run" command which comes to a halt due to segmentation fault. Then we try to see the register values with "info reg" command.
Concentrate on EBP and EIP values. They're all 0x5a5a5a5a. Hey! 5a is the hex of ascii of "Z" character which we used to overflow the buffer. That means, we have overwritten the values of ebp and eip in that stack frame!
Now try reducing the number of "Z"s in the program and try to see for how many characters it just overflows the eip...
We overflowed eip and ebp register through a buffer of 10 characters. Well if you put only 14 characters instead of 40, you will notice that you can overwrite ebp with those 4 extra characters. If you use 18 characters, you can overwrite the eip too, with the last 4 characters. 
Now the last 4 bytes which will overwrite the eip can be replaced by the memory address where the exploit to be launched is stored. This can lead to total compromise of the system and attacker can gain shell access or even root access to the system.