Waterbear回归,使用API钩子来逃避安全产品检测

Change Web安全 2019年12月23日发布
Favorite收藏

导语:本文将主要介绍Waterbear的新攻击动向。

BlackTech间谍组织是一支针对东亚地区进行网络攻击的犯罪团伙,其主要目的是窃取机密信息。自2012年以来,BlackTech已经针对多个国家的政府机构和私营机构进行了大量攻击,他们发起的行动中,有三类最为出名,代号分别为Waterbear、PLEAD和Shrouded Crossbow。本文将主要介绍Waterbear的新攻击动向。

“Waterbear”的命名源自攻击行动中使用的恶意软件功能。Waterbear采用了模块化的处理方式,加载模块执行后将会连接到C&C服务器下载主后门程序,随后将后门程序加载到内存中。之后发现的版本利用服务器应用程序作为加载模块,主后门程序通过加密文件加载,或者从C&C服务器下载。然而在其最近的一项活动中,趋势科技发现了一个新的Waterbear有效负载,能通过API钩子技术对特定的安全产品隐藏其行为。这些安全供应商都是基于亚太地区,与BlackTech的目标国家/地区一致。

挂钩特定的API可能意味着攻击者熟悉这些安全产品,知道如何在其客户端的端点和网络上收集信息,而且由于API钩子shellcode采用了一种通用的方法,类似的代码片段将来可能会用于针对其他安全产品,从而使Waterbear活动更难检测。

近看Waterbear

新Waterbear样本采用了模块化方法,利用DLL加载器解密并执行有效负载(RC4加密),有效负载通常是第一阶段的后门,后门用于从外部接收并加载其他可执行文件。

第一阶段的后门可以分为两种:第一,用于连接到命令和控制(C&C)服务器;第二,用于侦听特定端口。有时,加密后的有效负载的硬编码文件路径不在Windows本机目录下(比如在安全产品或第三方库的目录下),这可能表明攻击者已经事先知晓了目标环境。攻击者也有可能使用Waterbear作为辅助负载,以在获得对目标系统的一定级别的访问权限后帮助维持存在。证据表明,Waterbear经常使用内部IP作为其自己的C&C服务器(例如,样本b9f3a3b9452a396c3ba0ce4a644dd2b7f494905e820e7b1c6dca2fdcce069361使用内部IP地址10[.]0[.]0[.]0[.]]211作为其C&C服务器)。

典型Waterbear感染链

图1.典型的Waterbear感染链

如图1所示,Waterbear感染从恶意DLL加载程序开始,DLL加载程序有两种触发技术:一种是修改合法的服务器应用程序以导入和加载DLL加载器,第二种技术是执行虚拟DLL劫持和DLL端加载。有些Windows服务会在启动过程中尝试使用硬编码的DLL名称或路径加载外部DLL,但如果DLL是旧版DLL(即Windows不再支持的DLL)或第三方DLL(即不属于原始Windows系统DLL的第三方DLL),则攻击者可以将其恶意DLL授予DLL硬编码的DLL名称,并在DLL加载过程中将其放置在搜索到的目录之一下。恶意DLL加载后,它将获得与加载它的服务相同的权限级别。

在近期Waterbear活动中,我们发现DLL加载程序加载两个有效负载,且有效负载执行了其他Waterbear活动中从未见过的功能。第一个有效负载将代码注入特定的安全产品中隐藏后门,第二个有效负载是典型的Waterbear第一阶段后门,我们将根据在分析过程中观察到的特定情况对其进行剖析。

Waterbear的第一阶段后门

我们在%PATH%环境变量的其中一个文件夹中看到了名为“ ociw32.dll”的Waterbear加载器,DLL文件的名称在“ mtxoci.dll”中进行了硬编码,“ mtxoci.dll”由MSDTC服务在启动期间加载。 “ mtxoci.dll”首先尝试查询注册表项“HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\MSDTC\MTxOCI” ,查看值“ OracleOciLib”是否存在。如果存在,则将检索其中的数据并加载相应的库;如果该值不存在,则“ mtxoci.dll”会尝试加载“ ociw32.dll”。在调查过程中,我们注意到从受害者的计算机中值“ OracleOciLib”被删除了,如图2所示,恶意加载程序“ ociw32.dll”在主机上加载并成功执行。

图2.值“ OracleOciLib”在受害者主机上删除

注意:左图显示了普通计算机上DLL的正常样式,右图展示了受害者计算机上的DLL的显示方式。因为没有“ OracleOciLib”值,所以它将加载硬编码的DLL“ ociw32.dll”,从而触发恶意的Waterbear DLL加载器。

