Buffer overflow is a state where application will try storing data beyond the size of the buffer. This buffer can be either static buffer or dynamic buffer which is allocated in heap. Due to Buffer overflow either application might crash or it will produce the wrong result. This overflow largely happens due to the underlying libraries are unsafe and lack of knowledge in writing code by developer.
Buffer overflow on the Stack
A stack is a segment where C/C++ language will allocate space dynamically and destroy once it leaves the scope of local variable. This stack will also store return address for transferring control after finishing execution of function.
After executing the function TestFunc(), you will see in the stack data in following order:
- 0x004153D0(4 bytes) is a return address – Top of stack
- 0x0000000A(4 bytes) – 1st parameter of a function
- 0x00000014 (4 bytes) – 2nd parameter of a function
- 0x0000001E(4 bytes) – 3rd parameter of a function
- 0x00000028(4 bytes) – 4th parameter of a function
After executing TestFunc () it will clear all parameter data which is stored in stack during calling function and remaining is return address (0x004153D0). After executing RET instruction, the nature of RET instruction is take 4 bytes from top of stack and transfer control to that address. In our example, it will transfer control to 0x004153D0 which is a next instruction after TestFunc () function (Marked rectangle is return address)
Attacker can manipulate this return address to transfer control to their code and gain access to the system or to shut down the system. Buffer overflow bug is one of the top vulnerability which threatens the security of the whole system from many years. With recent shipping of secured CRT libraries of compilers and compilers providing few options to check the buffer overflow vulnerability will help mitigating this risk.
Check following buffer overflow sample:
LBuffer and BugBuffer is a buffer variable which is declared inside a function. Space is reserved for these 2 variables once execution enters inside this function. memset() function is used to make all bytes Zero for our clarity.
BugBuffer is declared only ONE byte and we are trying to write more in a for loop 26 bytes. Since stack allocation for variable happens in reverse due to nature of Stack. for loop will overwrite next local variable which is located in same stack.
Check watch window, BugBuffer has all the values which is written in loop, since it is using the next buffer LBuffer. If you look at the data of LBuffer you will understand how much for loop has overwritten. LBuffer data is “BCDEFGHIJKLMNOPQRSTUVWXYZ”.
In the same way if we are not taking care buffer operations, it can overwrite other local variables and make program to crash or allow attacker to exploit the system by running attackers code.
Buffer overflow on the Heap
A heap is a memory allocation where application allocates memory either using malloc or new. This area is completely separate from program data and stack. Application can allocate memory in the heap as long as system has virtual memory. This segment is both readable and writable and it contains only data.
After overflowing heap attacker can send a shell code buffer where it contains executable code to gain the access to system or compromise the system. Compare to stack-based buffer overflow Heap-based overflow is less popular.
Check the following heap-overflow sample:
Two buffers pLBuff and pRBuff are allocating memory from the heap of 10 bytes each. After allocating memory get the difference of these two addresses. In our example, pLBuff has higher virtual address compare to pRBuff. pLBuff is allocated after the distance of 17464 (Read DiffCount variable ) from pRBuff. We are filling pRBuff with ‘Q’ of 17464+5 bytes, these 5 bytes is overwriting the pLBuff – check watch window where it is displaying ‘Q’ of 5 bytes.