文/郭文博 徐軍
為了驗證LEMNA的有效性,我們將其應用到兩個基于安全的深度學習上:惡意軟件分類以及二進制代碼逆向。在本文中,只介紹LEMNA在二進制代碼逆向工程中的應用。
二進制代碼逆向將二進制代碼逆向成匯編代碼,對于惡意軟件檢測、軟件安全加強,以及安全補丁都是至關重要的。多年來,二進制分析主要是通過有經驗的安全分析員手工分析。最近,研究人員發現RNN在逆向工程中,比如發現函數開始位置,有很好的效果。考慮到檢測函數開始位置的重要性,我們選擇在此應用上測試LEMNA,按照 [1] 中的方法使用了2200個程序來訓練RNN網絡。
我們將這些程序在O0、O1、O2和 O3這些優化級別下分別編譯成二進制代碼。由此,得到了四個不同的數據集,并且對每一個數據集訓練了一個分類器,同時將這些數據集中的每一個二進制代碼都表示成二進制序列。如圖1所示,我們首先將這些二進制序列替換成數值序列,并且將每一個數值認為是一個特征。在訓練中,每一個特征都有一個為“a function start”或者“not function start”的標簽。同樣依據 [1] 將長序列切分成最大長度為200的短序列,并且將最終生成的序列輸入到RNN中。用Theano作為后端,并且使用Keras來訓練模型,利用70%的樣本用于訓練剩下的30%用于測試。

圖1 進制序列替換成數值序列
將上面提到的RNN作為LEMNA的目標模型,給定一個輸入樣本,LEMNA模擬這個目標聚類器然后解釋聚類結果。其中,“解釋”代表著一個輸入樣本中最重要的特征。對于“函數開始位置”聚類器,我們在圖1中展示了一個例子。給定一個樣本數值序列以及RNN標定的函數開始位置(即“83”),LEMNA標定序列中擁有最大貢獻的字節集合。其中,“83”是函數開始字節,而且LEMNA將函數開始位置前的“90”標記為RNN聚類的最重要的原因。LEMNA有三個可配置的超參數。首先為了擬合局部決策邊界,我們構建N個數據樣本來做模型擬合。第二個以及第三個參數分別是混合模塊中的K以及Fused Lasso中的閾值S。在函數開始位置檢測中,我們將這些參數分別設置為:N=500, K=6, S=1e 。
LEMNA的計算開銷是相對比較低的。在函數開始位置檢測中,解釋一個給定的輸入樣本的開銷大概是10秒鐘,這個開銷還可以通過并行進一步降低。
為了更直觀地展示LEMNA的效果,我們選擇了兩個baseline來作對比。首先,用現在最先進的黑盒解釋方法 LIME[2]作為比較的基礎。為了公平的比較,在LIME中,同樣將500設定為擬合線性回歸模型的樣本基數。其次,用隨機特征選擇作為比較的基礎。給定一個輸入,這個方法隨機地選擇特征作為解釋的結果。
為了評估解釋的精度,我們設計了一個兩步的實驗。第一步,直接檢測對于決策邊界的局部擬合,這極有可能會給出一個解釋精度的初步估計。第二步,對于解釋精度進行端到端的評估。設計了三種精度測試來展示LEMNA標定的特征確實是聚類結果的主要原因。
(1)局部擬合精度: 這個度量直接比較解釋得到的決策邊界以及原始的決策邊界。具體而言,衡量Root Mean Square Error(RMSE):, 其中,代表著從目標聚類器中得到的一個單一的預測,表示我們的解釋方法得到的擬合決策,n是測試數據樣本的數量。從一個給定的聚類器和一個測試數據樣本出發對于每一個測試樣本x1,首先通過聚類獲取一個預測概率。然后對于x1,我們依據前文公式(6)來產生一個回歸模型,并由其得到一個估計的預測概率。我們對所有的n個樣本進行如上步驟,并且獲取一個預測向量)以及對應的擬合向量。最終,我們基于這兩個向量計算RMSE。一個較低的RMSE意味著擬合更接近真實的邊界,表明我們得到了一個更高的解釋精度。
(2)端到端的精度測試:為了驗證選取的特征的正確性,我們設計了一些端對端的精度測試。為了方便理解,使用圖片歸類作為一個例子。需要注意的是,這個過程同樣適用于其他的聚類器。如圖2所示,這個圖片聚類器將鞋子和毛衣區分。圖2a中的輸入圖片被分類成毛衣。圖2b中,解釋工具用紅色標定了那些重要的像素(特征)。我們將這些標定的特征表示為Fx。為了度量這些解釋的精度,我們有三個思路:
如果Fx是被精確選擇的,那么把Fx從輸入中刪除,那么這個圖片將會被錯誤的分類, 即分類為 “鞋子” (圖2c)。
如果Fx是被精確選擇的,那么把Fx加到一個鞋子的圖片中,將導致聚類器犯錯,即將圖片歸類為“毛衣”(圖2d)。
如果Fx是精確選擇的,我們生成只包含這些特征的圖片,而且這些生成的圖片,應該大概率被歸類成“毛衣”(圖2e)。

