导航菜单

1 介绍

恶意代码分析是在应急响应中需要的一部分,如今,随着恶意软件(特别是其反分析技术)的复杂性,很难及时地消除威胁。在完成分析时,威胁可能已经扩散到整个环境。该文章将重点介绍传统的手动分析(仅人为操作)步骤,以使读者了解如何分析DotNet文件。

2 总览

在开始之前,先提及下DotNET的基础。如今,有多种编程语言允许程序员开发可执行文件。其中一些语言是Microsoft Visual C/C++,VB6(DotNET的前身)和DotNET框架,这些语言中的每一种都有其缺点和优点。相对于C/C ++,Microsoft C#是一种用于应用程序开发的简便语言。因此,许多攻击者和合法开发人员都喜欢使用C#开发其PE文件和应用程序,但是许多编译的DotNET可执行文件也可能会使用反分析技术,以使它们的代码混乱并在系统上执行的期间隐藏其操作。

DotNET可执行文件有许多静态分析技术,接下来将提出两个分析案例。第一个案例将关注混淆的键盘记录器(keylogger),而第二个案例将研究DotNET可执行文件在内存中的动态加载。

以下有一些识别DotNET可执行文件特征的方法。

DotNET可执行文件的特征

已编译的DotNET可执行文件通常会导入DLL文件mscoree.dll,也会导入API函数_CorExeMain或_CorDllMain

下图(取自VirusTotal)说明了DotNET可执行文件导入的DLL和Windows API函数的导入:

.NET恶意代码分析入门.NET恶意代码分析入门

如果仅看到mscoree.dll文件的导入和对API函数_CoreExeMain的调用,则可能是遇到了DotNET可执行文件。

如何识别?当遇到可执行文件,并且不确定是使用哪个编译器将文件编译为可执行文件的,则可以使用一些免费工具对文件进行静态分析。这些工具中的有 Easy-It-Easy(DIE),PEstudio和CFF Explorer。但在大多数情况下,这些工具都可以用来确定可执行文件链接到哪些导入DLL和API。

DotNET可执行文件还具有另一个非常独特的特性,比如使用Visual Studio开发DotNET可执行文件,该可执行文件本身将获得两个不同的全局唯一标识符(GUID)。一旦编译为可执行文件,通常会将它们作为字符串存储在DotNET文件中。可以在DotNET可执行文件上搜索字符串找到这些GUID,或者如图所示,VirusTotal将在可执行文件的详细信息部分下列出它们:

.NET恶意代码分析入门.NET恶意代码分析入门

Module Version ID(MVID)GUID是在DotNET项目构建期间生成的,并且对于当前构建的项目是唯一的。TypeLib ID是在项目创建期间由Visual Studio生成的。这些GUID除了可以帮助将文件标识为DotNET可执行文件之外,还可以用于将文件与特定项目相关联,因为如果不断维护同一DotNET项目,则编译后的可执行文件应该会存在类似的GUID。

