保密技術概論:11A網絡攻擊之緩沖區溢出_第1頁
保密技術概論:11A網絡攻擊之緩沖區溢出_第2頁
保密技術概論:11A網絡攻擊之緩沖區溢出_第3頁
保密技術概論:11A網絡攻擊之緩沖區溢出_第4頁
保密技術概論:11A網絡攻擊之緩沖區溢出_第5頁
已閱讀5頁,還剩51頁未讀 繼續免費閱讀

下載本文檔

版權說明:本文檔由用戶提供并上傳,收益歸屬內容提供方,若內容存在侵權,請進行舉報或認領

文檔簡介

11A緩沖區溢出攻擊技術2內容提要11A.1緩沖區溢出概述11A.2緩沖區溢出原理

11A.3緩沖區溢出的過程311A.1緩沖區溢出概述什么是緩沖區?它是包含相同數據類型實例的一個連續的計算機內存塊。是程序運行期間在內存中分配的一個連續的區域,用于保存包括字符數組在內的各種數據類型。所謂溢出,其實就是所填充的數據超出了原有的緩沖區邊界。兩者結合進來,所謂緩沖區溢出,就是向固定長度的緩沖區中寫入超出其預告分配長度的內容,造成緩沖區中數據的溢出,從而覆蓋了緩沖區周圍的內存空間。黑客借此精心構造填充數據,導致原有流程的改變,讓程序轉而執行特殊的代碼,最終獲取控制權。411A.1緩沖區溢出概述利用緩沖區溢出漏洞進行攻擊最早可追溯到1988年Morris蠕蟲,它所利用的就是fingerd程序的緩沖區溢出漏洞。Windows系統中緩沖區溢出的事例更是層出不窮。2001年“紅色代碼”蠕蟲利用微軟IISWebServer中的緩沖區溢出漏洞使300000多臺計算機受到攻擊;2004年5月爆發的“振蕩波”利用了Windows系統的活動目錄服務緩沖區溢出漏洞;2005年8月利用Windows即插即用緩沖區溢出漏洞的“狙擊波”被稱為歷史上最快利用微軟漏洞進行攻擊的惡意代碼。2008年底至2009年的Conficker蠕蟲利用的是Windows處理遠程RPC請求時的漏洞(MS08-067)。5目前,利用緩沖區溢出漏洞進行的攻擊已經占所有系統攻擊總數的80%以上。緩沖區溢出攻擊其原因在于各種操作系統和應用軟件上存在的緩沖區溢出問題數不勝數,而其帶來的影響不容小覷。對緩沖區溢出漏洞攻擊,可以導致程序運行失敗、系統崩潰以及重新啟動等后果。更為嚴重的是,可以利用緩沖區溢出執行非授權指令,甚至取得系統特權,進而進行各種非法操作。11A.1緩沖區溢出概述與其他的攻擊類型相比,緩沖區溢出攻擊不需要太多的先決條件殺傷力很強技術性強緩沖區溢出比其他一些黑客攻擊手段更具有破壞力和隱蔽性。這也是利用緩沖區溢出漏洞進行攻擊日益普遍的原因。611A.1緩沖區溢出概述7破壞性它極容易使服務程序停止運行,服務器死機甚至刪除服務器上的數據隱蔽性首先,漏洞被發現之前,程序員一般是不會意識到自己的程序存在漏洞的,于是疏于監測其次,被植入的攻擊代碼一般都很短,執行時間也非常短,很難在執行過程中被發現,而且其執行并不一定會使系統報告錯誤,并可能不影響正常程序的運行11A.1緩沖區溢出概述隱蔽性第三,由于漏洞存在于防火墻內部的主機上,攻擊者可以在防火墻內部堂而皇之地取得本來不被允許或沒有權限的控制權第四,攻擊的隨機性和不可預測性使得防御變得異常艱難,沒有攻擊時,被攻擊程序本身并不會有什么變化,也不會存在任何異常的表現最后,緩沖區溢出漏洞的普遍存在,針對它的攻擊讓人防不勝防(各種補丁程序也可能存在著這種漏洞)11A.1緩沖區溢出概述811A.2緩沖區溢出原理11A.2.1棧溢出11A.2.2堆溢出11A.2.3BSS溢出11A.2.4格式化串溢出910當程序運行時,計算機會在內存區域中開辟一段連續的內存塊,包括代碼段、數據段和堆棧段三部分11A.2緩沖區溢出原理程序在內存中的存放形式11A.2緩沖區溢出原理11代碼段(.text),也稱文本段(TextSegment),存放著程序的機器碼和只讀數據,可執行指令就是從這里取得的。如果可能,系統會安排好相同程序的多個運行實體共享這些實例代碼。這個段在內存中一般被標記為只讀,任何對該區的寫操作都會導致段錯誤(SegmentationFault)。數據段,包括已初始化的數據段(.data)和未初始化的數據段(.bss),前者用來存放保存全局的和靜態的已初始化變量,后者用來保存全局的和靜態的未初始化變量。數據段在編譯時分配。11A.2緩沖區溢出原理12堆棧段分為堆和棧。堆(Heap):位于BSS內存段的上邊,用來存儲程序運行時分配的變量。堆的大小并不固定,可動態擴張或縮減。其分配由實時內存分配函數來實現。當進程調用malloc等函數分配內存時,新分配的內存就被動態添加到堆上(堆被擴張);當利用free等函數釋放內存時,被釋放的內存從堆中被剔除(堆被縮減)。堆的內存釋放由應用程序去控制,通常一個new()就要對應一個delete(),如果程序員沒有釋放掉,那么在程序結束后操作系統會自動回收。11A.2緩沖區溢出原理13棧(Stack)是一種用來存儲函數調用時的臨時信息的結構,如函數調用所傳遞的參數、函數的返回地址、函數的局部變量等。在程序運行時由編譯器在需要的時候分配,在不需要的時候自動清除。棧的特性:最后一個放入棧中的物體總是被最先拿出來,這個特性通常稱為先進后出(FILO)隊列。棧的基本操作:PUSH操作:向棧中添加數據,稱為壓棧,數據將放置在棧頂;POP操作:POP操作相反,在棧頂部移去一個元素,并將棧的大小減一,稱為彈棧。11A.2緩沖區溢出原理14堆和棧的區別分配和管理方式不同堆是動態分配的,其空間的分配和釋放都由程序員控制棧由編譯器自動管理。棧有兩種分配方式:靜態分配和動態分配。靜態分配由編譯器完成,比如局部變量的分配。動態分配由alloca()函數進行分配,但是棧的動態分配和堆是不同的,它的動態分配是由編譯器進行釋放,無須手工控制產生碎片不同對堆來說,頻繁的new/delete或者malloc/free勢必會造成內存空間的不連續,造成大量的碎片,使程序效率降低對棧而言,則不存在碎片問題,因為棧是先進后出的隊列,永遠不可能有一個內存塊從棧中間彈出生長方向不同堆是向著內存地址增加的方向增長的,從內存的低地址向高地址方向增長棧的生長方向與之相反,是向著內存地址減小的方向增長,由內存的高地址向低地址方向增長1516在這里,假設現在有一個程序,它的函數調用順序如下

