This tutorial is not going to teach you how to code an exploit, but what it is going to do is give you a good understanding of what a buffer overflow is, what types of buffer overflows there are, how we would go about exploiting a buffer overflow, and how to identify a buffer overflow. C and ASM knowledge is not required.
3b09e6c7b77a96b63d7b66bb3c986b732511691a13617d29880e2b53c3d34f5a
____ __ __ ___ ____
| __ ) _ _ / _|/ _| ___ _ __ / _ \__ _____ _ __ / _| | _____ _____
| _ \| | | | |_| |_ / _ \ '__| | | | \ \ / / _ \ '__| |_| |/ _ \ \ /\ / / __|
| |_) | |_| | _| _| __/ | | |_| |\ V / __/ | | _| | (_) \ V V /\__ \
|____/ \__,_|_| |_| \___|_| \___/ \_/ \___|_| |_| |_|\___/ \_/\_/ |___/
_____ _ ___ _
| ___|__ _ __ | |/ (_) __| |___
| |_ / _ \| '__| | ' /| |/ _` / __|
| _| (_) | | | . \| | (_| \__ \
|_| \___/|_| |_|\_\_|\__,_|___/
by bob [www.dtors.net]
[[--Introduction--]]
This tutorial is not going to teach you how to code an exploit, but what it is going to do
is give you a good understanding of what a buffer overflow is, what types of buffer overflows
there are, how we would go about exploiting a buffer overflow, and how to identify a buffer overlow.
You do not need to have any knowledge in C or ASM, as I will try my best to explain it to you.
This tutorial is aimed at the people that want to get a better understanding of buffer overflows.
If you want to start coding your own exploits, or identifying bugs and reporting them, then this
is one of the many places you should start. At the end of this tutorial I will put some good
references on articles that will help you in this subject.
I hope you learn something from this and enjoy the read.....here goes.......
[[--Jargon Buster--]]
First off, the most annoying thing when reading a tutorial like this, is all the confusing
words. Well I intend to get that out the way first, so that you can read this tutorial with
complete understanding.
exploit: is a program designed to exploit a problem another program may have. The exploit
will allow us to run arbitary code that will allow us to do something we shouldnt.
buffer: is a block of memory that holds "multiple instances of the same data type."
heap: is a space a program reserves for a variable. (You access the heap when you use the
malloc() function).
stack: is what a program uses to store temporary information such as our return address from
a function that the program called, or a local variable.
SFP: Stack Frame Pointer. This is the start address of the stack.
RET: Return address. This is when a function was called, and the system saved where it was called
from. So when the function ends, it will read the return address and let the program return
to where is left off. Now if we were to change the return address, we could point it to
another address to execute something we shouldnt. <evil grin>
[[--What is a buffer overflow?--]]
What happens when we try and put a pint of beer into a half pint glass? It OVERFLOWS, it spills
everywhere and we waste our damn beer.
The technical way to explain this, is to say that a buffer overflow is the result of putting
to much data into a buffer than it can handle. So this may lead to us executing arbitary code
IF a certain memory pointer is overwritten.
Lets do this by example, below will be a program that we will use to demonstrate how this may
occur.
---------------------------------cut-here--------------------------
/*
* beer.c
*/
void main() {
char pint[10];
char half_pint[1];
memset(pint,0x41,10);
strcpy(half_pint,pint);
}
---------------------------------cut-here--------------------------
This program trys to put a pint of beer into a half pint glass, like the example I used earlier.
For those of you that dont understand C, ill take each line and explain it to you.
void main() -- This is our "main" function.
char pint[10]; -- This is our first variable called pint. Notice the size of our pint.
char half_pint[1]; -- This is our second variable, notice this is 10x smaller than our pint.
memset(pint,0x41,100); -- memset fills the variable pint with 0x41 which is hex for the
character "a". So think of the a's as our beer.
strcpy(half_pint,pint); -- Now we try and put our pint of beer into our half pint glass, but it
OVERFLOWS.
} -- Function ends.
See its really not that hard to understand. We simply try to stuff to much data into a variable.
Now during the overflow the SFP and the RET will be overwritten with a's "lots of beer :)".
This means that our return address will now be 0x41414141. When our main function exits,
the computer will try and execute the instruction at 0x41414141. In this case it will cause
an error as it is outside the process space. << ill explain this bit later.
So now that we know we can overwrite the RET address, we can go on to exploit it. To do this
we would have to point it to our new address where we would instruct it to execute our arbitary
code.
See how fun this is?
One thing I will make clear, is the fact that when trying to overflow a program in most
cases, there is no point in doing this unless the program is owned by root and it has suid
permissions.
If your asking your self "what the hell is this guy going on about now?". Well to explain it
a bit clearer, a program must be suid to give you ROOT privileges.
SUID? A suid permission is given to a program that may need to perform tasks that normal programs
cant do. For example. If as a normal user you tried to edit /etc/passwd, you would get permission
denied. BUT if you used the program /usr/bin/passwd, it gives you permissions to edit passwd, in
a certain environment that allows you to edit YOUR password only.
[[--Different types of buffer overflows.--]]
There are two well known types of buffer overflows. One based on the stack, the other on the
heap.
The most common of the two is the stack based overflow, but now days there are non-executable
stack patches. Which will stop stack-based attacks. This is where heap overflows come in
handy, we can then actually work around the stack guard. Unfortunatley heap overflows are not
very well understood. So to keep things simple for you and ME, we will stick with stack based
overflows.
I have already given you the definition of what the stack is, and I have shown you a worked
example, of how a stack-based buffer overflows occurs.
Now im going to go into more details, so hang on, it may get bumpy...
Lets make a new Vulnerable program...
/* for testing purposes change the function from bob to main */
void bob(){
char beer[10];
gets(beer);
}
The way the stack works is simple. LIFO: Last in, First off. Doesnt make sense huh?
Ok think of bricks of lego. Each time you add one, you put it on top, and when you take one away,
it comes off from the top. This may sound confusing...but really its very simple. This is how
the stack organises its data.
Anyway back to our program, what this program is doing is asking for user input. But
if the user inputs over 15 char's, it will overflow, causing a Segmentation Fault.
So when our program calls bob() "our function" it will make room for beer[] on the stack.
+++++++++++++++++++++
+ beer[] +
+++++++++++++++++++++
+ +
+ Return Address +
+++++++++++++++++++++
+ +
+ +
^^^ This is a primitive example of what the stack will look like.
Now our goal is to overwrite beer[] with malicious code...
..when we make beer[] overflow, we can write beyond the end of beer[] and overwrite the
RETurn address.
What we want to do is overwrite the RET, with the address of beer[] so that when our function
bob() finishes, our malicious code will be executed.
Lets have a look now at what the stack would look like:
+++++++++++++++++++++
+ Malicious Code +
+++++++++++++++++++++
+ +
+ Address of beer[] +
+++++++++++++++++++++
+ +
+ +
So bob() will then return to the code in beer[].
Are you still awake? Well if you have got this far, im very sure you would have learnt SOMETHING.
[[--Conclusion--]]
Almost finished now...
Ive given you a basic overview of what a buffer overflow is, how we would exploit it, and how
the stack works.
There are ways to protect against stack-based overflows, for example, "make sure you use secure
functions when using the stack". Also try to make sure you provide methods to deal with the
potential dangers of user defined input.
To go about finding a buffer overflow is simple. As all of linux, and linux related programs are
open source, you can use programs such as FlawFinder to examine the source code.
Things Flawfinder checks for are libary funtions that dont perform boundary checking like:
strcpy() strcat() sprintf() vsprintf() scanf() getc() and getchar().
You can download FlawFinder at www.packetstormsecurity.org.
Thanks for reading, I hope you enjoyed it, and learnt something from this tutorial.
[[--Contact--]]
My email is bob@dtors.net
my homepage is: http://bob.dtors.net
[[--References--]]
http://www.11a.nu/stack/stack-smash.txt
http://www.11a.nu/stack/heaptut.txt
http://www.11a.nu/stack/exploit.txt
http://www.11a.nu/stack/adv.overflow.paper.txt