使用运行时操作码的恶意软件动态分析
摘要
迄今为止,针对故意恶意软件的持续斗争一直有利于恶意软件的传播者。特征检测方法在应对快速演变的混淆技术时正变得越来越无效。最近的研究集中在对可执行程序进行低级别的操作码分析,包括静态和动态分析。虽然静态分析能够检测恶意软件,但通常仍无法解开混淆代码;而动态方法则使研究人员能够揭示运行时代码。过去研究中使用的老化且采样不足的数据集限制了研究成果的可推广性。本文提出一种基于动态操作码分析的恶意软件检测方法,并将机器学习技术应用于同类中最大规模的数据集,无论是在广度(610至10万特征)还是深度(48k样本)方面均如此。应用了从n D1:: 3的操作码序列进行n元语法分析,以增强特征集。随后研究了特征选择,以应对由此产生的特征爆炸问题,某些情况下特征数量超过10万个。由于越早检测到恶意软件越有利,因此考察了运行长度(即执行轨迹中记录的操作码数量),以确定最佳捕获大小。本研究发现,利用仅32k个操作码序列和50个特征,动态操作码分析可以以99.01%的准确率区分恶意软件与良性软件。这表明,动态操作码分析在速度方面可与静态分析相媲美。此外,该方法在对抗恶意软件这一始终处于被动防御状态的无尽斗争中具有非常实际的应用前景。
1 引言
自Brain于1986年发布以来,作为首个PC病毒,恶意软件(malicious software)的不断扩散以及标准反病毒(AV)软件的失效,已为所有技术用户带来了重大挑战。2016年第二季度,McAfee实验室报告称,在此前三个月中,此前未见过的恶意软件实例数量已超过4000万。独特的恶意软件样本总数达到6亿,比前一年增长了近三分之一[4]。
恶意软件过去被认为是不良少年的产物,而现在人们普遍认为它是犯罪团伙和疑似国家层面不法行为的一种高效工具。作为一种工具,恶意软件助长了全球范围的犯罪产业,并在全球范围内实现了盗窃和勒索。据估计,美国公司发生的一次数据泄露事件平均代价高达585万美元,即每条被泄露记录成本为102美元[1]。将网络犯罪成本归因于现代发达国家的GDP估算显示,德国高达1.6%,其他技术密集型国家也显示出令人担忧的水平(美国— 0.64%和中国—0.63%)[4]。
本章内容安排如下:当前部分的其余内容描述了恶意软件、检测恶意代码的技术以及后续的反制措施。第2节介绍了该领域的相关研究以及现有文献中的空白。第3节描述了建立数据集所采用的方法论,第4节展示了对数据进行机器学习分析的结果。最后一节讨论了基于这些结果所能得出的结论,并阐述了未来可能的研究方向。
1.1 恶意软件分类法
恶意软件可以根据多种特征进行分类,但通常依据其家族类型进行分类。Bontchev、Skulason和Solomon在[8]中为恶意软件建立了命名规范,这些规范在一定程度上考虑了此类文件的分类法。随着恶意软件的迅速发展,原有的命名规范需要更新,以适应恶意软件开发的新标准[15]。一个独特恶意软件的标准名称通常由四个部分组成,如图1所示,尽管具体格式(分隔符等)因组织而异。
图1 恶意软件命名规范
此类包括:
- 后门:安装到受害机器上,允许攻击者远程访问;
- Botnet:与back door类似,但受害机器是连接到命令与控制服务器的一组受感染机器中的一个;
- Downloader:用于下载进一步的恶意代码的初始代码;
- Information-stealing malware:从受害机器上抓取信息并将其转发至指定来源的代码,例如银行信息;
- Launcher:通过非合法方法启动其他恶意程序以保持隐蔽性;
- Rootkit:允许访问机器的未授权区域,并旨在隐藏其他恶意代码的存在;
- Scareware:通常模仿杀毒软件(AV)警告,旨在吓唬不知情的用户购买其他软件;
- 发送垃圾邮件的恶意软件:导致受害机器在不知情的情况下发送垃圾邮件;
- 病毒:能够自我复制并感染其他计算机的代码,但需要宿主文件;
- 蠕虫:通过网络协议进行自我传播的恶意软件;
- 木马:通常伪装成良性软件且不会自行传播的恶意软件,但允许访问受害机器;
- 勒索软件:加密受害机器文件的恶意软件,向受害用户勒索钱财以换取解密;
- 下载器:设计用于绕过杀毒扫描器,包含其他恶意软件,在下载器安装完成后从原始代码中释放这些恶意软件。
由于恶意软件经常跨越多个类别或实现多种机制,因此建立一个清晰的分类系统可能是一项困难的任务[25]。因此,采用家族作为离散的名义属性,可以为所提及的恶意软件提供充分的定义。例如,广为人知且高度复杂的震网网络武器,曾被用于攻击和破坏伊朗核计划,它横跨了多个恶意软件类别。最初的攻击向量是通过一个受感染的U盘,其中包含蠕虫模块和一个指向该蠕虫本身的.lnk文件。震网利用了多个漏洞,其中之一允许U盘上的.lnk文件自动执行。蠕虫模块包含了有效载荷的例程以及第三个模块,即rootkit,该模块可隐藏对终端用户的恶意活动和代码[42]。由于这是一种多层面攻击,可能难以充分描述该类型的恶意软件使用传统方法。然而,引用家族变量可以对整个恶意软件进行描述性引用。
1.2 恶意软件检测方法
恶意软件检测技术的发展类似于与恶意软件编写者之间的军备竞赛。当杀毒软件供应商部署新方法来检测恶意软件时,恶意软件编写者就会创建新方法以使其代码绕过检测算法。图2给出了目前使用的标准恶意软件检测技术的分类法。
图2 恶意软件检测方法
1.2.1 基于签名的
基于签名的检测依赖于将程序的有效载荷与从恶意软件中提取的预学习正则表达式存储库进行比较[14]。这些字符串的提取、存储和分发需要大量工作以及大量的人力时间[13]。此类检测通常静态地执行,因此存在主要缺点:对未知的正则表达式无效,并且无法在混淆代码中搜索此类字符串。这使得该技术在面对指数级增长的恶意软件攻击时变得越来越无力。
1.2.2 基于异常的
基于异常的检测系统将文件或系统的典型行为进行分类,任何偏离这些典型行为的情况都被视为异常[41]。训练阶段会创建文件或系统的典型行为模型或结构模型。系统。监控阶段随后会检测与训练阶段建立的基线之间的偏差[16]。例如,中毒的PDF可能与干净的PDF的典型或预期结构大相径庭。同样,一个一小时的电视节目文件预计大小约为350兆字节。如果该文件仅有120千字节,则会被归类为可疑。异常检测的一个主要优势是具备检测零日威胁的潜力。由于系统是基于典型特征进行训练的,因此无需预先了解所有非典型特征即可实现检测。然而,基于异常的系统受限于较高的误报率以及为充分建模被检测系统所需特征规模的影响[16]。
1.2.4 基于规范的
基于规范的检测是异常检测的衍生方法,旨在解决后者高误报率的问题。该检测方法试图创建一个规则集,用以近似描述系统的需求,而非系统的实现[41]。对大型系统进行充分建模是一项困难的任务,因此基于规范的检测可能与基于异常的系统存在类似的缺点,即模型无法充分捕捉复杂系统的行为。
每种分析类型都可以通过以下三种方式之一进行:
1.2.4 静态分析
当被分析对象未执行时,该分析被视为静态分析,可以在源代码或编译后的二进制表示[13]上进行。该分析通过使用其中的代码和数据结构[40]来确定程序的功能。可执行文件的MD5哈希表示可以与先前检测到的恶意软件样本的哈希数据库进行比对。调用图可以展示软件的架构以及功能之间的可能流程。字符串分析旨在查找URL、IP地址、命令行选项、Windows可移植可执行文件(PE)和密码[29]。使用静态分析技术的主要优势在于,由于恶意软件样本从未被执行,因此不会构成威胁,从而可以在安全环境中进行详细分析。当全部代码可见时,理论上所有代码路径都可被检查,而动态分析仅能检查正在执行的代码。然而,并非所有情况下检查全部代码路径都是优势,因为所揭示的信息可能是为掩盖文件真实意图而插入的冗余死代码。
随着恶意软件变得越来越复杂,静态分析技术正日益变得无效,因为这些恶意软件能够对其自身进行混淆,直到执行时才暴露真实代码。由于静态分析中代码从未被执行,因此混淆方法并不总是能揭示真实代码。
1.2.5 动态分析
动态分析涉及运行被分析文件。该技术在内存入口点、运行时和执行后挖掘信息,从而绕过许多阻碍静态分析技术的混淆方法。动态环境可以是:(a)原生:分析环境与主机之间没有隔离,分析在原生主机操作系统中进行。对于恶意软件分析而言,这显然会导致恶意软件对主机产生影响的问题。已有软件可提供干净原生环境的快照,在每次恶意软件执行后可重新加载该快照,例如DeepFreeze。然而,这一过程可能相当耗时,因为整个系统必须恢复到初始状态[23];(b)模拟:主机通过模拟硬件的软件来控制客户环境。由于该软件受底层主机架构驱动,模拟可能引发性能问题;(c)虚拟化:虚拟机提供由主机控制的隔离的客户环境。在理想环境下,被分析对象的真实行为能够被揭示并加以分析。然而,作为反制措施,恶意软件编写者开发了一系列规避技术,以检测模拟、仿真或虚拟化环境,包括反调试、反插桩和反虚拟机策略。动态方法的一个主要缺点是需要执行程序一段时间所带来的运行时开销。IDAPro等静态工具可在几秒钟内反汇编一个可执行文件,而动态分析所需时间可能要长数百倍。
1.2.6 混合分析
混合技术在其检测算法中结合了静态和动态分析的组件。在[34],中,罗恩迪和米勒使用解析在执行前静态分析可疑代码,构建代码结构的分析,而对混淆代码则采用动态执行。作者建立了一种算法,将动态和静态技术结合起来,以实现对混淆代码的插桩。
1.3 检测规避技术
代码混淆是指使代码变得晦涩或难以理解的行为。传统的合法软件公司一直使用混淆技术来防止其产品遭受逆向工程攻击。这也是数字版权管理等方法的基础,例如通过加密电子邮件、音乐等内容以防止未经授权的使用。恶意软件编写者也采用了这些技术,以类似的方式试图使其代码避开杀毒扫描器的检测。在[11]中,列出了四种最常用的混淆技术:
- 垃圾代码插入:在代码块中插入额外的代码,而不改变其最终行为。这可以是死代码,例如NOP填充、无关代码(如简单的数学函数)或无实际用途的复杂代码;
- 代码置换:重新排列代码中的指令,使得生成的二进制文件与原始可执行文件或预期的执行顺序不同;
- 寄存器重分配:在特定范围内用一个寄存器替换另一个寄存器的使用;
- 指令替换:利用计算机科学中存在多种方式完成同一任务的概念,通过使用替代指令来实现相同的结果,从而有效改变代码外观。
打包软件(加壳器)用于对PE文件进行混淆、压缩和加密,主要目的是规避静态检测方法。当加载到内存时,原始可执行文件会从只读存储器中的打包状态恢复,准备在受害机器上释放有效载荷[5]。
多态(many shapes)恶意软件由有效载荷和加解密引擎组成。多态引擎会变异静态代码/有效载荷,该代码在运行时被解密回原始代码。这可能导致杀毒扫描器难以检测,因为有效载荷在其原始代码的任何变种中均不相同。然而,加解密引擎本身可能保持不变,因此可能被基于签名或模式匹配的扫描器[26]检测到。可采用变异引擎来混淆解密例程。该引擎在每次迭代时随机生成新的解密例程,意味着有效载荷被加密,且解密器被修改,使其与之前使用的解密器看起来不同[41]。
变形(changes shapes)恶意软件在混淆技术上比多态性更进一步。对于变形恶意软件,每次变体都会完全重写代码,这意味着任意两个样本都不完全相同。与多态恶意软件类似,尽管其结构或字节码不同,代码在语义上是相同的,不同变体之间甚至仅有六个字节的相似性[21]。变形恶意软件还可以从良性软件中引入惰性代码片段,不仅导致完全不同的表示形式,而且使文件更接近良性软件,从而逃避检测[20]。
1.4 总结
针对恶意软件的持续斗争旨在寻找策略,以在恶意代码对目标系统造成损害之前进行检测、预防和缓解。基于规范和基于异常的检测方法通过对整个系统或网络建立基线模型,报告其中的变化(如异常网络流量、注册表更改等),但容易产生较高的误报率。签名检测是商业杀毒软件中最常用的方法[43]。随着恶意软件不断明显的演变,此类方法已显示出日益不足的应对能力。
在恶意代码检测方面效果不佳[31]。这在零日漏洞利用中尤为明显,因为恶意软件发布与生成特征码之间的时间差为恶意代码造成了重大损害留下了显著的窗口期。由于这些方法依赖于预先学习的特征码,而现代恶意软件混淆此类特征码的能力不断增强,基于签名的杀毒方法从定义上就一直处于被动应对的状态。因此,需要一种新方法来更准确、高效地检测对检测算法而言未知的恶意软件。
2 相关研究
混淆技术从商业应用和研究角度来看,都严重阻碍了有效且高效的恶意软件检测。先前研究试图通过将机器学习和数据挖掘方法应用于该问题,以寻找成功的恶意软件检测算法。Schultz等人[38]是首批提出使用机器学习作为分析恶意二进制文件工具的研究者。他们实现了三种分类器(RIPPER、朴素贝叶斯和多朴素贝叶斯),并与基于签名的算法(即杀毒扫描器)进行了比较,所使用的特征包括程序头、字符串和字节序列。所有机器学习方法的表现均优于杀毒扫描器,其中两种分类器的准确率甚至达到商业方法的两倍。Kolter和Maloof[20]成功地使用二进制存在/不存在属性对恶意软件PE文件的十六进制表示进行n元语法分析。在评估的其他分类器中,提升型决策树在受试者工作特征(AU‐ROC)曲线下的面积达到了99.6%。在[27],中,研究人员基于主机系统的特征来检测以前未见过的蠕虫。每秒收集了323个特征的数据,重点关注主机的配置、后台活动和用户活动。五种蠕虫与基线行为设置进行了比较,仅使用20个特征时,平均检测准确率为>90%,个别特定蠕虫的准确率可达>99%。
2.1 操作码分析
最近关于恶意软件检测方法的研究考察了恶意软件在运行时的行为,即代码正在做什么,而不是如何做,以及这些行为与良性代码有何不同。操作码(operationalcodes)是可读的机器语言指令,直接发送给中央处理器。在如此底层进行分析提供了检测恶意软件的机会,从而绕过运行时混淆[31]。
在[36], Santos等人分析了静态生成数据集中的操作码的n‐gram组合。采用了一种图分析方法[35],并将其应用于可移植可执行文件和变形恶意软件,这是对[6]的扩展。他们的模型能够将变形恶意软件与良性应用程序区分开来,并能区分不同的多态恶意软件家族。
[31]中的作者使用有监督机器学习对动态生成的数据集中的操作码进行了分析。通过在虚拟机中运行应用程序,获取了良性与恶意可执行文件的运行轨迹。该受控环境实现了客户机操作系统的隔离,从而将恶意软件的影响与主机解耦。研究人员使用调试程序(OllyDbg)结合掩码工具(StrongOD)来捕获每个被研究程序的运行时跟踪。由此获得包含每个操作码及其操作数的原始跟踪文件,并提供了内存寄存器地址等更多细节信息。
通过定制解析器从该跟踪文件中提取操作码并统计其出现次数。根据操作码在样本中的频率计算其密度。为应对不同的运行长度问题,采用样本内的总次数对操作码频率进行归一化处理。使用预过滤器选择可能为支持向量机提供最大信息量的特征,同时最小化因使用n元语法分析所有操作码组合而带来的整体规模问题。主成分分析(PCA)用于按各操作码对支持向量机分类任务的重要性进行排序。主成分分析在保持数据方差的同时压缩了数据大小,从而生成一组主成分子集。研究人员发现,数据中99.5%的方差可由前8个操作码解释,从而将数据从原始150个操作码大幅缩减,这一结果也通过支持向量机的使用得到了进一步验证。然而,所使用的数据集仅包含300个良性样本和350个恶意软件PE文件。尽管先前研究的样本数量更少(例如[7]),但样本数量少和覆盖范围不足一直是文献中反复出现的问题。
在[38],Schultz等人首次研究此类恶意软件文献时,使用了3265个恶意软件和1001个良性可执行文件。Santos等人[37]考虑了2000个文件,各类别数量相等。[28]和[39]均使用了相同的数据集,包含7688个恶意文件和22,735个良性文件,研究人员称这是当时文献中最大的数据集。然而,这些研究的数据收集方法存在显著局限性。研究人员指出,所使用的反汇编器仅能分析其样本的74%。由于失败的主要原因是文件的压缩或打包(即混淆),恶意软件的损耗率(26%)高于良性软件(10%)。
[36]所使用的数据集包含2000个文件,这是由于未明确说明的技术限制所致。这些恶意软件样本是从VxHeaven网站包含17,000个样本的语料库中随机采样得到的[2],,但所采用的静态分析未包括加壳文件。这意味着在该研究中未使用复杂的混淆恶意软件,这是该研究的一个显著局限性。此外,样本集中有>50%由三个恶意软件家族组成:黑客工具、后门和电子邮件蠕虫,这可能导致了类内人为的不平衡。
6721个恶意软件样本被用于[17],,这些样本采集自VxHeaven,并分为三类(后门、蠕虫和木马),包含26个恶意软件家族以及每个家族>100种变种。在跨类别采样时未使用任何控制,样本包括497个蠕虫、3048个后门和3176个木马变种,且未说明这些类别是如何采样的。
2.2 当前研究的原理
该领域的先前研究通常使用从VxHeaven网站获取的样本,这些样本陈旧,最后一次更新是在2010年。所采用的方法存在明显且显著的局限性,大多数研究的数据集在规模、结构或抽样方面均不够充分。静态生成的数据集未能充分应对任何形式的混淆,有些研究甚至最初就排除了任何加壳的样本。尽管动态分析存在劣势,但它能够提供恶意软件在运行时行为的快照,不受混淆影响,因此已被先前专注于静态分析的研究人员推荐[36]:
事实上,广泛使用的静态检测方法只能通过加壳器的特征码来应对加壳的恶意软件。因此,动态分析似乎是解决此问题更有前景的方法([18])[36, p.226]
3 方法论
3.1 源数据
该领域的研究通常使用在线存储库,例如VxHeaven[2]或VirusShare[33]。前者的语料库已过时,最后一次更新是在2010年。然而,VirusShare包含更多的样本,持续更新,并提供有用的元数据。该网站从研究人员、安全团队和公众处接收恶意软件,并仅通过邀请方式向研究人员提供。在撰写本文时,下载了最近的三个恶意软件文件夹,代表了约195,000个不同格式的恶意软件实例。此外,还获取了从野外的恶意下载中收集的Malicia数据集,并将其纳入总的恶意软件语料库中。良性软件则采集自Windows机器,代表了在基准环境中可能遇到的标准可执行文件。
3.2 数据库创建
由于恶意软件语料库中的文件仅以MD5哈希列出,没有文件格式信息,因此构建了一个专用系统来生成样本的属性元数据数据库。曾考虑使用标准*nix命令,例如file来获取文件格式。但这种方法无法提供所有必要信息,因此开发了一套定制解决方案。图3展示了所采用的系统。
图3 处理恶意软件样本来存储其描述性属性
VirusTotal为此预处理阶段提供了一个功能完整的API密钥。这允许将哈希值与VirusTotal的后端数据库进行比对,该数据库包含文件定义以及54个杀毒软件扫描器对该文件的扫描结果。生成的报告被解析以提取所需的特征(类型、格式、首次出现时间、54项杀毒扫描结果等),并写入本地数据库进行存储。归因系统的最后一步是允许查询本地数据库,以针对特定文件类型进行检索,并相应地对文件进行分组。在当前研究中,我们关注的是WindowsPE文件,初始数据集产生了约90,000个样本。其他文件类型(安卓、PDF、JavaScript等)也被分类并存储,供未来研究使用。
在创建本地属性数据集时,各个杀毒软件扫描器对特定文件是否为恶意文件以及其指定的恶意软件类型和家族的判断存在明显差异。这给我们的方法论带来了挑战。如果一个文件仅被54个杀毒软件扫描器中的极少数检测到,则可能被视为潜在的误报(即被判定为恶意,但实际上为良性),或者确实是一种能够成功逃避大多数杀毒软件扫描器检测的恶意软件实例。当扫描器错误地将文件识别为恶意时,就会发生误报。模糊哈希的使用加剧了这一问题,因为文件的哈希表示与恶意文件相似,而且多个厂商经常共享扫描引擎和签名数据库。误报问题可能带来严重后果,例如导致操作系统无法使用。该问题已变得足够严重,以至于VirusTotal尝试从其受信任来源构建一个应用程序白名单,以便检测并缓解误报[24]。因此,我们采用了一种多数规则算法,并重点关注被50%或更多杀毒软件扫描器判定为恶意软件的实例。这一做法是合理的,因为我们希望建立一个基础的恶意软件数据集,优先纳入已被确认的恶意软件,而非可疑样本。事实上,杀毒软件扫描器在样本判断上的分歧正凸显了该领域的一个关键问题。
图4 被杀毒扫描器数量(横轴)检测到的样本数量的分布(累积百分比)
图4描绘了被指定数量的杀毒软件扫描器判定为恶意的样本分布情况。例如,根据VirusTotal报告(右侧纵轴),964个样本被4个杀毒软件扫描器判断为恶意,而12,704个样本被48个扫描器检测到。累积来看,这表示3%(左侧纵轴)的恶意软件被4个或更少的扫描器检测到,89%被48个或更少的扫描器检测到。在图4中,中心分界线表示选择样本进入实验数据集的阈值,即26个或更多的杀毒软件扫描器将该样本识别为恶意。此阈值表明,通过采用多数规则决策,实验数据集排除了18%的数据集。换句话说,在确保严格纳入机制的前提下,保留了82%的恶意样本。由于这些实验的目的是构建一个关于恶意软件动态行为的可靠模型,因此在训练目的上优先考虑那些被广泛认可的样本。
3.3 自动化运行轨迹收集
从执行的恶意软件中提取操作码运行轨迹的过程已在[31, 32]中建立。该方法能够生成所需的执行轨迹,但需要手动设置和操作,因此不适合大规模数据集的生成。因此,考虑采用可自动扩展的流程。
[23]中的研究展示了可用于VirtualBox虚拟机的实用自动化功能,但所使用的方法现已弃用。[12]开发了一种位于主机操作系统之外的虚拟化测试平台。作者声称该工具在测试25,118个恶意软件样本时无法被检测到,但未提供数据集的具体构成。然而,该软件最后一次更新是在2015年10月,仅兼容WindowsXP,并且需要一个已弃用版本的Xen虚拟机监视器,因此未被采用。
还考虑了普遍使用的Cuckoo沙箱环境。尽管它在恶意软件和数字取证分析中是一种有价值的工具,但我们希望寻找一个能够为[31, 32]中建立的方法提供精确输出的系统。此外,我们希望开发一个以操作码为重点的恶意软件分析环境,因此选择设计一个定制的自动化执行与追踪系统。
VirtualBox被实现为虚拟化平台。尽管存在其他虚拟化软件,如VirtualPC、Xen和VMWare,但VirtualBox的应用程序编程接口功能丰富,特别适合当前研究。VirtualBox在核心虚拟机监控器之上包含多个层次,该监控器在内核级别运行,允许每个虚拟机相对于主机和其他虚拟机具有独立性。该应用程序编程接口支持通过图形用户界面和编程方式对VirtualBox堆栈进行功能完整的实现,因此具有完善的文档记录并经过广泛测试[3]。
创建了一个包含64位Windows10、2GB内存、VT‐x加速、英特尔i55300处理器的2个核心以及已安装VBoxGuestAdditionsv4.3.30插件的基线镜像。选择Windows10作为最新的客户机操作系统,因其具有现代性和较高的市场占有率。VBoxGuestAdditions可在虚拟机内启用额外功能,包括文件夹共享和从主机执行应用程序,这两者均为该实现的关键特性。为客户机提供完整的互联网访问权限,并对网络流量进行部分捕获以用于独立研究,同时监控流量以进一步验证恶意软件的活跃性。在客户机操作系统中尽量减少安全功能,以最大化已执行恶意软件的影响效果。
VM快照中预装了OllyDbg v2,用于跟踪每个已执行文件的运行时行为。这是一个开源的汇编级调试器,可直接加载可移植可执行文件和DLL文件并进行调试。恶意文件和良性文件都可能检测到调试器的存在,此类实例可能会采用伪装技术。根据[31],,我们使用StrongOD v0.4.8.892来隐藏调试器的存在。
客户机操作系统被设计成类似于标准操作系统,包含文档和网页历史记录、Java、Flash、.Net、非空的回收站等。尽管研究并适当实施了反反虚拟化策略,但在保持远程等基本功能的同时,并非所有策略都能实现执行。然而,在操作码级别运行时,我们可以监控反虚拟化行为,并将其转化为检测的一个特征。此外,本研究旨在调查恶意软件的执行情况,以模拟用户实际体验,包括基于云的虚拟化机器实例。图5展示了当前研究中所用自动化实现的工作流程。启动时,系统会解析用户指定的共享文件夹中的所有文件,并将其列入执行列表。使用基线快照启动虚拟机,以消除之前执行的恶意软件可能带来的残留影响。加载带有掩码插件的OllyDbg,并将执行列表中的下一个文件作为参数传入。调试器将可移植可执行文件加载到内存中,并在执行前暂停。调试器设置为实时覆盖一个已存在的空文件,记录发送到中央处理器的操作码指令的执行轨迹,设置为单步进入级别,以便捕获每一步操作。这与静态分析不同,静态分析仅能提供可能执行的代码和代码路径。图6显示了一个已生成的运行跟踪文件示例。
图5 自动化数据采集系统模型
图6 运行时跟踪文件中的样本行
在设定的运行长度(设置为9分钟)结束后,虚拟机被拆解,并重新启动以执行下一个文件,直到列表中的文件全部处理完毕。我们选择了9分钟的执行时间,其中包含1分钟用于启动和拆解,因为我们致力于尽可能准确地检测恶意软件,同时尽可能缩短运行时长。尽管更长的运行时间可能会产生更丰富的跟踪文件,并更有效地追踪具有混淆睡眠函数的恶意软件,但我们的研究重点是检测过程中的初始执行阶段。
动态执行的瓶颈在于运行时间,因此在运行时间保持不变的情况下,捕获率的任何提升都将取决于并行性。所提出的实现有两个关键优势:可扩展性和自动化执行。初始执行阶段分布在14台物理机器上,使得数据集能够并行处理。这使得在文献背景下,能够在合理的时间内创建如此大规模的数据集。实际上,这一规模仅受限于可用物理机器的数量。完全可行的是,对该跟踪系统进行基于云或服务器的实现,从而拥有几乎无限数量的节点。
3.4 操作码统计收集
在分析之前,需要对跟踪文件语料库进行解析,以按顺序提取操作码。我们采用了一个定制解析器来扫描每个运行跟踪文件,并对Intel x86/x64架构中列出的610个操作码的出现次数进行累计计数[22]。该列表比[31, 32],更全面,因为先前研究表明,罕见出现的操作码相比频繁出现的操作码能更好地实现恶意软件与良性软件之间的区分能力[7, 17]。
由于运行轨迹的长度(即行数)各不相同,当前研究需要一致的运行长度,以探究运行长度对恶意软件检测的影响。使用文件切片器对运行跟踪数据集进行处理,将所有文件截断至所需的最大长度,以控制运行长度。如[31, 32],部分所述,运行长度按顺序被限制为1、2、4、8、16、32和64千操作码,以及图7中列出的非截断集合。
图7 衍生数据集
图8 样本n元语法组合
每个跟踪文件的计数被追加到整体数据集,并以CSV格式文件存储以供分析。由于恶意软件在运行时的行为以文本形式表示,因此可以将其视为一个具有明确定义词典的自然语言问题。N‐gram被用于文本处理中的机器学习,同样可应用于当前的问题。先前研究显示,n元语法分析可用于区分恶意和良性应用程序,但所用数据集严重受限。因此,本文重点使用n元语法分析,在大规模数据集上研究恶意软件分类。
操作码计数过程的第二个独立阶段随后从精简列表(n D 2::3)中解析执行轨迹的二元组和三元组。系统会移除所有未出现的操作码,因为随着n的增加,可能的组合数量呈指数级增长。由于在n D 1时未出现的操作码不可能出现在n D 2等的组合中,因此这种方法可以在不丢失任何数据的情况下缓解特征爆炸。如图8所示。
| 恶意软件类别 | 样本 |
|---|---|
| 广告软件 | 592 |
| 后门 | 1031 |
| 浏览器修改器 | 721 |
| Malicia | 8242 |
| Null | 5491 |
| PWS | 1964 |
| 勒索软件 | 76 |
| 流氓软件 | 498 |
| 软件捆绑器 | 630 |
| 木马 | 6018 |
| 特洛伊下载器 | 3825 |
| 特洛伊投递器 | 1619 |
| 特洛伊间谍程序 | 405 |
| 病毒工具 | 2206 |
| 病毒 | 6341 |
| Worm | 7251 |
| 良性 | 1065 |
| 47,975 |
表1 数据集组成
从初始下载到执行,样本数量减少了约20%。另有10%的文件由于缺少dll或被锁定等原因未能提供运行轨迹(表1)。任何大型数据集中的样本和特征数量都可能为分析带来方法论上的挑战,这在本研究中尤为相关。例如,在n D364k运行长度数据集中,有47,975个实例和100,318个特征,即共计4.82十亿个数据点。当以CSV格式存储时,文件大小接近9.4GB。所有分析均在一台配备12核英特尔至强CPU和96GB内存的服务器级计算机上进行。尽管具备如此强大的计算能力,如此大规模的数据集仍存在处理难题,因此选择了一种稀疏表示的文件格式(即从数据集中显式删除零值,通过省略来隐含)。这使得数据集文件大小最多减少了90%,表明存在大量零值条目,因此如后文将进一步讨论的,对特征降维进行了研究。
3.5 机器学习的应用
所有恶意软件类型被合并为一个恶意软件类别,并与良性类别进行比较。由于样本规模不平衡,采用了混合的过采样/欠采样/子采样方法来平衡各个类别。少数类(良性类别)通过合成少数类过采样技术(SMOTE)[10]进行合成过采样。该方法使用反向KNN算法生成具有新值的实例
图9 采样方法
基于5个最近邻的值,在我们的数据集中使良性样本数量增加了400%。然后将多数类随机子采样为九倍,通过匹配算法确保数据集具有相等大小。图9展示了这一方法。这确保了训练模型时使用的数据在两类之间是平衡的,以尽量缓解不平衡数据对模型性能可能产生的负面影响。
在所有实验中,使用了WEKA 3.9实现的随机森林(RF)[9]分类算法对数据进行分类。RF是一种集成学习器,通过结合多个小型学习器(决策树)的决策来实现分类。与传统的基于树的学习算法不同,RF在树的每个节点上随机选择一定数量的特征来确定参数,从而提高了抗噪性并减少了过拟合。RF在包含大量实例和特征的数据集中表现良好,尤其适用于宽数据集(即特征数量多于实例数量的情况)。它具有良好的并行化性能[9],,并且在处理不平衡数据时也被高度推荐[19]。在初步实验中,即使存在类别不平衡、运行长度较短以及使用大量特征的情况,RF仍表现出较高的准确率。
对每个子集的分类采用了十折交叉验证,并对九个子集的结果取平均值得到最终的整体结果。针对树的数量和特征数量的参数选择进行了优化最初通过粗网格搜索进行,随后进行细网格搜索。对于这两个参数而言,值越高越好,
使用运行时操作码的恶意软件动态分析
4 结果
在每个数据集上对分类器进行评估时,都产生了标准的机器学习输出:
-
准确率,即正确分配的类别的百分比(0% 表示分类器性能差,100% 表示完全准确)
$$
ACC = \frac{TP + TN}{TotalPopulation}
$$ -
F1分数是精确率和敏感性的调和平均值(理想值为1)。
$$
F1 = \frac{2TP}{2TP + FP + FN}
$$ -
受试者工作特征曲线下面积,即当真正例百分比与假正例百分比绘制曲线时,该曲线下方的面积(理想值为1)。
-
精确率‐召回率曲线下面积(1 为理想值)其中
$$
Precision = \frac{TP}{TP + FP}, \quad Recall = \frac{TP}{TP + FN}
$$
4.1 运行长度和n元大小对检测率的影响
每次分类在进行任何特征降维之前的评估结果如图10所示。
所有21项分析的整体准确率平均为95.87%,范围在93.01%至99.05%之间。在7个类别中,有3个类别的准确率在n = 2 和 n = 3 之间下降,而在3个类别中上升,1个类别保持稳定。这表明将n从2增加到3时边际增益较小(平均为0.06%)。然而,n = 1 队列在除一个运行长度(16k)外的所有情况下均表现出更高的整体准确率,其平均值分别比n = 2 高1.29%,比n = 3 高1.23%。F分数范围为0.93至0.991,其中3个n元语法的平均值再次显示出更高水平。
性能在n = 1时表现最佳,n = 2与n = 3之间的差异较小。AUROC值较高,>0.979,其中n = 1的取值范围为0.99至0.999。
所有指标随着运行长度的增加而上升,最高达到32k。在64k时,所有指标均保持稳定或性能略有下降,其中准确率下降尤为明显(从99.05%降至98.82%)。在所有指标中,整体表现最佳的是在32k运行长度下的n = 1,其准确率为99.05%,F值为0.991,AUROC为0.999。
4.2 特征选择与提取
由于特征数量庞大,尝试在保持模型检测能力的同时减少属性数量。此外,特征集过大导致在合理时间内使用特征提取算法在计算上不可行。因此,首先采用了一种特征选择策略。
| 无FS n=1 | 无FS n=2 | 无FS n=3 | GR ≥ 0.01 n=1 | GR ≥ 0.01 n=2 | GR ≥ 0.01 n=3 | 前20 n=1 | 前20 n=2 | 前20 n=3 | 前50 n=1 | 前50 n=2 | 前50 n=3 | |
|---|---|---|---|---|---|---|---|---|---|---|---|---|
| 1k | 610 | 1023 | 66,443 | 111 | 912 | 10,103 | 20 | 20 | 20 | 50 | 50 | 50 |
| 2k | 610 | 6075 | 70,777 | 111 | 2448 | 12,270 | 20 | 20 | 20 | 50 | 50 | 50 |
| 4k | 610 | 6358 | 75,907 | 115 | 2597 | 14,220 | 20 | 20 | 20 | 50 | 50 | 50 |
| 8k | 610 | 6677 | 80,876 | 116 | 2734 | 15,804 | 20 | 20 | 20 | 50 | 50 | 50 |
| 16k | 610 | 6956 | 85,693 | 135 | 2909 | 17,493 | 20 | 20 | 20 | 50 | 50 | 50 |
| 32k | 610 | 7215 | 91,403 | 119 | 2947 | 19,533 | 20 | 20 | 20 | 50 | 50 | 50 |
| 64k | 610 | 7215 | 91,403 | 139 | 3532 | 22,796 | 20 | 20 | 20 | 50 | 50 | 50 |
表2 每个FS类别下每运行长度的特征数量
采用增益比率算法来减少数据集中的特征数量。当考虑具有大量不同取值范围的属性时,信息增益可能会引入偏差,而增益比率通过考虑分割后产生的分支数量来尝试解决这一问题。在该比率中,分子表示关于标签所获得的信息,分母表示关于特征所获得的信息。使用ranker搜索方法遍历特征集。针对当前问题,ranker具有优势,因为它是线性的,且步骤数不会超过特征数量。鉴于当前数据集的规模,这节省了计算开销。
表2显示了每个队列和运行长度在每一步的特征数量。随着观测到的操作码的潜在数量增加,特征数量在n = 2和n = 3中以及每次运行长度增加时均有所上升。
研究了使用增益比率进行特征选择的四个级别:无特征选择、增益比率优点分数 ≥ 0.01(即非零)、前20个特征和前50个特征。最初还调查了一个额外类别(优点分数 ≥ 10),但这导致模型等同于随机选择(即所有度量得分均为50%)。然后将相同的随机森林分类器用于缩减的数据集进行分类。
移除优度评分为<0.01的特征后,与完整特征集相比,准确率的影响微乎其微(0.013–0.018%),但去除了最多84%的特征。
随后研究了选择前n个特征,因为非零特征的去除在每个数据集中都是独特的,但前n个特征将提供一致性。n = 1数据集在前20和前50个特征上的表现比n = 2和n = 3组更具韧性。这可能是由于从无降维到前n个特征的特征数量差异所致,例如,n = 3 64k在此方法中从100,316个特征减少到20个特征。图11显示了n = 1的准确率。
在使用机器学习的恶意软件检测模型中,应考虑假阳性率(FP)(即被错误地检测为特定类别)。这在处理不平衡数据时尤为相关。表3列出了针对不同运行长度和n元大小的良性类和恶意类的假阳性率。
| n=1 | n=1 | n=1 | n=2 | n=2 | n=2 | n=3 | n=3 | n=3 | |
|---|---|---|---|---|---|---|---|---|---|
| 良性 | 恶意 | Mean | 良性 | 恶意 | Mean | 良性 | 恶意 | Mean | |
| 1k | 0.042 | 0.081 | 0.061 | 0.029 | 0.111 | 0.070 | 0.031 | 0.107 | 0.069 |
| 2k | 0.040 | 0.048 | 0.044 | 0.036 | 0.079 | 0.057 | 0.040 | 0.075 | 0.058 |
| 4k | 0.046 | 0.032 | 0.039 | 0.046 | 0.068 | 0.057 | 0.044 | 0.071 | 0.057 |
| 8k | 0.022 | 0.028 | 0.025 | 0.023 | 0.059 | 0.041 | 0.024 | 0.059 | 0.041 |
| 16k | 0.215 | 0.027 | 0.121 | 0.011 | 0.044 | 0.027 | 0.020 | 0.052 | 0.036 |
| 32k | 0.008 | 0.011 | 0.009 | 0.008 | 0.047 | 0.027 | 0.010 | 0.045 | 0.027 |
| 64k | 0.013 | 0.011 | 0.012 | 0.022 | 0.060 | 0.041 | 0.011 | 0.044 | 0.028 |
| Mean | 0.055 | 0.034 | 0.044 | 0.025 | 0.067 | 0.046 | 0.026 | 0.065 | 0.045 |
表3 使用所有特征时,n = 1::3 各运行长度的假阳性率
“良性”列表示模型将样本错误标记为良性的比率,“恶意”列则相反。总体假阳性率较低,尽管数值范围明显,这与其他机器学习指标一致。同样,n = 1数据的表现略优于其他n元大小(平均值分别为0.044,而其他为0.046和0.045)。32k数据集显示出最低的假阳性率(良性为0.008,恶意为0.011,平均值为<1%)。这表明该模型在准确检测方面具有优势,同时有效控制了假阳性。此外,采用多次平衡训练数据的采样方法似乎降低了非平衡数据集导致假阳性增加的风险(图12)。
模型的进一步指标如表4所示。随着运行长度增加,除异常的16k数据集外,无FS和merit>0组的模型性能均有所提升。当使用固定数量的特征(前20)时,n = 2和n = 3数据集的性能随运行长度增加而下降。
以及前50)。特别是,当使用20个特征且n元大小为2时,AUROC分数随着运行长度的增加而下降。直观的解释可能是由于原始特征数量与所选特征数量的比例所致。然而,在三种n元大小中,n = 2在GR>0特征选择后的平均特征丢失百分比最低(n = 1:80.19%,n = 2:51.81%,n = 3:80.67%)。在原始队列中,其特征数量大约仅为n = 3的十分之一,因此如果特征比例是关键因素,那么减少到固定的20或50个特征应产生更大的影响。由于AUROC衡量的是区分能力,似乎在检查二元组时,用于正确区分良性代码与恶意代码的信息分布有所不同。
5 结论
在如此大规模的数据集上通过十折交叉验证达到了99.05%的准确率,这明确表明动态操作码分析可用于实际应用中检测恶意软件。尽管动态分析所需时间可能是一个劣势,但本文提出的工作表明,仅需包含1000个操作码的执行轨迹即可正确区分恶意软件与良性软件93.8%的成功率。将执行轨迹增加到前32,000个操作码,准确率可提升至99%以上。就执行时间而言,该运行长度与IDA Pro等静态工具相差不大。
进一步将特征集减少至前50个属性,并采用一元语法表示,可在保持分类准确率>99%的同时,降低解析、处理和分类的计算开销。在n元语法分析方面,当n = 2和n = 3之间增加时,收益极小。此外,在控制运行时的情况下,n > 1并未提高检测准确率。考虑到随着n级别的增加所带来的计算开销和特征爆炸问题,研究应集中于一元语法分析。
结果表明,[32]发现32k运行长度提供最高准确率的结论一致。然而,该模型的准确率峰值为86.31%,包含13个特征。此外,本研究使用的数据集规模约为[32]的80倍。在以往类似研究的背景下,本模型的准确率更高,且数据集显著更大,更能代表恶意软件的真实情况。
1201

被折叠的 条评论
为什么被折叠?