圖2 圖片聚類器分鞋子和毛衣
根據這三個思路,我們構建了三個不同的精度測試來度量選取的這些特征。形式化來說,給定一個輸入樣本x以及它的聚類標簽,LEMNA標定一個小的重要特征集合Fx作為解釋。然后,根據三個步驟來產生三個測試樣本t(x)1,t(x)2,…t(x)3來做特征校準:
特征移除:將x中的Fx摘除得到 t(x)1;
特征加強:首先從相反的類別中選擇一個隨機樣本。然后我們通過將這個樣本中的某些特征用Fx代替,來產生樣本 t(x)2;
特征生成:我們通過保留樣本中的Fx,然后將其他的特征賦予隨機值來生成樣本t(x)3。
為了保證結果的可解讀性,將Fx約束在一個小的集合內。對于每一個分類器,我們將精度測試運行到所有的測試樣本。給定測試樣本中的一個實例,我們產生三個樣本,依次對應著我們的三個精度度量方法。將這三個樣本放進分類器中,然后觀測positive classification rate (PCR)。注意這里的“positive”的意味是這個新樣本的標簽跟原樣本一致。
實驗表明,LEMNA在不同的精度指標上都比LIME和隨機方法要好(見表1)。LEMNA有著比LIME小幾個量級的RMES,IME給出的最好的結果是0.1532,然后它依舊比LEMNA最差的結果(0.0196)大了差不多十倍。 這個結果驗證了混合擬合模型可以構建一個精度更高的解釋。

表1 LEMNA與LIME對比

