本文由Blaze于2024年3月25日发表于其个人博客网站上。
就在不久前,我们意外发现了一个PureCrypter样本,而PureCrypter则是一款适用于各种类型恶意软件(例如Agent Tesla和RedLine)的加载器和混淆处理工具。深入分析之后,我还专门为该样本编写了Yara检测规则,当时我便意识到,我是不是也可以写一些Yara规则来识别.NET开发的恶意软件或.NET程序集。
在这篇文章中,我将跟大家分享如何使用.NET元数据分析、跟踪和分类恶意软件的相关内容。
背景概述
.NET程序集或二进制文件通常包含各种元数据,例如内部程序集名称和GUID,尤其是MVID和TYPELIB:
GUID:也被称为TYPELIB ID,会在创建一个新项目时生成;
MVID:模块版本ID,.NET模块的唯一识别符;
TYPELIB:TYBELIB版本,或类型库编号;
这些特定的识别符可以使用strings命令下列正则表达式来解析:
[a-fA-F0-9]{8}-[a-fA-F0-9]{4}-[a-fA-F0-9]{4}-[a-fA-F0-9]{4}-[a-fA-F0-9]{12}
我们以PureLogStealer的一个样本为例,基于MVID或Typelib来编写一个Yara规则。VirusTotal上的样本检测信息如下:
对应的Yara规则如下:
rule PureLogStealer_GUID { strings: $mvid = "9066ee39-87f9-4468-9d70-b57c25f29a67" ascii wide fullword condition: $mvid }
但现在存在的问题如下:
1、MVID会以二进制值的形式存储,而不是以字符串形式,同时Typelib GUID是以字符串形式存储的,由于我们这里只有MVID,因此该规则无法检测上面给出的这个样本;
2、VirusTotal似乎并没有报告Typelib;
3、使用字符串和正则表达式“手动操作”很麻烦,尤其是在较大的数据集上,而且容易出现假阳性和假阴性问题;
需要注意的是,在IlSpy或dnSpy(Ex)之类工具的帮助下,我们是可以查看到Typelib GUID和MVID的,但并不是所有的工具都会显示所有的数据,比如说:
如果我们使用ildasm来查看到话,会得到如下所示的信息:
针对上述所有的原因,我们要想办法解决,解决方案就是Yara规则结合我所开发的一个新Python工具。
解决方案和工具
在介绍解决方案和我的工具之前,我不得不提一下,多亏了Yara规则一直在进化,并且引入了下列新的模块,我们现在才能够更加有效地检测和捕捉恶意软件样本:
2017:引入.NET模块;【传送门】
2022:引入console模块;【传送门】
这也就意味着,在.NET模块的帮助下,我们现在可以按照下列方式来写Yara规则了:
import "dotnet" rule PureLogStealer_GUID { condition: dotnet.guids[0]== "9066ee39-87f9-4468-9d70-b57c25f29a67" }
检测样本:
Yara规则
现在我们可以利用Yara的强大能力,以及dotnet和console模块来编写一个新的Yara规则,并显示给定.NET样本的全部有用信息,例如程序集名称、Typelib和MVID:
首先,我们需要验证目标二进制代码是否是一个.NET编译文件,如果是,记录下特定的PE或代码信息,然后显示所有相关的.NET信息。上述样本的Yara规则数据(元数据)如下:
这也就意味着,我们现在可以编写下面这样的Yara规则:
import "dotnet" rule PureLogStealer_GUID { condition: dotnet.guids[0]=="9066ee39-87f9-4468-9d70-b57c25f29a67" or dotnet.typelib=="856e9a70-148f-4705-9549-d69a57e669b0" }
Python工具
那么,如果我想要对大规模样本集执行检测,并生成统计数据,然后进行恶意软件家族跟踪和分类的话,该怎么办呢?
为此,我专门开发了一个Python工具,这个工具就可以解决我们的需求问题。它支持输入一个文件、整个样本文件夹或恶意软件代码库,该工具会跳过任意非.NET代码,并报告Typelib、MVID和Typelib ID。
针对单个样本的工具执行结果如下:
该工具的帮助信息如下:
当然了,该工具并不仅限于搜索.NET恶意软件的MVID或Typelib,你也可以使用使用它并结合Yara和Python来提取各种你需要的信息。相关的Yara规则和Python工具(DotNet-MetaData )已经发布在【GitHub】上,有需要的研究人员可以自行访问下载。除此之外,广大研究人员也可以根据自己的需求对工具进行自定义开发和调整,以获取和显示更多的信息。
集群
跟踪威胁行为者的活动,一直以来都是研究人员的常规挑战之一,虽然有的时候会很有趣,但绝大多数都是枯燥乏味的。下面给出的是我遇到的一个恶意软件集群活动示例:
这里涉及到大量的样本集(1300个),主要针对的是SteamStealer。
针对我们的分析目标,我选择了目前四个比较热门的恶意软件(基于.NET或拥有.NET变种版本)进行分析:
RedLine
Agent Tesla
Quasar
Pure*(与PureCrypter, PureLogs等相关)
下载并使用DotNetMetadata分析后,我们会得到如下图所示的结果。
RedLine(56个样本)
RedLine Typelib GUID频率:
RedLine MVID频率:
Agent Tesla(140个样本)
Agent Tesla Typelib GUID频率:
Agent Tesla MVID频率:
Quasar(141个样本)
Quasar Typelib GUID频率:
Quasar MVID频率:
Pure*家族(194个样本)
Pure* Typelib GUID频率:
Pure* MVID频率:
上述的饼状图能够显示相同Typelib或MVID出现的频率和情况,同时我们也可以利用这些饼状图数据来为每个恶意软件样本集群创建有效的Yara检测规则。
你可能会认为,这些饼状图不会特别有效,因为如果数据集再大一些的话,缩放会比较困难。但是,我们可以通过限制显示的结果数量,来获取更好的结果。上述四个恶意软件家族样本数据集中,总共有531个样本,再次运行可视化处理后,我们将进行下列操作:
1、针对整个样本集执行分析;
2、提取程序集名称;
3、仅列出排名前十的程序集名称;
4、使用柱状图代替饼状图;
结果如下图所示:
排名前三的为:
1、“Client”:Quasar家族;
2、“Product Design 1”:Pure家族;
3、“Sample Design 1”:Pure家族;
“Client”貌似是Quasar恶意软件编译时使用的默认程序集名称,而“Product Design”和“Sample Design”则可能是PureCrypter构建器的默认程序集名称。
接下来,我们就可以根据默认程序集名称为Quasar编写一个Yara规则:
import "dotnet" rule Quasar_AssemblyName { condition: dotnet.assembly.name == "Client" }
我们还可以构建Yara规则来对我们的恶意软件数据集或存储库进行分类:
import "dotnet" import "console" rule DotNet_Malware_Classifier { condition: (dotnet.assembly.name == "Client" and console.log(“Likely Quasar, assembly name: ", dotnet.assembly.name)) or (dotnet.assembly.name == "Product Design 1" and console.log("Likely Pure family, assembly name: ", dotnet.assembly.name)) or (dotnet.assembly.name == "Sample Design 1" and console.log("Likely Pure family, assembly name: ", dotnet.assembly.name)) }
针对Pure家族和Quasar合并样本运行新的Yara规则后,分类结果输出如下:
我们可以将基于程序集名称、Typelib、MVID等的Yara规则集组合起来,创建具有更高置信度的规则,并将其用于进一步的恶意软件搜索和分类等操作。
意外收获
既然已经走到了这里,我们再努力一下!现在,我们可以尝试去寻找新的加密器或混淆处理器了。
当我使用工具脚本对500+个样本执行测试时,有一个程序集/代码吸引了我的注意:
针对它写一个简单的Yara规则:
import "dotnet" rule cronos_crypter { strings: $cronos = "Cronos-Crypter" ascii wide nocase condition: dotnet.is_dotnet and $cronos }
Unpac.me Yara捕捉结果:
由此看来,这个加密器(Cronos-Crypter)似乎并不是很受欢迎。目前为止,只有两个Async RAT样本和两个PovertyStealer样本使用了它。
通过审查Async RAT并改进之前的“分类规则”,我们看到这个加密器至少在两个Async RAT样本上使用过,基于86个样本,我们得到了下列统计数据:
我们得到了下列程序集名称:
AsyncClient
Client(Quasar中也有)
XClient
Output
Loader
Stub
AsyncClient很可能是Async RAT项目的默认名称,针对该样本的Yara规则优化版本如下:
import "dotnet" import "console" rule DotNet_Malware_Classifier { condition: (dotnet.assembly.name == "Client" and console.log("Suspicious assembly name: ", dotnet.assembly.name)) or (dotnet.assembly.name == "Output" and console.log("Suspicious assembly name: ", dotnet.assembly.name)) or (dotnet.assembly.name == "Loader" and console.log("Suspicious assembly name: ", dotnet.assembly.name)) or (dotnet.assembly.name == "Stub" and console.log("Suspicious assembly name: ", dotnet.assembly.name)) }
分类器Yara规则结果如下:
总结
在这篇文章中,我们主要介绍了两种用于从.NET恶意软件中提取元数据的技术方法和工具,简而言之,就是通过可靠的方法提取两个唯一GUID(Typelib和MVID)来识别恶意软件。
我们提供的Python脚本可以从大量.NET程序集中提取出所需的数据,广大研究人员可以根据实际情况调整大型集合的Yara规则,并扩展脚本以获取更多有价值的数据。
你可以在下列存储库中找到本文涉及到的工具和Yara规则示例:
https://github.com/bartblaze/DotNet-MetaData
最后,祝大家恶意软件“狩猎”愉快!
参考资料
https://malpedia.caad.fkie.fraunhofer.de/details/win.purecrypter
https://twitter.com/James_inthe_box/status/1767548157003743382
https://twitter.com/James_inthe_box
https://github.com/VirusTotal/yara/releases/tag/v3.6.0
https://github.com/VirusTotal/yara/releases/tag/v4.2.0
参考链接
https://bartblaze.blogspot.com/2024/03/analyse-hunt-and-classify-malware-using.html