Pages

3.20.2012

The Beer Battered B0f (and friends)

Hello and welcome, to the world of tomorrow! Okay, so buffer overflows aren't exactly the most NEW thing hanging around, the little devils were discovered in the 90s by a bunch of Unix hackers, but you know, that's okay. We are here today and now, to rediscover the magic (for win32)!

Things you probably need!

  • A computer!
  • mingw32 cross compiler! (sudo apt-get install mingw32)
  • A debugger! (I use OllyDbg as my all time favorite 3 time Emmy winner)
  • If you are doing this under Linux like myself, get yourself Wine! (sudo apt-get install wine)


Here, my friends, is your first C file! Simple, yet effective, as we are not going to hop right into the stack based overflows, but rather, the heap based overflows, with a few toppings! Heap based overflows are a tad different than your traditional stack based overflows, in the sense that instead of attempting to overwrite a local variable placed on that ever so loving stack, we have a global variable in the '.data' section! Now low and behold there's also a chance a 'clever' programmer may have placed a lovely dword value JUST after this global-variable-turned-string, and if so we may have ourselves some fun IF this dword is a resolvable address that can be called later! Let's see if we can whirl this out, in a lovely source!

(Viewer's discretion is advised, the following source file was conceived on a Linux operating system with mingw32. Not for the faint of heart.)



#define _WINNT_WIN32    0x501
#include <windows.h>
#include <stdio.h>


char my_message[16];
int WINAPI (*my_api_call)(HWND, char*, char*, unsigned int);


int main(int argc, char* argv[])
{
        //Load user32.dll into address space, and
        //then use win32api to return the function
        //address for MessageBox
        HANDLE lib = LoadLibrary("User32.dll");
        my_api_call = GetProcAddress(lib, "MessageBoxA");
        printf("Hello and welcome! Please try to insert a 16\n");
        printf("character only string! Please don't hack me!\n");
        //Get the string from user input, with NO CARE about it's
        //length, demeanor, or intent!
        gets(my_message);
        //Now we just call MessageBox with our string from user
        //blindly skipping through a meadow.
        my_api_call(NULL, my_message, 
"UserInput!", MB_OK);
        //Free our library from the address space for 
        //good measure, then exit
        FreeLibrary(lib);
        exit(0);
}



So there we have it folks! A seemingly innocent software bug no one would EVER think about hijacking and using to dial back to a server to upload malicious software onto the host without the user's consent! Why no one would ever even dream of that!

So let's get a rundown of what exactly all this ruckus is about! Well we have a program here that simply asks for user input, then displays it in the form of a message box, like so!



Well look at that! Seems simple enough! Just throw whatever string you want in there, and it shows up on the MessageBox! But let's say we become a wee bit 'evil' and go against what this lovely program is telling us NOT to do. We are going to bypass the 16 character limit with 20 characters! Oh dear!


Well this looks a bit bad if you notice that our access violation occurs at 0x21657265! Well that seems to be an odd address in the first place! Let's see if a bit of python can't clear up this horrible mess!



$python -c 'print("\x21\x65\x72\x65")'
!ere



Well! Seems to be that the address it was attempting to call was none other than the string "!ere". This means that it took the last four characters and tried to use that as the address to call! (Remember though that even though it appears backwards, and you are probably saying "Jeez David, are you crazy? It's backwards!", this is little-endian my man!)


So what does this all mean? All this hokum and nonsense? Well this means that one could easily derail your application and use it for evil and malicious purposes! That's no good if you're trying to make a living! So let's dissect this for a bit real fast...



  1. The calling program, looking at the source, uses win32api functions 'LoadLibrary' and 'GetProcAddress' to get the address from the export table, of the function 'MessageBoxA'.
  2. This is then placed in a variable that follows immediately after a 16 character buffer, in all it's glory!
  3. Prints text to the screen in hopes the user will be gentle with it.
  4. Grabs input from the user without sanitizing/limit checking it at all.
  5. Shoves that string in as an argument in a 'MessageBoxA' call, and then just jumps willy-nilly into the fray with a 'call near eax' (with eax containing the value of my_api_call).
  6. 'FreeLibrary' of loaded user32.dll.
  7. 'exit(0)' to close it all up!
So that is the basic flowchart of this program's lifetime. Simple, but one inherent and huge problem. The buffer overflow. Since we were able to crash this program without so much as a care in the world, this could lead to severe problems down the road! For example, what if I were to simply just craft the user input to do this...

Hex: (of which I merely edited inside of OllyDbg, no 'cat' to stdin this time!)
68 28 40 40 00 E8 B2 D5 FF FF EB FE 90 90 90 90 14 40 40 00 49 20 65 6E 6A 6F 79 20 68 61 63 6B 69 6E 67 21


Hmmm? Well let's see the outcome shall we?

Well, well, well! Would you look at that! I do enjoy hacking! So all that lovely hexadecimal did was call 'puts' with the string I made in there 'I enjoy hacking!'. Since 'puts' was already imported by the linker and included as an IAT stub to MSVCRT, all we simply had to do was call the <jmp &msvcrt.puts> and we are in the clear!

So, in conclusion, we learned about the lovely heap based buffer overflow, and all of it's simple, yet effective mechanics. This just goes to show that information security is a vital role in today's market. It's hard to stay one step ahead of today's hackers, and they are skilled individuals, but it takes a hacker to beat a hacker!

Until next time folks!

No comments:

Post a Comment