Windows平臺記憶體防護與繞過技術的進化演變系列之(一)記憶體攻防發展概述

wyzsk發表於2020-08-19
作者: Chuck · 2015/05/12 10:32

0x00 引言


最初有總結下的想法始於近期看過的幾篇關於CFG繞過以及EMET繞過的文章,這些文章裡大概都有提到類似這樣的句子“As with every known exploitation mitigation, there are ways to bypass it if certain conditions are met.”。無論攻與防的技術都是有時間與條件限定的,某種技術一般只在某段時間內對某特定場景有效,而攻與防又是在互為前提、互為基礎、又互為對手彼此砥礪發展的,那麼如果對這些技術的由來以及互相之間的爭鬥歷史(歷程)有一個宏觀整體的、脈絡清晰的認識,對於學習理解Windows平臺記憶體防護機制以及新出現的各種記憶體攻防技術應該是有積極意義的。

其實很早之前就已經有人做過類似的總結,早期國內的nsfocus、xfocus、邪惡八進位制,國外的微軟安全部門以及一些早期駭客組織的牛們都寫過關於記憶體攻擊防護、緩衝區溢位相關的總結,內容側重點各有不同,有講漏洞原理分析的、有漏洞利用的、有側重研究防護與緩解技術的,本系列擬在前人總結的基礎上,結合近幾年新出現的一些思路、技術、手段,把各種防護與繞過技術從頭至尾連線起來,嘗試做一個平衡、全面的講述。在寫的過程中,會盡量選擇新增一些例項分析來增加文章的可讀性,但水平所限,難免顧此失彼或出現各種錯漏,懇請各位大神諒解並多批評指正。

0x01 文章結構


0x02對記憶體緩衝區溢位進行概述,主要分三塊內容:什麼是緩衝區溢位、緩衝區溢位原因、早期緩衝區漏洞利用技術發展簡史。0x03討論記憶體防護機制的出現,主要分也分三塊內容:記憶體防護的安全需求、防護原則、防護策略。0x04簡單羅列目前主流的攻防技術。

0x02 記憶體緩衝區溢位概述


記憶體安全違規類漏洞可以泛指一切訪問記憶體時引入的安全缺陷利用,如緩衝區溢位,Use-After-Free、Double Free等,其中緩衝區溢位攻擊是最基礎最典型也可能是出現最早的記憶體類安全問題。記憶體攻擊利用的歷史也是從緩衝區溢位攻擊開始的。(本章純基礎,神請繞過)

1、什麼是緩衝區溢位

計算機程式一般都會使用到一些記憶體,這些記憶體或是程式內部使用,或是存放使用者的輸入資料,這樣的記憶體一般稱作緩衝區。緩衝區溢位指的是計算機沒有對接收的輸入資料進行有效的長度檢測,輸入資料的長度超過了程式緩衝區本身的容量,而導致資料溢位到被分配空間之外的記憶體空間,使得溢位的資料覆蓋了其他的記憶體空間的資料。

簡單來說就是使用者輸入的東西太多,覆蓋了不該覆蓋的地方,從而使程式執行跳轉到不該跳轉的地方。

x86的棧結構:

緩衝區溢位簡單示例程式:

#!c
void overflow_basic()
{
    char buffer[30];
    gets(buffer);
    printf("%s\n",buffer);
}
int main()
{
    overflow_basic();
    return 0;
}

當輸入超過30個‘a’字元時,會覆蓋掉前棧幀的EBP和函式返回地址,如下圖所示:

2、緩衝區溢位原因

緩衝區溢位攻擊出現的根本原因源於現代計算機的基礎架構。現代計算機指的是馮諾依曼體系架構的計算機,在馮氏體系計算機中,程式和資料是以二進位制程式碼的形式不加區分地存放在儲存器中的,存放位置由地址決定。既然程式與資料在記憶體中的存放形式是沒有區別的,那麼使用者輸入的資料在理論上當然也是可以作為程式執行的。緩衝區溢位發生後,資料覆蓋改變了程式的執行流程,使程式能夠跳轉到使用者構造的資料區執行使用者指定的程式碼,攻擊就發生了。

緩衝區漏洞的出現與C語言的出現與流行是脫不開關係的, C/C++支援記憶體的分配與回收,以及指標的計算、轉換等,語言本身也沒有對陣列邊界進行檢查等記憶體保護,這些都為緩衝區溢位漏洞的出現以及攻擊利用提供了條件。

3、早期緩衝區溢位利用技術發展簡史(1988-2004)