在谈到DotNET GUID时,安全研究人员还将它们称为NetGUID。这些NetGUID还可用于识别具有特定项目的DotNET文件,如果DotNET开发的恶意软件变体具有相同的值,则它们也可以由同一NetGUID关联。 几年前,发表了一篇有关通过NetGUIDS搜索恶意软件的好文章(https://www.virusbulletin.com/virusbulletin/2015/06/using-net-guids-help-hunt-malware/)。

接下来开始分析两个案例

3 案例1-混淆文件

技术细节

本节中分析的可执行文件包含以下静态特征:

文件名:Mixed Grade.exe

SHA1:b33bb284b540a69b9c6a65912a439d00682c896a

大小:2350080字节

编译时间:2020-03-23 07:57:14

Mixed Grade.exe文件是与HawkEye Keylogger相关的恶意软件。但是,Mixed Grade.exe本身不是DotNET文件,只有它产生的实际有效的恶意文件是DotNET文件。

当执行Mixed Grade.exe文件时,它将释放文件RegAsm.exe (一个合法的Windows程序集注册工具)。但是在生成之后,Mixed Grade会将恶意PE文件注入到挂起模式的RegAsm.exe中(此技术也称为进程镂空)。此时RegAsm不再是合法进程,因为它包含主要的HawkEye恶意文件。通过查看RegAsm.exe内存转储内容,很明显可以发现注入文件的名称是Reborn stub.exe,而它是DotNET可执行文件,下图说明了该过程:.NET恶意代码分析入门

.NET恶意代码分析入门

如版本信息所示,文件名取自PE头。有很多方法可以从内存中转储Reborn Stub.exe文件。但是,从内存中转储此文件的最简单最直观的方法之一就是使用pe-sieve(Hook finder)之类的工具。从内存中转储该可执行文件后,发现它确实是DotNET可执行文件。

如下图所示,确实是DotNET可执行文件:

.NET恶意代码分析入门.NET恶意代码分析入门

Reborn Stub.exe静态特征:

文件名:Reborn Stub.exe

SHA1:5fb78f117d48b7f2cdb312cb553a33aa8bc17346

编译时间:2019-01-22 15:01:45

现在通过DnSpy分析此文件,将可疑的DotNET可执行文件Reborn Stub.exe拖放到DnSpy中。如下图所示,DnSpy能够将可执行文件反编译为“源代码”:

.NET恶意代码分析入门.NET恶意代码分析入门

为了查看程序的main函数,请在程序名称上单击鼠标右键,然后选择“转到入口点”或单击程序主单元中的“主程序”,如下所示:

.NET恶意代码分析入门.NET恶意代码分析入门

通过查看代码发现不可读,因为代码被混淆了,默认情况下混淆了类,模块以及介于两者之间的所有内容。此处使用的混淆技术可能是通过免费的.NET混淆工具 ConfuserEx进行的。为了对此代码进行反混淆,可以使用免费的反混淆器和解包工具de4dot,该工具非常适合查找混淆的模式并对其进行反混淆。下图说明了使用de4fot工具对该DotNET可执行文件进行反混淆处理的命令:

.NET恶意代码分析入门.NET恶意代码分析入门

如果去混淆处理成功完成,则应该有一个新的输出文件。在上面这种情况下,经过反混淆的输出文件是400000.RegAsm.output,该文件默认位于运行de4dot工具的当前文件夹中(如果此过程使用了与上面相同的命令)。

现在,有了一个新的输出文件,通过将其拖回DnSpy中来查看去混淆的文件。

.NET恶意代码分析入门.NET恶意代码分析入门

在新的输出文件中,分析人员可以了解到一些内容。首先,新的DotNET可执行文件在文件头中包含一个NetGUID,如下图所示:

.NET恶意代码分析入门.NET恶意代码分析入门

由于现在可以阅读函数和代码,因此分析人员可以通过阅读代码来尝试学习和理解HawkEye恶意文件的作用。例如,在阅读代码时,它很清楚地提到此恶意文件是HawkEye键盘记录器:

.NET恶意代码分析入门.NET恶意代码分析入门

可以查看去混淆的可执行文件中的静态变量,如下图所示:

.NET恶意代码分析入门.NET恶意代码分析入门

在代码中,这些变量用于键盘记录密码,从剪贴板中获取信息等等。此DotNET可执行文件是Keylogger的变体,典型的键盘记录器会将其窃取的信息存储在一个.tmp文件中。但是,在我们的情况下,写入.tmp文件后,获取的信息立即复制到内存中并发送到远程服务器,然后从系统中删除临时文件的内容。通过更深入的分析和调试,我们在将tmp文件从系统中删除之前捕获了该文件的内容。该文件包含来自Chrome和Internet Explorer Web浏览器的被盗信息,但它也设法从Internet Explorer(IE)窃取密码,如下图所示:

.NET恶意代码分析入门.NET恶意代码分析入门

4 总结

MixedGrade键盘记录器通过将Reborn Stub.exe文件注入到合法的RegAsm.exe中来执行进程镂空技术。Reborn Stub.exe是DotNET可执行文件,我们使用DnSpy将其反编译为“源代码”。该代码原来是不可读且难以理解的,因此我们运行de4dot命令并创建了一个具有相同内容的新文件,但是这次它是可读的。

5 案例2-内存中可执行文件的动态加载

可执行文件包含以下静态特征:

名称:TenClips.exe

SHA1:0acefc6bd7e1620eba0198255a220948b4723cb2

编译时间:2010-12-09 18:58:13

这种情况比前一种情况更有趣。该案例包含一个合法的应用程序。但是,应用程序会动态加载内存中的另一个可执行文件,该可执行文件似乎是DotNET可执行文件。

在这里,我们将介绍在调试过程中使用DnSpy加载原始程序后如何从内存中转储原始程序。将可执行文件拖放到DnSpy并查看入口点(主函数)。下图说明了逐步执行main函数时代码的显示方式:

.NET恶意代码分析入门.NET恶意代码分析入门

乍一看,代码并不能说明太多,但是变量rawAssembly似乎很有趣。理解代码后发现获取rawAssembly的值内容唯一方法是通过DnSpy调试此可执行文件。让我们从两个断点开始,然后进入函数。

下图显示了248行(if条件)上的一个断点,258行(rawAssembly加载过程)上的另一个断点:

.NET恶意代码分析入门.NET恶意代码分析入门

通过按开始(绿色播放键),调试器将在第一个断点运行并停止。如果单击“继续运行”,它将进入下一个断点。到达第二个断点后,请查看Locals字段RawAssembly。本地变量是实时加载到内存中的变量,可以在调试过程中查看。如果在两个断点处比较Locals下的RawAssembly变量,将会注意到第二个断点处的rawAssembly变量现在的内存大小为:

.NET恶意代码分析入门.NET恶意代码分析入门

一个非常有趣的问题是,“两个断点之间的变量发生了什么,实际值是多少?” DnSpy程序具有一项很酷的功能,该功能使分析人员可以通过右键单击值->在内存窗口中显示->选择一个内存号(与选择哪一个无关)来检查变量的内存。

.NET恶意代码分析入门.NET恶意代码分析入门

通常,内存部分的显示内容不是很明显。但是在这种情况下,很明显代码段是可执行文件。存在MZ字符串(十六进制:4D 5A),这意味着rawAssembly的值是已加载到内存中的可执行文件。DnSpy的另一个很酷的功能是它能够将内存部分导出到磁盘上的文件。要将该部分保存到文件中,只需右键单击内存->保存选择...(此处的输出保存为output_TenClips.exe):

.NET恶意代码分析入门.NET恶意代码分析入门

如之前所述,有多种方法来检查文件是否是DotNET可执行文件。这次选择的方法是CFF Explorer。如下图所示,该文件导入DLL文件mscoree.dll:

.NET恶意代码分析入门.NET恶意代码分析入门

之前提到过,RawAssembly在第二个断点处具有一定的大小。在本地中查看rawAssembly的大小(以十六进制表示)(右侧图),然后查看output_TenClips.exe可执行文件的大小(左侧图),会注意到它们是相同的(0x00044A08 HEX等于到281096字节的文件大小):

.NET恶意代码分析入门.NET恶意代码分析入门

由于TenClips通常是合法文件,因此我们将不再继续分析output_TenClips.exe。但是,如果对原始可执行文件TenClips.exe中的可执行代码来自何处感到好奇,请进一步看一下调试过程。而不是从一个断点跳到另一个断点,而是在调试过程中通过使用step into选项或仅按F11键逐行进入代码内部。246行上的byte [] rawAssembly只是一个声明,意味着246和258行之间的rawAssembly会得到一个值。如果仔细观察,会在第一个if条件(第248行)中看到变量raw Assembly被声明为引用,这意味着在该行之后rawAssembly可能会有一个值。通过按F11键,将使调试器进入第248行,它将进入lf函数内部:

.NET恶意代码分析入门.NET恶意代码分析入门

大致解释一下lf的功能。通过使用许多条件,它会在TenClips.exe程序本身中查找特定的代码部分,然后将它们组合为一个可执行代码-output_TenClips.exe。现在可以了解主函数(入口点-248行)中的if条件会检查拼接是否成功。如果失败,将打印错误。如果成功,它将执行后续的代码。

6 总结

当执行TenClips.exe可执行文件时,程序将从程序本身收集代码段,将它们组装成一个可执行代码(output_TenClips.exe),将其加载到内存中,然后执行它。此技术称为“动态加载内存”。如果想知道为什么合法应用程序会执行这种技巧,答案很简单,与恶意可执行文件一样,程序员可能希望隐藏代码并使其难以静态读取。为什么?可能会有很多答案。但是,如果恶意文件完成这个操作,则通常会隐藏恶意文件的实际代码,并仅在执行后才将其加载到内存中。但是,动态加载内存中的另一个可执行文件并不一定总是意味着它是恶意可执行文件或恶意操作,记住这一点!

7 来源

https://www.fortinet.com/blog/threat-research/the-use-and-abuse-of-dotnet-files-and-the-value-of-fortresponder-automation-in-threat-analysis.html?utm_source=social&utm_medium=twitter-org&utm_campaign=sprinklr

相关推荐

国外某工业SCADA软件漏洞复现

  概述 近年来随着网络安全形势的日渐严峻,国内外越来越重视工业信息安全的研究。“等保2.0”专门加入了工业控制系统扩展要求,呼之欲出的“关保”中,大多数涉及国计民生的关键信息基础设施也属于工业控制系统...

微软轻量级系统监控工具sysmon原理与实现完全分析——ProcessGuid的生成

  Sysmon的众多事件看起来都是独立存在的,但是它们确实都是由每个进程的产生的,而关联这些信息的东西正是ProC++essGuid,这个对进程是唯一的。如下图 Event 23 都会有个ProcessGuid 字段,今天的这篇文章...