劉 淵,謝家俊,張春瑞,嚴 可,滕 斌
(中國工程物理研究院 計算機應用研究所 新一代信息技術中心,四川 綿陽621900)
完整的漏洞挖掘包括異常發現和異常分析兩部分。前者目的是發現軟件潛在的安全隱患,后者目的是評估安全隱患的可利用性及威脅程度。
對于異常的發現,目前模糊測試是最有效的方法[1]。核心思想是構造海量的畸形樣本,并監測程序處理過程是否發生異常。在高性能計算與程序分析技術的支撐下,模糊測試可自動化的發現大量的潛在安全隱患。例如文獻[2-4]的工作通過搭建相應的平臺,發現了各類軟件數十個甚至上萬個不同種類的異常,但是,這些異常是否可利用的軟件漏洞仍需要大量的異常分析工作。異常分析存在著高度依賴人工經驗、效率低下、經驗難以復用等缺陷,已成為制約軟件漏洞挖掘的瓶頸,導致大量安全隱患無法被正確認識、評估與消除[5],因此專業的異常分析人才已被認為是網絡信息安全的核心[6]。可見,研究高效、通用性強的二進制程序異常分析方法具有重要意義。
為提高異常分析效率,近年來人們進行了深入的研究。微軟的MSEC[7]是一款著名的二進制程序異常分析工具,可實現異常的分類及可利用性的初步評估。然而,由于軟件異常形成原因的復雜性,多數異常被劃分至 “未知”類別,無法提供可靠的分析信息。對于堆緩沖區溢出分析,Windows Debugger提供了 “頁堆”機制,通過對ntdll.dll中的HeapAlloc函數申請的內存后添加不可讀/寫的柵欄頁,實現對了堆緩沖區溢出的精確定位[7],可顯著提高堆緩沖區異常的分析效率。然而,棧內存由應用程序自身維護,因此該方法無法分析棧緩沖區溢出產生的軟件異常。Miller提出基于Bitblaze系統的差分污點標記分析方法,并列舉了被MSEC判斷為未知的5個異常的分析過程[5],但Bitblaze系統存在著穩定性差、運行速度極慢等嚴重缺陷,上述方法實用性較差;Cha等提出污點跟蹤的軟件異常分析方法,通過判斷EIP是否被污點數據所控制實現了可覆蓋保存在棧幀中EIP 的棧緩沖區溢出[9](下文均簡稱為“普通棧溢出”)的分析自動工作,并在此基礎上實現了利用代碼的自動生成方法[10,11],可見,針對普通棧緩沖區溢出的分析已較為成熟。
然而與普通棧緩沖區溢出不同,許多情況下程序只允許產生一個字節的棧緩沖區溢出,即單字節棧溢出 (通常稱為off-by-one棧溢出)。單字節棧溢出的概念由Halvar Flake提出,并指出由于x86 采用小端 (little-endian)模式,溢出的這個字節只能覆蓋保存在棧楨中的EBP的最低有效字節,無法覆蓋保存在棧楨中的EIP 及S.E.H.等其它函數指針。單字節棧溢出發生時,程序不會在函數返回時崩潰,但運行邏輯會遭到嚴重破壞,進而引發深層安全隱患。實踐結果表明,部分單字節棧溢出漏洞仍能允許攻擊者實現任意代碼的注入攻擊,帶來嚴重的信息安全風險。然而,據作者對公開文獻的調研,目前單字節棧溢出漏洞的分析主要依賴手工調試,尚未發現自動化程度高、具備一定通用方法。針對上述問題,本文將提出一種單字節棧溢出異常的黑盒分析方法。該方法具有無需高層語義分析、自動化程度高、通用性強的特點,能顯著提高單字節棧溢出的異常分析效率。
棧緩沖區動態的存儲了函數之間的調用關系,以保證被調用函數在返回時恢復到母函數中繼續執行。程序中的每一個函數都有自己獨立的棧幀空間,當前正在運行的函數使用ESP寄存器指向棧頂,EBP寄存器指棧底。在函數棧幀中,一般包含局部變量、棧幀狀態值、函數返回地址等重要信息,如圖1所示。