main()->;func_1()->;func_2()->;func_3()

即:主函數main調用函數func_1;函數func_1調用函數func_2;函數func_2調用函數func_3。其詳細結構圖如下頁圖所示。11A.2緩沖區溢出原理2023/1/3網絡入侵與防范技術1717程序在內存中的影像隨著函數調用層數的增加,函數棧幀是一塊塊地向內存低地址方向延伸的。隨著進程中函數調用層數的減少,即各函數調用的返回,棧幀會一塊塊地被遺棄而向內存的高址方向回縮。各函數的棧幀大小隨著函數的性質的不同而不等,由函數的局部變量的數目決定。在緩沖區溢出中,我們主要關注數據區和堆棧區。1819程序所使用的棧在使用棧時,引用棧幀需要借助兩個寄存器。一個是SP(ESP),即棧頂指針,它隨著數據入棧出棧而發生變化。另一個是BP(EBP),即基地址指針,它用于標識棧中一個相對穩定的位置,通過BP,再加上偏移地址,可以方便地引用函數參數以及局部變量。20程序所使用的棧函數被調用的時候,棧中的壓入情況如下:Func函數中的局部變量調用Func函數前的EBP退出Func函數后的返回地址傳遞給Func的實參內存低地址內存高地址最先壓入棧最后壓入棧21程序所使用的棧在局部變量的下面,是前一個調用函數的EBP,接下來就是返回地址。如果局部變量發生溢出,很有可能會覆蓋掉EBP甚至RET(返回地址),這就是緩沖區溢出攻擊的“奧秘”所在22如果在堆棧中壓入的數據超過預先給堆棧分配的容量時,就會出現堆棧溢出,從而使得程序運行失敗;如果發生溢出的是大型程序還有可能會導致系統崩潰。11A.2緩沖區溢出原理11A.2.1棧溢出程序中發生函數調用時,計算機做如下操作:首先把指令寄存器EIP(它指向當前CPU將要運行的下一條指令的地址)中的內容壓入棧,作為程序的返回地址(下文中用RET表示);之后放入棧的是基址寄存器EBP,它指向當前函數棧幀(stackframe)的底部;然后把當前的棧指針ESP拷貝到EBP,作為新的基地址,最后為本地變量的動態存儲分配留出一定空間,并把ESP減去適當的數值。2311A.2.1棧溢出實例一段簡單程序的執行過程中對棧的操作和溢出的產生過程。

