第七章 緩沖區(qū)溢出攻擊及防御技術(shù)_第1頁
第七章 緩沖區(qū)溢出攻擊及防御技術(shù)_第2頁
第七章 緩沖區(qū)溢出攻擊及防御技術(shù)_第3頁
第七章 緩沖區(qū)溢出攻擊及防御技術(shù)_第4頁
第七章 緩沖區(qū)溢出攻擊及防御技術(shù)_第5頁
已閱讀5頁,還剩131頁未讀, 繼續(xù)免費閱讀

下載本文檔

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

文檔簡介

第七章緩沖區(qū)溢出攻擊及防御技術(shù)NetworkSecurityTechnology2014AutumnSemesterNetworkSecurityTechnology網(wǎng)絡(luò)安全技術(shù)本章內(nèi)容安排7.1緩沖區(qū)溢出概述7.2緩沖區(qū)溢出原理

7.3緩沖區(qū)溢出的過程7.4代碼植入技術(shù)7.5實例:ida溢出漏洞攻擊7.6緩沖區(qū)溢出的防御7.7小結(jié)NetworkSecurityTechnology2014AutumnSemester27.1緩沖區(qū)溢出概述什么是緩沖區(qū)?它是包含相同數(shù)據(jù)類型實例的一個連續(xù)的計算機內(nèi)存塊。是程序運行期間在內(nèi)存中分配的一個連續(xù)的區(qū)域,用于保存包括字符數(shù)組在內(nèi)的各種數(shù)據(jù)類型。所謂溢出,其實就是所填充的數(shù)據(jù)超出了原有的緩沖區(qū)邊界。兩者結(jié)合進來,所謂緩沖區(qū)溢出,就是向固定長度的緩沖區(qū)中寫入超出其預(yù)告分配長度的內(nèi)容,造成緩沖區(qū)中數(shù)據(jù)的溢出,從而覆蓋了緩沖區(qū)周圍的內(nèi)存空間。黑客借此精心構(gòu)造填充數(shù)據(jù),導(dǎo)致原有流程的改變,讓程序轉(zhuǎn)而執(zhí)行特殊的代碼,最終獲取控制權(quán)。NetworkSecurityTechnology2014AutumnSemester37.1緩沖區(qū)溢出概述利用緩沖區(qū)溢出漏洞進行攻擊最早可追溯到1988年Morris蠕蟲,它所利用的就是fingerd程序的緩沖區(qū)溢出漏洞。1989年,Spafford提交了一份分析報告,描述了VAX機上BSD版Unix的Fingerd的緩沖區(qū)溢出程序的技術(shù)細節(jié),引起了一部分安全人士對這個研究領(lǐng)域的重視。1996年,AlephOne發(fā)表了題為“Smashingthestackforfunandprofit”的文章后,首次詳細地介紹了Unix/Linux下棧溢出攻擊的原理、方法和步驟,揭示了緩沖區(qū)溢出攻擊中的技術(shù)細節(jié)。1999年w00w00安全小組的MattConover寫了基于堆緩沖區(qū)溢出專著,對堆溢出的機理進行了探索。NetworkSecurityTechnology2014AutumnSemester47.1緩沖區(qū)溢出概述Windows系統(tǒng)中緩沖區(qū)溢出的事例更是層出不窮。2001年“紅色代碼”蠕蟲利用微軟IISWebServer中的緩沖區(qū)溢出漏洞使300000多臺計算機受到攻擊;2003年1月,Slammer蠕蟲爆發(fā),利用的是微軟SQLServer2000中的缺陷;2004年5月爆發(fā)的“振蕩波”利用了Windows系統(tǒng)的活動目錄服務(wù)緩沖區(qū)溢出漏洞;2005年8月利用Windows即插即用緩沖區(qū)溢出漏洞的“狙擊波”被稱為歷史上最快利用微軟漏洞進行攻擊的惡意代碼。2008年底至2009年的Conficker蠕蟲利用的是Windows處理遠程RPC請求時的漏洞(MS08-067)。NetworkSecurityTechnology2014AutumnSemester57.1緩沖區(qū)溢出概述目前,利用緩沖區(qū)溢出漏洞進行的攻擊已經(jīng)占所有系統(tǒng)攻擊總數(shù)的80%以上。緩沖區(qū)溢出攻擊之所以日益普遍,其原因在于各種操作系統(tǒng)和應(yīng)用軟件上存在的緩沖區(qū)溢出問題數(shù)不勝數(shù),而其帶來的影響不容小覷。對緩沖區(qū)溢出漏洞攻擊,可以導(dǎo)致程序運行失敗、系統(tǒng)崩潰以及重新啟動等后果。更為嚴重的是,可以利用緩沖區(qū)溢出執(zhí)行非授權(quán)指令,甚至取得系統(tǒng)特權(quán),進而進行各種非法操作。如何防止和檢測出利用緩沖區(qū)溢出漏洞進行的攻擊,就成為防御網(wǎng)絡(luò)入侵以及入侵檢測的重點之一。NetworkSecurityTechnology2014AutumnSemester67.1緩沖區(qū)溢出概述與其他的攻擊類型相比,緩沖區(qū)溢出攻擊不需要太多的先決條件殺傷力很強技術(shù)性強緩沖區(qū)溢出比其他一些黑客攻擊手段更具有破壞力和隱蔽性。這也是利用緩沖區(qū)溢出漏洞進行攻擊日益普遍的原因。NetworkSecurityTechnology2014AutumnSemester77.1緩沖區(qū)溢出概述破壞性:它極容易使服務(wù)程序停止運行,服務(wù)器死機甚至刪除服務(wù)器上的數(shù)據(jù)。隱蔽性:首先,漏洞被發(fā)現(xiàn)之前,程序員一般是不會意識到自己的程序存在漏洞的(事實上,漏洞的發(fā)現(xiàn)者往往并非編寫者),于是疏于監(jiān)測;其次,被植入的攻擊代碼一般都很短,執(zhí)行時間也非常短,很難在執(zhí)行過程中被發(fā)現(xiàn),而且其執(zhí)行并不一定會使系統(tǒng)報告錯誤,并可能不影響正常程序的運行;NetworkSecurityTechnology2014AutumnSemester87.1緩沖區(qū)溢出概述隱蔽性:第三,由于漏洞存在于防火墻內(nèi)部的主機上,攻擊者可以在防火墻內(nèi)部堂而皇之地取得本來不被允許或沒有權(quán)限的控制權(quán);第四,攻擊的隨機性和不可預(yù)測性使得防御變得異常艱難,沒有攻擊時,被攻擊程序本身并不會有什么變化,也不會存在任何異常的表現(xiàn);最后,緩沖區(qū)溢出漏洞的普遍存在,針對它的攻擊讓人防不勝防(各種補丁程序也可能存在著這種漏洞)。NetworkSecurityTechnology2014AutumnSemester97.2緩沖區(qū)溢出原理7.2.1棧溢出7.2.2堆溢出7.2.3BSS溢出7.2.4格式化串溢出NetworkSecurityTechnology2014AutumnSemester107.2緩沖區(qū)溢出原理當程序運行時,計算機會在內(nèi)存區(qū)域中開辟一段連續(xù)的內(nèi)存塊,包括代碼段、數(shù)據(jù)段和堆棧段三部分。NetworkSecurityTechnology2014AutumnSemester117.2緩沖區(qū)溢出原理程序在內(nèi)存中的存放形式NetworkSecurityTechnology2014AutumnSemester12NetworkSecurityTechnology2014AutumnSemester137.2緩沖區(qū)溢出原理代碼段(.text),也稱文本段(TextSegment),存放著程序的機器碼和只讀數(shù)據(jù),可執(zhí)行指令就是從這里取得的。如果可能,系統(tǒng)會安排好相同程序的多個運行實體共享這些實例代碼。這個段在內(nèi)存中一般被標記為只讀,任何對該區(qū)的寫操作都會導(dǎo)致段錯誤(SegmentationFault)。數(shù)據(jù)段,包括已初始化的數(shù)據(jù)段(.data)和未初始化的數(shù)據(jù)段(.bss),前者用來存放保存全局的和靜態(tài)的已初始化變量,后者用來保存全局的和靜態(tài)的未初始化變量。數(shù)據(jù)段在編譯時分配。NetworkSecurityTechnology2014AutumnSemester147.2緩沖區(qū)溢出原理堆棧段分為堆和棧堆(Heap):位于BSS內(nèi)存段的上邊,用來存儲程序運行時分配的變量。堆的大小并不固定,可動態(tài)擴張或縮減。其分配由malloc()、new()等這類實時內(nèi)存分配函數(shù)來實現(xiàn)。當進程調(diào)用malloc等函數(shù)分配內(nèi)存時,新分配的內(nèi)存就被動態(tài)添加到堆上(堆被擴張);當利用free等函數(shù)釋放內(nèi)存時,被釋放的內(nèi)存從堆中被剔除(堆被縮減)。堆的內(nèi)存釋放由應(yīng)用程序去控制,通常一個new()就要對應(yīng)一個delete(),如果程序員沒有釋放掉,那么在程序結(jié)束后操作系統(tǒng)會自動回收。NetworkSecurityTechnology2014AutumnSemester157.2緩沖區(qū)溢出原理棧(Stack)是一種用來存儲函數(shù)調(diào)用時的臨時信息的結(jié)構(gòu),如函數(shù)調(diào)用所傳遞的參數(shù)、函數(shù)的返回地址、函數(shù)的局部變量等。在程序運行時由編譯器在需要的時候分配,在不需要的時候自動清除。棧的特性:最后一個放入棧中的物體總是被最先拿出來,這個特性通常稱為先進后出(FILO)隊列。棧的基本操作:PUSH操作:向棧中添加數(shù)據(jù),稱為壓棧,數(shù)據(jù)將放置在棧頂;POP操作:POP操作相反,在棧頂部移去一個元素,并將棧的大小減一,稱為彈棧。NetworkSecurityTechnology2014AutumnSemester16堆和棧的區(qū)別分配和管理方式不同堆是動態(tài)分配的,其空間的分配和釋放都由程序員控制。棧由編譯器自動管理。棧有兩種分配方式:靜態(tài)分配和動態(tài)分配。靜態(tài)分配由編譯器完成,比如局部變量的分配。動態(tài)分配由alloca()函數(shù)進行分配,但是棧的動態(tài)分配和堆是不同的,它的動態(tài)分配是由編譯器進行釋放,無須手工控制。產(chǎn)生碎片不同對堆來說,頻繁的new/delete或者malloc/free勢必會造成內(nèi)存空間的不連續(xù),造成大量的碎片,使程序效率降低。對棧而言,則不存在碎片問題,因為棧是先進后出的隊列,永遠不可能有一個內(nèi)存塊從棧中間彈出。生長方向不同堆是向著內(nèi)存地址增加的方向增長的,從內(nèi)存的低地址向高地址方向增長。棧的生長方向與之相反,是向著內(nèi)存地址減小的方向增長,由內(nèi)存的高地址向低地址方向增長。NetworkSecurityTechnology2014AutumnSemester17NetworkSecurityTechnology2014AutumnSemester187.2緩沖區(qū)溢出原理在這里,我們假設(shè)現(xiàn)在有一個程序,它的函數(shù)調(diào)用順序如下。main()->;func_1()->;func_2()->;func_3()

