SCRUTINIZER:通过反编译和机器学习检测恶意软件中的代码复用
2021-06-02 09:00:00 Author: mp.weixin.qq.com(查看原文) 阅读量:85 收藏

原文作者:Omid Mirzaei,Roman Vasilenko,Engin Kirda1,Long Lu,and Amin Kharraz
原文标题:SCRUTINIZER: Detecting Code Reuse in Malware via Decompilation and Machine Learning
原文链接:http://seclab.nu/static/publications/dimva2021scrutinizer.pdf
笔记作者:bight@SecQuan

解决的问题

现有方法不足以表征现代恶意软件攻击中的恶意代码重用和活动归因,主要有两个原因:首先,有关高级(例如 APT)样本的相关数据很少。因此,在实际部署中,这种限制使得常见的机器学习技术(例如监督式机器学习)在查找特定类型的恶意软件方面的效率明显降低。其次,由于恶意软件作者大量使用规避技术,当前的静态代码相似性测试方法在定位以前未知的威胁方面无效,这使得几乎所有现存的静态分析方法在实践中都无效(因此,经常需要进行动态分析)。

论文主要贡献

借助来自各种恶意软件样本的大量反编译代码样本,本文提出了一种新颖的编码机制来执行自动代码相似性分析。论文开发了一个基于 Python 的框架来对运行时内存快照进行post处理,并提取源代码,以便能够将任意恶意软件样本转换为一组代表代码功能的编码函数。为了实现这一点,作者利用文档分类领域的进步,将反编译代码中的每个函数视为一个单词序列。最后作者结合了孪生神经网络 (SNNs) 来对函数进行矢量化并构建能够执行相似性测试的编码模型。

SCRUTINIZER模型设计

系统的总体架构

构建满足此目标的解决方案需要提取给定有效载荷的解压缩版本以进行反编译,针对反编译代码开发有效的编码机制以进行相似性测试,并构建无监督模型以对未知样本运行代码分析。用于建模和测试阶段的拟议系统的整体架构如图 1 所示。

1.反编译
我们模型的第一步进行二进制反编译以生成给定有效负载的解压缩版本。为此,我们的方法依赖于现有的动态分析技术,其中给定的二进制文件在由 Lastline 开发的高级沙箱中执行,以加载和解包有效负载并记录运行时行为。沙箱通过在来宾操作系统中运行示例来充当通用解包器。
动态分析引擎在分析的不同阶段的关键点生成多个进程转储(或快照)。如果满足以下条件之一,则分析阶段被认为是关键的:1) 执行敏感 API 时,导致新进程创建(例如 CreateProcess)、新文件创建(例如 CreateFile)或特权升级(例如, AdjustTokenPrivileges),2) 当执行发生在原始 PE 映像之外时,以及 3) 当原始 PE 映像更改时。进程转储包含有关正在分析的二进制文件的加载代码和内存块的运行时信息。当引擎检测到可疑行为(例如,来自不受信任的内存区域的敏感 API 调用)时,这些在分析的不同阶段拍摄的快照会保存在单个分析主题下。我们解析这些快照并运行后处理分析以在 C/C++ 中重建程序的源代码。为此,我们为 Ghidra  开发了一个插件,将快照中的内存区域映射到 Ghidra 的虚拟内存空间,并反编译内存中找到的代码。

2.Func2vec编码

Siamese网络整体架构

模型的第二步旨在对恶意负载执行代码相似性测试。恶意操作者有很大自由利用规避技术和绕过现有源代码相似性测试机制。我们对矢量编码机制的功能依赖于Siamese神经网络。先前的研究和我们对恶意软件的实证初步实验表明,SSNs 在广泛的任务中非常有效,尤其是在相似性和度量学习以及散列中。SSNs 由两个或多个具有相同架构的子网组件组成。最常见的Siamese网络类型是具有两个相似子网络的网络,它同时接受两个输入并为输入计算两个表示向量(编码)。然后它利用距离度量来估计两个向量之间的相似性。每个子网络组件是一个长短期记忆(LSTM),一种人工循环神经网络(RNN)架构,它已被证明在各种任务上都很有效。为了向量化函数并将它们作为输入提供给 Siamese 网络,我们依赖抽象语法树 (AST)。特别是,我们将每个函数映射到其 AST 节点类型的扁平版本。最后,为了比较两个 LSTM 层的最终隐藏状态,我们利用了曼哈顿距离度量,这将我们的 Siamese 网络变成了 MaLSTM 变体。为了在反编译样本中找到相似的函数,我们首先提取每个函数向量(即一系列 AST 节点)的 n-gram。然后我们通过对这些 n-gram 应用局部敏感散列 (LSH) 算法来散列所有提取的函数。LSH 可以将类似的函数映射到相同的哈希码,称为桶。在分析结束时,仅包含单个函数的桶被合并为不同的函数。然后我们选择这些函数的所有排列作为不同的对。我们已经观察到,单独依赖 LSH 通常会引入误报,特别是在从反编译代码中提取函数并且它们有很大差异的情况下。出于这个原因,我们利用这种散列机制和两种验证技术来丢弃误报并提出基于 ML 的散列机制。

