Tuesday, November 30, 2010

Buffer Overflow Vulnerability Part II : Heap Overflow


Today I will be discussing HEAP OVERFLOW. We have already seen that how a STACK OVERFLOW can be exploited to results in a massive system attack.
NO doubt, the first thing will be: WHAT IS BASIC DIFFERENCE BETWEEN STACK AND HEAP?

I will try to be as brief as possible on this topic as our discussion is on something else.

 Let me start with explaining some details about the Process, In WINDOWS every process is executed as a thread, to be very frank, Windows does not know anything with the name PROCESS, it simply schedules and run Threads. Now you all may doubt that what if the process you coded does not create any thread and runs as a single process.
The reply is that OS will run this process as a single threaded process and the main process itself runs as one thread.


To make it somewhat clearer, run Calculator application. After running calculator, start TASK MANAGER and see the number of threads count against the “calc.exe” application.





So OS is running Calculator application as a single thread and though we may say that Calculator Process is running, for OS it has to schedule a single threaded process’s parent thread.

Apparently you may also see a list of number of threads associated with all other listed applications.

So now we come back at our left discussion that what is the difference between STACK AND HEAP

The stack is the memory set aside as scratch space for a thread of execution. When a function is called, a block is reserved on the top of the stack for local variables and some bookkeeping data. When that function returns, the block becomes unused and can be used the next time a function is called.
The heap is memory set aside for dynamic allocation. Unlike the stack, there's no enforced pattern to the allocation and deallocation of blocks from the heap; you can allocate a block at any time and free it at any time.

Each thread gets a stack, while there's typically only one heap for the application (although it isn't uncommon to have multiple heaps for different types of allocation).

For an in-depth insight, let’s have a look at this program:

int foo()
{

  char *pBuffer; //<--nothing allocated yet
  bool b = true;
  if(b)
  {
    //Create 500 bytes on the stack
    char buffer[500];

    //Create 500 bytes on the heap
    pBuffer = new char[500];

   }//<-- buffer is deallocated here, pBuffer is not
} //<--- oops there's a memory leak, I should have called
   // delete[] pBuffer;

Heaps are generally used because the number and size of objects needed by the program are not known ahead of time or an object is too large to fit into a stack allocator.


Though Heap-overflow attacks are not very common in practices but still for have knowledge of this kinda of vulnerability, have a look at this code:


#include "stdio.h"
#include "stdlib.h"
#include  "string.h"
 
#define MAX_BUFFER_SIZE 16
 
//int main(void)
int main(int argc, char **argv)
{
        // Allocate memory for two buffers
        char *buffer1 = (char *) malloc(MAX_BUFFER_SIZE);
        char *input = (char *) malloc(MAX_BUFFER_SIZE);
 
        // Fill our victim buffer with As
        memset(buffer1, 'A', MAX_BUFFER_SIZE-1);
        buffer1[MAX_BUFFER_SIZE-1]='\0';
 
        printf("Buffer before overflow: %s\n",buffer1);
 
        // Use a non-bounds checked function
        strcpy(input,argv[1]);
        printf("After overflow: %s\n",buffer1);
 
        return 0;
}


This code dynamically allocates memory for 2 buffers, one buffer is filled with “A” and the other filled with arguments passed at the command line. Now just visualize that how memory looks like at different points:

With a normal amount of input:

Address
Variable
Value
003000B0
Input
BBBBBBBBBBBBBBBBB
003000C0
 ?????
 ?????????????????
003000D0
 ?????
 ?????????????????
003000E0
 ?????
 ?????????????????
003000F0
Buffer
AAAAAAAAAAAAAAAA
00300100
 ??????
 ????????????????


And

With the overflow:

Address
Variable
Value
003000B0
Input
BBBBBBBBBBBBBBBBB
003000C0
 ??????
BBBBBBBBBBBBBBBBB
003000D0
 ??????
BBBBBBBBBBBBBBBBB
003000E0
 ??????
BBBBBBBBBBBBBBBBB
003000F0
Buffer
BBBBBBBBAAAAAAAA
00300100
 ??????
 ????????????????




If we run this program with a few Bs everything works fine.
E:\Work\overflow\heapbasic\Release>heapbasic BBBBBBBBBBBBBB
Overflow buffer before: AAAAAAAAAAAAAAA
After overflow: AAAAAAAAAAAAAAA
However, if we increase the number of Bs on the command line, we see the buffer gets overflowed.
E:\Work\overflow\heapbasic\Release>heapbasic BBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBB
BBBBBBBBBBBBBBBBBBBBBBBBBb
 
Overflow buffer before: AAAAAAAAAAAAAAA
After overflow: BBBBBBBBBBBBBBBBBBBBBBBBBBBBb
Remember, this has nothing to do with the stack. These areas of memory that were overflowed were in the heap (and potentially non-executable).
The main aim of this tutorial is to tell how to save heap overflow so I will concentrate more over telling ways to lowers the possibility of heap overflow rather than telling the  ways to exploit the heap overflows as exploiting heap overflows is somewhat typical and out of the scope of this tutorial.
In code always check the buffer, basically any unchecked buffer is at risk.
The easiest thing to do is always check any data areas for size! Remember, just because you use a bounds checked function doesn't mean you are in the clear. strncpy(buffer, buffer2, strlen(buffer2)) is just as bad if not worse than strcpy(buffer,buffer2). Always ensures the buffer boundaries before filling data to it.





No comments:

Post a Comment