即:主函數(shù)main調(diào)用函數(shù)func_1;函數(shù)func_1調(diào)用函數(shù)func_2;函數(shù)func_2調(diào)用函數(shù)func_3。其詳細結(jié)構(gòu)圖如下頁圖所示。NetworkSecurityTechnology2014AutumnSemester19NetworkSecurityTechnology2014AutumnSemester20程序在內(nèi)存中的影像隨著函數(shù)調(diào)用層數(shù)的增加,函數(shù)棧幀是一塊塊地向內(nèi)存低地址方向延伸的。隨著進程中函數(shù)調(diào)用層數(shù)的減少,即各函數(shù)調(diào)用的返回,棧幀會一塊塊地被遺棄而向內(nèi)存的高址方向回縮。各函數(shù)的棧幀大小隨著函數(shù)的性質(zhì)的不同而不等,由函數(shù)的局部變量的數(shù)目決定。在緩沖區(qū)溢出中,我們主要關(guān)注數(shù)據(jù)區(qū)和堆棧區(qū)。NetworkSecurityTechnology2014AutumnSemester21程序所使用的棧在使用棧時,引用棧幀需要借助兩個寄存器。一個是SP(ESP),即棧頂指針,它隨著數(shù)據(jù)入棧出棧而發(fā)生變化。另一個是BP(EBP),即基地址指針,它用于標識棧中一個相對穩(wěn)定的位置,通過BP,再加上偏移地址,可以方便地引用函數(shù)參數(shù)以及局部變量。NetworkSecurityTechnology2014AutumnSemester22程序所使用的棧函數(shù)被調(diào)用的時候,棧中的壓入情況如下:Func函數(shù)中的局部變量調(diào)用Func函數(shù)前的EBP退出Func函數(shù)后的返回地址傳遞給Func的實參內(nèi)存低地址內(nèi)存高地址最先壓入棧最后壓入棧NetworkSecurityTechnology2014AutumnSemester23程序所使用的棧在局部變量的下面,是前一個調(diào)用函數(shù)的EBP,接下來就是返回地址。如果局部變量發(fā)生溢出,很有可能會覆蓋掉EBP甚至RET(返回地址),這就是緩沖區(qū)溢出攻擊的“奧秘”所在。NetworkSecurityTechnology2014AutumnSemester247.2緩沖區(qū)溢出原理如果在堆棧中壓入的數(shù)據(jù)超過預(yù)先給堆棧分配的容量時,就會出現(xiàn)堆棧溢出,從而使得程序運行失??;如果發(fā)生溢出的是大型程序還有可能會導(dǎo)致系統(tǒng)崩潰。NetworkSecurityTechnology2014AutumnSemester257.2.1棧溢出程序中發(fā)生函數(shù)調(diào)用時,計算機做如下操作:首先把指令寄存器EIP(它指向當前CPU將要運行的下一條指令的地址)中的內(nèi)容壓入棧,作為程序的返回地址(下文中用RET表示);之后放入棧的是基址寄存器EBP,它指向當前函數(shù)棧幀(stackframe)的底部;然后把當前的棧指針ESP拷貝到EBP,作為新的基地址,最后為本地變量的動態(tài)存儲分配留出一定空間,并把ESP減去適當?shù)臄?shù)值。NetworkSecurityTechnology2014AutumnSemester267.2.1棧溢出實例我們來看一段簡單程序的執(zhí)行過程中對棧的操作和溢出的產(chǎn)生過程。

