In section 1.1 we say that we can use stack overflow to destroy the contents of the stack, and in this section we'll look at how to scramble for the return address (EIP) so that we can control its value at will, so we can program it. Take a look at a classic program:
The Get_print function of this program defines an array of size 11 bytes, under normal circumstances our input should be up to 10 characters (there is also a \ s terminator), and the Get function does not explicitly define the size of the input, so we can enter more than 10 characters, resulting in a stack overflow. As below, enter 10 ' A ', everything is OK:
Figure 8
When I entered 11 ' a ', although the smooth print out 11 ' a ', but VS2008 reported the following error:
Figure 9
A run-time error check detects a stack crash, which is the measure that Windows uses to combat stack overflow exploits. Currently we do not know how to bypass, first remove it, in the project properties, "C + +"-"code Generation" of "Basic Runtime Check" selected as the default value, and then recompile.
Figure 10
After the modification, input 11 ' a ' seems to be no problem, but when entering 12 ' a ', another such dialog box:
Figure 11
Buffer overflow is checked, which is certainly not a good news. As a classic loophole, Windows naturally has a variety of counter moves, which is a kind of protection called stack cookie, can check the stack overflow. Again, remove it first, in the project properties, the "C + +"-code generation "Buffer Security check" is selected as No (gs-, see Figure 10), and then recompile. This time, we enter a large string of ' a ':
Figure 12
What the? VS2008 the pop-up window again? Don't be nervous, this is good news.
Figure 13
Seeing the familiar 0xc0000005 indicates that you have visited an address that should not be accessed. At the same time, 0x41414141 is not "AAAA"? This means that the "AAAA" we have entered has been used in some way by the program, which is good news.
Below, use immunity debugger to see what happened. First find the Code for function Get_print () in MOV EBP, esp statement up and down breakpoints:
Figure 14
Then run here to view the contents of the stack:
Figure 15
Recalling the contents of 1.1, Get_print has no parameters, so 0012ff14 (current ESP) is a saved ebp,0012ff18 (ebp+4) for the return address (important).
The following two lines of code allocating stack frames have a large impact on the stack:
/***** ***** ***** ***** ***** ***** ***** **/mov EBP, Espsub ESP, 4c/***** ***** ***** ***** ** ***** ***** ***** ***** *******/
Allocated 4C (76 bytes) of space, so the following stack space (Get_print) is what we are concerned about:
Figure 16
Now, to navigate to the Get function, we are not concerned with its calling procedure, but rather the parameter, which is located on the stack ebp-c position, so it is adjacent to the saved EBP. That is, the buffer below is the saved EBP, and the following is the saved return address. This is important, which determines how much content we need to enter to accurately rewrite the saved return address (EIP).
We set a breakpoint after the gets function and enter the following (16 A and 4 B):
Figure 17
At this point, view the contents of the stack:
Figure 18
Did you see it? The saved EBP is overwritten with ' AAAA ', and the Saved return address (ebp+4) is bbbb overwritten. Because we know the exact location of local variables, we can know exactly how many bytes are needed to overwrite the contents of the return address.
In this way, we scramble from the program to Eip,get_print () return, it will jump to 0x42424242 execution, because the address is inaccessible, so there will be a 0xc0000005 error. Later, we will write a meaningful address to the EIP to execute our own content.
Stack Overflow Note 1.2 covers EIP