圖1 函數棧幀布局
當向緩沖區中存儲數據時,如果沒有正確檢查數據拷貝的長度,將發生緩沖區的溢出,覆蓋保存在棧中的函數返回地址ret、S.E.H.,導致在函數返回 (ret)或調用異常處理函數時控制流被改變。若攻擊者精心構造輸入樣本,可將程序控制流劫持至攻擊者可控制的地址 (如buffer),實現欺騙程序執行任意代碼的目的。
普通棧溢出可直接覆蓋ret或S.E.H.等重要函數指針,實現控制流被輸入劫持。因此,在不考慮如ASLR (地址空間布局隨機化)、Cookie、DEP (數據執行保護)等內存保護的情況下,普通棧溢出通常是可利用的,異常分析與漏洞驗證有相對固定的方法可循,主要分析思想如圖2所示。

圖2 普通棧溢出異常的分析思路
典型的分析步驟如下所示:
(1)在調試器監控下讓程序處理異常樣本,收集異常信息。
(2)根據異常信息定位樣本中覆蓋EIP 的輸入字段,通常可通過在樣本中直接搜索得到。例如調試器反饋EIP非法訪問了0xAABBCCDD 地址的內存,可直接通過在樣本中搜索DDCCBBAA (注意x86 系統采用小端模式)實現。
(3)修改相應的字段至JMP ESP 的地址。例如0x7FFE4512是Windows XP 中文版各不同SP 版本相對穩定的地址,因此可將樣本中的DDCCBBAA 修改為1245EF7F即可實現對EIP 的劫持至棧頂指針ESP 指向的內存 (通常為可被輸入覆蓋的內存)。
(4)根據異常點內存布局,在輸入樣本中相應的位置布置shellcode。
(5)完成攻擊樣本的編寫。
對于特殊情況,如輸入被截斷、處理后無法直接在樣本中搜索到異常地址、異常點ESP 后的內存無法被覆蓋等情況,需要進一步調試分析。有興趣的讀者可參看相關書籍,本文不再贅述。
可見,異常分析的核心是定位輸入樣本中可控制EIP的字段。在發現輸入樣本中控制EIP 的字段后,異常的分析便有較固定的方法可循。在下文的單字節棧溢出異常的分析中,將利用上述結論簡化分析過程。
單字節棧溢出漏洞是由內存拷貝時邊界控制錯誤導致,如圖3所示的代碼片斷。

圖3 單字節溢出代碼片斷
雖然函數試圖防止字符串復制時的數組越界,但C 語言數據從0開始的約定容易讓習慣于其它編程語言的程序員在數組邊界位置出錯。例如上述循環控制中語句應為“i<len”,而程序員誤寫為 “i<=len”,導致了單字節棧溢出的產生。當緩沖區后正好緊跟著EBP和EIP時,溢出數組的一個字節將覆蓋EBP的最低有效字節,導致在函數返回后攻擊者能在255個字節范圍內移動EBP寄存器。
溢出不會立即導致程序終止,但將破壞程序正常執行邏輯,進而導致異常的產生。為便于說明,假設EBP 的最低有效字節為0xC0 被我們覆蓋為0x00。當函數返回時,將執行恢復棧幀的操作,即將分別執行mov esp,ebp;pop ebp;ret,棧的內存變化如圖4所示。
可見,在函數返回后,僅棧底指針寄存器EBP 被移動至0x0012FF00,而ESP、EIP等寄存器值正常。因此,程序通常可以正常執行。
然而,當程序運行至下一次函數調用時,將執行mov esp,ebp及pop ebp等保存當前運行時狀態的操作,如圖5所示。

圖4 函數第一次返回時棧內存變化

