Create a program that contains a buffer overflow vulnerability
Here, in order to achieve the requirements of the experiment, we first write a simple program that has buffer overflow hidden danger. This program I use vc++6.0 to write and execute under Windows XP. (Please note that if you are using a new version of the VC, because Microsoft has joined the GS mechanism to prevent the occurrence of buffer overflow situation, then this experiment will not be implemented.) )
Start by creating a new Win32 console application, and then enter the following C language code:
#include "stdio.h" #include "string.h" char name[] = "Jiangye"; int main () {char buffer[8];strcpy (buffer, name);p rintf ("%s \ n ", buffer); GetChar (); return 0;}
compile to generate the debug version and run the following results:
Figure 1
The visible program has been properly executed and output. But what I created in my program is an array of 8 bytes long, and my input in the program is 7 bytes. What happens if my input is more than eight bytes? Try it, please.
This time run the program again, try to enter "Jiangyejiangye", the result is as follows:
Figure 2
visible, although the program can also correctly output, but the error message pop-up dialog box. Why does this happen? We're going to look into it next.
determine the address of the main functionlet's look at the normal procedure (Overruntest_1.exe) first. Open the ollydbg and load the EXE program written above. Since we need to start the analysis from the main function, OD does not stop at the main function and stops in a series of initialized disassembly code, as shown in:
Figure 3
These are automatically generated by the system, regardless of our experiment, and we don't need to focus on the functionality of the code here. For this experiment, we just need to find the main function for further analysis. So how do you find the main function? Of course, we can continue to press F8 single-step execution, through observation to obtain, but this is a bit of experience, but also more troublesome. So it's worth using IDA Pro to open our lab program, as shown in:
Figure 4
As can be seen, IDA has helped us get the main function of the entry address, that is, 0x00401010, then we could at this time in OD, jump to that address, press F2 the next breakpoint. As shown in the following:
Figure 5
Locate the statement that invokes the main function
From the above, we can not only know the location of the main function, we also from the following paragraph, "Jumping from 00401005" to know that the main function is located at the 0x00401005 location of the statement jumped over. Since buffer overflow is closely related to stack space, we should now analyze the stack space before and after calling the main function, so here we need to locate exactly which statement called the main function. If we just pass OD, we are more difficult to locate, so here I still use Ida Pro.
Since we already know that the address of the main function is 0x00401010, in Ida, we use the mouse at that address point, and then use the shortcut key "Ctrl+x" to open the "Cross-reference window", came to jmp to this function location:
Figure 6
Then at the address of 0x00401005, using the cross-reference function again, we can find the location where the main function is called:
Figure 7
Now that we know that the statement that is located at 0x00401694 called the main function, our next step is to analyze the stack before and after the execution of the statement.
analyze the effect of the call statement on the stackIn OD, execute to the 0x00401694 location, as shown in:
Figure 8
As you can see, the address of the statement below the call is 0x00401699. This address is important because our program will first put the address of the statement below the call into the stack before it enters each of these lines, and then execute the call statement. When the call executes, the program then stacks the address so that it can know which instruction to execute next. We generally refer to this address as the "return address", which tells the program: "When call executes, execute the statement at this address." ”
Let's take a look at the current stack situation:
Figure 9
Note that the stack space from bottom to top is high address toward the low address. Then we press F7, step into this call, and then look at the stack space:
Figure 10
It is visible that the return address 0x00401669 is already in the stack. This is the effect of the call statement on the stack space, and this return address in the subsequent exploit, the impact of the key, please remember.
analyze the buffer condition in the main functionbecause we created an array of 8 bytes in the source program, the first thing to do after entering the main function is to allocate space for the local variable. Because our program compiles in debug form, it allocates more space (the release version allocates the exact space). In conjunction with this program, we can see that it allocates the local variable space size to 0x4c. We can look at the situation of our stack space after the allocation is complete:
Figure 11
In, the more important is the last two lines. The last line, which has been mentioned before, is a very important return address, which determines the address of the statement to be executed by the program when the main function is finished, while the second-penultimate line is the EBP of the parent function, and on this, we know that we can, and then go up, the local variable space of our main function. There may be doubts here, since it is the space allocated to us, then why are there other data? About this everybody don't worry, when we finish 0x0040da36 statement, then look at the space of this stack:
Figure 12
It can be seen that this space is filled with 0xCC. The program in order to fault tolerance and maintain its own robustness, so the use of 0xCC, that is, int 3 breakpoint to fill the area, so that if there is an unknown program jump to this area, there will be no crash, but directly broken down. Of course, this problem has nothing to do with our buffer overflow, as you can tell.
Then proceed to find the location of the disassembly code strcpy function, take a look at the normal situation, before and after the execution of this function, stack situation:
Figure 13
As you can see here, the second parameter of the strcpy is the location of the address where the received string is saved, which is saved in 0x0012ff78. Let's look at what happens in the stack when the string "Jiangye" is copied to this area:
Figure 14
Compared to the previous picture can be found, the address in the stack 0x0012ff20 location, save is strcpy the address of the second parameter, OD help us to parse out, its content is "Jiangye". And the address in the stack is 0x0012ff78, it is our real memory space to save the string "Jiangye". This is not a problem and the program can be executed normally. So what happens if I rewrite the first parameter of strcpy to "Jiangyejiangye"? Use OD to open the Overruntest_2.exe and come to the same position as shown:
Figure 15
It can be found that due to the length of the string we entered, the parent function EBP that was originally located at 0x0012ff80 in the stack and the return address that was originally located at 0x0012ff84 in the stack were rewritten. Here we mainly focus on the return address located at 0x0012ff84, originally it saved the value of 0x00401669, also told the program, after executing the main function, you need to execute the instruction at that address. But now the content in that stack has been destroyed and become 0x00006579, that is, when the main function is finished, the program will jump to the address to continue execution at 0x00006579. So what's going to happen? We might as well continue to look at:
Figure 16
Here, the main function needs to return, you can see it to return to the address of the 0x00006579, to execute the instructions at that address, we will run one step further:
Figure 17
At this point, we found two things, one is that the Disassembly Code window in OD is empty, indicating that there is no instruction at the 0x00006579 address, or that it is an invalid address. The second thing is that od pops up an error dialog box, prompting us to make an error in the address, which is somewhat similar to the error dialog box that pops up when we execute the program directly.
Summary of the principle of buffer Overflow vulnerability
At this point, you should have been aware of the buffer overflow vulnerability principle, it is because we have entered a long character, and the buffer itself does not have a valid validation mechanism, resulting in an excessive length of the character will be the return address is overwritten, when our function needs to return, because the return address is an invalid address, This causes the program to fail.
So according to this principle, assuming that the return address we cover is a valid address, and at that address contains a valid instruction, then our system will not hesitate to jump to that address to execute instructions. So, if you want to exploit a buffer overflow vulnerability, we can construct a valid address, and then write the code that we want the computer to execute to that address, so that we pass the program's vulnerability and let the computer execute the program we wrote ourselves. and the specific knowledge about exploit, I will give you a detailed explanation in the next lesson.
Buffer Overflow Analysis Lesson No. 02: The principle of buffer overflow