#include<stdio.h> intmain(){ charname[16]; gets(name); for(inti=0;i<16&&name[i];i++) printf(“%c”,name[i]); }2425編譯上述代碼,輸入helloworld!結果會輸出helloworld!在調用main()函數時,程序對棧的操作是這樣的:先在棧底壓入返回地址接著將棧指針EBP入棧,并把EBP修改為現在的ESP之后ESP減16,即向上增長16個字節,用來存放name[]數組11A.2.1棧溢出實例26現在棧的布局如圖所示11A.2.1棧溢出實例27執行完gets(name)之后,棧中的內容如下圖所示11A.2.1棧溢出實例28接著執行for循環,逐個打印name[]數組中的字符,直到碰到0x00字符最后,從main返回,將ESP增加16以回收name[]數組占用的空間,此時ESP指向先前保存的EBP值。程序將這個值彈出并賦給EBP,使EBP重新指向main()函數調用者的棧的底部。然后再彈出現在位于棧頂的返回地址RET,賦給EIP,CPU繼續執行EIP所指向的命令。說明1:EIP寄存器的內容表示將要執行的下一條指令地址。說明2:當調用函數時,Call指令會將返回地址(Call指令下一條指令地址)壓入棧Ret指令會把壓棧的返回地址彈給EIP11A.2.1棧溢出實例29如果輸入的字符串長度超過16個字節,例如輸入:helloworld!AAAAAAAA……,則當執行完gets(name)之后,棧的情況如圖所示11A.2.1棧溢出實例30由于輸入的字符串太長,name[]數組容納不下,只好向棧的底部方向繼續寫‘A’。這些‘A’覆蓋了堆棧的老的元素,從上頁圖可以看出,EBP,Ret都已經被‘A’覆蓋了。從main返回時,就必然會把‘AAAA’的ASCII碼——0x41414141視作返回地址,CPU會試圖執行0x41414141處的指令,結果出現難以預料的后果,這樣就產生了一次堆棧溢出。在Windows