#include<stdio.h> intmain(){ charname[16]; gets(name); for(inti=0;i<16&&name[i];i++) printf(“%c”,name[i]); }NetworkSecurityTechnology2014AutumnSemester277.2.1棧溢出實例編譯上述代碼,輸入helloworld!結(jié)果會輸出helloworld!在調(diào)用main()函數(shù)時,程序?qū)5牟僮魇沁@樣的:先在棧底壓入返回地址接著將棧指針EBP入棧,并把EBP修改為現(xiàn)在的ESP之后ESP減16,即向上增長16個字節(jié),用來存放name[]數(shù)組NetworkSecurityTechnology2014AutumnSemester287.2.1棧溢出實例現(xiàn)在棧的布局如圖所示。NetworkSecurityTechnology2014AutumnSemester297.2.1棧溢出實例執(zhí)行完gets(name)之后,棧中的內(nèi)容如下圖所示NetworkSecurityTechnology2014AutumnSemester307.2.1棧溢出實例接著執(zhí)行for循環(huán),逐個打印name[]數(shù)組中的字符,直到碰到0x00字符最后,從main返回,將ESP增加16以回收name[]數(shù)組占用的空間,此時ESP指向先前保存的EBP值。程序?qū)⑦@個值彈出并賦給EBP,使EBP重新指向main()函數(shù)調(diào)用者的棧的底部。然后再彈出現(xiàn)在位于棧頂?shù)姆祷氐刂稲ET,賦給EIP,CPU繼續(xù)執(zhí)行EIP所指向的命令。說明1:EIP寄存器的內(nèi)容表示將要執(zhí)行的下一條指令地址。說明2:當調(diào)用函數(shù)時,Call指令會將返回地址(Call指令下一條指令地址)壓入棧Ret指令會把壓棧的返回地址彈給EIPNetworkSecurityTechnology2014AutumnSemester317.2.1棧溢出實例如果輸入的字符串長度超過16個字節(jié),例如輸入:helloworld!AAAAAAAA……,則當執(zhí)行完gets(name)之后,棧的情況如圖所示。NetworkSecurityTechnology2014AutumnSemester327.2.1棧溢出實例由于輸入的字符串太長,name[]數(shù)組容納不下,只好向棧的底部方向繼續(xù)寫‘A’。這些‘A’覆蓋了堆棧的老的元素,從上頁圖可以看出,EBP,Ret都已經(jīng)被‘A’覆蓋了。從main返回時,就必然會把‘AAAA’的ASCII碼——0x41414141視作返回地址,CPU會試圖執(zhí)行0x41414141處的指令,結(jié)果出現(xiàn)難以預(yù)料的后果,這樣就產(chǎn)生了一次堆棧溢出。在Windows

XP下用VC6.0運行程序,結(jié)果如下頁圖所示。NetworkSecurityTechnology2014AutumnSemester33NetworkSecurityTechnology2014AutumnSemester347.2.2堆溢出當我們需要較大的緩沖區(qū)或在寫代碼時不知道包含在緩沖區(qū)中對象的大小,常常要使用堆。堆溢出的工作方式幾乎與棧溢出的工作方式完全相同,唯一不同的是,堆沒有壓棧和入棧操作,而是分配和回收內(nèi)存。C語言中使用malloc()和free()函數(shù)實現(xiàn)內(nèi)存的動態(tài)分配和回收,C++語言使用new()和delete()函數(shù)來實現(xiàn)相同的功能。NetworkSecurityTechnology2014AutumnSemester357.2.2堆溢出實例#include<stdio.h>#include<stdlib.h>#include<unistd.h>#include<string.h>#defineBUFFER-SIZE16#defineOVERLAYSIZE8/*我們將覆蓋buf2的前OVERLAYSIZE個字節(jié)*/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;}NetworkSecurityTechnology2014AutumnSemester367.2.2堆溢出實例運行結(jié)果:/users/test41%./heap1buf1=0x8049858,buf2=0x8049870,diff=0x18(24)bytesbeforeoverflow:buf2=aaaaaaaaaaaaaaaafteroverflow:buf2=bbbbbbbbaaaaaaa我們看到,buf2的前八個字節(jié)被覆蓋了,這是因為往buf1中填寫的數(shù)據(jù)超出了它的邊界進入了buf2的范圍。由于buf2的數(shù)據(jù)仍然在有效的Heap區(qū)內(nèi),程序仍然可以正常結(jié)束。

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

