Sunday, April 17, 2011

Buffer Overflows over Linux Platform

I am going to analyze a theme about buffer overflow in Linux OSs. I consider this post as a succession of this one here.


In this post I will create a vulnerable program in c, then I will analyze the executable using gnu debugger and I will try to find a buffer overflow vulnerability. Supposing that there is one, I will try to create a specific exploit in order to manage the program behavior to satisfy my needs.
Most of the contents based on images that I capture exactly as I used them from the command line.

What is required to read this topic?
1. Of course you have read and (most basically) to understand this one.
2. Some knowledge of c, assembly is required as well as some classic programming techniques, such as what is a breakpoint.
3. A basic knowledge of Linux command line environment.
4. An access to a Linux distro with the tools (below) installed in order to test by your self what you will actually read.

Tools and Os used
I used Debian 3.0 r4 but the specific example I used here (i thing) it is possible to be applied in many other Linux distros.
I also used gcc compiler and gnu debugger.
Linux command line is 100% enough. No fancy GUIs or Windows are required. Only command line and (of course) its ALT+F1, ALT+F2,... ALT+Fn feature. You can also use a linux distro from a virtual Machine. It will produce exactly the same results.

Lets start!
First we will enable core dump feature in order to be able to read some info in it, when a program (in this case, our program) crashes!
We entered

$ ulimit -c unlimited

I create now a simple but vulnerable program and I 'll compile it with the following flags
Attempt to keep the stack boundary aligned to a 2 raised to 2 byte boundary.
Produce debugging information for use by GDB.

As you see there is a vulnerability an line 5. If the user enters a very big argument there is no protection in the code. Lets see this in practice

First we run the program by entering a small argument

Then we run it with a very large argument. As you can see the program crashes! Then we run the gnu debugger to check the produced core file

As you can see there is an address 0x61616161 that points... nowhere! If we examine this address we can see it constitutes of 61s. 61 is the hex equivalent of ASCII character 'a'. Coincidentally? I don't thing so!
'a' is the string of characters that we entered as argument to our vulnerable program. This means that we (accidentally?) overwrite 'some' return address with a's!

Let be more specific & accurate Lets try the following

As you see I filled all the memory used for the variable 'data' with 'a's. It is actually 12 'a's, not 10. If you don't understand why then read again my first post about 'How a program works'. Finally I get 0x64646464 which is the 'd's. I just found the position of our string that overwrites the RET address!

Lets rock it!
I will try to prove my above conclusion (about overwriting the RET address) by debugging the executable

I run debugger and I disassemble the main function. As you can see the process_data function is called at address 0x08048402. Immediately after the function call the next program instruction is at address 0x08048407. Remember this address. Inside the process_data the RET address contains the value 0x08048407 which is the address that the program goes when process_data ends.

I will disassemble the process_data now in order to set some breakpoints

Pay attention at instruction at address 0x080483c7. What does is doing? Actually subtracts 0x18 from the esp i.e. It tries to reserve some space for all variables that take place in process_data. When I all vars I mean all, including base address and RET. Don't even thing to ask "why the subtraction?" You know why! The stack increases... downwards! Remember! ;-)
In addition the 0x18 is the 24 decimal. Does this number reminds you something?
Maybe is the total size of the string "aaaaaaaaaabbbbccccdddd". Does the function itself contains the magic number that every apparent attacker search for? I thing yes.
Lets c...
I put my break points

I run the program entering (again) the bad string "aaaaaaaaaabbbbccccdddd" as argument. The program stops at the 1st breakpoint.

I then print the 10 values after the ebp. Consider the addresses of ebp and the RET address. The RET address is the 0x08048407. Our breakpoint is actually where the function process_data starts. Immediately after the set of ebp and ret, the function prologue.

I continue to the 2nd breakpoint. I print again what it was at address of ebp (at 0xffffb2c in blue). You see! The ebp and ret address are overwritten with 63s ('c') and 64s ('d'). A classic buffer overflow just took place!

It is also possible to see the whole stack frame by searching backwards in memory

Now, i am staring to be a bit nasty. What if I replace the 'dddd' with an existing real address inside the vulnerable program, but in a location that I choose!
Lets thing...
I would like to skip the display of "Return from process" message and goto immidiatelly to "Bye now.". If I review the assembly code of the main function I can see that this command is at address 0x08048413. All I have to do is to replace 'dddd' with the above address in reverse order (DON'T FORGET THIS!). I will use a litle trick in order to pass the hexadecimal value of the address to my program as an external argument. Consider this

The "Return from process" message disappears.
I just used a buffer overflow vulnerability...

This was a basic step into buffer overflow word. Many advance topics remains to be posted such as shellocode creations, shellcode calls etc.
In addition many Linux distros don't allow stack overflow by using several techniques that we will explore then in a future post.

Happy hacking!

[1]The Shellcoder's Handbook: Discovering and Exploiting Security Holes

0 comments for "Buffer Overflows over Linux Platform"

Post a Comment