1. 概述
Daxin是一个高度复杂的rootkit后门,具有复杂、隐秘的命令于控制功能。使远程攻击者能够与未直接连接到互联网的安全设备进行通信,运行攻击者深入挖掘目标网络并泄露数据而不会引起怀疑。
和普通rootkit恶意程序利用合法的操作系统进程不一样,Daxin利用服务器之间合法的安全网络流量来感染计算机并避免检测。通过劫持TCP通信,可以将恶意通信隐藏在被认为合法的流量中而不被发现,被劫持的流量本质上可以被认为是被加密的TCP隧道,还能够通过受攻击组织内受感染计算机网络中继其通信,攻击者可以选择跨受感染计算即的任意路径并发送一条命令,指示这些计算机建立请求的连接。
从复杂的通信过程来看,Daxin开发者投入大量精力来开发通信技术,这些技术可以让恶意流量与目标网络的正常网络流量融合在一起。
2. 样本详情
文件名 | Md5 |
---|---|
Wantd.sys | b0770094c3c64250167b55e4db850c04 |
3. 流程图
4. 详细分析
驱动文件通过搜索某些重要结构来进行挂钩,将系统的收发包函数替换为自己的收发包函数,以此来达到隐蔽通信的效果,又因为拦截的是位于OSI七层结构最底层的链路层,而一般防火墙位于协议层,因此可以绕过大部分防火墙的流量监控,并且可以自定义协议或者伪装DNS、TCP/IP和ICMP等等协议数据而不被发现,当收到具有特定格式的数据包时才拦截并解析命令执行对应的操作,而对于其他流量数据则选择放过。
4.1 Wantd.sys分析
1. 文件信息
驱动文件名为”wantd.sys”,文件描述被伪装成windows系统文件。产品版本为6.1.7600,可以得知编译器生成驱动时指定的目标操作系统为Win7,如果用于win10或win11可能会导致蓝屏问题。
但是查看数字签名却不是微软的数字签名,使用的是某公司泄露的数字签名,安全意识高的用户很容易怀疑该文件为可疑文件。
2. HOOK NDIS中间层驱动
遍历所有已经加载的驱动,通过比较模块名来查找驱动并返回对应的模块信息。
遍历驱动模块的导出表获取api_name的函数地址。
因为协议驱动需要与网络适配器做绑定,而每个网络适配器都会与TCPIP做绑定,因此对TCPIP进行HOOK是比较省力方便的方式,这样可以拦截所有网卡的TCPIP流量通信。
ndisMiniDriverList为内核网络编程中比较重要的变量,在注册和枚举微端口驱动时都会用到。
ndisFindMiniportOnGlobalList 给定一个对象名,遍历ndisMiniportList的NextGloabalMiniport字段找到指定对象名的_NDIS_MINIPORT_BLOCK结构,这个结构用于表示微端口信息,物理网卡和虚拟网卡等存在这个结构。
变量ndisMiniDriverList和函数ndisFindMiniportOnGlobalList在内核中是未公开和导出的,因此无法通过正常方式来获取。
恶意驱动通过在特定函数中查找特征码的方式定位到关键结构然后获取其地址。
全局变量ndisMiniDriverList
在函数NdisMRegisterMiniportDriver中搜索特征码。
搜索到的汇编代码如下图:
函数ndisFindMiniportOnGlobalList
在函数NdisIMInitializeDeviceInstanceEx搜索特征码。
在ndis.sys中对应的汇编代码如下,获取到的数据为偏移,还需要计算以下转成函数地址。
通过微端口驱动的链表查找上一层网络(NDIS协议驱动)中名为”TCPIP”的协议驱动。
暴力搜索tcpOpenBlock的字段Openqueue的内存数据,判断是否是有效指针,如果是指向的内存是否是特征”\x5c\x00\x5e\x00\x5c\x00\x5c\x00”,如果是则
计算偏移。
要搜索的特征其实为设备名的长度。
继续暴力搜索字段Openqueue的字段ProtSendNetBufferListsComplete和ReceiveNetBufferLists字段。这两个字段为函数,主要用于接收和发送相关协议的数据包。
备份所有协议驱动对应的结构NDIS_OPEN_BLOCK中的收包和发包函数地址,用于在被hook的函数中调用原函数或者驱动卸载时恢复。
对所有已注册的协议驱动用于收发数据包的函数ReceiveNetBufferLists和SendCompleteNdisPacketContext,恶意驱动都将其替换成自己的处理函数。
在被hook的函数中,第二个参数为NET_BUFFER_LIST结构,待接收的数据包存放在其字段mdl描述里。
判断收到的数据包是否是LOOKUP_BACK类型,如果是则调用原函数,不进行任何拦截操作;否则拦截和修改数据包。
在函数hook_SendCompleteNdisPacket中,将由恶意驱动发送的数据包从链表中移除从而隐藏其通信数据,使Wireshark、Tcpdump等抓包工具不能捕捉到其通信流量。
数据包nbl的flags被设置成0x99100000,查找官方文档该值为无效值,应该是用来识别是否是由恶意驱动修改过的数据包,由于数据包被拦截不会到达系统的Windows TCP/IP堆栈,因此设置成任意值都不会对网络通信造成影响。
在hook_NextSendBufferListsHandler函数中,比较数据包的NdisPoolHandle是否是ndis_hook_pool。ndis_hook_pool由恶意驱动创建的用于存放数据包的buffer,如果两者相等则调用员函数,如果不相等则需要拦截或修改数据包。
3. 拦截和修改数据包
将保存在nbl的数据包提取出来保存到dst中,方便对其中部分报文进行修改或者重组。
解析数据包的格式用于在重组数据包的时候使用。
在网络数据包被篡改后需要重新计算数据包的检验和,该恶意驱动只拦截ICMP(1)、TCP(6)和UDP(11)三种协议的数据包,因此只需要计算这三种协议的检验和。
网络数据包的检验和计算方式如下:
遍历所有网络接口的ip和子网掩码,找到和ip_addr处于同一内网的IP地址。如果没有找到则返回最后一个网络接口的默认网关。
当发送包含”\x90\x10\x11”的数据到被感染的机器时,恶意驱动会断开用户连接并抢占连接。它与对等方进行自定义密钥交换,打开用于发送和接收据和命令的加密通信通道,使用这种隐蔽的通信方法,威胁参与者可以绕过防火墙并逃逸SOC分析师的检测。
从下图可以看出,恶意驱动发送了两个包,第一个为发送原始目的地的欺骗性RST TCP数据包,
因此其接收者将TCP连接标记为关闭。第二个包是发送到原始源的ACK
TCP数据包。从这时开始,恶意驱动会保持与原始源IP的TCP连接,依靠ReceiveNetBufferList挂钩劫持任何相关的网络数据包。
在生成网络数据包时,daxin使用自己的代码伪造网络数据包,绕过合法的Windows TCP/IP堆栈。根据原始TCP协议报文重新组装报文,修改原始报文中涉及到的mac地址。
遍历所有网卡对应的IP地址,获取IP地址对应的mac地址,将其保存到全局变量g_packets。后续在伪造数据包时通过从g_packets获取最佳路由。
初始化过程如下:
4.通信隧道
每当Daxin劫持TCP连接时,它都会检查接收到的数据中是否有特定消息。如果有则启动自定义密钥交换。密钥交换成功后会打开一个加密的通信隧道。Daxin使用这个通信隧道来交换各种信息。比如在被感染机器上启动任意进程,读写任意文件等等。
在受感染的机器上,任何恶意网络连接都会绕过Windows TCP/IP堆栈,这可以提供某种程序的隐蔽性。从密钥交换开始,所有后门都采用恶意驱动开发者自定义的协议格式。
1 | Struct protocol_head{ |
对于字段magic来说,其值总是0x9910或者0x9911。Kind为指定密钥交换时处于何种状态。一旦建立了加密通信通道,它就会对每条消息的用途进行编码并确定固定报文大小之后的数据格式。
4.1 密钥交换
密钥开始交换时初始消息处于未加密状态,字段magic和字段kind为TCP数据包前三个字节0x10 0x99 0x11。如果已经感染了恶意驱动的计算机接收到该数据包会导致TCP连接被劫持。
根据会话状态检查接收到的消息是否有效,确保magic值为0x9910,并且kind为0x10或者0x11。接下来会生成一个随机数,用于加密任何之后传入的消息。最后它发送一条响应消息,其中包含随机数、自身详细信息以及有关被感染机器的信息,从该数据包开始,后续所有的数据包无论是发送还是接收都处于加密状态。
发送的响应包格式如下,用于识别是否处于登录状态。
1 | Struct format{ |
发起者收到识别登录的数据包后,发送使用哈希密码登录后门的响应包。
响应的数据包数据格式为:
1 | Struct format{ |
如果登录成功则发送kind为0x16的成功登录消息包给发起登录方。假设请求建立隧道端为A,隧道另一端为B。
Kind | 描述 |
---|---|
0x10 | A向B请求建立通信隧道 |
0x11 | |
0x12 | B接收到A请求登录的消息时,B生成随机数以及将随机数和自身信息作为响应消息发给A。 |
0x15 | A发送登录信息到B,包括登录名和哈希密码 |
0x17 | B接收到A的登录信息,但是A在B机器上处于已登录状态。 |
0x16 | B接收到A的登录信息,A在B机器上处于未登录状态。生成共享密钥,用于加密消息正文。 |
4. APC注入
从所有运行的进程中找到进程svchost,通过APC的方式将dll或者exe注入到该进程。
使用函数KeAttachProcess附加到svchost的进程空间,并获取一些API的地址保存到apc参数上下文中。
附加到目标进程然后利用APC机制将shellcode注入到svchost进程中。
Shellcode的主要功能为执行可执行文件。当文件为dll时通过LoadLibrary加载,为exe时用CreateProcess创建进程。
6. IOC
b0770094c3c64250167b55e4db850c04
\\Device\\Tcp4
7. ATT&CK矩阵
Tactic | ID | Name | Description |
---|---|---|---|
Command and Control | T1572 | Protocol Tunneling | 劫持TCP创建加密通信隧道 |
T1573 | Encrypted Channel | 流量被加密 | |
Discovery | T1012 | Query Registry | 查询注册表获取网络接口信息 |
T1057 | Process Discovery | 查找进程svchost | |
Privilege Escalation | T1055 | Process Injection | 注入shellcode到进程svchost |
Command and Control | T1105 | Ingress Tool Transfer | 下载程序并执行 |
T1573 | Encrypted Channel | C&C之间使用加密流量 |
最后更新: 2024年01月07日 16:30:47
本文链接: http://shxi.cc/post/8e5746b1.html
版权声明: 本作品采用 CC BY-NC-SA 4.0 许可协议进行许可,转载请注明出处!