[toc]
.NET是Microsoft生态系统中重要的组成部分,为不同语言和硬件平台之间的互操作性提供了共享框架。 许多Microsoft工具(如PowerShell)和其他管理功能依赖于.NET平台的功能。 这使得.NET成为恶意软件开发人员的诱人语言。 因此,恶意软件研究人员还必须熟悉该语言,并具有分析在平台上运行的恶意软件的必要技能。
诸如ILSpy之类的分析工具有助于研究人员从应用程序中反编译代码,但不能用于自动分析许多样本。 在本文中,我们将介绍如何使用WinDBG来使用Microsoft提供的SOS扩展来分析.NET应用程序。
本文主要介绍:
如何通过在.NET API中插入断点来分析PowerShell脚本。
如何轻松创建一个脚本,以便在分析加壳的逻辑后自动解压缩.NET样本。
此外,您可以在我们的github上下载一个Python脚本(基于WinDBG pykd扩展),以自动分析.NET。 这个脚本也将在文章中描述。
SOS 扩展
SOS Extension为WinDBG提供.NET支持。 扩展提供了丰富的命令集; 在本文中,我们将仅介绍一些对分析有用的内容。
首先,SOS扩展名不在同一个库中,这取决于你所使用的.NET的版本。 在我们能够使用SOS扩展之前,我们必须将库加载到WinDBG中。
对于.NET 4,扩展名位于CLR.dll中,可以加载以下命令:
1 | .loadby sos clr |
而.NET 2 和 3的话:
1 | .loadby sos mscorwks |
以下是本文中使用的命令:
!bpmd:这个命令用于在.NET代码中设置断点。 该命令有两个参数。 第一个参数是函数所在的.NET dll,第二个是函数名。
!CLRStack:此命令显示CLR堆栈内容。 识别.NET函数的参数很有用。
!DumpObj:此命令显示有关参数中指定的特定对象的信息。
在本文中,这3个命令将用于在特定的.NET API中创建断点,以获取传递给API的参数,并显示内容。
案例1:POWERSHELL分析
很少有人意识到PowerShell可以使用.NET框架。 通过检查.NET API使用情况,我们可以轻松自动化PowerShell分析。
示例1:启动过程API
在本例中,我们将分析以下PowerShell代码:
1 | PS> start-process notepad.exe |
执行此任务时,PowerShell将调用Process.Start 这个API。 所以,我们可以在这个API设置之断点:
1 | 0:011> .loadby sos clr |
断点设置完成后,我们可以输入命令“g”来执行PowerShell脚本。 执行Start-Process时,WinDBG将会停止:
1 | Breakpoint 0 hit |
CLRStack命令会显示Process.Start API的参数。 在我们的例子中,参数是一个System.Diagnostics.ProcessStartInfo对象。
1 | 0:008> !CLRStack -p |
最后,DumpObj命令显示此对象的内容:
1 | 0:008> !DumpObj /d 0000028cbd5faa18 |
ProcessStartInfo对象的第一个字段是filename,类型是System.String对象。 我们可以使用DumpObj检索对象的内容:
1 | 0:008> !DumpObj /d 0000028cbd5fde18 |
那我们就可以看到我们运行的程序的路径了
示例2:DownloadFile API
代码如下:
1 | PS> $a = New-Object System.Net.WebClient |
此代码的目的是将文件下载并存储在硬盘驱动器上。 恶意软件经常使用这种技术来下载payload。
如果是这种情况,我们必须在DownloadFile API上放上断点,然后按’g’来执行PowerShelI:
1 | 0:008> .loadby sos clr |
之后便会断下来
1 | Breakpoint 7 hit |
在这种情况下,我们可以像以前一样使用CLRStack和DumpObj命令。 还可以手动,我们直接从寄存器获取值(第一个字符串位于RDX + 0xC中,第二个字符串位于R8 + 0xC中):
1 | 0:008> du rdx+c |
截图如下:
译者注: 32位的话如下(05083c88是第三个参数,对应上面的r8储存第3个参数)
1 | 0:023> du edx+8 |
案例2: .NET UNPACK
Talos每天处理包装恶意软件样本。 我们最近确定了一个包装的.NET可执行文件,它正在叙利亚政府网站上托管:http://www.syriantax.gov.sy/css/igfxCUIService.exe 最初我们想知道这是否是有针对性的攻击的一部分。 经过进一步的研究,我们现在认为,这个网站已被入侵,并被用来提供这种恶意软件。 恶意软件原来是njRAT,这是一个知名的远程管理工具,已经存在了很多年。 找到njRAT并不是特别有趣,我们认为写一个博客文章,看看njRAT的脱壳过程就相对有趣了。
因此,此用例将解释如何使用静态分析来处理未知的.NET包装程序。 我们还将介绍使用WinDBG的动态分析,以及如何创建一个WinDBG脚本,以自动化这种类型的打包程序的拆包过程。
静态分析
我们通过使用de4dot来开始我们对恶意软件样本的分析,因为它可以快速识别已知的壳。 这是一个开源分析平台(吾爱破解工具包2.0就有)
1 | C:> de4dot-x64.exe -d -r c:\to_test |
在本节中,我们还将使用ILSpy———开源.NET反编译器。
XOR 变种
样本SHA-256:45c695e610d78178ec5ca6f4e1993afacf4e435b566cd2caf65408fb6080300f
入口点是ob6eaGgG7Bht6B35c0.G9puOotvCiNCkEEPD9.XHh0nc9pu,我们可以使用ILSpy获得此信息:
首先,程序解码一个Base64编码的字符串(变量G9puOotvCiNCkEEPD9.EHQI8XHAH)。 该解码的字符串将传递给函数G9puOotvCiNCkEEPD9.vovYCiNCk的第二个参数,最终作为XOR(异或) 的key:
通过向下看,我们可以通过查看ILSpy的反编译结果看到异或操作,就是这个符号”^”,我们可以确定这是XOR(异或)操作。
最后,函数的输出作为参数传递给函数Assembly.Load。 此函数用于加载.NET二进制文件。
AES 变种
样本SHA-256:21acd3457c1a589e117988fe0456e50ed627f051a97ccd11bfeeaf3c0cd79bfe
这个变种中包含的逻辑是相同的,但不是使用XOR混淆,而是使用AES加密(也称为Rijndael):
(译者注:可以看到下面用到了RijndaelManaged类)
最后,使用Assembly.Load函数将解密的数据加载到内存中。
共同点
虽然每个分析的样本使用的算法是不同的,但编码与加密的逻辑是完全相同的。 如果我们可以导出在Assembly.Load函数的参数中找到的字节数组变量,那么我们就可以获得脱壳了的恶意软件(译者注:因为调用Assembly.Load的时候,传递给该函数的参数就是解密后了程序数据)。
用windbg动态调试
先看 .NET 4
为了动态分析 .NET 4样本,我们需要获得WinDBG SOS扩展。 此扩展允许使用Microsoft Debugger进行 .NET 4调试。(译者注:这个SOS.dll就在 .NET目录啊)
让我们执行恶意软件吧…
第一步是在加载CLRJIT库时停下来:
1 | 0:000> sxe ld clrjit |
然后,我们加载WinDBG SOS扩展以对.NET应用程序进行分析:
(译者注:不应该是这个么:.loadby sos clr
)
1 | 0:000> .load "C:\\Psscor4\\x86\\x86\\psscor4.dll" |
我们现在有了与.NET调试相关的新的WinDBG命令。 我们可以基于.NET API使用设置断点。 在这种情况下,我们对Assembly.Load API感兴趣:
1 | 0:000> !bpmd mscorlib.dll System.Reflection.Assembly.Load |
(目前在扩展中有一个bug,需要执行两次命令)
当执行Assembly.Load函数时,调试器就暂停下来了:
1 | 0:000> g |
显然,我们可以使用CLRStack和DumpObj命令来完全获得前面用例中提到的参数。 在这个例子中,我们只会使用寄存器的内容——传递给Assembly.Load的参数可以通过esp寄存器找到:
1 | 0:000> dp esp |
栈中的第二个值是指向字节数组的指针:0x026b30b8。
1 | 0:000> dp 026b30b8 |
第二个参数0x5e00是字节数组的大小,之后我们可以看到以MZ:0x4d 0x5a开头的PE文件的文件头。 我们现在可以直接从WinDBG中转储被加密代码解密完成的样本:
1 | .writemem C:\\unpacked_sample.exe 026b30b8+8 L00005e00 |
再看 .NET 2 、3
使用.NET版本2和3编译的恶意软件的动态分析过程是一样的。 不同的是参数如何传递给Assembly.Load API。 在这种情况下,参数不使用堆栈,而是存储在ECX寄存器中:
1 | 0:000> dp ecx |
自动脱壳
得益于上述分析,我们可以创建一个通用的脱壳器。 您可以在附录2中找到.NET版本2,3和4的WinDBG脚本。
可以使用以下语法调用此脚本:
1 | "c:\Program Files (x86)\Windows Kits\10\Debuggers\x86\cdb.exe" -c "$$>a< C:\unpack.script C:\unpacked_sample.exe" "c:\sample.exe" |
以下是脚本执行的截图:
python 脚本
您可以从我们的github中下载一个python脚本来自动化的.NET分析。 该脚本需要pykd扩展才能在WinDBG中执行python。 该脚本使用本文前面提到的SOS命令,目的是获得更好的输出。 配置位于脚本的开头:
bp_list变量包含断点列表。 在该示例中,该脚本将在3个 .NET API(System.Diagnotics.Process.Start,System.Net.WebClient.Download.File和Sysyem.Reflection.Assembly.Load)上下断点。 3个函数的参数将显示在WinDBG中。
如果dump_byte_array变量设置为1,脚本将自动转储分析函数(其中有断点的位置)的参数中提供的字节数组。 转储将位于dump_byte_array_path目录中。
该脚本允许文本或json输出。 本文中的示例输出文本,但我们可以通过将JsonDebug变量设置为“True”来切换json。
示例1
下面是当调用Assembly.Load函数时脚本的输出:
1 | 0:000> .loadby sos clr |
Assembly.Load参数中的字节数组的内容将自动存储在c:\users\lucifer\Desktop\dump_1496942775_0x02f67e04_5644.dmp
示例2
以下是执行start-process的PowerShell脚本上的脚本输出:
1 | [.NET plugin] Breakpoint: System.Diagnostics.Process.Start(System.Diagnostics.ProcessStartInfo) |
该脚本显示有趣字段的参数和内容(在该示例中为fileName字符串)。(译者注:可以看到C:\WINDOWS\system32\calc.exe)
示例3
以下是在Powershell中使用DownloadFile API时脚本的输出:
1 | [.NET plugin] Breakpoint: System.Net.WebClient.DownloadFile(System.Uri, System.String) |
第一个参数是System.URI对象。 对象自动解析,相关内容显示在WinDBG中。 在这种情况下,显示第一个字段(字符串m_string)。 此字符串包含URL。 第二个参数是也显示的字符串(译者注:下载到的位置)。
示例4
这是JSON启用的输出:
1 | 0:020> .loadby sos clr |
总结
WinDBG是由Microsoft提供的一个非常强大的工具。 如果不熟悉windbg的语法和界面意味你将忽略这么一个这么好的恶意软件分析工具。 有了正确的扩展,它可以很容易地用于分析.NET等类似代码。
我们希望这篇文章引导您的好奇心,并且您将在下一次分析.NET等类是代码时考虑WinDBG。
附录
加壳样本 SHA256
- 21acd3457c1a589e117988fe0456e50ed627f051a97ccd11bfeeaf3c0cd79bfe
- 344ce133363f005346210611d5abd2513934a32739bc6e1bbd2257a298484051
- 45c695e610d78178ec5ca6f4e1993afacf4e435b566cd2caf65408fb6080300f
- 61653b2811fb7c672584d00417cbc1a56c8372331f1913104f9807a775f25773
- ac7bd77245bdf284d36ce1f9e2cb6a21d2dbd38aa1964dbaee4d06563f057ca6
- b607e87acdcb2ef0f102298decc57ca3ea20fabbf02375fd30eddddffbeec320
- e93c0aed6bbb4af734403e02d399c124f2d07f8e701fb716c2efe65942f83504
脱壳样本 SHA256
- 35dee9106e4521e5adf295cc945355d72eb359d610230142e5dd4adda9678dee
- b5ce02ee3dfccf28e86f737a6dde85e9d30ff0549ec611d115a1d575b5291c2e
- d9a732dcf87764a87f17c95466f557fac33f041ac6f244dba006ba155d8e9aea
- fe068ce56b258762c10cc66525c309e79026c0e44103ca9b223c51382722cb09
WinDBG 脚本
.NET4之前
1 | sxe ld mscorjit |
.NET4
1 | sxe ld clrjit |