Before:num=0x6161616100000000001633771873After:num=0x14變量num的值已經(jīng)變成了0x14(20)。NetworkSecurityTechnology2014AutumnSemester457.2.4格式化串溢出實例如果將第二個printf語句修改為:printf(″%.20d%n\n″,num);//注意,這里沒有壓num的地址入棧則運行的結(jié)果為:Before:num=0x61616161Segmentationfault(coredumped)//執(zhí)行第二個printf()時發(fā)生段錯誤了原因:printf()將堆棧中main()函數(shù)的變量num當作了%n所對應(yīng)的參數(shù),因此會將0x14保存到地址0x61616161中去,而0x61616161是不能訪問的地址,因此系統(tǒng)提示發(fā)生段錯誤。如果可以控制num的內(nèi)容,那么就意味著可以修改任意地址(當然是允許寫入的地址)的內(nèi)容。NetworkSecurityTechnology2014AutumnSemester467.2.4格式化串溢出在實際應(yīng)用中,如果遇到脆弱的程序,將用戶的輸入錯誤地放在格式化串的位置,就會造成緩沖區(qū)溢出的攻擊。如果攻擊者可以事先構(gòu)造好可以攻擊的代碼shellcode,如果可以將返回地址覆蓋成shellcode的起始地址,當緩沖區(qū)溢出發(fā)生后,程序就會跳到精心設(shè)計好的shellcode處執(zhí)行,達到攻擊的目的。NetworkSecurityTechnology2014AutumnSemester477.3緩沖區(qū)溢出攻擊的過程7.3.1在程序的地址空間安排適當代碼7.3.2使控制流跳轉(zhuǎn)到攻擊代碼NetworkSecurityTechnology2014AutumnSemester487.3緩沖區(qū)溢出攻擊的過程緩沖區(qū)溢出攻擊的目的在于擾亂某些工作在特殊權(quán)限狀態(tài)下的程序,使攻擊者取得程序的控制權(quán),借機提高自己的權(quán)限,控制整個主機。一般來說,攻擊者要實現(xiàn)緩沖區(qū)溢出攻擊,必須完成兩個任務(wù),一是在程序的地址空間里安排適當?shù)拇a;二是通過適當?shù)某跏蓟拇嫫骱痛鎯ζ?,讓程序跳轉(zhuǎn)到安排好的地址空間執(zhí)行。NetworkSecurityTechnology2014AutumnSemester497.3.1在程序地址空間安排適當代碼這一步驟也可以簡稱為植入代碼的過程。如果所需要的代碼在被攻擊程序中已經(jīng)存在了,那么攻擊者所要做的只是向代碼傳遞一些參數(shù),然后使程序跳轉(zhuǎn)到目標。比如攻擊代碼要求執(zhí)行“exec(‘/bin/sh’)”,而在libc庫中存在這樣的代碼“exec(arg)”,其中,arg是一個指向字符串的指針參數(shù),那么,攻擊者只要把傳入的參數(shù)指針指向字符串“/bin/sh”,然后跳轉(zhuǎn)到libc庫中的相應(yīng)的指令序列就OK了。NetworkSecurityTechnology2014AutumnSemester507.3.1在程序地址空間安排適當代碼很多時候所需要的代碼并不能從被攻擊程序中找到,這就得用“植入法”來完成了。構(gòu)造一個字符串,它包含的數(shù)據(jù)是可以在被攻擊程序的硬件平臺上運行的指令序列,在被攻擊程序的緩沖區(qū)如棧、堆或靜態(tài)數(shù)據(jù)區(qū)等地方找到足夠的空間存放這個字符串。然后再尋找適當?shù)臋C會使程序跳轉(zhuǎn)到其所安排的這個地址空間中。NetworkSecurityTechnology2014AutumnSemester517.3.2將控制流轉(zhuǎn)移到攻擊代碼緩沖區(qū)溢出最關(guān)鍵的步驟就是尋求改變程序執(zhí)行流程的方法,擾亂程序的正常執(zhí)行次序,使之跳轉(zhuǎn)到攻擊代碼。原則上來講,攻擊時所針對的緩沖區(qū)溢出的程序空間可以為任意空間,但因不同地方程序空間的突破方式和內(nèi)存空間的定位差異,也就產(chǎn)生了多種轉(zhuǎn)移方式。FunctionPointers(函數(shù)指針)ActivationRecords(激活記錄)Longjmpbuffers(長跳轉(zhuǎn)緩沖區(qū))NetworkSecurityTechnology2014AutumnSemester52FunctionPointers(函數(shù)指針)函數(shù)指針:void(*foo)()聲明了一個返回值為void類型的函數(shù)指針變量foo。函數(shù)指針可以用來定位任意地址空間,攻擊時只需要在任意空間里的函數(shù)指針鄰近處找到一個能夠溢出的緩沖區(qū),然后用溢出來的數(shù)據(jù)改變函數(shù)指針的值。當程序使用函數(shù)指針調(diào)用函數(shù)時,程序的流程就會指向攻擊者定義的指令序列。NetworkSecurityTechnology2014AutumnSemester53用函數(shù)指針控制程序流程圖示NetworkSecurityTechnology2014AutumnSemester54ActivationRecords(激活記錄)當一個函數(shù)調(diào)用發(fā)生時,堆棧中會留駐一個ActivationRecord,它包含了函數(shù)結(jié)束時返回的地址。溢出這一記錄,使這個返回地址指向攻擊代碼,當函數(shù)調(diào)用結(jié)束時,程序就會跳轉(zhuǎn)到所設(shè)定的地址,而不是原來的地址。這樣的溢出方式比較常見。NetworkSecurityTechnology2014AutumnSemester55用活動記錄控制程序流程圖示NetworkSecurityTechnology2014AutumnSemester56Longjmpbuffers(長跳轉(zhuǎn)緩沖區(qū))在C語言中包含了一個簡單的檢驗/恢復(fù)系統(tǒng),稱為setjmp/longjmp,在檢驗點設(shè)定setjmp(buffer),用longjmp(buffer)來恢復(fù)檢驗點。和函數(shù)指針一樣,longjmp(buffer)能夠跳轉(zhuǎn)到buffer中信息所指向的任何地方。如果攻擊者能夠修改buffer的內(nèi)容,使用longjmp(buffer)就可以跳轉(zhuǎn)到攻擊代碼。使用這種方法,需要先找到一個可供溢出的緩沖區(qū)NetworkSecurityTechnology2014AutumnSemester57植入代碼和流程控制的綜合常見的緩沖區(qū)溢出攻擊是溢出字符串綜合使用了代碼植入和ActivationRecords改寫技術(shù)。攻擊者定位在一個可供溢出的局部變量,然后向程序傳遞一個設(shè)計好的長字符串,在引發(fā)緩沖區(qū)溢出改變ActivationRecords的同時植入代碼。即用一個長字符串完成代碼植入并覆蓋函數(shù)的返回地址。示意圖見下面。NetworkSecurityTechnology2014AutumnSemester58植入代碼和流程控制的綜合圖示NetworkSecurityTechnology2014AutumnSemester597.4代碼植入技術(shù)7.4.1shellcode7.4.2返回地址7.4.3填充數(shù)據(jù)7.4.4植入代碼的構(gòu)造類型7.4.5shellcode使用示例NetworkSecurityTechnology2014AutumnSemester607.4代碼植入技術(shù)所植入的代碼一般由shellcode、返回地址、填充數(shù)據(jù)這三種元素按照一定的結(jié)構(gòu)和構(gòu)造類型組成什么是shellcode是植入代碼的核心組成部分,是一段能完成特殊任務(wù)的自包含的二進制代碼。由于它最初是用來生成一個高權(quán)限的shell,因此而得名。雖然現(xiàn)在人們已經(jīng)遠遠不滿足于生成一個shell,但shellcode的“美名”一直延用至今。攻擊者通過巧妙的編寫和設(shè)置,利用系統(tǒng)的漏洞將shellcode送入系統(tǒng)中使其得以執(zhí)行,從而獲取特殊權(quán)限的執(zhí)行環(huán)境,或給自己設(shè)立有特權(quán)的帳戶,取得目標機器的控制權(quán)。NetworkSecurityTechnology2014AutumnSemester617.4.1shellcode除了經(jīng)典的利用exec()系統(tǒng)調(diào)用執(zhí)行/bin/sh獲取shell之外,下表列出了Unix/Linux系統(tǒng)中的shellcode經(jīng)常用到的一些其它系統(tǒng)調(diào)用。NetworkSecurityTechnology2014AutumnSemester627.4.1shellcode在linux中,為了獲得一個交互式shell,一般需要執(zhí)行代碼execve(“/bin/sh”,“/bin/sh”,NULL);對此代碼進行編譯后得到機器碼。charshellcode[]=“\xeb\x1f\x5e\x89\x76\x08\x31\xc0\x88\x46\x07\x89\x46\x0c\xb0\x0b\x89\xf3\x8d\x4e\x08\x8d\x56\x0c\xcd\x80\x31\xdb\x89\xd8\x40\xcd\x80\xe8\xdc\xff\xff\xff/bin/sh”;注意:不同的操作系統(tǒng)、不同的機器硬件產(chǎn)生系統(tǒng)調(diào)用的方法和參數(shù)傳遞的方法也不盡相同。NetworkSecurityTechnology2014AutumnSemester637.4.2返回地址返回地址是指shellcode的入口地址。攻擊者如果希望目標程序改變其原來的執(zhí)行流程,轉(zhuǎn)而執(zhí)行shellcode,則必須設(shè)法用shellcode的入口地址覆蓋某個跳轉(zhuǎn)指令。由于所植入的代碼是被復(fù)制到目標機器的緩沖區(qū)中,攻擊者無法知道其進入到緩沖區(qū)后的確切地址。不過,內(nèi)存的分配是有規(guī)律的,如Linux系統(tǒng),當用戶程序運行時,棧是從0xbfffffff開始向內(nèi)存低端生長的。如果攻擊者想通過改寫函數(shù)返回地址的方式使程序指令發(fā)生跳轉(zhuǎn),則程序指令跳轉(zhuǎn)后的指向也應(yīng)該在0xbfffffff附近。事實上,雖然不同的緩沖區(qū)溢出漏洞,其植入代碼的返回地址都不同,但均處于某個較小的地址區(qū)間內(nèi)。另外,為了提高覆蓋函數(shù)返回地址的成功率,往往在植入代碼中安排一段由重復(fù)的返回地址組成的內(nèi)容。NetworkSecurityTechnology2014AutumnSemester647.4.3填充數(shù)據(jù)由于攻擊者不能準確地判斷shellcode的入口地址,因此為了提高shellcode的命中率,往往在shellcode的前面安排一定數(shù)量的填充數(shù)據(jù)。填充數(shù)據(jù)必須對植入代碼的功能完成沒有影響,這樣只要返回地址指向填充數(shù)據(jù)中的任何一個位置,均可以確保shellcode順利執(zhí)行。填充數(shù)據(jù)還可以起到一個作用,就是當植入代碼的長度夠不著覆蓋目標如函數(shù)返回地址時,可以通過增加填充數(shù)據(jù)的數(shù)量,使植入代碼的返回地址能夠覆蓋函數(shù)返回地址。NetworkSecurityTechnology2014AutumnSemester657.4.3填充數(shù)據(jù)對于IntelCPU來說,填充數(shù)據(jù)實質(zhì)上是一種單字節(jié)指令,使用得最多的是空操作指令NOP,其值為0x90,該指令什么也不做,僅跳過一個CPU周期。除此之外,還有其他的單字節(jié)指令可以作為填充數(shù)據(jù)使用,如調(diào)整計算結(jié)果的AAA和AAS、操作標志位的CLC和CLD等。在植入代碼中,往往安排比較長甚至幾百上千的填充數(shù)據(jù),而一個有效的指令長度實際最大也不過10字節(jié)左右,因此,也可以根據(jù)這一特點來判斷是否發(fā)生了緩沖區(qū)溢出攻擊。NetworkSecurityTechnology2014AutumnSemester667.4.4植入代碼的構(gòu)造類型所植入的代碼是由黑客精心構(gòu)造的,而由于緩沖區(qū)溢出自身的特性,它的結(jié)構(gòu)和構(gòu)造類型有一定的特性。NSR模式RNS模式AR模式其中,S代表shellcode,R代表返回地址,N代表填充數(shù)據(jù),A表示環(huán)境變量。NetworkSecurityTechnology2014AutumnSemester67NSR模式NetworkSecurityTechnology2014AutumnSemester68NSR模式在shellcode的后面安排一定數(shù)量的返回地址,在前面安排一定數(shù)量的填充數(shù)據(jù),這種結(jié)構(gòu)稱為NSR型,或前端同步型。原理是:只要全部的N和S都處于緩沖區(qū)內(nèi),并且不覆蓋RET,而使R正好覆蓋存放RET的??臻g,這樣只要將R的值設(shè)置為指向N區(qū)中任一位置,就必然可以成功地跳轉(zhuǎn)到我們預(yù)先編寫的shellcode處執(zhí)行。NetworkSecurityTechnology2014AutumnSemester69NSR模式這是一種經(jīng)典結(jié)構(gòu),適合于溢出緩沖區(qū)較大、足夠放下我們的shellcode的情況。這是一種非精確定位的方法,N元素越多成功率越大,其缺點是緩沖區(qū)必須足夠大,否則shellcode放不下或者N元素數(shù)量太少都會造成失敗。NetworkSecurityTechnology2014AutumnSemester70RNS模式NetworkSecurityTechnology2014AutumnSemester71RNS模式其原理是:只要把整個緩沖區(qū)全部用大量的返回地址填滿,并且保證會覆蓋存放RET的棧空間,再在后面緊接N元素和shellcode,這樣就可以很容易地確定返回地址R的值,并在植入代碼中進行設(shè)置。這里填充的R的數(shù)目必須能夠覆蓋ret,R的值必須指向大量N中的任何一個。這種方法對大的和小的緩沖區(qū)都有效。而且RET地址較容易計算。NetworkSecurityTechnology2014AutumnSemester72AR模式NetworkSecurityTechnology2014AutumnSemester73AR模式又稱環(huán)境變量型。這種構(gòu)造類型不同于NSR型和RNS型,它必須事先將shellcode放置在環(huán)境變量中,然后將shellcode的入口地址和填充數(shù)據(jù)構(gòu)成植入代碼進行溢出攻擊。這種構(gòu)造類型對于大、小溢出緩沖區(qū)都適合。但由于必須事先將shellcode放置到環(huán)境變量中,故其應(yīng)用受到了限制,只能用于本地而不能用于遠程攻擊。NetworkSecurityTechnology2014AutumnSemester74緩沖區(qū)溢出攻擊的三步曲從上面的分析可知,不管哪種類型的緩沖區(qū)溢出攻擊,一般都存在下面三個步驟:構(gòu)造需要執(zhí)行的代碼shellcode,并將其放到目標系統(tǒng)的內(nèi)存。獲得緩沖區(qū)的大小和定位溢出點ret的位置??刂瞥绦蛱D(zhuǎn),改變程序流程。具體如何完成這三個攻擊步驟將在實驗課中介紹。NetworkSecurityTechnology2014AutumnSemester757.4.5shellcode使用示例下面通過一個例子說明棧溢出是如何產(chǎn)生的、以及如何利用它來執(zhí)行精心安排的shellcode:Vul-func(char*buf-src){