XP下用VC6.0運行程序,結果如下頁圖所示。11A.2.1棧溢出實例3111A.2.2堆溢出當我們需要較大的緩沖區或在寫代碼時不知道包含在緩沖區中對象的大小,常常要使用堆。堆溢出的工作方式幾乎與棧溢出的工作方式完全相同,唯一不同的是,堆沒有壓棧和入棧操作,而是分配和回收內存。C語言中使用malloc()和free()函數實現內存的動態分配和回收,C++語言使用new()和delete()函數來實現相同的功能3211A.2.2堆溢出實例#include<stdio.h>#include<stdlib.h>#include<unistd.h>#include<string.h>#defineBUFFER-SIZE16#defineOVERLAYSIZE8/*我們將覆蓋buf2的前OVERLAYSIZE個字節*/intmain(){ u-longdiff; char*buf1=(char*)malloc(BUFFER-SIZE); char*buf2=(char*)malloc(BUFFER-SIZE); diff=(u-long)buf2-(u-long)buf1; printf(″buf1=%p,buf2=%p,diff=0x%x(%d)bytes\n″,buf1,buf2,diff,diff); /*將buf2用’a’填充*/ memset(buf2,’a’,BUFFER-SIZE-1),buf2[BUFFER-SIZE-1]=’\0’; printf(″beforeoverflow:buf2=%s\n″,buf2); /*用diff+OVERLAYSIZE個’b’填充buf1*/ memset(buf1,’b’,(u-int)(diff+OVERLAYSIZE)); printf(″afteroverflow:buf2=%s\n″,buf2); return0;}33運行結果:/users/test41%./heap1buf1=0x8049858,buf2=0x8049870,diff=0x18(24)bytesbeforeoverflow:buf2=aaaaaaaaaaaaaaaafteroverflow:buf2=bbbbbbbbaaaaaaa我們看到,buf2的前八個字節被覆蓋了,這是因為往buf1中填寫的數據超出了它的邊界進入了buf2的范圍。由于buf2的數據仍然在有效的Heap區內,程序仍然可以正常結束。

11A.2.2堆溢出實例34雖然buf1和buf2是相繼分配的,但它們并不是緊挨著的,而是有八個字節的間距。這是因為,使用malloc()動態分配內存時,系統向用戶返回一個內存地址,實際上在這個地址前面通常還有8字節的內部結構,用來記錄分配的塊長度、上一個堆的字節數以及一些標志等。這個間距可能隨不同的系統環境而不同。buf1溢出后,buf2的前8字節也被改寫為bbbbbbbb,buf2內部的部分內容也被修改為b。11A.2.2堆溢出實例35示意圖11A.2.2堆溢出實例3611A.2.2堆溢出堆溢出不如棧溢出流行,原因在于比棧溢出難度更大需要結合其他的技術對于內存中變量的組織方式有一定的要求3711A.2.3BSS溢出.bss段存放全局和靜態的未初始化變量,其分配比較簡單,變量與變量之間是連續存放的,沒有保留空間。下面這樣定義的兩個字符數組即是位于BSS段:staticcharbuf1[16],buf2[16];如果事先向buf2中寫入16個字符A,之后再往buf1中寫入24個B,由于變量之間是連續存放的,靜態字符數組buf1溢出后,就會覆蓋其相鄰區域字符數組buf2的值。利用這一點,攻擊者可以通過改寫BSS中的指針或函數指針等方式,改變程序原先的執行流程,使指針跳轉到特定的內存地址并執行指定操作3811A.2.4格式化串溢出與前面三種溢出不同的是,這種溢出漏洞是利用了編程語言自身存在的安全問題。格式化串溢出源自*printf()類函數的參數格式問題(如printf、fprintf、sprintf等)。intprintf(constchar*format,arg1,arg2,…);它們將根據format的內容(%s,%d,%p,%x,%n,…),將數據格式化后輸出。問題在于:*printf()函數并不能確定數據參數arg1,arg2,…究竟在什么地方結束,即函數本身不知道參數的個數,而只會根據format中打印格式的數目依次打印堆棧中參數format后面地址的內容。3911A.2.4格式化串溢出實例/*程序說明: %#x:按16進制輸出,并在前面加上0x %.20d:按10進制輸出,輸出20位,并在前面補0 %n:將顯示內容的長度輸出到一個變量中去*/#include<stdio.h>main(){ intnum=0x61616161; printf(″Before:num=%#x\n″,num); printf(″%.20d%n\n″,num,&num); printf(″After:num=%#x\n″,num);}40當程序執行第二個printf語句時,參數壓棧之后的內存布局如下:11A.2.4格式化串溢出實例41根據C函數調用約定,參數從右向左依次壓棧,所以參數&num比參數num先壓入棧中。也就是說,程序中將&num(num的地址)壓入棧作為printf()的第三個參數,而使用打印格式%n會將打印總長度保存到對應參數(&num)的地址中去,從而改變了num的值。整個程序的輸出結果為:

