simple Buffer overflow tutorial

I will explain to you the basics of a Stack Based Buffer Overflow.

What can you do with that ?
Redirect the flow of a program, wherever you want in the memory.

It is a very powerful and a funny exploitation.

Recquirements :
- Understand a bit C and ASM language. (You have to understand what a stack and registers are)
- Know vaguely what a buffer overflow means.

The goal of this tutorial is to teach you what is a stack based buffer overflow, only with observations and reflections with GDB.

Let's analyse this code (compiled with -g -fno-stack-protector) :
[Image: InXEg.png]

There is a typical buffer overflow in the function vuln() ;
Indeed, the size of "arg" is not checked.
If it exceeds 50 bytes, there is a buffer overflow, because the size of buffer is 50 bytes.

Let's try to launch it with 10*A (normal execution), and then with 100*A (crash) :
[Image: Awc3f.png]

"Segmentation Fault" means that something went wrong during the process of our program. Indeed, we can notice that the program doesn't display "Good Bye!" at the end for the 2nd execution.
Something went wrong.

Let's try to figure out what happened.

We are going to use GDB for that.

[Image: tHorf.png]

Line 16 of main.c, at the end of the function vuln, the program received a SIGSEGV signal.

That means that our stack is compromised, and we cannot exit the function vuln.

Let's disassemble the vuln function, and put some strategic breakpoints so we can analyze easily what happened.

[Image: 0DY9D.png]

Let's put 4 breakpoints :
- At the beggining of the function vuln
- Before the strcpy
- After the strcpy
- At the end of the function vuln

[Image: 3pEhk.png]

Now let's run the program with a buffer overflow, and see what happens on the stack :

[Image: rpinb.png]

The first breakpoint is reached, we are at the beggining of the function vuln.

Let's take a look at the top of our stack :
[Image: k99zS.png]

0x004005fe is the adress of the instruction right after the call of the function vuln :

[Image: r3RlP.png]

Indeed, "call 0x40059c" is equivalent to "push next_eip; jmp 0x40059c"

So it is not surprising to find our next_eip at the top of the stack at the beginning of the function vuln().

It also means that, if we are able to modify this value, we can redirect the program at whatever adress we want.

Let's continue our analysis.

[Image: ajUtX.png]

We continue the execution until the next breakpoint; Before the strcpy.
At this point, nothing is copied yet. Let's see our stack :

[Image: P766O.png]

Now let's see what happens after our buffer overflow :

[Image: 3Q3AP.png]

Apparently, our main_EIP has been overwritten by 0x41414141.
Let's check this by going to the next breakpoint at the end of the function :
[Image: SoMtz.png]

The main_EIP at the adress 0x7ffe668 has been overwritten.
In case of you didn't know, ascii('A') = 0x41.

So, in practice, our buffer[50] begins at the adress 0x7ffe620.
Our main_EIP is at the adress 0x7ffe668.

So we know that we have to write 0x7ffe668 - 0x7ffe620 = 0x48 = 72 bytes before erasing the main_EIP.

Let's try to reach the unreachable_code() function :
[Image: 1J6WU]

It is located at the adress 0x400614.

Let's repeat the previous operation, but we will try to overwrite main_EIP with 0x400614 instead of 0x41414141.

[Image: 1J74Y]

Our main_EIP has been effectively overwritten.
The message "This code is not executed" is displayed, because we changed the flow of the program.

Now you know how to explore and exploit the stack.
Don't forget that \x00 are NULL byte = end of string, all bytes after it will be ignored by strcpy.

Hope you enjoyed !

No comments:

Post a Comment