【技术分享】使用Windbg分析.NET恶意软件

https://p3.ssl.qhimg.com/t0130a919d0300be60e.png

作者:myswsun

预估稿费:200RMB

投稿方式:发送邮件至linwei#360.cn,或登陆网页版在线投稿

0x00 前言

.NET渐渐成为微软生态系统的重要组成部分,为不同的语言和硬件平台提供交互操作的共享框架。很多微软的工具(如PowerShell)和其他的管理函数都会依赖.NET平台。很明显,这使得.NET也成为恶意软件开发者的宠儿。因此,恶意软件研究人员必须熟悉这门语言并且能有必要的技能来分析这个平台的恶意软件。

分析工具(如ILSpy)帮助研究员反编译代码,但是不能用于自动分析多个样本。本文我们将介绍如何使用Windbg和微软提供的SOS扩展来分析.NET应用程序。

本文描述:

在.NET API中插入一个断点来分析PowerShell脚本

创建简单的脚本完成.NET样本自动化脱壳

另外,你能从我们的github上下载一个Python脚本(基于Windbg pykd扩展),来自动分析.NET。这个脚本也在本文中有描述。


0x01 SOS扩展

SOS扩展为Windbg提供.NET支持。扩展提供了丰富的命令;本文我们将只介绍一些帮助分析的命令。

首先,SOS扩展不只一个库,且依赖于.NET的版本。在我们使用SOS扩展之前我们必须将库加载到Windbg中。

对于.NET 4,扩展位于CLR.dll,并且可以使用下面的命令加载:

 http://p6.qhimg.com/t01f7e09ffaa83da42d.png

在.NET 2和3中,SOS扩展位于mscorwks库:

 http://p2.qhimg.com/t019509bcf6e970e561.png

下面是本文使用的命令:

!bpmd:这个命令用于在托管代码(.NET)中设置断点。命令有两个参数。第1个参数是函数所在的.NET dll,第2个是函数名

!CLRStack:显示CLR栈内容。对于确定.NET的参数很有用

!DumpObj:显示指定对象的信息

本文中,这3个命令用于针对一个指定的.NET API创建一个断点,以得到传入API的参数,并且显示内容。


0x02 用例#1:PowerShell分析

很少有人知道PowerShell能使用.NET框架。通过检查.NET API的用法,我们能自动化分析PowerShell。

例1:Start-Process API

这个例子中,我们将分析下面的PowerShell代码:

 http://p0.qhimg.com/t019fab39cf23f1f3a2.png

当你执行这个任务时,PowerShell使用Process.Start() API。因此,我们能设置断点,能暂停代码执行(在加载SOS扩展之后):

 http://p5.qhimg.com/t018e578d2ec4a834ac.png

一旦设置断点后,我们输入g命令来执行PowerShell脚本。Windbg将断在Start-Process处:

 http://p2.qhimg.com/t015a9b8e403678a8f7.png

CLRStack命令显示了提供给Process.Start API的参数。在我们的例子中,参数是一个System.Diagnostics.ProcessStartInfo对象。

 http://p5.qhimg.com/t01a5d31ea5c33ed794.png

最后,DumpObj命令显示这个对象的内容:

 http://p4.qhimg.com/t01e77810c59f6d8f6c.png

ProcessStartInfo对象的第一个字段是一个System.String对象(名为filename)。我们能使用DumpObj得到对象的内容:

 http://p8.qhimg.com/t013a89cbeb3f789dd6.png

我们能看那个filename字符串是notepad二进制文件的路径。

例2:DownloadFile API

在第二个例子中,我们将分析下面的代码:

 http://p1.qhimg.com/t01e4fad4d3b78356f8.png

这个代码的目的是下载一个文件,并存储在硬盘上。这是恶意软件下载payload常用的技术。

我们在DownloadFile API处设置一个断点,并输入g执行PowerShell:

 http://p9.qhimg.com/t01dbfcffce99f301b1.png

当API执行时,WIndbg自动断下执行:

 http://p2.qhimg.com/t01c788b0580a3dde7d.png

我们还是使用CLRStack和DumpObj命令。根据微软内存布局的标准,我们能直接从寄存器中得到值(第一个字符串位于RDX+0xC,第二个位于R8+0xC):

 http://p3.qhimg.com/t01fd7e0e69c698a63c.png