Waterbear DLL加载程序执行后,它将搜索硬编码路径,并尝试解密相应的有效负载,有效负载是一段加密的Shellcode。解密算法为RC4,它采用硬编码路径来形成解密密钥。如果解密后的有效负载有效,它将选择一个特定的现有Windows服务——LanmanServer(由svchost.exe运行),并将解密后的shellcode注入到合法服务中。在大多数情况下,有效负载是第一阶段的后门,它的主要目的是检索第二阶段的有效负载——通过连接到C&C服务器或打开一个端口来等待外部连接和加载传入的可执行文件。

第一阶段后门的配置

Waterbear的第一阶段后门配置包含正确执行和与外部实体通信所需的信息。

· 偏移量0x00,大小0x10:函数的加密/解密密钥

· 偏移量0x10,大小0x04:0x0BB8(保留)

· 偏移量0x14,大小0x10:版本(例如0.13、0.14、0.16等)

· 偏移量0x24,大小0x10:互斥或保留字节

· 偏移量0x34,大小0x78:C&C服务器地址,由密钥0xFF进行XOR加密。如果后门打算在特定端口上侦听,则此部分将填充0x00。

· 偏移量0xAC,大小0x02:端口

· 偏移量0xAE,大小0x5A:保留字节

· 表:有效负载的函数地址表。该块最初以0x00填充,并将在运行时传播。

· 表:函数大小

· 表:API地址表。该块最初用0x00填充,并且在运行时将用已加载的API地址填充。

· 表:用于动态API加载的API哈希

· DLL名称和要加载的API数量的列表

图3.第一阶段后门的配置结构

Shellcode有效负载的反内存扫描

为了避免在运行时进行内存扫描,有效负载会在执行实际的恶意例程之前对所有函数块进行加密,每当需要使用函数时,再解密相应函数执行,之后再次对函数加密,如图4所示。如果在执行过程中不使用某个函数,它可以通过另一个混淆函数将其打乱,如图6所示。混淆函数用随机值混淆字节,并使输入块不可恢复。这样做的目的是进一步避免被安全解决方案检测到。

图4. Shellcode执行例程中的解密-执行-加密流程

图5.用于函数块加密和解密的函数

图6.有效负载的混淆函数

相同的Waterbear,不同的故事

此次Waterbear活动与我们之前见过的大多数都不同。这次DLL加载器加载了两个有效负载,第一个有效负载将代码注入特定的安全产品中进行API钩子,隐藏后门,绕过检测;第二个有效负载则是典型的Waterbear第一阶段后门。

Figure 7. An unusual Waterbear infection chain

图7.非常规的Waterbear感染链

两种有效负载均被加密并存储在受害者的磁盘上,并注入到同一服务中,在本例中为LanmanServer。我们观察到加载器试图从文件中读取有效载荷,对其解密,并在以下条件下执行线程注入:

如果在磁盘上找不到第一个有效负载,则将终止加载程序而不会加载第二个有效负载。

如果第一个有效负载被成功解密并注入到服务中,那么不管第一个线程发生了什么,第二个有效负载也将被加载并注入。

在第一个注入的线程中,如果找不到来自安全产品的必要可执行文件,则该线程将被终止,而无需执行其他恶意例程。请注意,只有线程终止,但服务仍将运行。

无论是否执行了API钩子,第二个后门在成功加载后仍将执行。

利用API钩子逃避检测

为了隐藏第一阶段后门(即第二个有效负载),第一个有效负载使用API钩子技术来避免被特定的安全产品检测到。它挂钩了两个不同的API——“ ZwOpenProcess”和“ GetExtendedTcpTable”来隐藏特定进程。有效负载只修改安全产品进程内存中的函数,因此原始系统DLL文件保持不变。

有效负载由两阶段的Shellcode组成:第一阶段的shellcode使用硬编码名称查找特定安全产品的进程,并将第二阶段的shellcode注入进程。然后,第二阶段的shellcode在目标进程内部执行API钩子。

隐藏进程标识符(PID)

要隐藏的进程标识符将存储在共享内存“Global\<computer_name>.” 中。如果共享内存不存在,它将采用第一阶段Shellcode嵌入的PID。在本例中,恶意代码的目的是对安全产品隐藏Waterbear的后门活动。因此,第一阶段的shellcode采用Windows服务的PID(第一阶段的shellcode和随后的后门都注入该服务)隐藏目标进程,并将PID嵌入第二阶段的shellcode。