上世紀70年代末C語言出現並逐漸流行,到了80年代國外的駭客就開始意識到緩衝區溢位的問題並開始加以利用。較為典型的或有里程碑意義的事件如下:

  • 早期最著名的一次(也許是第一次)緩衝區溢位攻擊是1988莫里斯蠕蟲病毒。作者Robert T. Morris利用Unix fingerd服務程式沒有限制輸入長度的漏洞,輸入512個字元後導致緩衝區溢位。

    隨後第二年(1989年)Spafford提交了一份VAX機上的BSD版UNIX的fingerd緩衝區溢位程式細節的技術報告,開始引起一部分安全人士對緩衝區溢位領域研究的重視。之後又有L0pht heavy Industries的Mudge寫了一篇利用BSDI上的libc/syslog緩衝區溢位漏洞的文章。但並未引起廣泛的關注。

    注:莫里斯蠕蟲病毒造成了9600萬美元的損失。

  • 1996年,出現了具有里程碑意義的一篇文章---|||-Aleph One在Underground發表了《Smashing The Stack For Fun And Profit》。這篇文章詳細描述了linux系統棧的結構,以及如何利用基於棧的緩衝區溢位。受這篇文章啟發,講述如何利用緩衝區溢位並寫一段所需的shellcode的文章開始在網路上大量湧現。

    國外是這樣評論Aleph One這篇文章的:“Everything started with Aleph One's paper”。Aleph One前輩另一處值得我們記住的是,他是shellcode一詞的發明者。Aleph One文章中最初指的是如何在linux上寫一個開shell的Exploit。

  • 1997年,Smith在以前文章的基礎上,收集了各種處理器體系下的Shellcode,提出了在各種Unix變種中寫緩衝區Exploit更詳細的指導原則。

    Smith在文章中還談到了類Unix系統的一些安全屬性,並對安全程式設計進行了討論。

  • 1998年,國外駭客團隊“死牛崇拜”(Cult of the Dead Cow)的Dildog在Bugtrq Maillist中以Microsoft Netmeeting服務緩衝區溢位為例,詳細介紹瞭如何利用WIndows平臺的棧緩衝區溢位漏洞。可以說Dildog為Windows下緩衝區漏洞利用奠定了基礎

    這篇文章提出了利用棧指標的方法來完成跳轉,Windows下的溢位利用邁出了關鍵一步。Dildog還有另一篇可與Aleph One的《Smashing The Stack For Fun And Profit》齊名的經典之作《The Tao of Windows Buffer Overflows》(Windows緩衝區利用之道),著重講述了Windows平臺下的利用技巧。儘管對於今天來說文中的技術已老去而不再適用,作者文中的一些想法以及思考問題的角度直到今天還是值得我們借鑑的。(例如利用程式中已有的程式碼,如call *||或jmp *||來讓程式流轉向shellcode執行;還有小的shellcode與達成實際利用的exp程式分開;加殼消除shellcode中的空字元等等)

  • 1999年也是Windows緩衝區漏洞利用技術發展的很重要的一年,這一年中發生了這麼幾件事:一件是Dark Spyrit在Phrack 55上提出使用系統核心DLL中的Jmp ESP指令完成跳轉(如上文所述,這種想法其實Dildog之前也提起過),推動Windows溢位利用邁出實質性的一步;另一件是Litchfield詳細討論了Windows NT的程式記憶體以及棧結構,以及基於棧的緩衝區溢位,並以rasman.exe為物件,給出了提權建立一個本地shell的shellcode;還有一件是w00w00的M. Conover寫的基於堆的緩衝區溢位教程。他在研究中注意到當時的記憶體保護方法如非執行棧等是無法防止基於堆的溢位的。

可以說,2000年之前,緩衝區溢位漏洞利用作為漏洞利用中一種“殺傷性武器”所應具備的所有條件都已經具備了,剩下的只是一個契機來爆發。而2000之後個人電腦與Windows系列作業系統以及網際網路的推廣應用都是其爆發的契機。讓我們看一下接下來的發展(2001年至2004年緩衝區溢位攻擊發展達到一個高峰,在所有CVE漏洞排名裡連續四年排名第一):

  • 2000年,Cerberus小組釋出了微軟IIS 4/5的一個緩衝區溢位漏洞,2001年開始,Microsoft的IIS5.0一系列的漏洞被發現,該系列漏洞很多都是由於Unicode字符集的處理問題造成的。因為IIS是Web伺服器程式,因此,該漏洞給網站的安全構成了極大的威脅。

    Code Red蠕蟲就是一個應用IIS漏洞的一個典型例子,由於其主要針對英文版本的Windows NT/2000作業系統,因此國內使用中文版系統的大都沒感覺到什麼影響。 Code Red病毒實際上造成了26億美元的損失。

如果說大多數人對Code Red沒什麼印象的話,接下來的2003年的“衝擊波”,一定讓所有經歷過的人都印象深刻。

  • 2003年,引起全球轟動的“衝擊波”病毒及其變種,就是利用Windows RPC服務的緩衝區溢位漏洞(著名的MS03-026、MS03-039)來進行傳播的。中毒後的症狀是系統頻繁重啟,所有網路服務均出現故障,無法複製貼上、檔案顯示不正常等等。

    一個趣聞是,蠕蟲“衝擊波”變種病毒(Blaster.B)的作者,18歲的美國少年Jeffrey Lee Parson在程式中內嵌了自己的名字,FBI因此順利找到並逮捕了他。

    2003年另一個著名的病毒是Mydoom,這兩種病毒共造成了數十億美元的損失。

  • 2004年,另一個讓人印象深刻的“震盪波”病毒及其變種爆發,同樣也是利用了Windows RPC的緩衝區溢位漏洞(MS04-011)。