下面是执行的片段:

 http://p2.qhimg.com/t010b8735000db65f98.png


0x03 用例#2:.NET脱壳

Talos每天都会处理加壳的恶意样本。我们最近确定了一个加壳的.NET可执行文件,其托管于一个叙利亚政府网站上:http://www[.]syriantax[.]gov[.]sy/css/igfxCUIService.exe。最初,我们想知道这是否是一个针对性的攻击的一部分。在进一步研究后,现在我们相信网站失陷了,并且被用于传播恶意软件。这个恶意软件原来是njRAT啊,一个知名远程管理工具,多年以来它传播甚广。尽管找到了RAT,但是我们觉得没啥特别的,我们认为写一篇关于njRAT脱壳的文章比较有用。

这个用例将解释如何处理未知的.NET壳,我们首先静态分析。我们也会使用Windbg动态分析,同时会创建一个Windbg脚本来自动化脱壳。

静态分析

我们使用de4dot来分析这个恶意软件,因为它能快速的识别已知壳。它是一个开源分析平台。

 http://p9.qhimg.com/t015cc15ab9f5a51fc7.png

本节,我们也会使用ILSpy,其也是个开源的.NET反编译器。

XORED变种(45c695e610d78178ec5ca6f4e1993afacf4e435b566cd2caf65408fb6080300f)

壳的入口点是ob6eaGgG7Bht6B35c0.G9puOotvCiNCkEEPD9.XHh0nc9pu,我们能使用ILSpy识别这个信息。

 http://p6.qhimg.com/t01513f593c6e16b128.png

首先,壳会解码一个base64编码的字符串(变量G9puOotvCiNCkEEPD9.EHQI8XHAH)。这个解码的字符串和第二个参数(作为XOR密钥)一起被传入函数G9puOotvCiNCkEEPD9.vovYCiNCk():

 http://p2.qhimg.com/t0121fdef9575705313.png

浏览输出,我们能使用ILSpy浏览反编译的.NET代码来能观察XOR操作。可以看到“^”,能确定这是XOR操作。

 http://p3.qhimg.com/t019d03606b1424b0f6.png

最后,函数的输出被作为Assembly.Load()的参数。这个函数用于加载.NET二进制。

 http://p5.qhimg.com/t01954da0bdb532834f.png

传入Assembly.Load()的参数是一个字节数组,其包含一个Windows二进制(PE32)。这个例子中,脱壳的恶意软件就位于字节数组中。

AES变种(21acd3457c1a589e117988fe0456e50ed627f051a97ccd11bfeeaf3c0cd79bfe)

这个壳的变种中包含的逻辑是相同的,但是用AES加密(也叫Rijndael)而不是XOR混淆。

 http://p6.qhimg.com/t0121ddb3b48c434952.png

最后,使用Assembly.Load()将解密的数据加载到内存中,

常见点

尽管每个分析的样本使用的算法是不同的,编码与加密逻辑是一样的。如果我们能转储Assembly.Load()的参数(字节数组变量),我们就能得到脱壳的恶意软件。

使用Windbg动态分析

.NET 版本4

为了动态分析.NET 4版本的样本,我们需要获得Windbg的SOS扩展。这个扩展能帮助微软调试器调试.NET 4。

让我们运行加壳的恶意软件。

第一步是在加载CLRJIT库时加断点:

 http://p3.qhimg.com/t0133d0a7c27003555a.png

然后,我们加载Windbg的SOS扩展来分析.NET应用(托管应用):

 http://p8.qhimg.com/t0116fbacd3a21220f5.png

现在我们有新的.NET调试命令。我们能针对使用的.NET API设置断点。这个例子中,我们的目标是Assembly.Load():

 http://p3.qhimg.com/t0119b25b9c227f9e8d.png

目前,在扩展中有个bug,需要执行命令两次。

现在,调试器将断在Assembly.Load()处:

 http://p3.qhimg.com/t018ad51a6bdc99e620.png

很明显,我们能使用CLRStack和DumpObj命令得到参数。这个例子中,我们只使用寄存器的内容。传入Assembly.Load()的参数位于栈上(ESP)。

 http://p1.qhimg.com/t013fa6431b3f7a03db.png