3.编码聚类
我们模型的主要目标是提供有关以前未知的二进制文件的预测。为此,我们首先结合训练好的 Siamese 网络对函数进行编码,然后利用无监督学习方法将来自不同代码样本的相似函数聚类在一起。生成的集群构成了我们的知识库,用于在以前未知的样本中定位代码重用,并推断样本的潜在行为。也就是说,样本被转换为一组编码函数,这些函数与对应于先前检测到的活动或恶意软件系列的数十万个编码函数的集群进行比较。对于每个集群,我们通过维护在不同反编译代码样本中观察到的每个函数的出现频率来生成唯一的字典标签。每个集群的标签揭示了一个或多个活动使用的恶意软件样本中集群功能的使用情况或流行程度。我们还有主要用于良性代码示例的函数的标签。根据我们的观察,恶意和良性二进制文件共享大量代码示例。例如,静态链接的标准库函数、全局变量初始化代码和导入解析代码在这两种类型中都很常见。因此,如果在恶意软件中观察到某个功能,则不能简单地将其标记为恶意。良性代码样本只能被识别为恶意代码,因为它们与恶意二进制文件共享多行代码。因此,在这项工作中,我们依赖于函数编码集群,如果新函数被分配到包含恶意和良性样本函数的混合集群,则它们会自动将新函数标记为嘈杂。然后,在进行任何进一步分析之前,我们会丢弃所有这些嘈杂的函数。为了提供 SCRUTINIZER 如何对未知样本执行自动代码重用检测的示例,我们在沙箱中运行样本并重构其源代码后,提取了 534 个函数,具有 45,902 个 LoC。然后,系统使用 func2vec 方法通过经过训练的 SSN 和来自 44K 良性和恶意有效载荷的大约 170 万个函数编码的知识库,生成相应的编码函数进行相似性测试。系统丢弃了 434 (81%) 个函数,相当于 36,957 个 LoC,并在之前看到的恶意软件二进制文件中识别出 100 个 (29%) 函数,其中大部分被分配到带有 Turla 标签的集群——一个基于俄罗斯的威胁组超过 45 个国家/地区的受感染受害者。经过进一步调查,我们发现这个样本是一个木马包,被计算机安全研究人员和西方情报人员怀疑是俄罗斯同名政府机构的产品。

实验与评估

训练网络的准确性通过非分层 5 折交叉验证进行评估。特别是,数据集首先被分成大小大致相等的 5 折。接下来,在 5 次迭代中的每一次迭代中,我们对系统进行了 4 次迭代训练,然后在剩余的次迭代中对其进行评估。恶意软件和良性函数向量的预测误差的平均值、中位数和标准差(如表 2 所示)分别为 0.082、0.097、0.056 和 0.061,表明我们的系统运行良好。此外,我们随机选择了 1,000 个函数编码,并手动检查了结果的完整性。我们的手动检查确认了编码机制的完整性和准确性,并且相似的 AST 节点在潜在空间中彼此正确放置。

使用在线威胁报告和 AV 扫描程序手动验证样本子集的活动分析结果。

安全学术圈招募队友-ing, 有兴趣加入学术圈的请联系secdr#qq.com


文章来源: http://mp.weixin.qq.com/s?__biz=MzU5MTM5MTQ2MA==&mid=2247485927&idx=1&sn=ab2490fc6238fb4210a2ac4d9409768f&chksm=fe2ef66cc9597f7a64a6a78fa7c6dd2a3d27fa661566be03caea7b7c7308bb90b08515b9c38c#rd
如有侵权请联系:admin#unsafe.sh