charbuf-dest[16];

strcpy(buf-dest,buf-src);}main(){

inti;

charstr[256];

for(i=0;i<256;i++) str[i]=’a’;

Vul-func(str);}NetworkSecurityTechnology2014AutumnSemester767.4.5shellcode使用示例顯然,數(shù)組str的大小(256字節(jié))遠遠超過了目的緩沖區(qū)buf-dest的大小(16字節(jié)),發(fā)生了緩沖區(qū)溢出。調(diào)用函數(shù)Vul-func前后,堆棧使用情況如下頁圖所示。NetworkSecurityTechnology2014AutumnSemester777.4.5shellcode使用示例

NetworkSecurityTechnology2014AutumnSemester787.4.5shellcode使用示例從上頁圖可以看出,Vul-func函數(shù)調(diào)用完成后,str數(shù)組的內(nèi)容(256個字母‘a(chǎn)’即0x616161?)已經(jīng)覆蓋了從地址buf-dest到地址buf-dest+256內(nèi)存空間原來所有的內(nèi)容,包括調(diào)用函數(shù)Vul-func時保存的EBP和返回地址RET。這樣,函數(shù)返回時就返回到地址0x61616161,發(fā)生錯誤。緩沖區(qū)溢出使得程序執(zhí)行的流程發(fā)生了變化。NetworkSecurityTechnology2014AutumnSemester797.4.5shellcode使用示例如果能在返回地址RET處寫入一段精心設(shè)計好的攻擊代碼的首地址,系統(tǒng)就會轉(zhuǎn)去執(zhí)行攻擊代碼,從而被攻破。如要獲得一個shell,可以安排執(zhí)行如下代碼:execve(“/bin/sh”,“/bin/sh”,NULL)NetworkSecurityTechnology2014AutumnSemester807.4.5shellcode使用示例將這段代碼進行反匯編,就獲得了一個交互式shell的shellcode。只需將函數(shù)的返回地址RET覆蓋為此shellcode的首地址即可獲得一個shell:charshellcode[]=

