Buffer overflow principle
As the name implies, a buffer overflow means that the buffer provides more data than its storage capacity, as if it were poured into a cup in excess of water. Typically, buffer overflow data only destroys program data, causing an unexpected termination. But if someone carefully constructs the content of the overflow data, then it is possible to gain control of the system! If the user (or possibly a hacker) provides data for the water-buffer overflow attack, then the system provides the overflow container-the buffer.
Buffer in the system is a variety of manifestations, high-level language definitions of variables, arrays, structures, etc. can be said to be stored in the buffer at run time, so the so-called buffer can be more abstractly understood as a section of the memory area can read and write, The ultimate goal of a buffer attack is to expect the system to execute malicious code that has been deliberately set up in the read-write memory. According to the principle of von Neumann storage program, the program code is stored as binary data in memory, the same program data is in memory, so directly from the memory of the binary form is not able to distinguish which is the data which is the code, this also provides the possibility of buffer overflow attack.
Process address space distribution
is a simple representation of the process address space distribution. The code stores all executable code for the user program, and the program counter (pc when the program executes properly) Pointers) are addressed only within the code snippet and the operating system address space (kernel state). The data section stores the user program's global variables, the text pool, and so on. The stack space stores the function stack frames of the user program (including parameters, local data, etc.), implements the function call mechanism, and its data growth direction is the low address direction. The heap space stores the memory data requested by the program when it is run, and the direction of data growth is high address direction. In addition to code snippets and operating system-protected data regions, other memory regions may be buffers, so buffer overflow locations may be in the data segment or in the heap, stack segment. If the code of the program has a software vulnerability, the malicious program will "abet" the program counter from the above buffer to take the finger, execute the data code provided by the malicious program!
The main function of the stack is to implement function invocation. Each time a function call is made, the system will return the address of the function (the address of the instruction immediately after the function call), some key register values are stored in the stack, and the actual parameters and local variables of the function (including data, struct, object, etc.) are also stored in the stack. These data are collectively referred to as stack frames of function calls, and each function call will have a separate stack frame, which also provides the possibility of recursive function implementation. When invoking a function, the function stack frame base is saved with EBP , so the original value of the EBP is saved to the stack, and the stack pointer ESP content is saved to ebp. You need to do the opposite before the function returns--restore the ESP pointer and pop up ebp. In this way, the stack does not lose its balance in the normal context of the function, regardless of how it is used. There is a possibility of buffer overflow, mainly because the return address of the function is saved in the stack space. This address holds the location of the instructions that are executed after the function call is complete and is sensitive to computer security. If someone maliciously modifies the return address and points the return address to a new code location, the program can continue execution from another location.
Experiment Preparation
The lab building provides 64-bit Ubuntu Linux, and in this experiment we need to operate in 32-bit environments to facilitate the observation of assembly statements, so we need to do some preparation before the experiment. Install something to compile a 32-bit C program:
When the installation is complete, enter "/bin/bash" Using bash:
Initial setup of experimental steps
In Ubuntu and some other Linux systems, the initial address of random heap (heap) and stack (stack) is randomized using address space, which makes it difficult to guess the exact memory address, and guessing the memory address is the key to the buffer overflow attack. So in this experiment, we use the following command to turn off this feature.
In addition, in order to further protect against buffer overflow attacks and other attacks using shell programs, many shell programs automatically abandon their privileges when called. Therefore, even if you can trick a set-uid program into invoking a shell, you cannot maintain root privileges in the shell, which is implemented in/bin/bash.
In a Linux system,/bin/sh is actually a symbolic link to/bin/bash or/bin/dash. To reproduce the situation before this protective measure was implemented, we used another shell program (zsh) instead of/bin/bash. The following instructions describe how to set up the ZSH program:
Shellcode
InESPContinue to append afterShellcodeThe code will overwhelm the stack frame of the ancestor function, and there is no benefit in doing so, and may even lead to runtime problems. Now that the buffer is provided within the overflow function stack frame, we still put the coreShellcodeIn the buffer, and in theESPThen put the jump command to move to the original buffer position. Because doing so makes the location of the codebefore the ESP pointer, if a push instruction is used in the shellcode , the ESP directive is associated with the shellcode the code gets closer and even drowns its own code. This is obviously not the result we want, so we can force the ESP pointer to be raised before shellcode (low address position) so that it can be shellcode the Push command is normally used within the
Vulnerability procedures
The code lets you know that the program reads a file named "Badfile" and loads the contents of the file into "buffer".
Compile the program, and set the Set-uid. The command is as follows:
The GCC compiler has a stack protection mechanism to prevent buffer overflows, so we need to use –fno-stack-protector to close this mechanism when compiling the code. The-Z execstack is used to allow execution of the stack.
Attack program
Our goal is to attack the vulnerability program just now and gain root access through the attack. Save the following code as a "expolit.c" file and save it to the/tmp directory. The code is as follows:
Notice the above code, "\x??" \x?? \x?? \x?? " Need to add shellcode to the address stored in memory because the location can overwrite the return address just after an overflow occurs. and strcpy (Buffer+100,shellcode); This sentence tells us again that Shellcode is stored in the buffer+100 position. Now we're going to get shellcode in-memory address, enter the command:
According to the statement strcpy (Buffer+100,shellcode); We calculate the address of Shellcode as 0xffffd1b0 (hex) +100 (decimal)
Then, compile the EXPLOIT.C program:
Attack results
Root privileges can be obtained by comparing the front and back. The experiment was successful.
Feelings
Before the experiment, there was a lot of talk about buffer overflow attacks, so you wanted to do it on your own, write your own attack code, disassemble yourself and calculate the offsets you need to overflow. However, when compiling, it was found that the attack code could not be compiled, although the protection mechanism of some stacks was blocked (the method that was found on the net), but never compiled. Had to do in the experimental building buffer an experiment, the experiment also success rate. Although the entire experimental process is based on the steps of the lab building, it also complements some of the important knowledge that is available online. Through this practice, the "stack" has a deeper understanding, but also more familiar with the buffer overflow attack This classic attack method, benefited.
Through this experiment, I think it is very necessary for the students who are learning the basis of information security system design to complete the buffer overflow attack, just like the gdb disassembly practice, many things can be mastered by this experiment. Through the study of the third to fourth chapter of the textbook, we can only slightly understand some of the fur, and through the GDB disassembly practice and Buffer overflow experiment, we will certainly will those conceptual things, deeply recorded in the brain, and will learn the knowledge, improve a grade.
Textbook matching Project--buffer experiment