100%(24)24 out of 24 people found this document helpful
This preview shows page 1 - 3 out of 8 pages.
CS 6035 Project 1: Buffer Overflow Monica Tare [email protected]1. Understanding Buffer Overflow Stack Buffer Overflow A stack is a limited access data structure wherein elements can be added and removed from only at the top. This type of order has a name –LIFO (Last-in-first-out) principle. The two crucial operations supported by stack are push and pop. Push adds an item to the top of the stack and Pop removes an item from the top. With regard to a Virtual Address Space, the stack can be visualized in the following manner: Text Data Heap Unused Memory Stack Text contains the code to be executed. Data contains global information for the program. Heap is where the dynamically allotted memory lies. Functions like malloc allocate memory in this part of the address space. Heap grows upwards, from a lower memory to a higher memory address as and when data gets stored here. Stack contains function parameters, local variables and return addresses of the functions to be stored. As opposed to heap, it grows downwards, from a higher memory to a lower memory address as and when new function calls are made. In stack based buffers, there are three main CPU registers namely EBP, EIP and ESP. EBP points to the higher memory address, which is at the bottom of the stack. ESP on the other hand points to the top of the stack, at the lowest memory location. EIP hold the address to the next instruction to be executed. Low memory High memory Figure 1: Memory Layout of a Program
To hijack the execution flow, we need to be aware of the EIP. EIP is a read only register, and hence we cannot assign the memory address of the instruction to be executed to it. When we execute a function, a stack frame for its information gets pushed onto the stack. After it finishes executing, the related stack frame is popped from the stack and execution get resumed in the function that called this one where it left off. For the CPU to know from where it has to continue the execution, the function that has finished executing, pushes a return address on the stack. This address is then used by CPU to return to the required point of execution.