圖5 單字節棧溢出漏洞形成原理
可見,在執行mov esp,ebp操作時,由于EBP可被攻擊者在255字節范圍內移動,因此,該操作將進一步導致攻擊者可在255字節范圍內移動ESP。接下來,程序運行pop ebp時,將使得錯誤的ESP 指向的值被彈至EBP,通常將導致EBP為畸形值。因此,可根據該特點判斷異常是否為單字節棧溢出導致。接下來,由于ESP的錯位,導致程序運行邏輯發生嚴重錯誤,因此程序將因異常而終止。
可見,單字節棧溢出異常的分析面臨著如下難點:
(1)難以定位溢出字節。對于棧緩沖區溢出的精確定位,需要分析緩沖區大小及起始位置,并在內在拷貝時進行相應的檢測。然而二進制程序本身并沒有緩沖區的概念,緩沖區及其大小由程序高層語義賦予,在沒有源代碼支持的情況下,無法實現精確的靜態指針分析[12],因此難以有效定位溢出字節。
(2)將導致程序產生不同的異常。觸發單字節棧溢出的函數會正常執行,僅僅是在返回時EBP最低有效字節被改變,在程序的下一次函數調用過程中導致程序的控制邏輯受到破壞,進而導致程序的執行異常。從溢出至程序崩潰,已經運行了大量指令。同一個單字節溢出情況,采用不同的值覆蓋EBP最低有效字節將導致程序在不同的地址崩潰,增加了手工調試分析的難度。
雖然上述問題難以克服,但本文認為對單字節棧溢出異常分析任務,上述問題通常是可繞過的。
(1)單字節棧溢出異常是可識別的。雖然單字節棧溢出可能導致不同的程序異常,但在異常發生前,會將棧中某個值POP至EBP,因此,可根據畸形的EBP值判斷漏洞是否為單字節棧溢出。 (雖然普通棧溢出也將導致EBP 畸形,但此時表現為EBP、EIP 均被輸入控制,可根據1.2節方法分析和排除)。
(2)異常可利用性的判斷可以無需精確定位溢出點。控制劫持流的本質就是利用輸入控制EIP,并不需要回溯、定位到導致緩沖區溢出的指令。因此,若在程序崩潰處能發現輸入可以控制EIP,將大大簡化異常分析工作。
(3)無需分析所有異常,只需實現一個異常的利用便可完成威脅的評估。從上述分析可知,棧幀的抬高 (即ESP減小)更有利于形成可利用的環境。從2.2節的分析中,我們知道單字節棧溢出將允許攻擊者通過覆蓋保存在棧中的EBP進而在一定范圍內移動ESP。由于棧具有從高位向低位生長的特性,抬高棧更有利于ESP 指向應廢棄的、但被用戶輸入控制的緩沖區中。
綜上所示,本文提出了基于黑盒測試思想的單字節棧溢出分析方法,實現過程如圖6所示。
該方法主要分為以下幾個步驟:
(1)單字節異常的確定。2.2節的分析結果表明,單字節異常將導致EBP 異常且EIP 正常 (即程序可正常執行)的情況,在程序運行過程中的EBP及EIP能確定異常是為由單字節棧溢出導致。具體做法可采用手工調試或指令追蹤等方式實現。
(2)異常點EIP被是否被輸入控制的監測。可利用在Intel pin的基礎上利用污點分析技術實現。然而,污點分析將大大降低測試速度。因此,本文在Windbg輸出的異常信息,通過在樣本里搜索是否包含EIP 的值實現EIP 是否被輸入控制的監測。