图8.将当前PID注入第二阶段shellcode的代码

在ntdll.dll中挂钩“ ZwOpenProcess”

挂钩“ ZwOpenProcess”的目的是为了防止安全产品访问特定的进程。每当调用“ ZwOpenProcess”时,注入的代码将首先检查打开的进程是否命中了受保护进程ID列表中的任何PID。如果是,它将修改进程ID,该进程ID应在另一个Windows服务PID上打开。

首先,它构建钩子函数并将函数写入“ ntdll.dll”的末尾。该函数包括两部分,如图9所示:

1.PID检查程序。它递归检查由“ ZwOpenProcess”打开的PID是否在受保护进程ID的列表中。如果是,它将用另一个由Waterbear加载程序在开始时写入的Windows服务PID替换要打开的PID。

2.在执行PID检查程序之后,它将执行原始的“ ZwOpenProcess”并返回结果。

图9.“ ZwOpenProcess”的函数钩子,用于检查和修改函数的输出

其次,它在原始“ ZwOpenProcess”地址的开头写入“ push <ADDRESS> ret”。因此,当调用“ ZwOpenProcess”时,将执行“ ZwOpenProcess”的修改版本。

图10.修改后的“ ZwOpenProcess”

仅当主机上存在“%temp%\KERNELBASE.dll”时,才会触发挂钩到“ ZwOpenProcess”的API。这种检查可能是根据它所针对的安全产品的性质设计的。

iphlpapi.dll中的“ GetExtendedTcpTable”和“ GetRTTAndHopCount”挂钩

API钩子的第二部分位于“ GetExtendedTcpTable”上。“ GetExtendedTcpTable”用于检索包含该应用程序可用的TCP端点列表的表,该表经常用于某些与网络相关的命令,例如netstat。挂钩的目的是删除某些PID的TCP端点记录。为了实现这一点,它修改了两个函数:“ GetExtendedTcpTable”和“ GetRTTAndHopCount”。第二个函数“ GetRTTAndHopCount”充当放置已插入的钩子代码的位置。

“ GetExtendedTcpTable”仅在函数开头写入对“ GetRTTAndHopCount”的跳转。 API“ GetExtendedTcpTable”的代码的仅前5个字节被更改,如图11所示。

 

图11.“ GetExtendedTcpTable”中仅更改了5个字节

该例程的其余部分全部放在“ GetRTTAndHopCount”中。在代码的第一部分中,它将[“ GetRTTAndHopCount” + 0x3E]作为返回地址,然后执行原始“ GetExtendedTcpTable”函数的前四条指令(已由图11中的跳转指令代替)。之后,它跳转到“ GetExtendedTcpTable”以正常执行该函数并捕获其返回值。代码如图12所示。

图12.在“ GetRTTAndHopCount”中注入的代码的第一部分,执行“ GetExtendedTcpTable”并返回到下一条指令

在执行“ GetExtendedTcpTable”并且过程返回到代码的第二部分之后,它迭代地检查返回的Tcp表中的每个记录。如果任何记录包含要隐藏的PID Waterbear,它将删除相应的记录,修改表中的记录编号,并继续检查后续记录。最后,它返回修改后的表。

图13.在“ GetRTTAndHopCount”中注入的代码的第一部分,执行“ GetExtendedTcpTable”并返回到下一条指令

使用API钩子的方法不是直接禁用这两个函数,而是使恶意行为检测变得更加困难,因为这两个函数仍然可以正常工作并返回正常结果。虽然受影响的进程是在第一阶段的Shellcode中指定的,但API钩子逻辑非常通用,可以使用同一段Shellcode来挂钩其他安全产品。

结论

这是我们第一次看到Waterbear试图隐藏其后门活动。通过产品的硬编码名称,我们可以推断出攻击者了解受害者的环境以及他们使用的安全产品。攻击者可能还知道这些安全产品是如何在客户端的端点和网络上收集信息的,进而知道要挂接哪些API。由于API钩子shellcode采用的是通用方法,因此将来可能会使用类似的代码段来针对其他安全产品,使得Waterbear活动更难检测到。

本文翻译自:https://blog.trendmicro.com/trendlabs-security-intelligence/waterbear-is-back-uses-api-hooking-to-evade-security-product-detection/如若转载,请注明原文地址: https://beta.4hou.com/web/22074.html
点赞 0
  • 分享至
取消

感谢您的支持,我会继续努力的!

扫码支持

打开微信扫一扫后点击右上角即可分享哟

发表评论