This week, we're going to be talking about the saved return pointer overwrite. The saved return pointer overwrite is sort of the main technique for traditional buffer overflow exploits. So, imagine that you have a little program written in C that looks something like this, right here. You've got your main function, which has some function calls, and it calls another function called "do something," and inside that it's got a little buffer over here that we're going to overflow. What happens in memory is you have a construct referred to as the "stack", and the stack grows upwards as you go through the program. So, when we're in the main function here, everything we need for memory that's saved in the stack is saved in this portion of the stack.
Now, we get to the point where we call do something and a few things happen, a new stack section is created called a "stack frame", and that stack frame is specific for the do something function here. So, you can see, we have our blue section of memory here that corresponds to our main function and then we gain the do something stack frame. In order to set that up though, we need some way of knowing how to get back to this code over here. So, after we finish with do something, we have to know how the program is supposed to get to this next instruction that says to call the do something else method.
Now, the way a program actually keeps track of what instruction it's on is something called the EIP register. When we jump into a new function, we save a pointer to that next instruction so that it can be loaded into EIP when we're done. So as we go into the do-something method, the current value of the EIP register gets placed onto the stack, in what's called the "saved returned pointer". Then, we build up the rest of this stack frame. We see here that we need a hundred character string for a foo. It allocates a section of memory just big enough to hold that string. This space, right here, is able to hold a hundred A's or other characters in it.
But what happens if we put more than 100 A's in it? This is where your buffer overflow comes in that you've probably heard about but maybe you don't quite understand how it works. So, what happens is we have this section with just enough space for a hundred A's. But, as we start to write more than a hundred A's, those A's will continue to flow down into this space here, filling all of this up until we get down to here, where the saved return pointer is. What happens when we finish the do something method, is it's going to collapse this whole section of memory, and then take whatever the value here at the saved return pointer is and load it back into the processor register of EIP, and then that's going to tell the program what instruction to execute next. So, if we overflow this all the way down into the saved return pointer we can actually overwrite that value and tell the program an arbitrary place to commit its next execution.
So, if you imagine, instead of filling this buffer with A's, you were to fill it with actual bite codes that could be interpreted as instructions, when you get down to this part in the saved return pointer, you're going to overwrite that with an address that points way back to the beginning of this section that you wrote, and instead of reading this as data now, what it's going to do is start interpreting it as instructions, and it can execute your shellcode. This is the basis of how a stack based buffer overflow works. So, a lot of your traditional exploits in Metasploit are based on this principle. We put all our shellcode, which will be our payload, through the buffer, and then continue to overflow until we write a memory location into the saved return pointer, and the program will then change where it executes, executing our shellcode and giving us a shell usually.
So, that's about it for this week. We'll see you on next week's Whiteboard Wednesday.