【翻译】Static Data Exploration
两年前,我们完全被数据收集、一次性编写的 Python 代码和炫目的图表所吸引,在 2018 年 EMBER 论文的启发下,我们开始收集、解析和分析恶意和良性二进制文件。我们最终在 Steelcon 2024 会议上讨论了这一过程和我们的发现,在我们的演讲《统计隐匿性》中,我们试图确定一个新植入程序需要做什么才能融入当代良性软件的格局。我们希望这项分析既能启发和激励创建更好的有效载荷,也能为蓝队提供静态恶意软件分析的进一步属性和行为指导。
我们的初步发现相当有趣,但由于生活和倦怠的混合因素,我们早就应该进行后续研究了。但上周,Ember 2024 作为 EMBER2024 - 恶意软件分类器整体评估基准数据集的一部分发布,重新点燃了我们对这个主题的兴趣。我们开始更新和扩展我们的 2024 年数据集,更新我们的审查流程,并基于 EMBER2024 论文,EMBER2024 - 恶意软件分类器整体评估基准数据集以及自我们上次演讲以来发表的其他研究进行进一步的分析技术。最终,我们想在这篇和即将发布的博客中从静态角度审视软件的状态,看看我们能学到什么来创建更好的恶意软件,以及更好地区分恶意软件和良性可执行文件的方法。我们将介绍我们如何收集样本,如何创建数据集,然后使用我们更新的方法探索和记录我们最初且严重拖延的发现。
数据收集
与许多项目一样,获取数据是这个问题中最困难的部分——确保我们的样本大体一致,并反映整个群体的适当广度和深度。在我们的处理过程中,我们将样本分为两大类,然后尽可能多地寻找示例:
|
|
---|---|
|
|
|
|
收集恶意软件样本
我们从恶意软件开始。恶意软件很容易获得,集中且遍布互联网。虽然许多有用的网站提供免费恶意软件,一次一个植入程序,但我们发现了几家拥有大量恶意软件收藏的知名组织。我们从以下数据集中收集了样本:
-
Sophos ReversingLabs 2000 万数据集 SOREL-20M -
Abuse.ch 和 Spamhaus 的 MalwareBazaar -
无与伦比的 VX-Underground
Sophos Reversinglabs SOREL-20M 数据集是我们发现的最方便的恶意软件数据集,因为它包含(毫不奇怪)2000 万个样本,这些样本都可以从 Amazon S3 轻松下载。然而,正如他们的博客 Sophos-ReversingLabs (SOREL) 2000 万样本恶意软件数据集中详细描述的那样,数据集中的样本通过剥离 Subsystem 和 FileHeader.Machine 头值被解除武装,这可能会通过减少子系统字段中可用的元数据来影响我们的分析。
对于恶意软件样本,我们审查了完整的二进制文件,将 OptionalHeader.Subsystem
标志和 FileHeader.Machine
头值都设置为 0,以防止意外执行。
收集良性软件样本
良性软件更难获得,经过验证的良性软件更是如此。对于良性软件,我们在演讲中使用了多种来源:
-
国家软件参考库 (NSRL) -
各种配置、版本和分发的 Microsoft Windows 和 Microsoft Windows 服务器。 -
典型的 Microsoft 软件,包括应用程序、服务、库和其他可分发文件。 -
Chocolatey -
ninite
国家软件参考库 (NSRL) 数据库维护了供应商提交的应用程序的哈希值列表。有了这些哈希值,挑战在于找到文件本身。对我们来说,我们发现 Hybrid Analysis API 可以让我们拉取原始二进制文件。我们还使用了其他公开可用的助手;我们编写了一些简单的脚本来从 Windows 的包管理器 Chocolatey 中拉取二进制文件的版本,以及从初始安装助手 Ninite 中拉取(较少的)样本。我们还从我们的 Windows 实验室环境中尽可能多地获取了样本,包括多个桌面和服务器安装的 Windows,以及我们可以在其上安装的许多角色和服务。
这个数据集绝不是所有可用或可访问的良性软件样本的完整代表。我们应该注意到,正如 EMBER 所做的那样,与(大多数!)恶意软件不同,良性软件的许可和分发要严格得多,我们鼓励有抱负的读者负责任和道德地构建更完整的良性软件数据集。
数据解析
有了涵盖恶意软件和良性软件的新样本,我们构建了一个解析器来复制 ember 的工作并构建具有类似特征的数据集。关于我们如何自动化样本静态审查的全面演练,请参见 Mez0 的博客,"Citadel: 二进制静态分析框架"。为了避免在这里重新创建整个博客,我们的解析旨在审查每个二进制文件并突出显示其元数据和数据中的特征,包括:
-
导入 -
导出 -
可选头 -
节 -
熵(包括整个文件和逐节) -
文件大小 -
工具链(编译器、链接器等) -
代码签名 -
TLS -
符号 -
哈希(TLSH 和 SHA256)
我们发现我们无法获得的是恶意软件家族。也许 Citadel 可以更新为我们做到这一点,但这需要一些时间来开发和执行——也许我们将来会探索这一点。如果你有任何关于我们如何实现这一点的想法,请联系我们!
通过这些努力,我们总共获得了 644,140 个样本,其中 613,879 个是恶意软件样本,30,261 个是良性软件样本。
恶意软件与良性软件分布
数据探索
在展示了我们如何整理和解析数据集之后,让我们深入分析解析结果,并分享我们在探索数据集时的初步发现和理论。
架构分析
首先从架构开始分析。让我们看看数据集中恶意软件 (malware) 和良性软件 (goodware) 在 x64 和 x86 架构上的分布情况。
恶意软件分布:
|
|
---|---|
|
|
|
|
良性软件分布:
|
|
---|---|
|
|
|
|
恶意软件架构
良性软件架构
有趣的是,恶意软件样本中有 613,878 个是 x64 架构,只有 1 个未知架构。而良性软件的分布则更为均衡,x64 架构有 19,880 个,x86 架构有 10,380 个。从开发者的角度来看,虽然 x64 架构已经存在相当长的时间,但 x86 样本的完全缺失仍然令人惊讶。我们不能完全排除样本提交到数据集时的异常行为,但我们对这个结果持怀疑态度。
节区分析
我们以 PE 格式调试页面作为官方实现的节区名称基础,可以直接比较相似节区的大小和熵值,同时使用节区名称列表来检查非官方或非常规的节区。
|
|
---|---|
.bss |
|
.cormeta |
|
.data |
|
.debug$F |
|
.debug$P |
|
.drective |
|
.edata |
|
.idata |
|
.idlsym |
|
.pdata |
|
.rdata |
|
.reloc |
|
.rsrc |
|
.sbss |
|
.sdata |
|
.srdata |
|
.sxdata |
|
.text |
|
.tls |
|
.tls$ |
|
.vsdata |
|
.xdata |
|
我们将所有节区的数据放入 JSON 对象中,每个节区包含熵值和大小列表,然后计算平均值。下表总结了这些数据。
|
|
|
|
|
---|---|---|---|---|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
首先,包含可执行代码的 .text
节区在恶意软件中显示出明显更高的平均熵值(6.26 vs 5.99),我们推测这是由于恶意二进制文件中更严重的混淆和/或打包造成的。此外,虽然恶意软件的 .text
节区数量更多,但良性软件的版本平均更大,可能反映了更广泛的合法代码库。
.rsrc
节区在恶意软件中明显更大且更频繁。其在恶意软件中的较高平均熵值(4.56 vs 3.75)暗示了经常被滥用于嵌入混淆或加密的有效载荷。相反,通常用于只读数据的 .rdata
节区则显示出相反的趋势:良性软件具有更高的平均熵值和更大的大小,可能是由于嵌入了更丰富的常量或资源。
良性软件对某些节区的使用极少,而这些节区在恶意软件中完全不存在,例如 .srdata
(仅 1 个实例)和 .sxdata
,尽管它们的低数量限制了统计解释。
最后,.debug
节区在恶意软件中异常大,尽管很少见,平均大小超过 1MB。这很不寻常,因为调试符号通常在生产二进制文件中被剥离;这可能反映了故意的滥用或错误分类。
总体而言,节区熵值和大小的差异为区分恶意软件和良性软件提供了有用的信号,特别是在考虑打包行为和节区利用模式时。
现在让我们反过来,只查看我们不认识的节区名称,得到以下结果:
|
|
|
|
|
---|---|---|---|---|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
恶意软件样本中普遍存在非标准节区,如 UPX1、UPX0 和 UPX2,这些是 UPX 打包可执行文件的典型特征。UPX1 显示出非常高的熵值(6.40),这与打包文件的特征一致。其他节区如.bak 和.NewSec 表明使用了注入或重命名的节区,其中.bak 显示出异常高的熵值(7.02),进一步暗示了混淆或多态技术的使用。
相比之下,良性软件(goodware)表现出更少且更一致的非标准节区,具有较低的熵值和较小的尺寸,例如.buildid 和.00cfg。这些节区通常用于存储良性元数据或运行时配置。良性软件中有限的变化和低熵值表明了透明性和可预测性,与恶意软件节区的多样性和高熵值形成鲜明对比。总体而言,数据强调了熵值和异常节区命名作为区分恶意二进制文件和合法文件的重要指标。
文件大小
文件大小是另一个值得关注的指标,因为它通常与规避和检测相关。我们观察到有些恶意软件会通过增加文件大小来逃避扫描,而有些则使用极小的可执行文件来减少可扫描内容。让我们对数据集进行分析,看看有什么发现。
|
|
|
|
|
|
|
---|---|---|---|---|---|---|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
---|---|---|---|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
恶意软件展现出比良性软件更广泛和更大的文件大小分布。虽然 59.3% 的恶意软件样本小于 1MB,但仍有相当一部分(35.8%)在 1-5MB 之间,甚至有些异常值达到 30MB。这表明恶意软件通常采用两种策略:
-
最小化载荷:通过减少可扫描内容来规避基于签名的检测 -
膨胀技术:通过增加文件大小来超过某些扫描器的阈值限制
相比之下,良性软件绝大多数(86.3%)集中在 1MB 以下,中位数大小仅为 84.39KB。这种一致性反映了结构化软件开发实践和最小的代码膨胀,与恶意软件的多样性形成鲜明对比。有趣的是,两类样本在 50MB 以上的文件都很少见,表明如此大的二进制文件很少被用于良性或恶意目的。然而,防范恶意软件不能简单地通过阻止大于 50MB 的文件来实现。在我们的机器上,我们可以看到许多良性文件(如游戏、安装程序和其他可信文件)远大于这个阈值,这些文件不应该被自动删除。相反,许多被恶意使用的库也超过了最小阈值,这表明单独使用文件大小并不能形成可靠的规则,但可以与其他指标结合使用。
恶意软件较高的标准差(2.41MB vs. 2.37MB)和中位数与平均值的差距(688KB vs. 1.45MB)暗示了右偏分布,这可能是由于包含打包器、资源填充载荷或多阶段投放器的大型文件造成的。相比之下,良性软件的中位数与平均值差距较小,且平均值较低,反映了更严格的控制和更少的异常。
这里有趣的是良性软件和恶意软件在用途上的明显差异。虽然良性软件旨在实现从计算器应用到任务管理器的各种功能,但恶意软件的范围要严格得多,通常试图植入更多恶意软件。这是我们数据集的一个关键限制,我们无法轻易判断样本是勒索软件、投放器还是植入物本身。
总体而言,恶意软件文件大小的可变性突显了其适应性——在隐蔽和过度之间摇摆——而良性软件的趋势显示出一致性,这可以为静态分析管道中的异常检测基线分析提供参考。
熵值
另一个被广泛讨论的指标是熵值,特别是香农熵(Shannon entropy)。它用于测量数据的随机性,在恶意软件中,加密被用来保护攻击者不想让你看到的内容。例如,考虑一个想要执行 shellcode 来投放植入物的可执行文件...该 shellcode 很可能被加密。
以下是文件中熵值的汇总表:
|
|
|
|
|
|
|
---|---|---|---|---|---|---|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
---|---|---|---|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
恶意软件的平均熵值(6.37)通常高于良性软件(6.10),当检查熵值范围的分布时,这种差异变得更加明显。
53.4% 的恶意软件样本落在 6.5 到 8 的熵值范围内,这表明超过一半的数据集使用了某种程度的混淆或加密部分。相比之下,良性软件在 6.0 到 6.5 之间达到峰值(40.6%),在更高的熵值区间急剧下降,只有 5% 的良性软件超过 7.0。
这种模式支持了高熵值可能是恶意行为的强有力指标的假设。然而,单独使用熵值并不是完美的预测指标。例如,一些良性软件(如安装程序、压缩的可执行文件或加密工具)可能自然表现出较高的熵值。良性软件相对较低的标准差(0.7566)与恶意软件(1.3545)相比,也表明良性文件的结构更加一致,不太可能包含大的加密块或随机数据。
导入函数分析
接下来我们分析导入函数。在 Categorising DLL Exports with an LLM 一文中,mez0 使用 LLM 对 MSDN 中的 Windows API 函数进行分类 - 分类映射文件可在此处找到:https://gist.github.com/mez-0/833314d8e920a17aa3ca703eabbfa4a5
以 VirtualAlloc 函数为例,该函数从 Kernel32.dll 导出,分类如下:
|
|
|
|
---|---|---|---|
|
|
|
|
通过分析导入函数,我们可以了解文件可能执行的操作。需要注意的是,有多种方法可以隐藏这些函数并通过动态获取地址来调用,但这不在我们当前的讨论范围内。以下是 Chrome 中导入函数的示例:
对于每个样本,我们可以统计导入函数的调用次数,以了解各个调用的普遍性。通过这种方式,我们可以与良性软件进行交叉参考,找出关键差异。
恶意软件常用函数:
|
|
|
|
---|---|---|---|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
一个关键观察是,恶意软件样本大量使用与进程和文件操作相关的核心 Windows 内核函数。例如 kernel32.dll!ExitProcess
(63.66%)、GetModuleHandleA
(49.64%)和 WriteFile
(48.67%)是恶意软件样本中最常出现的函数。这表明恶意软件依赖程序化控制执行流程和 I/O 操作。LoadLibraryA
和 GetProcAddress
等函数也值得注意,它们在动态代码加载和函数解析中扮演重要角色——这些是恶意软件用于规避静态分析和实现模块化 payload 交付的常见技术。
良性软件常用函数:
|
|
|
|
---|---|---|---|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
相比之下,良性软件样本更频繁地调用系统自省和诊断函数,包括 GetSystemTimeAsFileTime(51.36%)和 QueryPerformanceCounter
(51.14%)。这些函数通常用于性能监控、日志记录和异常处理——这是合法软件的预期行为。SetUnhandledExceptionFilter
和 RtlVirtualUnwind
等异常相关函数的频繁出现进一步支持了良性软件倾向于包含健壮的错误处理机制的观点,这可能是由于更高的开发标准和测试要求。
|
|
|
|
|
---|---|---|---|---|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
共享函数集,如 CloseHandle、GetLastError
和 Sleep
,在恶意软件和良性软件中都有出现,但在恶意软件中的调用频率和数量明显更高。这反映了这些 API 的通用性;它们对良性和恶意应用程序都是必不可少的。然而,使用频率的差异可能反映了不同的操作强度或结构设计。例如,恶意软件中 GetProcAddress
的调用次数(401,545 次)与良性软件(11,004 次)的显著差异强化了动态行为是恶意代码特征的观点。
总体而言,数据表明虽然某些 API 的使用在良性软件和恶意软件中不可避免且存在重叠,但在这些函数的使用方式上存在明显差异。恶意软件倾向于利用有助于代码注入、持久化和隐蔽性的 API,而良性软件则倾向于使用与可靠性和诊断相关的 API。这支持了将 API 调用分析作为恶意软件检测和行为分类的可行特征,前提是它考虑了上下文使用情况,而不仅仅是存在或频率。
清单文件分析
清单文件 (Manifest) 包含文件描述、商标等信息,可以在任何文件的"详细信息"选项卡中查看:
从数据集来看,39.44% 的恶意软件样本 (242,122/613,879) 包含清单文件,而良性软件的比例为 78.94%(23,888/30,261)。这种现象可以理解...由合法公司提供的软件通常会填写这些信息,为什么不呢?而对于恶意软件来说,传统上没有这个必要——除非试图伪装成正常软件。
|
|
|
|
|
---|---|---|---|---|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
良性软件在元数据完整性方面表现更为突出,file_version、product_version、product_name 和 company_name 等字段在超过 75% 的样本中出现。相比之下,这些字段在恶意软件样本中仅出现在 26-39% 的样本中。这种差异可能反映了合法软件开发者的优先级,他们通常需要遵守合规性、版本控制和品牌要求——这些因素在恶意软件开发实践中基本不存在。此外,original_file_name 等字段在两组数据中几乎不存在(恶意软件 0.01%,良性软件 0.07%),表明某些元数据属性的诊断价值有限。有趣的是,虽然 comments 和 assembly_version 等字段在少数良性软件样本中存在,但它们在恶意软件中的出现率更低(2-9%),这意味着攻击者倾向于省略非功能性的描述性元数据,可能是为了减少文件大小或避免暴露开发痕迹。这种元数据使用上的差异可能为自动化恶意软件分类提供可行的启发式方法,但需要注意对抗性适应,即恶意软件作者可能伪造或模仿良性软件元数据以逃避检测。
bce48fd0850969f93da9e85a0c65f74b10d85aee68fdf6fe0e65d881f52f69ad 被发现包含清单文件,如果我们将其转储,可以看到其内容:
或者,我们可以查看 70bc155082505cdc0ec08428b39fe03212ff06653549f36cd8a9577202fc20a5 来了解它应该如何编写:
虽然这看起来很明显,但这类数据可能还是应该填写。虽然它不能确保植入成功,但至少减少了一个可疑点。因此,总的来说,添加这些信息基本上不需要什么努力,但很值得。
工具链分析
在完成上述分析后,我们不得不提到工具链。这包括:
-
链接器 (linker) -
编译器 (compiler) -
打包器 (packers) -
等
根据我们的经验,填充这些信息的最佳方法是使用 Detect-it-Easy。启动它并指向一个样本,我们可以看到大量信息。
elastic 还提供了一个 python 绑定。然而,它在处理样本数量时花费了惊人的时间,最终卡住了。我们尝试在 python 函数中引入超时包装器,但它仍然很慢。于是,我们构建了一个.NET 应用程序来异步解析所有样本——这工作得很好,解析所有样本花了 3 个小时。从 CLI 执行此操作的主要命令是:
diec.exe E:datasetmalware -g -j -U -d --heuristicscan
The output from the .NET wrapper:
DIEC Scan Summary - 09/06/2025 01:48:39
==================================================
Total files: 616,524
Successful: 118,415
Failed: 498,109
Success rate: 19.2%
Top error types:
Process timeout: 498,109 files
让我们分析链接器 (linker)、编译器 (compiler)、打包器 (packer) 和保护器 (protector) 的数据。
链接器 (Linker)
通过数据分析,我们识别出 107,234 个样本的链接器信息,占收集样本的 17.46%。以下是完整数据:
|
|
|
|
|
|
---|---|---|---|---|---|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
Microsoft Linker 在两类软件中都很普遍。这很合理,因为 Visual Studio IDE 易于使用,大多数软件都会使用它来构建。Turbo Linker、Polink、LCC Linker、Watcom Linker、GoLink 和 TCC Linker 几乎完全与恶意软件相关(98.25%-100%),表明这些工具要么是利基产品,要么特别受恶意软件开发者青睐,可能是因为它们的灵活性或隐蔽性。相反,PowerBASIC 和 Borland TLINK 仅用于良性软件(100%),表明它们要么已经过时,要么受到严格控制,限制了它们在恶意环境中的使用。GNU Linker 在良性软件中的占比更高(61.18%),而在恶意软件中占比较低(38.82%),这可能是因为它易于获取、自动化,并且在许多 GitHub 项目中常见。
编译器 (Compiler)
在编译器方面,我们看到了更多的多样性。
|
|
|
|
|
|
---|---|---|---|---|---|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
Microsoft Visual C/C++ 在两类软件中都很普遍(恶意软件 81.01%,良性软件 18.99%)。这再次表明它的广泛采用,使其成为开发者的常见选择。MASM、Microsoft Visual Basic、FASM、LCC-Win32、Virtual Pascal、Visual Objects、Intel C/C++ Compiler、Tiny C 和 Go 几乎完全用于恶意软件(100% 或接近 100%)。然而,这可能是数据集的问题,也可能反映了样本的年代。同样的情况也出现在 Visual Basic(99.93% 恶意软件)和 Borland Delphi(99.09% 恶意软件)中。MinGW(60.92% 恶意软件,39.08% 良性软件)通常用于开源工具,因此这一结果并不令人意外。
打包器 (Packer)
打包器用于通过加密和/或压缩文件来保护其他文件。执行时,原始文件会完全或部分解密/解压缩并加载到内存中。以下是我们收集的数据:
|
|
|
|
|
|
---|---|---|---|---|---|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
值得注意的是,这些工具几乎 100% 用于恶意软件。UPX(11,774 个样本,99.86% 恶意软件)、Petite(2,603 个样本,98.42% 恶意软件)和 MPRESS(2,032 个样本,99.95% 恶意软件)在样本数量上占主导地位。尽管合法开发者希望保护他们的作品,但恶意软件作者在试图植入恶意程序或勒索软件时更有动力这样做。
此外,py2exe 以 78.57% 的良性软件比例(14 个样本中的 11 个)脱颖而出,表明其在合法的 Python 软件开发中的使用,尽管样本量较小限制了更广泛的结论。这是合理的,因为 Python 代码易于阅读和理解,py2exe 虽然不是直接的打包器,但具有相同的影响。其他工具,如 DxPack(1,632 个样本)和 NeoLite(923 个样本),报告了 100% 的恶意软件,但较小的样本量(例如 PyInstaller,1 个样本)降低了这些百分比的可信度。
值得注意的是,我们这里的数据集存在局限性。获取恶意软件比获取良性软件容易得多,因此样本量可能不够全面。
保护器 (Protector)
如果将打包器视为打包和保护文件的工具,那么保护器旨在混淆二进制文件本身。以 VMProtect 为例,它提供以下功能列表:
-
混淆方法 -
变异 -
虚拟化 -
超级(变异 - 虚拟化) -
保护选项 -
内存保护 -
导入保护 -
资源保护 -
打包 -
调试器检测 -
虚拟工具检测 -
附加功能 -
控制台版本 -
水印 -
脚本语言 -
许可系统 -
激活系统 -
虚拟文件
直接引用:
保护您的代码免受逆向工程、分析和破解。利用代码虚拟化的优势,在嵌入受保护应用程序的多个虚拟机上执行虚拟化的代码片段。
以下是我们分析结果。
|
|
|
|
|
|
---|---|---|---|---|---|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
VMProtect
(619 个样本,99.52% 恶意软件)在样本量上领先,其次是 .NET Reactor
(181 个样本,83.98% 恶意软件)和 Confuser
(156 个样本,100% 恶意软件)。只有五个工具——VMProtect
(0.48% 良性软件)、.NET Reactor
(16.02%)、Smart Assembly
(14.93%)、Crypto Obfuscator
(6.52%)和 Dotfuscator
(7.69%)——报告了任何良性软件,但它们的良性软件比例较低,且样本量差异显著。
与打包器类似,我们在这里看到了大量的恶意软件使用。.NET Reactor 和 Smart Assembly 具有显著的良性软件比例,表明它们可能在某些 .NET 开发中的合法使用,但其恶意软件主导地位(83.98% 和 85.07%)仍然令人担忧。像 Confuser 和 SoftSentry 这样的工具,具有中等样本量和 100% 的恶意软件,是安全监控的高风险候选者。
代码签名 (Code Signing)
为了验证文件的合法性,我们使用代码签名技术。我们可以通过微软在 Windows 中包含的默认文件看到这一点 - 以 NTDLL.DLL 为例:
LolCerts 项目旨在追踪泄露的证书,例如 MSI 证书事件:MSI 数据泄露:私有代码签名密钥在暗网泄露
通过为恶意软件进行代码签名,攻击者希望供应商能够允许该二进制文件运行。在撰写本文时,我们试图找到一些官方文档来证明代码签名证书对规避检测有积极影响,但我们只能参考"这对我们有效"的经验。以下是我们解析的所有 CA 的统计:
|
|
---|---|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
虽然这些数据很有趣,但更多是作为参考信息。以下是关键发现:在 613,879 个恶意软件样本中,我们发现 568,456 个(92.61%)样本未签名,45,423 个(7.39%)样本已签名。相反,在 30,261 个良性软件样本中,9,490 个(31.36%)未签名,20,771 个(68.64%)已签名。因此,良性软件往往经常签名,而恶意软件则相反。我们无法明确证明签名会产生影响或成为融入系统的唯一原因,但它确实有助于二进制文件更好地融入。然而,获取代码签名证书很困难;虽然 ADCS 可以颁发证书,但我们没有看到任何研究表明使用内部 ADCS 代码签名证书签名文件的影响,而受损证书和已知问题显然不是一个好的选择。值得注意的是,即使是合法服务也使用商业可用的开发者证书,这增加了真实性,并进一步使二进制文件远离恶意软件的外观。
|
|
|
|
---|---|---|---|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
结论
获取这个数据集(包括良性软件和恶意软件)相当费时,但我们尽力而为,并且仍在寻求获取更多数据。两者中,恶意软件比良性软件更容易获得,且从许可角度来看,分发问题较少,但同样可能会根据状态和来源进行一些修改。
我们最初的主要结论是:如果你表现得像一个合法的开发者,那么你看起来也会像一个合法的开发者。
这两个数据点之间的关键差异构成了一个有趣的对比。然而,我们注意到,要让一个二进制文件最好地融入环境,虽然听起来很明显,但需要像开发者一样进行开发。使用 Visual Studio 等工具并配备所有正确资源构建和设置的恶意软件,看起来会更加真实可信。尝试融入恶意软件和良性软件之间的灰色地带是更可取的。如果任何检测逻辑纯粹基于"如果没有 manifest"这样的规则,那么这种规则理应被打破,希望编写这种低质量逻辑的厂商能够从中吸取教训。与我们所有的博客一样,我们不想直接告诉你构建更好恶意软件的确定方法,如果你从头到尾阅读了这篇博客并且有能力,你就会知道需要改进什么。
原文始发于微信公众号(securitainment):恶意和非恶意二进制文件静态数据解析和分析
- 左青龙
- 微信扫一扫
-
- 右白虎
- 微信扫一扫
-
评论