王于葉,張皓天,許澤遙
(南京郵電大學,江蘇 南京 210023)
漏洞檢測技術是保障軟件安全性的主要手段,是軟件安全領域不可或缺的一環。為了提升漏洞檢測的工作效率,將機器學習中具備良好性能的深度學習算法和漏洞檢測技術相結合已逐漸成為一種研究的趨勢。對于深度學習而言,選用特征明顯的樣本集往往會對深度學習的結果產生決定性影響,如何處理漏洞樣本才能突出其特征性是一個至關重要的問題。
根據分析對象的不同, 漏洞檢測技術可以分為基于源碼的漏洞挖掘技術和基于二進制代碼的漏洞挖掘技術兩大類[1]。兩類檢測技術對被檢測對象也采用了不同的處理方式。
傳統的源代碼漏洞檢測技術對于被檢測對象,即源代碼的處理主要集中在對其語法語義的分析上。控制流分析技術就是直接從代碼中收集程序的各種語義信息,并通過相關算法推測程序的可能執行路徑,例如DREAM[2]算法。2012年提出的在代碼中提取抽象語法樹[3]來分析漏洞的新方法,在后來基于Bi-LSTM的源代碼漏洞檢測[4]中被用作樣本預處理。
針對二進制代碼的漏洞檢測技術對于被檢測對象,即二進制程序的處理更側重于對程序執行漏洞可疑行為的分析。以動態污點跟蹤、模糊檢測為例,動態污點跟蹤技術是指在程序中人為地引入被標記的污點數據并執行,通過跟蹤其運行路徑找出漏洞。模糊測試技術通過構造大量畸形樣本數據交由目標程序處理從而遍歷程序狀態空間。
無論是針對源代碼,還是針對二進制代碼,現存漏洞檢測技術以及它們對檢測對象的分析處理方式都各自存在不足。針對源代碼的檢測,由于不斷擴充特征庫或詞典,造成了檢測的結果集大、誤報率高[5]。針對二進制代碼的檢測,以匯編語言為例,由于缺少函數、變量、變量類型等信息,不容易找到分析點,效率不高,難以實現自動化發現[5],易導致漏報。
當兩類漏洞檢測技術與深度學習算法結合時,其缺陷客觀反映在深度學習的準確率(precision)和回歸率(recall)上。
文章提出了一種在運用Bi-LSTM深度學習對二進制程序進行漏洞檢測,基于中間語言VEX IR,針對作為學習樣本的二進制程序進行處理的方法,其基本思路如下:
將二進制可執行程序轉換為一種兼具二進制代碼和源代碼部分特性的中間語言代碼,并利用這種特性,從程序動態執行過程和代碼的語法語義兩個維度上對樣本代碼進行分析,結合Word2Vec等字符處理工具,將分析后的代碼轉換為抽象的二維向量序列,將得到的數據作為深度學習的樣本集,從而在漏洞檢測的誤報率提升不明顯的前提下降低漏報率。
VEX IR是由二進制分析框架Valgrind[6]生成的一種中間表示式(IR)。二進制程序轉譯為VEX后被分成許多小的代碼塊“超級塊”,每個代碼塊中包含許多指令,這些指令具有語句(Statements)和表達式(expressions)兩種類型,語句一般表示寄存器寫入、緩存和變量賦值等操作;表達式一般表示算術操作、讀取內存和常量表示等操作。此外,還包含函數名、變量名等匯編語言中不具有的語義信息。
以一條匯編指令addl %eax, %ebx對應的VEX代碼為例:

因此,VEX IR所包含內存讀寫和算術運算等指令不僅能夠建立起二進制程序數據流的靜態分析,確定函數輸入與輸出之間的聯系,而且實現了嵌套的二進制控制流圖,能夠提取出程序的邏輯語義信息。
對于經過輸出的VEX IR代碼,基于其語法語義的表達特性,以一個“超級塊”為最小單位,根據漏洞特征存在的層面先后對其進行了函數名和語句跳轉關系的特征化處理。
對函數名進行特征化處理,是因為VEX IR代碼中的一些語句記錄了每個“超級塊”所在函數的函數名和地址信息,而這對判斷和函數名有直接關系的漏洞(危險函數漏洞)十分有利,因此編寫自動化腳本建立函數地址-函數名關系對照表十分必要,如圖1所示。

圖1 函數地址對照表(Vexfunction工作輸出)
隨后,對其中的已知函數(如memcpy等)進行直接數字編號,于是盡管同一函數在不同程序中擁有不同的函數地址,也能為其添加相同的數字標注。對于未知函數,采用二進制比對工具Bindiff,對其進行一定的修改,使其能夠對比VEX IR中不同未知函數的內容,將相似率超過85%的未知函數定義為同一函數,并對其進行數字編號。
為了體現和函數名沒有直接關聯的語法特征,通過提取超級塊中的跳轉語句,分析出程序語句的執行順序,并按照每個超級塊在程序流程中被調用的先后關系,使用二進制數對其編碼。對于函數名或跳轉關系的編碼,構成二維向量的縱坐標。
對于二進制程序執行維度的特征化處理,參考了Gascon等[7]學者關于使用行為特征圖進行機器學習分類的算法研究,以每條指令為最小單位,通過判定運行時刻的大量行為特征圖之間的相似之處,來體現惡意行為。以簡化VEX IR為目的,從中提取出關鍵的算術和邏輯操作以及運行時內存空間發生的變化,最終選取了1 100個保留了必要信息的相關操作指令作為VEX IR的程序執行過程描述。
對于一個IR塊,提取其關鍵指令并將其序列化,形成如[IMark,WrTmp,16Uto32,GET:I32,PUT,…]的形式。將這個文本向量視為具有含義的“句子”,其含義由向量的元素及其序列組成。將這些文本向量元素唯一地映射到一個整數,將這些整數充當“標記”,唯一地標識每個文本元素,以此構成二維向量的橫坐標。
二維向量的序列化過程中,使用Word2Vec工具來實現,并使用主成分分析(Principal Component Analysis,PCA)將結果投影到二維平面,如圖2所示。由數字表示的VEX指令的平面位置將成為深度學習的樣本集。

圖2 向量投影
先將二進制可執行文件樣本用ida轉化為匯編語言,僅進行程序執行維度序列化的處理,將完全相同的二進制可執行文件樣本用valgrind處理成VEX IR后,采用二維序列化處理方法進行樣本集預處理,作為Bi-LSTM的輸入,而后兩種方法對于測試集的預測結果對比如圖3所示。
從漏洞預測得到的結果數據可以看出,Vulnerable一欄的召回率相較單純,針對匯編語言的學習而言,從0.33增長到了0.77,有了明顯的提升。而深度學習的準確率仍然維持在較高水平,為0.96。由此數據可以證明,文章提出的方法成功降低了二進制漏洞檢測的漏報率。

圖3 針對不同代碼的深度學習檢測結果
經驗證,文章基于中間語言的代碼特征提出的一種深度學習樣本集預處理的方法,成功使原本基于純二進制代碼的漏洞檢測技術具備了源碼檢測的一些優勢,最終實現了在基本不增加誤報的前提下減少漏報率。但該方法仍存在漏報率大于誤報率等二進制檢測的固有缺陷,尚有較大的發展空間。