“\xeb\x1f\x5e\x89\x76\x08\x31\xc0\x88\x46\x07\x89\x46\x0c\xb0\x0b”

“\x89\xf3\x8d\x4e\x08\x8d\x56\x0c\xcd\x80\x31\xdb\x89\xd8\x40\xcd\”

“\x80\xe8\xdc\xff\xff\xff/bin/sh”;NetworkSecurityTechnology2014AutumnSemester817.4.5shellcode使用示例為了說明如何使用shellcode以及如何精心安排溢出字符串,下面舉個例子來說明。通過運行下面的代碼,就能獲得一個shell,當然,這個程序只具有實驗?zāi)康?,不具有攻擊性。詳細的攻擊實例將在實驗課中介紹。NetworkSecurityTechnology2014AutumnSemester827.4.5shellcode使用示例ReturnaddBuffer(96bytes)ilong_ptr高地址低地址Para2Para1EBPBufferaddBufferaddBufferadd…Bufferadd…charshellcode[]=(前面的shellcode)charlarge-string[128];voidmain(intargc,char**argv){charbuffer[96];inti;long*long-ptr=(long*)large-string;/*用buffer的首地址填滿large-string*/for(i=0;i<32;i++)*(long-ptr+i)=(int)buffer;/*將shellcode填入large-string的前面部分*/for(i=0;i<strlen(shellcode);i++)

large-string[i]=shellcode[i];strcpy(buffer,large-string);}shellcodeNetworkSecurityTechnology2014AutumnSemester837.4.5shellcode使用示例這是一個利用棧溢出的程序。當strcpy函數(shù)調(diào)用返回時,其返回地址RET已被修改為buffer的首地址,而該地址正好存放的是shellcode。于是,shellcode被執(zhí)行,成功獲得一個交互式shell。這是由于strcpy執(zhí)行時不進行邊界檢查所致。NetworkSecurityTechnology2014AutumnSemester847.4.5shellcode使用示例以上說明的是攻擊我們自己的程序的原理。實際上,被攻擊程序的代碼及其緩沖區(qū)地址對攻擊者來說是未知的,這就增加了攻擊的難度。一個有效地解決這個問題的辦法是使用NSR模式,下面介紹NSR模式在此例中的應(yīng)用。NetworkSecurityTechnology2014AutumnSemester857.4.5shellcode使用示例首先,用猜測的buffer地址填充整個large-string;然后,把shellcode放置在large-string的中部,前部用空指令NOP填充;再將large-string的內(nèi)容放入注入到帶有緩沖區(qū)溢出隱患的程序,就可能獲得一個shell。前部填充的NOP是為了增加函數(shù)調(diào)用返回命中shellcode的命中率,只要返回地址指向其中一個NOP,shellcode將最終會被執(zhí)行,從而獲得shell。NetworkSecurityTechnology2014AutumnSemester867.5實例:ida溢出漏洞攻擊Ida漏洞判斷:Windows2Kserver或NT的IIS服務(wù)器的沒有打servicepark(補丁包,簡稱SP),那么它就存在一個ida漏洞,我們在瀏覽器里輸入一個不存在的.ida文件,如:http://xxx.xxx.xxx.xxx/Nature.ida