Before:num=0x6161616100000000001633771873After:num=0x14變量num的值已經變成了0x14(20)。11A.2.4格式化串溢出實例42如果將第二個printf語句修改為:printf(″%.20d%n\n″,num);//注意,這里沒有壓num的地址入棧則運行的結果為:Before:num=0x61616161Segmentationfault(coredumped)//執行第二個printf()時發生段錯誤了原因:printf()將堆棧中main()函數的變量num當作了%n所對應的參數,因此會將0x14保存到地址0x61616161中去,而0x61616161是不能訪問的地址,因此系統提示發生段錯誤。如果可以控制num的內容,那么就意味著可以修改任意地址(當然是允許寫入的地址)的內容。11A.2.4格式化串溢出實例4344在實際應用中,如果遇到脆弱的程序,將用戶的輸入錯誤地放在格式化串的位置,就會造成緩沖區溢出的攻擊。如果攻擊者可以事先構造好可以攻擊的代碼shellcode,如果可以將返回地址覆蓋成shellcode的起始地址,當緩沖區溢出發生后,程序就會跳到精心設計好的shellcode處執行,達到攻擊的目的。11A.2.4格式化串溢出實例11A.3緩沖區溢出攻擊的過程11A.3.1在程序的地址空間安排適當代碼11A.3.2使控制流跳轉到攻擊代碼4511A.3緩沖區溢出攻擊的過程緩沖區溢出攻擊的目的在于擾亂某些工作在特殊權限狀態下的程序,使攻擊者取得程序的控制權,借機提高自己的權限,控制整個主機。一般來說,攻擊者要實現緩沖區溢出攻擊,必須完成兩個任務,一是在程序的地址空間里安排適當的代碼;二是通過適當的初始化寄存器和存儲器,讓程序跳轉到安排好的地址空間執行。4611A.3.1在程序地址空間安排適當代碼這一步驟也可以簡稱為植入代碼的過程。如果所需要的代碼在被攻擊程序中已經存在,那么攻擊者所要做的只是向代碼傳遞一些參數,讓使程序跳轉到目標比如攻擊代碼要求執行“exec(‘/bin/sh’)”,而在libc庫中存在這樣的代碼“exec(arg)”,其中,arg是一個指向字符串的指針參數,那么,攻擊者只要把傳入的參數指針指向字符串“/bin/sh”,然后跳轉到libc庫中的相應的指令序列就OK了。47很多時候所需要的代碼并不能從被攻擊程序中找到,這就得用“植入法”來完成了。構造一個字符串,它包含的數據是可以在被攻擊程序的硬件平臺上運行的指令序列,在被攻擊程序的緩沖區如棧、堆或靜態數據區等地方找到足夠的空間存放這個字符串。然后再尋找適當的機會使程序跳轉到其所安排的這個地址空間中。11A.3.1在程序地址空間安排適當代碼4811A.3.2將控制流轉移到攻擊代碼緩沖區溢出最關鍵的步驟就是尋求改變

溫馨提示

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

評論

0/150

提交評論