當前位置:
首頁 > 新聞 > 緩衝區實例講解之protostar stack3挑戰篇

緩衝區實例講解之protostar stack3挑戰篇

引言

在上兩篇文章中1、2,我們已經解決了stack0、stack1和stack2挑戰,今天,我們將為讀者介紹如何解決protostar stack3。在解決前三個挑戰的時候,我們使用了二進位文件的源代碼,來識別緩衝區溢出發生的位置並加以利用。然而,對於stack3來說,我們雖然也有源代碼,但是,我們卻不打算使用它,相反,我們將使用一些實用的技術來解決這個挑戰。那我們為什麼要這麼做呢?在現實情況下,我們基本上是沒有機會得到目標程序的源代碼,對吧?

如果您還沒有讀過我之前撰寫的關於緩衝區溢出的文章,建議您先閱讀它們。

./Stack3

讓我們先來考察一下這個程序,看看它是做什麼的。

./stack3

如圖所示,我們沒有看到任何輸出內容,所以,看來我們應該給它提供一個參數。為了檢測該程序是否含有緩衝區溢出漏洞,我們可以為其傳遞100個字元的參數,看看它有什麼反應:

python -c "print "A" * 100" | ./stack3

這時,我們看到一個segfault錯誤,這說明發生了緩衝區溢出;同時,我們還看到這樣一行內容:「calling function pointer , jumping to 0x41414141」。

現在,我們已經大體知道發生了什麼情況:其中有一個函數指針,它會根據函數給定的內存地址來執行函數。由於該內存地址存儲在一個變數中,因此,當發生緩衝區溢出時,我們就可以覆蓋或者說重寫該變數了。我們看到,函數指針正在調用地址0x41414141,其中0x41是「A」的十六進位表示。所以,接下來我們要做兩件事:第一件事是弄清楚緩衝區溢出是在哪裡發生的,雖然上面給這個程序輸入了一個100個字元的參數,但是我們並不知道緩衝區的確切大小;第二件事是找到我們需要執行的函數的內存地址。如何完成這兩件事情呢?下面將為讀者詳細介紹。

確定緩衝區的大小

為了簡單起見,這裡將使用Kali box系統來完成這個程序的編譯和測試工作。

Metasploit提供了兩個分別名為pattern_create和pattern_offset的腳本,它們位於kali系統中的/usr/share/metasploit-framework/tools/exploit目錄中。

pattern_create可以幫助我們創建一個指定長度的惟一字元串,就這裡來說,我們將創建一個包含100個字元的模式(pattern)。

./pattern_create.rb -l 100

現在,讓我們在GDB中運行該程序,對於我而言,使用的是gdb-peda。

首先,我們需要在main函數中設置一個斷點。

break *main

這樣一來,程序就會在main()函數的第一條指令之後中斷。

然後,讓我們運行該程序。

現在,它在斷點處如期停止運行。之後,我們按c鍵,讓它繼續運行,並向其傳遞我們指定的參數。

如圖所示,與偏移64處的內容是完全匹配的,這意味著緩衝區大小為64個字元,大於這個閥值就會發生溢出。

查找函數的內存地址

如果我們在GDB中運行info functions命令,就能看到所有函數及其內存地址,此外,我們也可以使用objdump來完成這一任務。但是,我們要找的函數是什麼呢?

info functions

如圖所示,這裡有很多函數,但我們最感興趣的一個函數是「win」,並且,它在我的Kali Box系統上的地址與在protostar機器上的地址並不相同。於是,我們返回protostar機器,並通過objdump來定位它。

objdump -d stack3

利用漏洞

現在,我們可以輕鬆地構建相應的漏洞利用程序了——我們已經知道緩衝區長度為64個字元,所以,我們可以傳遞一個函數的地址,然後通過函數指針來執行它。

python -c "print "A" * 64 "x24x84x04x08"" | ./stack3

如圖所示,這裡的輸出內容為「Code flow changed successfull」。

上面,我們已經在不藉助源代碼的情況下搞定了這個挑戰,接下來,我們不妨看看這個程序的源代碼到底長啥樣:

#include

#include

#include

#include

void win()

{

printf("code flow successfully changed
");

}

int main(int argc, char **argv)

{

volatile int (*fp)();

char buffer[64];

fp = 0;

gets(buffer);

if(fp){

printf("calling function pointer, jumping to 0xx
", fp); fp(); }}

我們看到,該程序先定義了一個函數win(),然後,又定義了函數main(),並在該函數中定義了一個函數指針,創建了一個長度為64個字元的緩衝區,並將其值設置為0。之後,它會接受我們提供的參數,並將其存儲在該緩衝區中。最後一條if語句會檢查函數指針的值是否發生了改動,即是否依然為0;如果不為0的話,就根據新值來調用相應的函數。

本文到此結束,希望對大家有所幫助!


喜歡這篇文章嗎?立刻分享出去讓更多人知道吧!

本站內容充實豐富,博大精深,小編精選每日熱門資訊,隨時更新,點擊「搶先收到最新資訊」瀏覽吧!


請您繼續閱讀更多來自 嘶吼RoarTalk 的精彩文章:

通過Post Types進行WordPress提權
在Microsoft Edge中實現DOM樹

TAG:嘶吼RoarTalk |