專利名稱:一種二進制程序漏洞自動化定位方法
技術領域:
本發(fā)明主要涉及漏洞定位方法,更確切地是涉及一種二進制程序漏洞自動化定位方法,屬于網(wǎng)絡信息安全領域。
背景技術:
漏洞已經(jīng)給Internet帶來很大威脅:一方面,攻擊者可以利用漏洞入侵系統(tǒng) ’另一方面,蠕蟲利用漏洞進行傳播,并產(chǎn)生破壞。近些年,軟件漏洞數(shù)量持續(xù)上漲,但是其補丁的生成需要很長時間,據(jù)分析微軟當前的21個漏洞(MS11-087 MS12-007)公布和補丁發(fā)布平均需要115天。補丁的生成需要較長時間的主要原因:首先,軟件越來越復雜,分析人員需要針對數(shù)以萬計的指令進行分析,因此,在軟件中快速定位漏洞代碼是困難的;其次,漏洞種類繁多,分析人員需要熟悉各種類型,也增加了查找漏洞的難度;最后,由于大部分程序并不開源,只有開發(fā)人員可以對漏洞分析并打補丁,降低了第三方專業(yè)人員的參與度,減少了發(fā)布補丁的有效通道。由此可見,需要很長時間來發(fā)布漏洞補丁,給用戶帶來了很大安全威脅。為了解決上述問題,現(xiàn)有方法主要分為三類:1) 一類方法主要針對單一類型的漏洞進行分析(如緩沖區(qū)溢出)定位并產(chǎn)生補丁,但是只能解決一種類型的漏洞且大多數(shù)方法需要源代碼的支持;2) —類方法從正常執(zhí)行流中研究不變量來定位漏洞,但是這類方法無法尋找出漏洞的真正成因;3)差分切片可以在兩個相似的路徑中發(fā)現(xiàn)不同,幫助分析人員識別執(zhí)行中的異常,但是需要一個正常執(zhí)行流作比對,而不同程序輸入會使得執(zhí)行流差異不可控,因此難以找到合適的用于比對的執(zhí)行流。因此,如何對漏洞進行快速定位是當前補丁生成面臨的重要難題,也是當前研究的熱點。
發(fā)明內容
針對上述問題, 本發(fā)明的目的在于面向無需源碼的二進制程序提供一種二進制程序漏洞自動化定位方法,它支持多種類型的漏洞,包括堆/棧/整數(shù)型/緩沖區(qū)溢出,內存泄漏,格式字符串等。通過對程序執(zhí)行路徑進行記錄,進而對異常位置進行分析,產(chǎn)生的相應漏洞依賴樹(以下簡稱“依賴樹”),有效減少需要分析指令的數(shù)量,實現(xiàn)對漏洞位置的快速定位。在此基礎上,提出一種簡單有效的樣例補丁生成方法,有效保證系統(tǒng)不被惡意利用。根據(jù)以上目的,實現(xiàn)本發(fā)明的技術方案是:一種二進制程序漏洞自動化定位方法,其步驟為:I)運行待檢測二進制程序,記錄從該程序開始運行到出錯過程中所有指令;2)根據(jù)所記錄的指令構建漏洞依賴樹,并根據(jù)所構建漏洞依賴樹從所記錄指令中檢測指令中的漏洞指令;其中,構建所述漏洞依賴樹的過程中,每增加若干個節(jié)點檢查是否出現(xiàn)漏洞候選節(jié)點,如果出現(xiàn),則產(chǎn)生該漏洞候選節(jié)點的臨時補?。?)觀察該臨時補丁是否有效,如果有效則停止構建漏洞依賴樹,并作為定位到漏洞位置的依據(jù);否則繼續(xù)構建漏洞依賴樹。進一步的,所述漏洞依賴樹中的節(jié)點表示該程序中的指令,指令之間通過邊連接。進一步的,所述漏洞依賴樹的構建方法為:I)初始化一工作集Wl為空集;對所記錄指令中每一執(zhí)行路徑,從該執(zhí)行路徑的最后一條指令開始,順次取出一指令i ;2)將指令i對應的指令地址加入漏洞依賴樹V,將由指令i使用的變量加入工作集wl ;3)初始化一變量 branchNum = O ;4)如果指令i不為空且工作集wl不為空,則進行以下循環(huán):如果指令i是依賴輸入數(shù)據(jù)的分支指令,則branchNum = branchNum+1,即對依賴于外部輸入的分支進行計數(shù),i指向前一條指令,繼續(xù)循環(huán)過程;如果當前指令i定義的變量var和wl有交集,貝Ij從wl中移除這個變量var,并在wl中加入當前指令i使用的變量;計算邊長度edgeLen =branchNum-j為指令j到樹根的長度,指令j為漏洞依賴樹中使用var的節(jié)點;然后在漏洞依賴樹V中增加節(jié)點i,在漏洞依賴樹V中增加邊(j,i),其長度為edgeLen。進一步的,所述每增加若干個節(jié)點檢查是否出現(xiàn)漏洞候選節(jié)點的方法為:a)每增加若干個節(jié)點后,檢測所述漏洞依賴樹中連接每一新增加節(jié)點的入邊和出邊,如果其長度的比值大于設定閾值則將此節(jié)點作為漏洞候選節(jié)點山)選擇所增加若干個節(jié)點中改變變量范圍值超過設定比例的節(jié)點,將此節(jié)點作為漏洞候選節(jié)點。進一步的,所述記錄從該程序開始運行到出錯過程中所有指令的方法為:首先設定一閾值;然后從該程序開始運行到出錯過程中,對每條指令進行記錄,包括每個分支指令和選用的分支進行記錄,當記錄指令超過設定閾值時則新記錄的指令將覆蓋最先記錄的指令,進行循環(huán)記錄。進一步的,如果該程序的指令指針依賴于外部輸入,或者內存引用依賴于外部輸入,或者指定的異常函數(shù)被觸發(fā),則判定該程序出錯。進一步的,所述臨時補丁的生成方法為:利用指令的執(zhí)行條件,實現(xiàn)不執(zhí)行這條指令即可得到程序運行不出錯結果的臨時補丁。進一步的,如果函數(shù)A調用函數(shù)B出現(xiàn)問題,但該函數(shù)B也被其他函數(shù)調用且沒出現(xiàn)問題,則對函數(shù)A打補丁。本發(fā)明的主要內容為:I)在攻擊檢測階段:在攻擊輸入,即輸入待檢測二進制程序,程序運行過程中記錄導致程序錯誤的執(zhí)行路徑。通過污點分析或程序是否崩潰來檢測攻擊,如程序指針(EIP)依賴于外部輸入或者某些異常被觸發(fā),異常觸發(fā)包括UNHANDLED_EXCEPTION_FILTER函數(shù)被調用等。2)當檢測到攻擊后:找到執(zhí)行路徑中相關指令中的漏洞,并產(chǎn)生依賴樹。與傳統(tǒng)切片方法不同,我們在樹中增加邊的長度來顯示指令和漏洞之間的相關度,依賴樹中節(jié)點表示程序中某個指令,邊是連接這些指令的。當節(jié)點之間存在數(shù)據(jù)依賴關系時,例如指令a中使用了在指令b中定義的變量,則有一條從a到b的邊。相關度即“邊的長度”,指兩個指令之間的“依賴于外部輸入的條件指令”數(shù)目。利用當前執(zhí)行路徑即可產(chǎn)生依賴樹。3)依賴樹的構建:并不是路徑上所有指令都需要分析。實際上在構建依賴樹的過程中,當發(fā)現(xiàn)可能是漏洞的代碼,就停止構建依賴樹,并產(chǎn)生一個臨時補丁。臨時補丁可以驗證漏洞位置的正確性,同時也是對攻擊的一種臨時防御措施(有可能產(chǎn)生程序的非正常運行),為真實漏洞分析提供參考;驗證方法為:如果變化程序輸入,漏洞不再出現(xiàn),程序也能正常運行,則判斷這個補丁有效。如果驗證失敗,則繼續(xù)構建依賴樹,找其他指令;如果成功,則停止依賴樹的構建過程。臨時補丁的生成方法,即利用指令的執(zhí)行條件(控制這條指令執(zhí)行的條件指令),從而不執(zhí)行這條指令,也就避免了漏洞的發(fā)生。(如執(zhí)行條件是判斷某個標志位不為1,則把這個標志位設置為1,這樣這條指令就不執(zhí)行了。)這個是臨時的方法,本文的目的不在于找到正確的補丁,而是提供一個定位漏洞的方法,為今后正確補丁提供支持。與現(xiàn)有技術相比,本發(fā)明的積極效果為:本發(fā)明的優(yōu)點在于,在無源碼情況下定位多種類型的未知漏洞位置,通過構建依賴樹,并在依賴樹邊上進行賦值,有效描述指令和漏洞之間的相關度,在減少了需要分析的指令數(shù)量的同時,極大地提高了分析效率;此外,提出一種臨時漏洞補丁生成方法,可以臨時防御漏洞被惡意利用。
圖1為程序執(zhí)行中漏洞定位處理流程圖;圖2為跟蹤路徑。圖3為根據(jù)圖2樣例代碼生成的依賴樹。
具體實施例方式I)在待檢測二進制程序運行中記錄錯誤運行的執(zhí)行路徑,即記錄從程序開始運行到出錯過程中所有指令(已知某個輸入會導致程序出錯,如崩潰現(xiàn)象,然后從頭就開始記錄)。為了避免再次對程序進行分析,記錄過程中包括對每個分支指令和選用的分支也進行記錄。在實際分析中,由于漏洞位置與指令較為接近,而且考慮到程序和硬盤空間的限制,我們設定閾值進行指令跟蹤與記錄,目前選用100000個,如果超過此閾值,新記錄的指令將覆蓋最先記錄的指令,進行循環(huán)記錄。如果在記錄的指令中無法找到漏洞代碼,我們將重新設定閾值并運行程序。對指令進行記錄后,將檢測利用漏洞的位置。當滿足如下條件時,判定漏洞被利用,即導致程序出錯: 指令指針EIP依賴于外部輸入數(shù)據(jù),此時程序指針能夠被外部輸入改寫,易出現(xiàn)任意代碼執(zhí)行的危險。 內存引用依賴于外部輸入,此時內存引用被外部輸入任意指定,易產(chǎn)生任意讀/
寫錯誤。 系統(tǒng)默認異常處理函數(shù)被觸發(fā),此時表示系統(tǒng)出現(xiàn)異常,也屬于錯誤類型一種。2)因為執(zhí)行路徑中有數(shù)以百萬計的指令,很難直接找到漏洞代碼。我們將選擇與漏洞相關的指令,為后續(xù)分析漏洞代碼位置提供基礎。
首先,根據(jù)指令構建漏洞依賴樹。漏洞依賴樹構建算法如下:輸入:執(zhí)行路徑t,執(zhí)行路徑由記錄的指令組成,即路徑是一組指令;即輸入上一步記錄的指令;輸出:依賴樹V
1INS i=t.last; "i 指向 t 中指令
2WorkList wl= Φ\
3v.addNote(i); //將指令i加入依賴樹
4wl.add(use(i)); //use(i)由 i 使用的變量組成
5int branchNum = O;
6while i^NULL and wl^ Φ do
7if i是依據(jù)輸入數(shù)據(jù)的分支指令then
8branchNum++; i=1.prev; continue;
9end 10if def(i)Dvvl then
11wl.remove(def(i)); wl.add(use(i));
12INS j=v.node(def(i)); //v.node(var)返回使用 var 的節(jié)點
13int edgeLen = branchNum -v.len(rootj); //v.len(rootj)返丨11I W1: root 和 j 之丨丨丨]的邊的
長&
14v.addNode(i);
15v.addEdge(j丄edgeLen);//添加新的邊到 v
16if edgeLen>delta then Il delta 是某個閾值
17嘗試修復漏洞
18if修復成功then
19break; //退出循環(huán)
20end
21end
22end
23i=1.prev;//i指向t中目If一個指針
24end艮P;I指令i=路徑中最后一條指令2工作集wl=空集;
3將指令i對應的指令地址加入依賴樹V4將由指令i使用的變量加入工作集wl;
5 branchNum - O;
6如果指令i不為空而且工作集wl不為空,則進行以下循環(huán):
7if i是依賴輸入數(shù)據(jù)的分支指令then
8branchNum++,即對依賴于外部輸入的分支進行計數(shù);i指向前一條指令;繼續(xù)循環(huán)過程。(一直累加直到算法停止運行,三種情況下會停止運行:I)當前路徑所有指令取出;
2)工作集wl為空:3)發(fā)現(xiàn)合適的補丁位置并成功修補;)
9end
10ifi中定義的變量和wl有交集(即當前指令i中被定義的變量在后續(xù)程序中被使用到)
then
11wl中移除這個變量var; wl中加入i使用的變量;例如指令“mov eax, ebx”,定義的變量為eax,使用的變量為ebx。
12指令j為依賴樹中使用var的節(jié)點
13edgeLen = branchNum -j為指令j到樹根的長度,
14在依賴樹V中增加節(jié)點i;
15在依賴樹V中增加邊(j,i),其長度為edgeLen
16if edgeLen的長度超出某個閾值then
17嘗試在此位置修補漏洞
18if修補成功then
19退出循環(huán)
20end
21end
22end
23指令i指向路徑t中前一個指令
24end在構建好依賴樹之后,可以通過對依賴樹的分析定位漏洞可能出現(xiàn)的程序位置,進而尋找漏洞解決方法。舉例說明:指令如表I所示,設置第9行作為程序的入口點;輸入字符為0x78作為終止符。表I中第12行為用戶終端輸入一個字符,第13行判斷是否為0x78,如果不等就繼續(xù)循環(huán),否則跳到第20行。表I代碼樣例
權利要求
1.一種二進制程序漏洞自動化定位方法,其步驟為: 1)運行待檢測二進制程序,記錄從該程序開始運行到出錯過程中所有指令; 2)根據(jù)所記錄的指令構建漏洞依賴樹,并根據(jù)所構建漏洞依賴樹從所記錄指令中檢測指令中的漏洞指令;其中,構建所述漏洞依賴樹的過程中,每增加若干個節(jié)點檢查是否出現(xiàn)漏洞候選節(jié)點,如果出現(xiàn),則產(chǎn)生該漏洞候選節(jié)點的臨時補??; 3)觀察該臨時補丁是否有效,如果有效則停止構建漏洞依賴樹,并作為定位到漏洞位置的依據(jù);否則繼續(xù)構建漏洞依賴樹。
2.如權利要求1所述的方法,其特征在于所述漏洞依賴樹中的節(jié)點表示該程序中的指令,指令之間通過邊連接。
3.如權利要求1或2所述的方法,其特征在于所述漏洞依賴樹的構建方法為: 1)初始化一工作集《I為空集;對所記錄指令中每一執(zhí)行路徑,從該執(zhí)行路徑的最后一條指令開始,順次取出一指令i ; 2)將指令i對應的指令地址加入漏洞依賴樹V,將由指令i使用的變量加入工作集wl; 3)初始化一變量branchNum= O ; 4)如果指令i不為空且工作集wl不為空,則進行以下循環(huán):如果指令i是依賴輸入數(shù)據(jù)的分支指令,則branchNum = branchNum+1,即對依賴于外部輸入的分支進行計數(shù),i指向前一條指令,繼續(xù)循環(huán)過程;如果當前指令i定義的變量var和wl有交集,則從wl中移除這個變量var,并在wl中加入當前指令i使用的變量;計算邊長度edgeLen = branchNum-j為指令j到樹根的長度,指令j為漏洞依賴樹中使用var的節(jié)點;然后在漏洞依賴樹V中增加節(jié)點i,在漏洞依賴樹V中增加邊(j,i),其長度為edgeLen。
4.如權利要求1或2所述的方法,其特征在于所述每增加若干個節(jié)點檢查是否出現(xiàn)漏洞候選節(jié)點的方法為:a)每增加若干個節(jié)點后,檢測所述漏洞依賴樹中連接每一新增加節(jié)點的入邊和出邊,如果其長度的比值大于設定閾值則將此節(jié)點作為漏洞候選節(jié)點;b)選擇所增加若干個節(jié)點中改變變量范圍值超過設定比例的節(jié)點,將此節(jié)點作為漏洞候選節(jié)點。
5.如權利要求1或2所述的方法,其特征在于所述記錄從該程序開始運行到出錯過程中所有指令的方法為:首先設定一閾值;然后從該程序開始運行到出錯過程中,對每條指令進行記錄,包括每個分支指令和選用的分支進行記錄,當記錄指令超過設定閾值時則新記錄的指令將覆蓋最先記錄的指令,進行循環(huán)記錄。
6.如權利要求1或2所述的方法,其特征在于如果該程序的指令指針依賴于外部輸入,或者內存引用依賴于外部輸入,或者指定的異常函數(shù)被觸發(fā),則判定該程序出錯。
7.如權利要求1所述的方法,其特征在于所述臨時補丁的生成方法為:利用指令的執(zhí)行條件,實現(xiàn)不執(zhí)行這條指令即可得到程序運行不出錯結果的臨時補丁。
8.如權利要求7所述的方法,其特征在于如果函數(shù)A調用函數(shù)B出現(xiàn)問題,但該函數(shù)B也被其他函數(shù)調用且沒出現(xiàn)問題,則對函數(shù)A打補丁。
全文摘要
本發(fā)明公開了一種二進制程序漏洞自動化定位方法。本方法為1)運行待檢測二進制程序,記錄從該程序開始運行到出錯過程中所有指令;2)根據(jù)所記錄的指令構建漏洞依賴樹,并根據(jù)所構建漏洞依賴樹從所記錄指令中檢測指令中的漏洞指令;其中,構建所述漏洞依賴樹的過程中,每增加若干個節(jié)點檢查是否出現(xiàn)漏洞候選節(jié)點,如果出現(xiàn),則產(chǎn)生該漏洞候選節(jié)點的臨時補??;3)觀察該臨時補丁是否有效,如果有效則停止構建漏洞依賴樹,并作為定位到漏洞位置的依據(jù);否則繼續(xù)構建漏洞依賴樹。本發(fā)明減少了需要分析的指令數(shù)量,極大地提高了分析效率。
文檔編號G06F17/30GK103198260SQ20131010495
公開日2013年7月10日 申請日期2013年3月28日 優(yōu)先權日2013年3月28日
發(fā)明者陳愷, 張穎君, 趙險峰 申請人:中國科學院信息工程研究所