如果瀏覽器就會返回如下的提示:找不到IDA文件在……則說明該WEB服務(wù)器存在IDA溢出漏洞。NetworkSecurityTechnology2014AutumnSemester87ida溢出漏洞攻擊工具:ofscan:IIS遠程溢出漏洞掃描工具Idahack:ida漏洞利用工具Nc:瑞士軍刀NetworkSecurityTechnology2014AutumnSemester88Ofscan使用方法NetworkSecurityTechnology2014AutumnSemester89用ofscan掃描存在ida漏洞的主機掃描到6臺有可能有漏洞。NetworkSecurityTechnology2014AutumnSemester90Idahack使用方法NetworkSecurityTechnology2014AutumnSemester91用idahack進行攻擊—失敗后的結(jié)果NetworkSecurityTechnology2014AutumnSemester92用idahack進行攻擊—成功后的結(jié)果NetworkSecurityTechnology2014AutumnSemester93用nc獲得一個shell

NetworkSecurityTechnology2014AutumnSemester94獲得shell后可以查看對方的信息NetworkSecurityTechnology2014AutumnSemester95在shell中運行命令:添加用戶NetworkSecurityTechnology2014AutumnSemester967.6緩沖區(qū)溢出的防御7.6.1緩沖區(qū)溢出防御概述7.6.2源碼級保護方法7.6.3運行期保護方法7.6.4阻止攻擊代碼執(zhí)行7.6.5加強系統(tǒng)保護NetworkSecurityTechnology2014AutumnSemester977.6.1緩沖區(qū)溢出防御概述從前面我們可以看出,緩沖區(qū)溢出的真正原因在于某些編程語言缺乏類型安全,程序缺少邊界檢查。這一方面是源于編程語言和庫函數(shù)本身的弱點,如C語言中對數(shù)組和指針引用不自動進行邊界檢查,一些字符串處理函數(shù)如strcpy、sprintf等存在著嚴重的安全問題。另一方面是程序員進行程序編寫時,由于經(jīng)驗不足或粗心大意,沒有進行或忽略了邊界檢查,使得緩沖區(qū)溢出漏洞幾乎無處不在,為緩沖區(qū)溢出攻擊留下了隱患。NetworkSecurityTechnology2014AutumnSemester987.6.1緩沖區(qū)溢出防御概述這樣要么放棄使用這類語言中的不安全類型,放棄不安全的類型就等于放棄這類語言的精華;要么使用其它的類型安全語言,如JAVA等。而放棄C/C++語言等這樣高效易用的編程語言對于大部分程序員又是不能接受的,所以只能采取其它的防護措施。NetworkSecurityTechnology2014AutumnSemester997.6.1緩沖區(qū)溢出防御概述首先,可以考慮在一般的攻擊防護產(chǎn)品中加入針對緩沖區(qū)溢出攻擊的防護功能,如防火墻和IDS等。可以從兩方面著手:一是可以提取用于攻擊的shellcode的普遍特征作為攻擊特征,過濾掉這樣的數(shù)據(jù)包或者觸發(fā)報警。二是對特定的服務(wù)限定請求數(shù)據(jù)的值的范圍,比如,某一服務(wù)要求請求數(shù)據(jù)為可打印字符串,如果發(fā)現(xiàn)對這一服務(wù)的請求存在不可打印字符則認為發(fā)生攻擊。NetworkSecurityTechnology2014AutumnSemester1007.6.1緩沖區(qū)溢出防御概述其次,通過分析緩沖區(qū)溢出攻擊的原理,可以發(fā)現(xiàn)緩沖區(qū)溢出能夠成功的幾個條件:編譯器本身或庫函數(shù)沒有對數(shù)組類型的數(shù)據(jù)結(jié)構(gòu)做嚴格的邊界檢查,這是溢出的首要原因;返回地址放在堆棧的底部,使得通過溢出可以覆蓋返回地址;堆棧的屬性一般是可執(zhí)行的,使得惡意代碼得以執(zhí)行。NetworkSecurityTechnology2014AutumnSemester1017.6.2源碼級保護方法避免源碼中的相關(guān)bug源碼中溢出bug的查找數(shù)組邊界檢查編譯器NetworkSecurityTechnology2014AutumnSemester102(1)避免源碼中的相關(guān)bug防患于未然。在軟件開發(fā)過程中,對涉及到緩沖區(qū)的操作,做嚴格的邊界檢查,從代碼編寫層防止緩沖區(qū)溢出。C語言是其中最具代表性的一種,由于只追求性能的傳統(tǒng)認識,它具有容易出錯的傾向,有許多字符串處理函數(shù)存在未檢查輸入?yún)?shù)長度和邊界問題、字符串以零結(jié)尾而不是用下標管理等。對使用C語言的開發(fā)人員來說,放棄這種高效易用的編程語言是不能接受的,因此,只能要求程序員提高自身編程水平,在編寫程序時盡量避免有錯誤傾向的代碼出現(xiàn)。不過,保證代碼的正確性和安全性是一個非常復(fù)雜的問題,這也將使開發(fā)人員的工作效率大大降低。在現(xiàn)代的程序開發(fā)中,應(yīng)用程序往往十分龐大,加之程序員的經(jīng)驗有限,要想徹底避免此類問題,在實際應(yīng)用中往往是很難做到的。NetworkSecurityTechnology2014AutumnSemester103(1)避免源碼中的相關(guān)bug這里列出了一些編寫程序時應(yīng)該盡量避免使用的C庫函數(shù)。使用時程序員要注意自行檢查邊界,或者盡可能使用其對應(yīng)的替代函數(shù)。NetworkSecurityTechnology2014AutumnSemester104(2)源碼中溢出bug的查找人們嘗試開發(fā)一些工具進行針對程序溢出漏洞的代碼審計工作。也就是利用工具對源碼中可能存在溢出bug的部分代碼進行分析以發(fā)現(xiàn)bug。最簡單的方法就是搜索源碼中容易產(chǎn)生漏洞的庫函數(shù)調(diào)用,如典型的strcpy和sprintf這兩個函數(shù)調(diào)用,它們都沒有檢查輸入?yún)?shù)的長度。如利用grep來查找和搜索。這種方法雖然可以提高查找的效率,但是它需要較多的專業(yè)知識,要求安全審計人員對語言本身非常熟悉。同時由于grep只是簡單的對字符串進行匹配,只能發(fā)現(xiàn)眾多問題中的很小的一部分,通常只是被作為輔助的工具使用。