圖3 實驗結果
圖3a 展示了特征移除實驗的結果。通過移除LEMNA標定的最重要的5個特征,函數開始位置的PCR降低到了25%甚至更低。考慮到這個聚類器極高的精度,這個劇烈的降低標志著這個小的特征集合對于聚類結果是及其重要的。
圖3b 展示了特征加強的結果。這個結果跟之前的測試是一致的:(1)通過加入一個小集合的特征,我們可以實現聚類結果的反轉;(2)我們的方法顯著的優于其他兩種方法。
圖3c 展示了在特征生成實驗中,LEMNA有同樣的優勢。利用LEMNA挑選的重要特征,這些生成的樣本極有可能會被歸類成原始的標簽。使用前五個最重要的特征,這些生成的樣本有85%~90%的概率會被歸類成原來的標簽,標志著核心的特征已經被標定。
下面介紹LEMNA解釋結果的應用,我們通過case study來展示如何用解釋結果來幫助分類器建立可信度以及定位分類錯誤的原因。
解釋方法的主要應用是評估聚類器的可靠程度并且建立可信度。我們認為聚類器的可靠度和可信度并不一定來自于高的聚類精度。相反的,可信度更可能通過理解模型行為來建立,這里從兩個關鍵的角度來觀測來評估聚類器的行為:一是抓取常見的原則;二是發現新的知識。
一個可靠的聚類器應該可以抓取應用場景中常見的原則。比如,在二進制代碼的逆向中,安全從業者已經積累了一系列有效的原則來尋找函數開始位置,其中一些已經被當成了既定原則。當ABI要求一個函數(如果使用棧幀指針的話)在開始的位置將父函數的棧幀指針放到棧上時,這就導致了最常見的prologue [push ebp;mov ebp, esp]。 通過分析解釋結果,我們發現了機器學習分類器成功地抓獲了這些眾所周知的原則。在表 2中,我們展示了幾個不同的具有代表性的例子。以Case-1為例。在這個例子中,這個聚類器正確檢測到了函數的開始位置“55”。LEMNA認為那些高亮的特征(即55附近的字節碼)是聚類器做這個決策的原因。這個結果跟上面提到的原則(即 [push ebp; mov ebp,esp])是匹配的,說明這個聚類器用一種合理的方式做出了決策。
除了匹配常見的原則外,還檢測了一個聚類器是否學習到了新的知識。我們認為,在安全應用中,新的知識需要能被領域內的專家理解。在二進制分析中,很多潛在的有效原則對于特定函數是有效的,而且他們很難通過手工完全總結。比如,很多鏈接器插入的輔助函數通常有特殊的開始片段,而且這些片段基本不會在其他地方出現 (比如,_start 函數通常從 [xor ebp, ebp;pop esi]開始)。通過手工總結這些規則是不現實的。但是,這些規則一旦被LEMNA發現,就可以給安全專家提供有效的知識補充。如表2所示,我們分析LEMNA的解釋結果,并且發現這個聚類器的確學習到了新知識。以Case-5為例。在這個例子中,“31”被檢測為函數開始位置,因為后續的字節( [ed 5e]. “[31 ed 5e])” 對應著_start函數的開始位置 (即 [xor ebp, ebp; pop esi])。這個展示了我們的解釋方法可以幫助總結某些函數使用的特殊的prologues 。
雖然深度神經網絡高度精確,但是它們仍然可能產生錯誤。這些錯誤不應該被忽略,因為它們通常意味著訓練不足并且這些不足可能在現實中會被放大。我們的解釋方法是嘗試尋找到錯誤聚類的原因。希望通過找到這些原因,能夠啟發解決這些錯誤的可行性方案。
對于二進制分析,這些聚類器不時會錯過函數開始的位置。如表2所示(R.F.N),給定一個漏掉的函數開始位置,我們解釋“為什么這些位置沒有被標記為開始位置”。
具體而言,我們將對象(代碼序列,真實函數開始位置)輸入LEMNA,并且選擇那些導致函數沒有被識別的特征作為解釋。以Case-10為例,“[50 fd]” 對應著“[jmp 0xfffffd50]”,被標記為主要的聚類錯誤原因。這條指令幾乎都出現在函數中間位置,導致聚類器認為后面的31不是函數開始位置。Case-10是一個異常樣例,因為“[50 fd]”剛好出現在一個特殊區域.plt的末尾(后面緊跟著_start函數)。

表2 不同的示例
表2也展示了聚類器錯誤的選擇函數開始的例子。我們將對象(代碼序列,錯誤的函數開始位置)輸入到LEMNA,并且解釋為什么這個錯誤的位置會被選擇。比如說,在Case-13中,LEMNA標定“c3”(對應著“ret”指令)。通常來說,“ret”位于函數的結尾使得函數退出,也就意味著后面的“83”將是一個新函數的開始位置。但是,這個例子是特殊的,因為“ret”被放到函數中間來實現優化。LEMNA展示了這些錯誤大部分是由于這些重要的特征在絕大部分例子中是標定函數開始位置的,因此LEMNA會犯這樣的錯誤。
我們設計了LEMNA—— 一種用于安全領域的深度學習模型,有著高精度,適用于單樣本聚類結果的解釋方法。LEMNA將目標聚類器視為一個黑盒子然后通過一個Fused Lasso加強的混合回歸模型來擬合聚類器的決策邊界。通過對安全應用的評估,展示了LEMNA有很高的解釋精度。同時,還展示了機器學習開發者以及安全專家如何從LEMNA的結果來理解模型行為以及定位分類錯誤。