時間大概以2004年為分界線,如果說2004年之前,緩衝區漏洞進行攻擊是一種非常方便又簡單易用的漏洞利用形式的話(Crispin Cowan在《Buffer Overflows:Attacks and Defenses for the Vulnerability of the Decade》中這麼總結的“Buffer overflow attacks form a substantial portion of all security attacks simply because buffer overflow vulnerabilities are so common [15] and so easy to exploit [30, 28, 35, 20]. ”),那麼2004年之後,這種情況就開始發生了變化。04年之後,新版本類Unix和Windows作業系統應用得越來越廣泛,新版本作業系統中都引入了一些記憶體防護機制,為記憶體攻防戰場增加了新的變數。

有一些防護技術,如/GS、SafeSEH等是在04年之前出現的,儘管技術出現了,大多數人在使用的還是老版本作業系統,因而類似GS的防護技術實際上在使用者計算機上並沒有得到廣泛應用。

0x03 記憶體防護機制的出現


1、安全需求

前文我們已經提到,緩衝區溢位漏洞可以造成嚴重的後果,在較為嚴重的情況下,軟體漏洞可以使攻擊者獲取使用者計算機的完全控制許可權,從而在使用者機上為所欲為。在早期,通用的應對漏洞的方法是為受感染的軟體安裝軟體供應商提供的安全補丁。然而補丁更新的方法有著很明顯的不足之處:

  • 時間耗費大。在瞭解了漏洞的存在並熟悉了漏洞相關的情況後,軟體供應商必須開發一個健壯的安全更新程式,該更新還必須要經過充分的測試,以保障其不會引入新的安全問題。從發現漏洞到補丁開發完成通常需要耗費大量時間,而使用者在沒有安裝補丁之前將一直處於易受攻擊的狀態。

  • 未知漏洞的存在。要想給漏洞打補丁,軟體供應商必須具備該漏洞相關的先驗知識,而軟體漏洞的存在是不可避免的,在實際中,一定是有一些軟體供應商並未發現的漏洞存在。對於這部分漏洞,當然也無法透過打補丁的形式進行防護。

2、防護原則

微軟對於漏洞的防護原則大致有兩個:要麼阻止,使攻擊者不能;要麼提高其攻擊成本,使其不願。

基於這兩種原則,在如何保護使用者免受未知的或尚未解決的安全漏洞的危害,或在無法阻止的情況下,有效降低軟體漏洞帶來的安全風險方面,微軟和其他的軟體供應商付出了大量的努力。例如透過防火牆阻斷連線、使用授權/驗證技術阻止訪問、關閉或停止有漏洞的服務等等。這些方法的目的只有一個:使攻擊者成功利用漏洞變得很難或不可能。

另一種可以在補丁未出來之前保護使用者安全的研究方向就是我們所要討論的記憶體防護技術。記憶體防護技術可以有效打斷攻擊者的攻擊鏈條,使攻擊者對記憶體的利用變得更加艱難,提高攻擊的門檻,從而保護使用者安全。

3、記憶體防護策略

  • 增強不變數策略

一種可用以打破攻擊技術的策略是透過引入新的不變數,以使攻擊者攻擊時對記憶體的隱含假設條件不再合法。採用這種策略的技術有DEP、SEHOP等。

  • 不確定性策略

攻擊者攻擊時通常會假設攻擊相關前提(模組地址、記憶體分佈等)是確定的,透過增加系統的不確定性可以使攻擊者的假設落空,從而阻斷攻擊程式的可靠執行。採用這種策略的技術有ASLR等等。

  • 不可預測性策略

在一些場景下,透過利用攻擊者不知道或不可簡單預測到的資訊,可以阻斷攻擊程式的利用過程。典型採用這種策略的技術有/GS等。

0x04 攻防技術概覽


基於0x03章討論的防護策略,在與攻擊技術的對抗中,各種各樣的防護技術開始發展併成熟起來。

本系列接下來將討論的記憶體防護緩解技術如下表所示:

相應的攻擊利用以及防護繞過技術如下表所示:

0x05 內容預告


下一章將進行Windows XP下記憶體攻防的討論(GS、SafeSEH、SEHOP、NX/W^X/DEP)。包括背景知識(Windows記憶體堆疊結構)、相關防護技術的引入與繞過、防護與繞過例項等等。

本文章來源於烏雲知識庫,此映象為了方便大家學習研究,文章版權歸烏雲知識庫!

相關文章