NetworkSecurityTechnology2014AutumnSemester105(2)源碼中溢出bug的查找一些組織和實驗室開發(fā)了一些高級的查錯工具,如faultinjection、ITS4等。ITS4是針對C/C++設(shè)計的靜態(tài)分析工具,可以在Windows、Unix/Linux環(huán)境下使用。它通過掃描源代碼、對源代碼執(zhí)行模式匹配來進行工作,對可能危險的模式(如特定的函數(shù)調(diào)用)進行提取和分析,確定危險的程度,對危險的函數(shù)調(diào)用提供問題的說明和如何修復(fù)源代碼的建議。NetworkSecurityTechnology2014AutumnSemester1067.6.3運行期保護方法運行期保護方法概述插入目標代碼進行數(shù)組邊界檢查返回指針的完整性檢查NetworkSecurityTechnology2014AutumnSemester107(1)運行期保護方法概述運行期保護方法主要研究如何在程序運行的過程中發(fā)現(xiàn)或阻止緩沖區(qū)溢出攻擊。這種方法具有簡潔、方便的特點,而且對相關(guān)知識要求不高,因而更為實用。目前,動態(tài)保護研究的主要方面是數(shù)組邊界檢查和如何保證返回指針的完整性。NetworkSecurityTechnology2014AutumnSemester108(2)插入目標代碼進行數(shù)組邊界檢查只要數(shù)組不能被溢出,溢出攻擊也就無從談起。數(shù)組邊界檢查就是檢查數(shù)組實際長度是否超過了分配的長度。如果超過,立即進行相應(yīng)的處理,如:舍去超出分配長度的部分。NetworkSecurityTechnology2014AutumnSemester109(2)插入目標代碼進行數(shù)組邊界檢查為了實現(xiàn)數(shù)組邊界檢查,則所有的對數(shù)組的讀寫操作都應(yīng)當被檢查以確保對數(shù)組的操作在正確的范圍內(nèi)。最直接的方法是檢查所有的數(shù)組操作,但是通常可以采用一些優(yōu)化的技術(shù)來減少檢查的次數(shù)。NetworkSecurityTechnology2014AutumnSemester110(2)插入目標代碼進行數(shù)組邊界檢查目前有以下的幾種檢查方法:

CompaqC編譯器Jones&Kelly:C的數(shù)組邊界檢查Purify:存儲器存取檢查類型-安全語言NetworkSecurityTechnology2014AutumnSemester111CompaqC編譯器Compaq公司為AlphaCPU開發(fā)的C編譯器支持有限度的邊界檢查(使用-check_bounds參數(shù))。這些限制是:只有顯示的數(shù)組引用才被檢查,比如“a[3]”會被檢查,而“*(a+3)”則不會。由于所有的C數(shù)組在傳送的時候是指針傳遞的,所以傳遞給函數(shù)的的數(shù)組不會被檢查。帶有危險性的庫函數(shù)如strcpy不會在編譯的時候進行邊界檢查,即便是指定了邊界檢查。NetworkSecurityTechnology2014AutumnSemester112CompaqC編譯器(2)由于在C語言中利用指針進行數(shù)組操作和傳遞是如此的頻繁,因此這種局限性是非常嚴重的。通常這種邊界檢查用來程序的查錯,而且不能保證不發(fā)生緩沖區(qū)溢出的漏洞。NetworkSecurityTechnology2014AutumnSemester113Jones&Kelly:C的數(shù)組邊界檢查

RichardJones和PaulKelly開發(fā)了一個gcc的補丁,用來實現(xiàn)對C程序完全的數(shù)組邊界檢查。由于沒有改變指針的含義,所以被編譯的程序和其他的gcc模塊具有很好的兼容性。更進一步的是,他們由此從沒有指針的表達式中導(dǎo)出了一個“基”指針,然后通過檢查這個基指針來偵測表達式的結(jié)果是否在容許的范圍之內(nèi)。NetworkSecurityTechnology2014AutumnSemester114Jones&Kelly:C的數(shù)組邊界檢查(2)

當然,這樣付出的性能上的代價是巨大的:對于一個頻繁使用指針的程序如向量乘法,將由于指針的頻繁使用而使速度比本來慢30倍。這個編譯器目前還很不成熟;一些復(fù)雜的程序還不能在這個上面編譯。NetworkSecurityTechnology2014AutumnSemester115Purify:存儲器存取檢查Purify是C程序調(diào)試時查看存儲器使用的工具而不是專用的安全工具。Purify使用“目標代碼插入”技術(shù)來檢查所有的存儲器存取。通過用Purify連接工具連接,可執(zhí)行代碼在執(zhí)行的時候帶來的性能上的損失要下降3-5倍。NetworkSecurityTechnology2014AutumnSemester116類型-安全語言所有的緩沖區(qū)溢出漏洞都源于語言缺乏類型安全。如果只有類型-安全的操作才可以被允許執(zhí)行,這樣就不可能出現(xiàn)對變量的強制操作。如果作為新手,可以推薦使用具有類型-安全的語言如Java和C#。NetworkSecurityTechnology2014AutumnSemester117類型-安全語言(2)但是作為Java執(zhí)行平臺的Java虛擬機是C程序,因此通過攻擊JVM的一條途徑是使JVM的緩沖區(qū)溢出。NetworkSecurityTechnology2014AutumnSemester118(3)返回指針的完整性檢查程序指針完整性檢查和邊界檢查的思路不同。它不是防止程序指針被改變,而是在程序指針被引用之前檢測它是否被改變。因此,即便一個攻擊者成功地改變了程序的指針,系統(tǒng)會事先檢測到指針的改變,而廢棄這個指針。NetworkSecurityTechnology2014AutumnSemester119(3)返回指針的完整性檢查返回指針的完整性檢查主要采用了如下幾種手段:堆棧監(jiān)測StackGuardStackShieldNetworkSecurityTechnology2014AutumnSemester120堆棧監(jiān)測堆棧監(jiān)測是一種提供程序指針完整性檢查的編譯器技術(shù),通過檢查函數(shù)活動記錄中的返回地址來實現(xiàn)。它在每個函數(shù)中,加入了函數(shù)建立和銷毀的代碼,加入的函數(shù)建立代碼實際上在堆棧中的函數(shù)返回地址前面加了一些附加的字節(jié),而在函數(shù)返回時,首先檢查這個附加的字節(jié)是否被改動過,如果發(fā)生過緩沖區(qū)溢出,那么就很容易在函數(shù)返回前被檢測到。NetworkSecurityTechnology2014AutumnSemester121StackGuardStackGuard是標準GNU的C編譯器gcc的一個修改版。它通過在函數(shù)返回地址之前插入一個“守衛(wèi)”值(canary值),在函數(shù)返回前檢查canary值是否被修改,來保證返回地址的完整性。StackGuard作為gcc的一個補丁,修改了函數(shù)建立和銷毀部分的代碼,由

溫馨提示

  • 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)方式做保護處理,對用戶上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對任何下載內(nèi)容負責。
  • 6. 下載文件中如有侵權(quán)或不適當內(nèi)容,請與我們聯(lián)系,我們立即糾正。
  • 7. 本站不保證下載資源的準確性、安全性和完整性, 同時也不承擔用戶因使用這些下載資源對自己和他人造成任何形式的傷害或損失。

評論

0/150

提交評論