在上一篇文章,我们分析了GOOTKIT木马的强大反分析能力,本文,我们继续探索GOOTKIT木马的持久性攻击和其他恶意功能。
Gootkit银行木马于2014年被发现,它利用Node.JS库执行一系列恶意任务,通过网站注入并获取密码,更绝的是它还有视频录制和远程VNC功能。自2014年Gootkit被发现以来,Gootkit背后的开发者一直在不断更新代码库,以减缓安全人员的分析并阻止自动沙箱的检查。
本文研究的样本是MD5: 0b50ae28e1c6945d23f59dd2e17b5632
运行配置
在讨论持久性和C2通信例程之前,让我们先看一下设备配置及其存储方式。
你可以在前一篇文章中介绍的反分析机制中,查看第一次在示例中提到的配置。快速浏览一下其中的代码,你可能会认为Gootkit正在解密样本使用的一些shellcode。但通过在调试器中运行该代码,则显示了不同的运行结果。其实解密程序相当简单,就是一个基于imul和idiv计算的带区分键的基本XOR循环。基本键值为0x22,在每次迭代中,idiv和imul值都是常量,分别是0x85和0x03,这个解密例程的Python脚本如下图所示。
在手动解密数据之后,我们可以很容易地分辨出这实际上是Gootkit用于检索下一阶段的配置:
me.sunballast.fr koohy.top 2700 svchost.exe
每个值都被多个空字节分割,这意味着几乎所有的配置都是空字节。前两个值显然是url,最后一个值是downloader可以注入的进程的名称。最后两个值也被设置为环境变量,特别是vendor_id和mainprocessoverride。vendor_id变量的值为exe_scheduler_2700, mainprocessoverride的值为svchost.exe。除了setup之外,这些变量不会在下载加载程序中使用,因此可以假设在最后阶段使用了这些变量。一旦创建了环境变量并分配了值,就会启动四个重要的线程:C2检索线程、浏览器注入线程、持久性线程和Kill Switch线程。现在,让我们从持久性线程开始讲。
持久性攻击能力
在本文的Gootkit示例中,有两个持久性选项可用。首先,有通过创建服务实现持久性的常用方法。在本例中,Gootkit将根据System32中的文件名使用Mersenne Twister算法生成一个随机文件名,然后继续在%SystemRoot%\中创建同名文件。Mersenne Twister算法译为马特赛特旋转演算法,是伪随机数发生器之一,其主要作用是生成伪随机数。此算法是Makoto Matsumoto (松本)和Takuji Nishimura (西村)于1997年开发的,基于有限二进制字段上的矩阵线性再生。可以快速产生高质量的伪随机数,修正了古老随机数产生算法的很多缺陷。在测试这个函数之后,会创建了一个名为msfearch.exe的文件。然后以相同的名称创建服务,再执行。最后,原始可执行文件通过从磁盘中进行自我删除并退出来清理执行痕迹,从而让创建的服务保持继续运行。
第二个持久性例程更有趣,以前也经常讨论过。这个例程最常用于Gootkit感染,理论上来说,创建该服务需要管理员权限,但事实并非如此。
首先创建一个简单的.inf文件,该文件与正在运行的可执行文件同名,并放在同一目录中。该文件的内容如下所示:
然后,该示例将创建一个位于以下位置的注册表项:
Software\Microsoft\IEAK\GroupPolicy\PendingGPOs
然后在这个表项中创建三个值:Count、Path1和Section1。Count被赋值为0x1, Path1被赋值为INF文件的路径,Section1被赋值为字符串[DefaultInstall],它也存在于INF文件中。explorer.exe将在每次加载组策略对象(GPO)时加载该函数,特别是在运行时。Gootkit所做的是为Internet Explorer管理工具包(IEAK)创建一个挂起的GPO,它直接指向INF文件。当explorer.exe在加载时,它将在创建的文件中执行[DefaultInstall],该文件将执行Gootkit可执行文件。
加载程序更新线程
在介绍了持久性线程之后,让我们继续分析C2接收线程。由于命令和控制服务器离线速度非常快,这一点尤其难以分析,因此乍一看,似乎是线程负责下载最后一个阶段并不断更新它,但随着深入研究,这种判断被证明是不正确的。
该函数并不是非常复杂,简单地说,就是Gootkit将检查变量是否设置为0或1,如果设置为1,它将退出线程,这个变量只在Kill Switch函数中被激活。
接着,示例将/rpersist4/-1531849038附加到URL,其中-1531849038是二进制的CRC32哈希。然后,根据体系结构,将把rbody32或rbody64将被附加到URL中。
此时将发生实际的连接,有趣的是,还有两种通信方式:可以通过诸如InternetOpenW之类的WinInet函数进行通信,也可以通过诸如WinHttpOpen之类的WinHTTP函数进行通信,但我还没有看到它调用WinHTTP函数。
在访问C2之前,Gootkit将首先添加到GET请求的标头中。这些新增内容如下:
X-File-Name: Filename X-User-Name: Username X-ComputerName: Computername X-OSVersion: 6.1.7601|Service Pack 1 1.0|1|0x00000100 X-VendorId: 2700 X-IsTrustedComputer: 1 X-HTTP-Agent: WININET X-Proxy-Present: False X-Proxy-Used: False X-Proxy-AutoDetect: False
如果设置了crackmeololo环境变量,则X-IsTrustedComputer仅设置为1,否则设置为0,这可以看作是另一种反分析、反沙箱、反vm机制。
如果示例和C2之间的连接失败,它将尝试连接到配置中发现的其他C2s。如果连接成功并且服务器返回可执行文件,Gootkit将在临时目录中创建一个随机命名的文件,并使用CreateProcessW使用–reinstall参数执行它。因此,我们完全可以把这个线程理解为一个“更新程序”线程,它将不断地检查所要连接的C2服务器,等待加载器的任何更新。
现在已经介绍了这个函数,在继续介绍浏览器注入函数之前,让我们简要地介绍一下Kill Switch函数。
Kill Switch函数
只有当uqjckeguhl.tmp位于..\¬AppData\Local\¬Temp\ 或..\¬Local Settings\¬Temp\才会触发Kill Switch线程,如果文件存在,那么Gootkit会自行清理,它将终止所有正在运行的线程,并重新启动计算机。目前还不是很清楚为什么要配备这样一个功能, 我们猜想可能是因为在执行Kill Switch线程之前建立了持久性,因此只需重新启动计算机就会最终再次执行加载程序,但是,如果在受感染的情况下发出并安装了加载程序更新系统,导致重新启动可能有助于防止多个实例立即运行。
最后,介绍一下浏览器注入功能。
浏览器注入
浏览器注入函数非常有趣,因为它负责两个任务:使用——vwxyz参数执行,并向运行中的浏览器注入两个DLL。本文,我们将专注于对第二个任务进行介绍。
为了将DLL注入到浏览器中,必须要有一个DLL驻留。实际上,二进制文件中存储了2个加密的DLL,一个x86 DLL和一个x64 DLL,它们用简单的XOR解密。有趣的是,其他变体中似乎也有可能存在占位符,因为本示例在两个DLL中都检查0x11223344和0x55667788,以便分别用0x12和0x13替换值。
在两个可执行文件都已解密的情况下,Gootkit会将以下注册表项的值更改为0x3:
Software\Microsoft\Windows\CurrentVersion\Internet Settings\Zones\0\2500 Software\Microsoft\Windows\CurrentVersion\Internet Settings\Zones\1\2500 Software\Microsoft\Windows\CurrentVersion\Internet Settings\Zones\2\2500 Software\Microsoft\Windows\CurrentVersion\Internet Settings\Zones\3\2500 Software\Microsoft\Windows\CurrentVersion\Internet Settings\Zones\4\2500 Software\Microsoft\Windows\CurrentVersion\Internet Settings\Zones\5\2500
这会导致为正在使用的每个安全区域禁用Internet Explorer保护模式,在此基础上,Gootkit将继续扫描所有正在运行的进程,直到找到一个正在运行的浏览器。为此,它将导入并调用NtQuerySystemInformation(),请求系统进程信息。之后,将返回正在运行的进程列表。使用这个列表,Gootkit将打开每个进程,使用IsWow64Process()检查进程架构,然后用CRC-32哈希(大写)进程名称。然后将这个哈希传递给一个负责检测和注入的函数。下面列出了目标浏览器及其相应的哈希值列表:
Microsoft EdgeCP: 0x2993125A Internet Explorer: 0x922DF04 Firefox: 0x662D9D39 Chrome: 0xC84F40F0 Opera: 0x3D75A3FF Safari: 0xDCFC6E80 Unknown: 0xEB71057E
其实,Gootkit所使用的注入技术并没有什么特别之处。本文的示例调用了NtCreateSection,然后使用NtMapViewOfSection将该部分映射到浏览器中。无论体系结构如何,这两个dll似乎都被映射到内存中。一旦文件被注入,函数将返回进程搜索函数,直到检测到另一个正在运行的浏览器。
x86 DLL的MD5:57e2f2b611d400c7e26a15d52e63fd7f x64 DLL的MD5:7e9f9b2d12e55177fa790792c824739a
快速浏览一下注入的DLL, 它们似乎包含了一些挂钩函数,似乎挂钩了CertVerifyCertificateChainPolicy和CertGetCertificateChain,以及可能充当某种形式的代理来拦截请求并根据来自C2服务器或NODE.JS有效载荷的信息重定向它们。
在本文的示例中,使用Gootkit感染虚拟机并尝试使用Internet Explorer浏览互联网是不成功的,好像是代理阻止了连接,不过这需要进一步分析。
在下一篇文章中,我们将查看使用–vwxyz参数调用Gootkit时发生了什么,然后快速查看从命令和控制服务器检索到的最终NODE.JS有效载荷。