緩沖區溢出: 緩沖區溢出,分為棧溢出與堆溢出,此類漏洞的原理是,程序由於缺乏對緩沖區的邊界進行合理化的檢測而引起的一種異常行為,通常是程序存在過濾不嚴格的輸入點,通過這些輸入點攻擊者可以向程序中寫入超過了程序員預先定義好的緩沖邊界,從而覆蓋了相鄰的內存區域,造成程序中的變量覆蓋,甚至控制EIP指針,從而造成程序的非預期行為,而像 C/C++ 程序中本身就缺乏內在的內存安全分配與管理,因此緩沖區溢出漏洞大部分都出現在編譯型語言中。
棧溢出: 棧溢出是緩沖區溢出中最為常見的一種攻擊手法,其原理是,程序在運行時棧地址是由操作系統來負責維護的,在我們調用函數時,程序會將當前函數的下一條指令的地址壓入棧中,而函數執行完畢后,則會通過ret指令從棧地址中彈出壓入的返回地址,並將返回地址重新裝載到EIP指令指針寄存器中,從而繼續運行,然而將這種控制程序執行流程的地址保存到棧中,必然會給棧溢出攻擊帶來可行性。
堆溢出: 除了棧溢出還有一個堆溢出,不同於棧溢出的是,堆是在程序運行時動態的分配的,以C/C++為例,當程序員需要堆空間時,可通過new(),calloc(),malloc()等函數來進行動態的申請,申請后會返回一個內存指針,我們可以通過返回的內存指針對分配的內存進行各種操作,但在使用完堆空間時必須手動的釋放,由於堆在內從中的分配位置不固定,大小比較自由,多次申請釋放后可能會讓內存更加凌亂,輕者內存泄漏,重者可對程序的安全造成致命的威脅。
堆空間雖然比較自由,但在分配時也會分配連續的內存空間,如果向堆區中寫入了超出其長度的內容,就會導致數據溢出,並覆蓋到堆塊后方的相鄰空閑堆塊,而后方的堆區中可能存放着指向下一個堆區的指針,如果該指針被惡意控制的話,就會出現很惡劣的后果,雖然危險,但是堆溢出的利用方式靈活性非常高,而且利用起來非常的困難,這里我們不討論這種溢出。
在大致弄清楚緩沖區溢出攻擊之后,我這里總結了攻防雙方的對抗博弈過程,攻擊者與防御者的對抗博弈斗爭從來都沒有停止過,在大環境下防御始終落后於攻擊,但不論如何正是因為有攻防雙方的對抗,才使得系統安全水平呈現螺旋式上升的態勢,如下是攻防雙方的對抗過程總結:
首先在當前的環境下,微軟的內存保護機制大致分為以下幾種
- 堆棧緩沖區溢出檢測保護 GS (編譯器)
- 安全結構化異常處理保護 Safe SEH
- 堆棧 SEH 覆蓋保護 SEHOP
- 地址空間布局隨機化保護 ASLR
- 堆棧數據執行保護 DEP
堆棧緩沖區溢出檢測保護 GS (編譯器)
保護原理: 該保護是通過編譯器進行限制的,GS選項是微軟堆棧檢測儀概念的具體實現:從 Visual Studio 系列的編譯器上就加入了GS保護機制且默認開啟,操作系統從 WindowsXP 開始就已經全面支持該選項了。
其原理是,將緩沖區變量置於棧幀的底部,且在緩沖區與棧指針(EBP)之間插入一個隨機化的 Cookie ,在函數返回時驗證該 Cookie 是否發生了改變,如果發生了改變,則說明惡意代碼覆蓋了該區域,從而決定不在使用該返回地址。
繞過措施: 實際上GS保護機制並沒有保護存放在棧上的 SEH 異常處理結構,因此,如果能夠寫入足夠的數據來覆蓋棧上的 SEH 記錄,並在函數收場白和 Cookie 檢測之前觸發 SEH 異常,那么將會繞過Cookie的檢查從而去執行我們構建好的異常處理例程。
安全結構化異常處理保護 Safe SEH
保護原理: GS保護缺陷就是可以通過覆蓋SEH結構實現繞過,隨后防守方就在其編譯器中加入了Safe SEH保護措施,該選項需要在鏈接時添加 linker /safessh:yes
來開啟,采用 SEH 句柄驗證技術驗證堆棧中SEH的合法性,來確保 SEH 結構不會被非法覆蓋。
繞過措施: 為了突破 SefeSEH 的保護,攻擊者又找到了新的繞過方式,通過利用進程中未被啟用的 SEH 模塊,將修改后的 SEH 例程指針指向這些模塊中的 (POP/RET) 等一些跳板指令,從而跳轉到棧上執行 ShellCode 代碼,除此之外還可以將惡意代碼布置到堆中,然后修改函數指針指向堆,同樣可以繞過。
堆棧 SEH 覆蓋保護 SEHOP
保護原理: 隨后防守方進一步提出了 SEHOP 技術,該技術默認從 Windows Vista 開始支持,而該技術在Win7-Win8系統上默認是關閉的,你可以通過注冊表開啟該選項,該技術的核心原理是在程序運行時驗證整個異常處理鏈表結構的完整性,如果攻擊者覆蓋了某個異常處理程序,那么該鏈表將被破壞,從而拋出異常停止執行。
繞過措施: 為了繞過SEHOP保護機制,突破方法就是進一步偽造 SEH 鏈,該方法的核心是能夠找到合適的跳板指令,且偽造最終異常處理函數指針應該與真實的相同,偽造最終異常處理函數指針前4字節(SEH鏈指針)應為0xFFFFFFFF,SEH鏈指針地址應該能被4整除即可。
地址空間布局隨機化保護 ASLR
保護原理: 如上所說我們需要找到合適的跳板指令,但恰巧的是防守方在此基礎上又添加了一個新的技術,ASLR 地址空間布局隨機化,該技術的核心原理是不讓攻擊者預測到布置在內存中的 ShellCode 的內存地址,因此即使溢出發生並成功填充內存,攻擊者也無法得知將EIP指針跳轉到何處,從而無法執行惡意代碼。
繞過措施: 針對 ASLR 技術,攻擊者同樣的找到了能夠繞過的方式,主要是利用堆噴射技術 (Heap Spray),通過使用腳本語言在堆上布置大量的含有 ShellCode 代碼的指令塊,從而增加某一個內存地址位於指令塊中的命中率,通過執行概率實現挫敗 ASLR技術。
堆棧數據執行保護 DEP
保護原理: DEP 保護直接切中了緩沖區溢出要害,數據執行保護將程序數據段所在的內存頁面 (堆棧) 的屬性強制設為 NX (不可執行),當程序執行這些內存頁面上的數據時,將報錯並禁止文件的執行,當今的CPU提供了硬件方面的安全防護,同樣也支持了DEP保護技術。
繞過措施: 為了繞過DEP保護,攻擊者提出了新的繞過方式 ROP(返回導向編程)
,它是ret2libc的繼承者,攻擊者在溢出程序之后,並不去執行棧中的 ShellCode 代碼,而是尋找程序中已加載的特殊指令塊,配合棧上的壓棧參數,將這些相對孤立的指令串聯起來,形成一條鏈,並通過調用VirtualProtect函數,將該棧設置為可執行屬性,然后在執行棧中的 ShellCode 代碼。