论文阅读 DeepReflect Discovering Malicious Functionality 恶意软件中恶意函数的定位和行为聚类
资料
USENIX Security 21: DeepReflect: Discovering Malicious Functionality through Binary Reconstruction ,相关代码开源在 DeepReflect Github 。
本文实验工作量十分丰富,篇幅所限这里重点讲设计的思路,实验细节推荐阅读原文Evaluation和Appendix部分。主要关注Design。
Abstract
对于未知恶意软件的恶意行为分析,需要分析师用几个小时的静态逆向分析整个binary中大量的函数,效率很低。尽管机器学习可用于帮助识别二进制文件的重要部分,但由于获取足够大的labeled dataset开销很大,监督方法是不切实际的。
作者提出了DeepReflect,首先用无监督的深度神经网络来定位(localize)恶意软件中恶意组件(函数)的位置,然后用半监督的聚类来对恶意组件做分类(classify,根据恶意行为分类,也就确定了恶意函数的行为)。训练定位用的模型无需label,而训练分类用的classifier只需要很少的label,且由分析师在分析过程中逐步提供,故本方法是实用的。实验证明,本方法可以降低分析师需要分析的函数的范围。
Introduction
静态逆向工程恶意软件可能是一个手动且乏味的过程。 公司每周最多可以收到 500 万个可移植可执行 (PE) 样本。 虽然大多数组织提前对这些样本进行分类以减少要分析的恶意软件数量(即,检查 VirusTotal以获取防病毒 (AV) 引擎结果、在受控沙箱中执行样本、提取静态和动态签名等) ,最终仍然会有需要静态逆向工程的恶意软件样本。这是因为,总会有新的恶意软件样本,之前没有反病毒公司分析过,或者没有经过精心设计的签名来识别这些新样本,或者样本可能拒绝在分析师的动态沙箱中执行。
当前的solutions包括为恶意软件样本创建签名、分类、聚类,然而,这些解决方案只预测样本的类别(例如,良性与恶意,或属于特定的恶意软件家族),但不能定位malware sample中恶意函数位置、解释恶意函数行为。需要分析师人工去做静态分析。
故需要一种工具来(1) 识别恶意函数在恶意软件中的位置,(2) 标记这些恶意函数的行为。
主要挑战是(1) 需要能够区分什么是良性的(benign),什么是恶意的,(2) 理解识别出的恶意行为的语义。对于第一个挑战,区分什么是良性和什么是恶意是困难的,因为恶意软件和良性软件的行为通常在高层次上重叠。对于第二个挑战,自动标记和验证这些行为是很困难的,因为没有单独标记的恶意软件函数的公开数据集。
作者开发了DEEPREFLECT,使用(1)一个无监督的深度学习模型,在二进制文件中定位恶意函数,(2)一个半监督的聚类模型,它使用从分析师的日常工作流程中获得的少量标签对识别的(在第一步定位到的)函数进行分类(根据行为分类,如提权、修改注册表)。
为了在二进制文件中定位恶意软件组件(函数),作者使用了无监督的自动编码器autoencoder (AE)。 AE 是一种基于神经网络的机器学习模型,可以将其输入重建为输出(即将输入编码,并将编码还原为输入)。作者的直觉是,如果用良性二进制文件训练 AE,它将难以reconstruction恶意二进制文件(即没有相关样本参与了AE的训练)。AE 将无法reconstruction二进制文件中包含恶意行为(在良性样本中没有或很少见)的区域,即无法重构相关恶意函数,从而可以定位(localize)或者说识别(identify)相关恶意函数(无法重构,即重构的loss很大的函数,就认为是恶意函数)。
为了对定位的恶意软件组件进行classify, (1) 对恶意软件样本中所有已identify的函数进行聚类, (2) 使用分析师在其日常工作流程中所做的注释(即少量人工分析的函数的行为标签),来标记聚类结果。 这种方法是半监督的,因为每个cluster只需要其中几个函数的行为标签即可确定整个cluster的行为标签(only a few labels are needed per cluster to assign the majority label to the entire cluster.)。随着时间的推移,我们可以将 AE 识别的函数映射到聚类模型来预测函数的类别,即认为函数和最接近的cluster有相同的行为标签。这反过来又节省了分析人员的时间。
Evaluation的设计:(1)识别恶意软件中的恶意函数(定位)(2)聚类相关的恶意函数(3)帮助分析师集中精力分析恶意二进制文件中重要的部分(缩小分析范围) (4)揭示不同恶意软件家族之间的共享行为,(5)处理涉及混淆的对抗攻击。
Contribution:
一个新的工具,它可以帮助恶意软件分析师(1)在静态恶意软件样本中自动定位和识别恶意行为,(2) 洞察分析不同恶意软件家族之间的功能关系。
在静态分析中使用机器学习的新方法(1)AE训练是在一种无监督的方式下进行的,无需标记就可以定位恶意函数(2)分类是半监督方式,具有最小的干预
提出了一种方法,localizing important parts of a malware with an explanation framework。使用可以映射回原始二进制或控制流图的特征。
Scope&Overview
Motivation
一个典型的恶意软件分析师Molly的工作流程:首先,询问 VirusTotal和其他组织,以确定以前是否见过这个特定的样本;没有的话,在自定义沙箱中执行它以了解样本的动态行为。若样本没有显示任何恶意或值得注意的行为——可能它已经检测到环境并拒绝执行;运行一些内部工具,诱使恶意软件执行其隐藏的行为;仍无效时,脱壳(unpacking)、并静态逆向恶意样本。在反汇编程序(例如 IDA Pro 或 BinaryNinja)中打开脱壳后的样本时,可能有几千个函数。首先运行各种静态签名检测工具来识别恶意软件的某些特定恶意组件。仍无效时,必须逐个查看每个函数(可能通过 API 调用和字符串过滤)以尝试了解它们的行为(经常求助于调试来验证观察到的行为)。在分析样本的行为后,撰写分析报告。
DeepReflect的目的就是减轻恶意分析师的分析工作。一方面定位恶意函数位置,缩小需要人工分析的范围。一方面根据分析师之前分析过的函数,为相似的函数打行为标签。
Proposed Solution
DEEPREFLECT工具, (1) 在恶意软件二进制文件中定位恶意函数 (2) 描述这些函数的行为。人工分析时可能首先静态的搜索特定字符串和 API 调用来识别函数行为,但这些信息很容易被混淆或隐藏。 因此,DEEPREFLECT 没有用上述方法,而是通过 CFG特征和 API 调用的组合来识别函数的行为。
DEEPREFLECT 的AE在良性样本上训练,从而了解良性二进制文件,进而AE在重构恶意软件时会出现异常(部分函数损失过高)。这些异常函数更可能是恶意函数,分析师可以只分析它们,从而缩小工作范围。如Figure 5 所示,DEEPREFLECT 将分析师必须分析的函数数量平均减少了 85%。 此外,实验表明我们的方法优于旨在实现相同目标的基于签名的技术。
Threat Model&Research Goals
在本文只考虑静态分析,中涉及动态分析,但从概念上讲,本文的工具可以扩展到处理动态分析数据。本文假设分析的恶意软件都是unpacked的、反汇编也是可信的,因为这些不是本文的主要工作。
DeePreflect有四个主要目标:(G1)准确地识别恶意软件样本内的恶意活动,(G2)帮助人工静态分析恶意软件样本时集中注意力(集中分析重要的部分),(G3)处理(UNESEN)恶意软件家族和(G4)给予insight into恶意软件家族的关系和趋势。
Design
Overview
DEEPREFLECT的目标是识别恶意软件二进制中的恶意函数。在实践中,它通过定位异常基本块(regions of interest - ROI)来识别可能是恶意的函数。有两个主要步骤,如Figure 2所示: (1) RoI detection and (2) RoI annotation. 使用AutoEncoder进行ROI detection。通过对每个函数的所有ROI聚类(一个函数可能有多个ROI,用每个函数自己的ROI的均值表示该函数,然后对函数聚类),标记聚类结果来进行annotation。
Terminology(术语)。恶意行为(malicious behaviors)的含义。GroundTruth通过分析恶意软件的源代码的核心组件(函数)生成。例如拒绝服务功能、垃圾邮件功能、键盘记录功能、命令和控制 (C&C) 功能、利用远程服务等(见Table 3)。通过一个叫做MITRE ATT&CK 的框架,可以标准化的描述这些恶意行为。
然而,在本文的evaluation中,有时无法肯定地将观察到的低级函数归因于这些高级描述。例如,恶意软件可能会出于多种不同的原因修改注册表项(其中许多原因可以由 MITRE 描述),但有时确定哪个注册表项因什么原因被修改很困难,因此只能粗略地标记为“修改注册表”。即使 CAPA 这样的现代工具只能模糊的标记这些行为。因此,在evaluation中,“恶意行为”意为可以由 MITRE 框架(准确)描述的函数(即不考虑模糊的标记)。
RoI Detection. 目标是自动识别(identify)恶意软件二进制文件中的恶意区域例如,我们想检测 C&C 逻辑的位置,而不是检测该逻辑的特定组件(例如,网络 API connect()、send() 和 recv())。RoI Detection的优点是可以帮助分析人员快速定位启动和进行恶意操作的代码区域。而之前的工作只创建临时签名,简单地将二进制文件识别为恶意软件、或仅基于 API 调用做一些分析。
RoI Annotation。目标是自动标记(label)包含 RoI 的函数的行为,即识别恶意函数在做什么。这是个半监督的过程,分析师需要为聚类结果的cluster做标记,但只需要前期做比较重要的工作,随着时间推移,工作量会减少。可以更快的帮助分析人员认识到(人工来看不同、不熟悉的)恶意软件样本的变体包含与先前恶意软件样本相似的逻辑。
RoI Detection
Features
前面提到使用autoencoder对样本编码、解码。为了可以在binary中定位恶意行为的位置,编码使用的特征必须可以一对一的映射回原样本。作者将每个二进制文件表示为一个m*c的矩阵,使用c个静态特征捕获前m个基本块,来总结样本的behavior。m设置为20k个基本块,是因为95%的数据集样本具有20k或者更少的基本块, c设置为18个特征
特征的选择受到先前使用ACFG的工作的启发(Genius、Gemini),consist of counts of instruction types within each basic block (a more detailed form of those extracted for ACFG features), structural features of the CFG, and categories of API calls。
structural features:结构特征2个,the number of offspring(后代数量) and betweenness score of each basic block. T。这些控制流特征可以很好的描述一部分函数行为的控制流结构,比如网络通信(连接、发送、接受)或文件加密(查找文件、打开、读取、加密、写入、关闭)。可见Figure 6.
Arithmetic Instructions: 算术指令3个, the number of "basic math", "logic operation", and "bit shifting" instructions contained within each basic block. 这些算术指令特征可以很好的描述执行数学运算的函数行为,例如加密函数可能包含大量异或指令,混淆函数可能包含逻辑和位移操作的组合。
Transfer Instructions:转移指令3个,the number of "stack operation", "register operation", and "port operation" instructions within each basic block. 这些底层的特征可描述高层函数的传输操作,比如函数的参数和返回值是如何与函数内其余数据交互的,从而可描述更复杂的逻辑和数据操作。例如去混淆/解密函数可能设计更多move-related指令,C&C control and command函数有更多堆栈相关指令。
API Call Categories:API类别10个, the number of "filesystem", "registry", "network", "DLL","object", "process", "service", "synchronization", "system information", and "time" related API calls within each basic block。调用不同类型API可执行不同类型功能,直接的表示了高层的函数行为,是很关键的特征。
本文工作API特征的选择受到先前恶意软件检测工作[18]的启发。本文使用的ACFG特征比Genius和Gemini更细致。本文没有用字符串特征,因为容易被混淆、隐藏。
Model
Autoencoder使用U-Net模型,U-Net的优点是其在编码器和解码器之间有跳过连接,对样本x可以跳过某些特征的压缩以在重构的x’中保持更高的保真度。
首先收集大量的良性样本,对每个binary抽取上述18个静态特征用于表示该binary。设有用feature表示的样本x,AE重构后得到x’,训练的目标是最小化重构损失,即输入x和输出x’之间的损失。
当使用大量良性样本训练AE后,给定一个随机的样本,可以利用公式Equation 2计算,超过MSE的即认为是恶意区域,突出显示ROI(Overview中有介绍)异常基本块。
注意到样本是m*c的矩阵表示的,RoI Detection会在m个基本块中检测出一些异常基本块。这些基本块分别属于不同的函数,使用例如BinaryNinja的工具就可以确定ROI属于哪些函数,即认为这些函数可能是恶意函数,也就完成了恶意函数定位的任务。后续RoI Annotation就是对这些函数聚类,完成恶意函数行为标记(分类)的任务。
RoI Annotation
Clustering Features
设一组脱壳恶意软件,按上述特征提取方式(18种特征)得到每个binary的特征表示,其中一个binary为x。设F为x中的函数的合集,通过BinaryNinja 获得。For each fi ∈ F ,定义the RoIs(RoI Detection中找到的异常基本块) in fi as qi。则一个函数的行为可以表示为:
其中qi ̸=∅。若qi = ∅,说明其中没有异常基本块,认为不是恶意函数。对每个qi ̸=∅的函数,按此公式计算其行为表示,得到18维向量,并加入聚类的训练集D.
公式是根据实验结果选择的,Silhouette Coefficient & Davies Bouldin Score。
Clustering Model
使用PCA降维,18到5,然后使用HDBSCAN算法对5维vector聚类。HDBSCAN与kmeans不同可以识别非凸集群;并且可以自动选择集群密度的最佳超参数。
Deployment 整个方案的流程
Initialization. DeepReflect的初始化。首先对良性benign和恶意malware binaries脱壳。然后(1)提取binary的静态特征,20k*18的矩阵(2)用良性样本训练AutoEncoder(3)使用训练好的AE从恶意样本中提取ROIs,即恶意基本块位置(5)使用行为表示的公式,计算恶意binary中恶意函数的行为表示,18维向量,并加入聚类的训练集D.(6)PCA降维,聚类得到聚类结果C。
于此同时,人工分析师手动分析了部分malware,手动对部分函数的行为打了label(一个函数一个label,根据MITRE框架)。将这些label注释到聚类训练集D,可以使聚类结果中部分cluster也有了label。每个cluster只需要其中几个函数的label,就可确定整个cluster的label,即确定整个cluster中函数的恶意行为。这是一个前期需要比较多的人工分析但后期越来越轻松的过程。
Execution.当有一个新的样本x,可以自动化的定位恶意函数、为恶意行为做标注:(1)脱壳(2)通过AutoEncoder获取ROIs(3)使用BinaryNinja以及ROIs,确定恶意函数集合,然后计算恶意函数的行为表示(4)降维(5)对每个恶意函数,认为其恶意行为和最接近的cluster相同。可以通过计算和聚类中心的距离,或者干脆重新聚类实现(6)得到每个恶意函数的行为label。当然由于部分cluster的行为label是unknown,部分函数行为也是unknown
于此同时,恶意软件分析师可以用上述结果,分析highlighted functions。(1)利用有行为label的函数对整个malware有更好的了解(2)利用MITRE,分析unknown函数,动态的更新聚类训练集的label
(3)根据不同的恶意软件家族间,在相同cluster的函数,分析恶意软件家族的相关性。
Evaluation
实验部分很详实,这里只做简单介绍,推荐看原文。
Dataset&Model Setup
Dataset。根据CNET爬取PE文件,然后脱壳、过滤(根据注册表、sha等等),得到23307个良性样本。根据VirusTotal ,脱壳、过滤,在沙箱中执行获取家族标签。得到36396个恶意样本,4407个家族。
Model Setup。使用80%的良性样本训练Autoencoder,20%测试。
Reliability
测试DeepReflect定位binary中恶意函数的表现。
Baseline (1) SHAP a classification model explanation tool (2) CAPA a signature-based tool by FireEye for identifying malicious behaviors within binaries (3) FunctionSimSearch a function similarity tool.
GroundTruth Dataset:静态的分析了三个恶意软件的源代码(rbot, pegasus, carbanak),分析了其中恶意组件的位置。
结果如Figure 3,横线为80% True Positive Rate。
Cohesiveness
测试DeepReflect聚类的凝聚性,对恶意函数行为分类的能力。
首先使用AutoEncoder,在25206个malware中识别的593181个恶意函数。TPR/FPR of 40%/5%。生成了22469个簇,最大的簇包含6321个函数,最小的簇包含5个。如Figure 10。邀请5位有经验的恶意软件分析师,手动标记了177个函数。这些函数是从最大的25个恶意软件家族中随机选取的。然后由一位分析师对这177个函数手动分组,和DeepReflect的cluster结果对比。177个函数中89.7%的函数,人工和本文方法的行为分类结果相同
Focus
即测试DeepReflect缩小需要人工分析的函数的范围的能力。如Figure5,很多样本需要分析的函数数量降低了90%以上。平均降低85%。
Insight
测试DeepReflect是否提供了恶意软件家族间行为的相关性的洞察。如Figure 4,部分恶意软件家族间分享了相同的函数;新的恶意软件家族的样本也可以被成功的分类。
Robustness
没有测试加壳,因为不是本文研究的范围。使用ollvm做混淆;使用模仿攻击,将包含本文使用的特征的良性样本的code插入到恶意样本;都没有对结果产生显著影响。
Limitations
Adversarial Attacks.
Training Data Quality.
Human Error。半监督的过程,函数的行为打标签的质量。
更强的混淆
以及依赖于脱壳质量、可靠的反汇编