在栈上的第二个值是字节数组的指针:0x026b30b8。

 http://p6.qhimg.com/t01dcc920e6b29149ed.png

第二个参数0x5e00是字节数组的大小(红色部分),之后我们能看见PE文件头(MZ: 0x4d 0x5a)(蓝色)。我们能dump脱壳后的样本:

 http://p1.qhimg.com/t01f2480bfe4a1cddb6.png

.NET版本2&3

.NET 2和3版本编译的恶意软件的分析过程是一样的。不同的是传递给Assembly.Load()的参数的方式。这个例子中,参数不使用栈,它存储在ECX寄存器中:

 http://p9.qhimg.com/t017c5a8eee2368139e.png

数据格式和上述的例子中的是一样的,数组的大小标记为红色,蓝色是加载的二进制。

自动化脱壳

多亏了之前的分析描述,我们能创建一个通用的脱壳器。你能在附录2中找到.NET版本2,3,4的Windbg脚本。

脚本调用语法如下:

 http://p4.qhimg.com/t01164a0ec17692d3f6.png

下面是脚本执行的截图:

http://p7.qhimg.com/t012401828a01647173.png

 

0x04 Python脚本

你能下载一个Python脚本来自动化.NET分析。这个脚本需要pykd扩展,以便能在Windbg中执行python。脚本使用SOS命令,目的是得到更好的输出。配置位于脚本的开头:

 https://p5.ssl.qhimg.com/t01fec76e5598942f72.png

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字节数组。dump的内容位于dump_byte_array目录。

脚本允许文本或json的输出。本文的例子输出是文本格式,但是我们通过JsonDebug变量设为“True”能调整格式为Json。

例1:

下面是Assembly.Load()调用的脚本输出:

 https://p3.ssl.qhimg.com/t016060bfa7e2c3c3a7.png

Assembly.Load参数字节数组的内容自动存储到c:usersluciferDesktopdump_1496942775_0x02f67e04_5644.dmp。

例2:

下面是PowerShell脚本执行start-process的输出:

 https://p0.ssl.qhimg.com/t0176615571cdfcc7ba.png

脚本显示了参数和我们感兴趣的字段的内容(例子中filename字符串)。

例3:

DownloadFile API的执行输出:

 https://p4.ssl.qhimg.com/t01e60e5d6d6edfab3e.png

第一个参数是System.URI对象。对象被自动解析,且相关的内容显示在Windbg中。这个例子中,显示的第一个字段(字符串m_string)。这个字符串包含了URL。第二个参数也是个字符串。

例4:

下面是JSON格式的输出(start-process执行):

 https://p3.ssl.qhimg.com/t01ddc169b7cdb39788.png


0x05 总结

WIndbg是微软提供的强大的调试工具。因为不熟悉语法和界面,使它不太容易成为恶意软件分析工具。但是使用正确的扩展,能有利于分析托管代码(.NET). 


0x06 附录

IOCs

加壳样本的SHA256

21acd3457c1a589e117988fe0456e50ed627f051a97ccd11bfeeaf3c0cd79bfe

344ce133363f005346210611d5abd2513934a32739bc6e1bbd2257a298484051

45c695e610d78178ec5ca6f4e1993afacf4e435b566cd2caf65408fb6080300f

61653b2811fb7c672584d00417cbc1a56c8372331f1913104f9807a775f25773

ac7bd77245bdf284d36ce1f9e2cb6a21d2dbd38aa1964dbaee4d06563f057ca6

b607e87acdcb2ef0f102298decc57ca3ea20fabbf02375fd30eddddffbeec320

e93c0aed6bbb4af734403e02d399c124f2d07f8e701fb716c2efe65942f83504

脱壳样本的SHA256

35dee9106e4521e5adf295cc945355d72eb359d610230142e5dd4adda9678dee

b5ce02ee3dfccf28e86f737a6dde85e9d30ff0549ec611d115a1d575b5291c2e

d9a732dcf87764a87f17c95466f557fac33f041ac6f244dba006ba155d8e9aea

fe068ce56b258762c10cc66525c309e79026c0e44103ca9b223c51382722cb09

Windbg脚本

.NET 4之前:

 http://p9.qhimg.com/t0184867478545e2316.png

.NET版本4:

 http://p5.qhimg.com/t0165d23a2f7a6157ba.png

(完)