恶意软件狩猎新途径:使用.NET元数据分析跟踪恶意软件

2024-04-25 06:44

本文主要是介绍恶意软件狩猎新途径:使用.NET元数据分析跟踪恶意软件,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

本文由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 fullwordcondition:$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" ordotnet.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 nocasecondition: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规则示例:

GitHub - bartblaze/DotNet-MetaData: Identifies metadata of .NET binary files.

最后,祝大家恶意软件“狩猎”愉快!

参考资料

PureCrypter (Malware Family)

https://twitter.com/James_inthe_box/status/1767548157003743382

https://twitter.com/James_inthe_box

VirusTotal

CyberChef

Release YARA v3.6.0 · VirusTotal/yara · GitHub

Release YARA v4.2.0 · VirusTotal/yara · GitHub

GitHub - bartblaze/DotNet-MetaData: Identifies metadata of .NET binary files.

GitHub - TalosSec/Cronos-Crypter: Cronos Crypter is an simple example of crypter created for educational purposes.

参考链接

https://bartblaze.blogspot.com/2024/03/analyse-hunt-and-classify-malware-using.html

这篇关于恶意软件狩猎新途径:使用.NET元数据分析跟踪恶意软件的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/933959

相关文章

Python使用getopt处理命令行参数示例解析(最佳实践)

《Python使用getopt处理命令行参数示例解析(最佳实践)》getopt模块是Python标准库中一个简单但强大的命令行参数处理工具,它特别适合那些需要快速实现基本命令行参数解析的场景,或者需要... 目录为什么需要处理命令行参数?getopt模块基础实际应用示例与其他参数处理方式的比较常见问http

C 语言中enum枚举的定义和使用小结

《C语言中enum枚举的定义和使用小结》在C语言里,enum(枚举)是一种用户自定义的数据类型,它能够让你创建一组具名的整数常量,下面我会从定义、使用、特性等方面详细介绍enum,感兴趣的朋友一起看... 目录1、引言2、基本定义3、定义枚举变量4、自定义枚举常量的值5、枚举与switch语句结合使用6、枚

使用Python从PPT文档中提取图片和图片信息(如坐标、宽度和高度等)

《使用Python从PPT文档中提取图片和图片信息(如坐标、宽度和高度等)》PPT是一种高效的信息展示工具,广泛应用于教育、商务和设计等多个领域,PPT文档中常常包含丰富的图片内容,这些图片不仅提升了... 目录一、引言二、环境与工具三、python 提取PPT背景图片3.1 提取幻灯片背景图片3.2 提取

使用Python实现图像LBP特征提取的操作方法

《使用Python实现图像LBP特征提取的操作方法》LBP特征叫做局部二值模式,常用于纹理特征提取,并在纹理分类中具有较强的区分能力,本文给大家介绍了如何使用Python实现图像LBP特征提取的操作方... 目录一、LBP特征介绍二、LBP特征描述三、一些改进版本的LBP1.圆形LBP算子2.旋转不变的LB

Maven的使用和配置国内源的保姆级教程

《Maven的使用和配置国内源的保姆级教程》Maven是⼀个项目管理工具,基于POM(ProjectObjectModel,项目对象模型)的概念,Maven可以通过一小段描述信息来管理项目的构建,报告... 目录1. 什么是Maven?2.创建⼀个Maven项目3.Maven 核心功能4.使用Maven H

Python中__init__方法使用的深度解析

《Python中__init__方法使用的深度解析》在Python的面向对象编程(OOP)体系中,__init__方法如同建造房屋时的奠基仪式——它定义了对象诞生时的初始状态,下面我们就来深入了解下_... 目录一、__init__的基因图谱二、初始化过程的魔法时刻继承链中的初始化顺序self参数的奥秘默认

SpringBoot使用GZIP压缩反回数据问题

《SpringBoot使用GZIP压缩反回数据问题》:本文主要介绍SpringBoot使用GZIP压缩反回数据问题,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教... 目录SpringBoot使用GZIP压缩反回数据1、初识gzip2、gzip是什么,可以干什么?3、Spr

Spring Boot 集成 Quartz并使用Cron 表达式实现定时任务

《SpringBoot集成Quartz并使用Cron表达式实现定时任务》本篇文章介绍了如何在SpringBoot中集成Quartz进行定时任务调度,并通过Cron表达式控制任务... 目录前言1. 添加 Quartz 依赖2. 创建 Quartz 任务3. 配置 Quartz 任务调度4. 启动 Sprin

Linux下如何使用C++获取硬件信息

《Linux下如何使用C++获取硬件信息》这篇文章主要为大家详细介绍了如何使用C++实现获取CPU,主板,磁盘,BIOS信息等硬件信息,文中的示例代码讲解详细,感兴趣的小伙伴可以了解下... 目录方法获取CPU信息:读取"/proc/cpuinfo"文件获取磁盘信息:读取"/proc/diskstats"文

Java使用SLF4J记录不同级别日志的示例详解

《Java使用SLF4J记录不同级别日志的示例详解》SLF4J是一个简单的日志门面,它允许在运行时选择不同的日志实现,这篇文章主要为大家详细介绍了如何使用SLF4J记录不同级别日志,感兴趣的可以了解下... 目录一、SLF4J简介二、添加依赖三、配置Logback四、记录不同级别的日志五、总结一、SLF4J