【原创】利用机器学习分析vmp的思路
作者论坛账号:白云点缀的藍
前言
继续使用上一篇文章《利用活跃变量分析来去掉vmp的大部分垃圾指令》的样本。有个小问题先需要说明一下,加壳的样本在wow64环境、32位环境和linux wine环境下,样本的执行流程是不同的,因为vmp会根据环境来调整通过sysenter或syscall指令来进行系统调用,比如NtProtectVirtualMemory函数。如果程序是32位的,qiling会设置成32位环境。所以利用qiling模拟执行和调试器的执行流程可能会不一样。本篇文章分析vmp的大致思路是通过机器学习对handle进行分类,然后分别处理和化简。
handle的提取
通过机器学习来进行分类,首先要提取出handle以及它的特征向量。为了能够方便的提取出handle,本文继续使用qiling模拟执行记录样本的vmp壳程序每一条指令以及eax, ebx, ecx, edx, esi, edi, ebp, esp, eip寄存器的值,记录这些寄存器的值是为了方便后面的化简。模拟执行的代码在traceCode.py文件,保存后的文件大小有1G多,大部分都是循环产生的重复指令。然后对这些指令序列根据jmp register和ret指令进行分割。分割后的指令序列需要删除一些因循环产生的重复指令。对于还有call指令的函数调用,需要把函数体对应的指令删除掉。vmp壳程序也是有一些正常函数的,比如一些字符串的解密函数和散列函数。handle的提取、分类和化简都在analyzeInsn.py文件中。主函数代码如下:

DeleteRedundantInsnInfo函数删除掉循环产生的重复指令,HandleCallInsn函数用来处理含有call的调用。GetUsefulInsnList在提取handle的特征前需要去掉handle一些不需要的指令,比如handle地址的计算和一些寄存器轮转相关的指令。这个可以通过一个简单的污点分析实现,保留与写内存操作相关的指令,实现代码在Taintanalysis函数中。
比如有如下handle:

有用的指令就这么两条:

handle的特征提取及模型训练
特征可以人工选取或者通过自然语言处理的一些模型得到,比如word2vec和bert模型,把汇编指令看成一个单词,handle看成一个句子。通过自然语言处理提取代码的特征可以参考一些代码相似度检测相关的论文。本文采用人工定义的特征和kmeans聚类算法,主要是实现简单,可以快速验证这个思路是否可靠。一个handle的特征定义如下:
代码实现如下:

壳程序所有handle的提取在ExtractHandleFeature函数实现。特征提取后,通过t-sne对这些数据降维然后可视化,效果如下:

可以看出这数据还是具有可分性的,一个簇一类,大致可以划分为14类。数据的可视化和模型的训练相关的代码在model.py。代码如下:

部分分类出的handle如下:




handle下面一行是特征向量和类别,大部分handle的分类还是正确的。错误分类的也有,比如:

这个handle归类为8,8和10应该分为同一类。为了提高正确率,可以重新定义其它的特征、调调参数或者使用其它模型,感兴趣的坛友可以去试试。
handle的化简
化简的思路是只保留和内存操作相关的指令,vmp是基于堆栈的虚拟机,执行过程含有大量的栈操作,本质上也是内存操作,把读写内存的操作数直接替换成绝对地址。比如如下handle:

然后通过qiling模拟执行保留的寄存器信息转换成

0xffff开头的地址是qiling默认的栈地址。这么做可以不用考虑寄存器轮转的问题和下一条handle的地址计算。去掉绝大部分指令,保留核心的指令还能够很好的分类。本文只实现了部分handle的转换,具体参考TranslateHandle函数实现的代码。vmp壳程序的执行会多次进入虚拟机、退出虚拟机、执行一个正常的函数然后又重新进入虚拟机。本文以第一次进入虚拟机然后退出虚拟机之间的代码作为转换例子,然后通过keystone转换到二进制文件,最后通过ida反编译。效果如下:
由于之前没有保存状态寄存器的值,所以暂时用0xef代替,主要是以下指令产生的

这两条指令是直接转换到mov dword ptr [0xXXXXXXXX], 0xef。观察上面的反编译代码,可以看到有一个call调用,地址0x7D92CC刚好是LocalAlloc导入表中的地址。这个call是由vmCall产生的,vmCall的转换没有保留参数,感兴趣可以自己修改一下代码。

总结
通过机器学习对vmp的handle进行分类是可行的,重点是提高分类的正确率,单纯使用聚类算法的正确率并不是很高,而且人为设置的特征又不够灵活。对于特征的提取,还是最好选择自然语言处理中的模型,比如word2vec或者bert。提取出特征后,可以先用聚类算法进行分类,然后筛选出一些正确分类的handle,再通过这些handle训练出一个有监督学习中的算法去预测其它未分类的handle,比如svm或者其它一些神经网络,最后根据这些分好类的handle再次进行训练。特征的提取可以参考以下论文
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