The Basic Stack Overflow



This is an excerpt taken from my MSc paper entitled "Wormability" that dissected how the vulnerability used by the conficker Worm was able to spread between network machines.


Chapter Four
How does a MS08-067 exploit gain control?


            This chapter provides an overall high level understanding of what is actually happening to cause the system to misbehave and execute code that would normally be considered to be data.  The difficulty however, is that a lot of exploits including MS08-067, actually occur at the machine-code\assembly level, which is the lowest (and most difficult) level in programming a computer. 

            The next chapter takes a closer look at the actual program execution occurring in real-time assembly language, but before that can occur, it is important to gain an overview of how the computer executes programs and how the exploit of the vulnerability occurs.

            The following picture shows the CPU stack status of a program that is being debugged. The program has stopped at a breakpoint that has been placed on the line Print (str) within function “DoSomething()”. 

 A CPU stack is a CPU feature that allows temporary storage of information that the CPU needs to remember so that it can be used at a later time.  Good analogies for a stack are post-it notes and notepads for recoding items that are to be acted upon later.  In memory, the stack grows from high-memory to low memory as values are placed on the stack.  The CPU “pushes” or stores a value into the memory location pointed to by a stack pointer and decrements the pointer.  When the CPU needs to obtain the stored value, the CPU loads or “pops” the value from the memory location pointed to by the stack and increments the stack pointer – the value hasn’t been deleted from memory and it is still present until a new value has been stored into that memory location.

            The CPU uses the stack to record temporary values, such as parameters and local variables used by a function.  This set of function information is called a “stack frame” and is pointed to by a Frame pointer.  Each time the CPU enters a new function, the Frame Pointer is saved onto the stack before the new function updates the pointer with a new value.  In the picture above, memory addresses 16 to 13 is the stack frame for the “Start ()” function and addresses 12 to 5 is the stack frame for the “DoSomething()” function.

            Local variables are stored on the stack by decreasing the stack pointer by however many memory locations are required for storing the variables.  The program might also create extra local variables that haven’t been declared within the original source code, for behind the scenes processing within the function.

            Parameters that are passed to the function are stored onto the stack before the function is called.   Local variables and function parameters are accessed relative to the frame pointer.  Parameters are a positive index away from the frame pointer, such as “ptr+3” to access parameter “str” in the above example and local variables have a negative index, such as  “ptr-5” for the start of the p array.

            The final and most important values that are stored on the stack are Return Addresses.  When the CPU calls a function, the address of the next instruction located after the function call is placed upon the stack. In the example above, 975 is the address to return to once the print function has finished and 721 is the address for the DoSomething() function to return back to the Start() function.

            If a function should accidently change its own return addresses, then it would mean that the CPU would go to a different location and execute code located at that position.  This is the fundamental mechanism that allows a MS08-067 exploit to gain control of the computer. 



Functions don’t normally change their own return address during program execution.  In fact, it usually means that something has gone drastically wrong if the return code has been changed.  However, exploit writers look for vulnerabilities, such as MS08-067, that allow the return code to be changed as this allows the exploit to execute code that they can provide.




No comments:

Post a Comment