【原創(chuàng)】利用機器學(xué)習(xí)分析vmp的思路
作者論壇賬號:白云點綴的藍
前言
繼續(xù)使用上一篇文章《利用活躍變量分析來去掉vmp的大部分垃圾指令》的樣本。有個小問題先需要說明一下,加殼的樣本在wow64環(huán)境、32位環(huán)境和linux wine環(huán)境下,樣本的執(zhí)行流程是不同的,因為vmp會根據(jù)環(huán)境來調(diào)整通過sysenter或syscall指令來進行系統(tǒng)調(diào)用,比如NtProtectVirtualMemory函數(shù)。如果程序是32位的,qiling會設(shè)置成32位環(huán)境。所以利用qiling模擬執(zhí)行和調(diào)試器的執(zhí)行流程可能會不一樣。本篇文章分析vmp的大致思路是通過機器學(xué)習(xí)對handle進行分類,然后分別處理和化簡。
handle的提取
通過機器學(xué)習(xí)來進行分類,首先要提取出handle以及它的特征向量。為了能夠方便的提取出handle,本文繼續(xù)使用qiling模擬執(zhí)行記錄樣本的vmp殼程序每一條指令以及eax, ebx, ecx, edx, esi, edi, ebp, esp, eip寄存器的值,記錄這些寄存器的值是為了方便后面的化簡。模擬執(zhí)行的代碼在traceCode.py文件,保存后的文件大小有1G多,大部分都是循環(huán)產(chǎn)生的重復(fù)指令。然后對這些指令序列根據(jù)jmp register和ret指令進行分割。分割后的指令序列需要刪除一些因循環(huán)產(chǎn)生的重復(fù)指令。對于還有call指令的函數(shù)調(diào)用,需要把函數(shù)體對應(yīng)的指令刪除掉。vmp殼程序也是有一些正常函數(shù)的,比如一些字符串的解密函數(shù)和散列函數(shù)。handle的提取、分類和化簡都在analyzeInsn.py文件中。主函數(shù)代碼如下:

DeleteRedundantInsnInfo函數(shù)刪除掉循環(huán)產(chǎn)生的重復(fù)指令,HandleCallInsn函數(shù)用來處理含有call的調(diào)用。GetUsefulInsnList在提取handle的特征前需要去掉handle一些不需要的指令,比如handle地址的計算和一些寄存器輪轉(zhuǎn)相關(guān)的指令。這個可以通過一個簡單的污點分析實現(xiàn),保留與寫內(nèi)存操作相關(guān)的指令,實現(xiàn)代碼在Taintanalysis函數(shù)中。
比如有如下handle:

有用的指令就這么兩條:

handle的特征提取及模型訓(xùn)練
特征可以人工選取或者通過自然語言處理的一些模型得到,比如word2vec和bert模型,把匯編指令看成一個單詞,handle看成一個句子。通過自然語言處理提取代碼的特征可以參考一些代碼相似度檢測相關(guān)的論文。本文采用人工定義的特征和kmeans聚類算法,主要是實現(xiàn)簡單,可以快速驗證這個思路是否可靠。一個handle的特征定義如下:
代碼實現(xiàn)如下:

殼程序所有handle的提取在ExtractHandleFeature函數(shù)實現(xiàn)。特征提取后,通過t-sne對這些數(shù)據(jù)降維然后可視化,效果如下:

可以看出這數(shù)據(jù)還是具有可分性的,一個簇一類,大致可以劃分為14類。數(shù)據(jù)的可視化和模型的訓(xùn)練相關(guān)的代碼在model.py。代碼如下:

部分分類出的handle如下:




handle下面一行是特征向量和類別,大部分handle的分類還是正確的。錯誤分類的也有,比如:

這個handle歸類為8,8和10應(yīng)該分為同一類。為了提高正確率,可以重新定義其它的特征、調(diào)調(diào)參數(shù)或者使用其它模型,感興趣的壇友可以去試試。
handle的化簡
化簡的思路是只保留和內(nèi)存操作相關(guān)的指令,vmp是基于堆棧的虛擬機,執(zhí)行過程含有大量的棧操作,本質(zhì)上也是內(nèi)存操作,把讀寫內(nèi)存的操作數(shù)直接替換成絕對地址。比如如下handle:

然后通過qiling模擬執(zhí)行保留的寄存器信息轉(zhuǎn)換成

0xffff開頭的地址是qiling默認(rèn)的棧地址。這么做可以不用考慮寄存器輪轉(zhuǎn)的問題和下一條handle的地址計算。去掉絕大部分指令,保留核心的指令還能夠很好的分類。本文只實現(xiàn)了部分handle的轉(zhuǎn)換,具體參考TranslateHandle函數(shù)實現(xiàn)的代碼。vmp殼程序的執(zhí)行會多次進入虛擬機、退出虛擬機、執(zhí)行一個正常的函數(shù)然后又重新進入虛擬機。本文以第一次進入虛擬機然后退出虛擬機之間的代碼作為轉(zhuǎn)換例子,然后通過keystone轉(zhuǎn)換到二進制文件,最后通過ida反編譯。效果如下:
由于之前沒有保存狀態(tài)寄存器的值,所以暫時用0xef代替,主要是以下指令產(chǎn)生的

這兩條指令是直接轉(zhuǎn)換到mov ?dword ptr [0xXXXXXXXX], 0xef。觀察上面的反編譯代碼,可以看到有一個call調(diào)用,地址0x7D92CC剛好是LocalAlloc導(dǎo)入表中的地址。這個call是由vmCall產(chǎn)生的,vmCall的轉(zhuǎn)換沒有保留參數(shù),感興趣可以自己修改一下代碼。

總結(jié)
通過機器學(xué)習(xí)對vmp的handle進行分類是可行的,重點是提高分類的正確率,單純使用聚類算法的正確率并不是很高,而且人為設(shè)置的特征又不夠靈活。對于特征的提取,還是最好選擇自然語言處理中的模型,比如word2vec或者bert。提取出特征后,可以先用聚類算法進行分類,然后篩選出一些正確分類的handle,再通過這些handle訓(xùn)練出一個有監(jiān)督學(xué)習(xí)中的算法去預(yù)測其它未分類的handle,比如svm或者其它一些神經(jīng)網(wǎng)絡(luò),最后根據(jù)這些分好類的handle再次進行訓(xùn)練。特征的提取可以參考以下論文
Asm2Vec: Boosting Static Representation Robustness for Binary Clone Search against Code Obfuscation and Compiler Optimization
Neural Machine Translation Inspired Binary Code Similarity Comparison beyond Function Pairs
Investigating Graph Embedding Neural Networks with Unsupervised Features Extraction for Binary analysis
Instruction2vec: Efficient Preprocessor of Assembly Code to Detect Software Weakness with CNN
Order Matters: Semantic-Aware Neural Networks for Binary Code Similarity Detection
論壇原文地址:https://www.52pojie.cn/thread-1496099-1-1.html