圖6 單字節棧溢出的黑盒分析方法
(3)樣本變異。隨機的對樣本的多個字節或單個字節進行變異。為實現棧幀的抬高以形成更利于漏洞利用的環境,更高的機率修改為較低的值。由于0x00通常被判定為字符串結尾,因此本文以更高的概率將樣本修改為0x01~0x41之間的值。
(4)可利用性的判定。對于EIP 被輸入控制的樣本,可初步判定為可利用異常。若通過測試超過了預設時間或次數而并未發現可以通過輸入控制EIP,便可初步判定該單字節異常是可能是不可利用的。
(5)對可利用異常的驗證。可參考1.2 節普通棧溢出的方法實現可利用性的驗證。但與普通棧溢出不同,在單字節棧溢出中實踐中JMP ESP后攻擊者可利用的緩沖區通常較少,需要更加深入的分析異常點內存布局并編寫相應的跳轉代碼。
為驗證方法的有效性,本文選擇了自己編寫的存在單字節漏洞的軟件及存在Winamp 5.12與Apache 2.0.58兩款存在單字節漏洞的真實軟件上進行。實驗及結果見表1。

表1 單字節棧溢出黑盒分析方法的驗證實驗
從表1可知,在僅獲得一個異常樣本的情況下,通過本文方法的不斷變異,可找EIP 被輸入控制的樣本,進而在此基礎上可實現利用代碼的編寫和漏洞的驗證。實驗結果表明,該方法無需深入分析程序的內部邏輯,因此具有黑盒測試的易于部署、通用性強等特點。樣本變異的本質是在單字節棧溢出可能導致的眾多異常中,尋找一個更利于分析的異常,將異常可利用性驗證轉化為與經典棧溢出類似的有相對固定的方法及步驟可循的工作,因此顯著提高單字節棧溢出異常分析效率。
本文深入分析了單字節棧溢出異常的形成原因及異常分析的難點,提出了一種單字節異常的黑盒分析方法。該方法無需深入分析程序內部語義,實現簡單,能顯著提升單字節漏洞的分析與利用的效率。該方法在單字節異常的確認及利用代碼生成上仍需少量人工參與,無法實現完全自動化。未來工作將借助指令追蹤技術,通過Intel Pin工具在程序執行過程中插裝相應的檢測代碼,實現異常類型的自動判斷并定位輸入控制EIP的字段,進而實現單字節棧溢出異常的全自動分析。
[1]WU Zhiyong,WANG Hongchuan,SUN Lechang,et al.Survey of fuzzing [J].Application Research of Computers,2010,27 (3):829-832 (in Chinese). [吳志勇,王紅川,孫樂昌,等.Fuzzing技術綜述 [J].計算機應用研究,2010,27 (3):829-832.]
[2]Nagy B.Finding Microsoft vulnerabilities by fuzzing binary files with ruby-a new fuzzing framework [C]//SyScan.http://www.syscan.org/Sg/program.html,2009.
[3]Miller C.Babysitting an army of monkeys:An analysis of fuzzing 4 products with 5lines of Python[C]//Cansecwest,2010.
[4]Avgerinos T,Rebert A,Cha S K,et al.Enhancing symbolic execution with veritesting[C]//Proc ICSE,2014:1083-1094.
[5]Miller C,Caballero J,Johnson N M,et al.Crash analysis with BitBlaze[C]//BlackHat USA,2010.
[6]Miller C.Kim Jong il and me how to build a cyber army to attck U.S.[C]//Defcon-18,2010.
[7]!exploitable crash analyzer [EB/OL].http://msecdbg.codeplex.com/,2013.
[8]Soulami T.Inside windows debugging [M].Pearson Education,2012.
[9]Cha S K,Avgerinos T,Rebert A,et al.Unleashing mayhem on binary code[C]//IEEE Symposium on Security and Privacy,2012:380-394.
[10]Avgerinos T,Cha S K,Hao B L T,et al.AEG:Automatic exploit generation [C]//Proceedings of the Network and Distributed System Security Symposium,2011:59-66.
[11]Caselden D,Bazhanyuk A,Payer M,et al.Transformationaware exploit generation using a HI-CFG [R].California Univ Berkeley Dept of Electrical Engineering and Computer Science,2013.
[12]Szekeres L,Payer M,Wei T,et al.SoK:Eternal war in memory [C]//IEEE Symposium on Security and Privacy,2013:48-62.