緩衝區實例講解之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的話,就根據新值來調用相應的函數。
本文到此結束,希望對大家有所幫助!
※通過Post Types進行WordPress提權
※在Microsoft Edge中實現DOM樹
TAG:嘶吼RoarTalk |