恶意样本分析手册——通讯篇

传统的恶意软件一般会采用基于 TCP/UDP 的自定义协议进行通 讯,在此基础上还有利用 HTTP/HTTPS,IRC,P2P 等其他应用层协议 来进行通讯的。一般来说在调试网络通信的过程中,无论恶意软件采 用何种协议均对我们所关注的内容无太多影响,只需要获取到对应的 网络通信数据即可,而且在调试方法上基本无差别,故我们将以调试 利用 TCP 通信的样本为例,讲述如何调试样本中的网络通信部分。对 于其他常见的应用层协议,我们将对其网络结构及相关的僵尸网络构 建方式和方法进行简单描述,便于读者理解。

基于 TCP/UDP 自定义协议网络通信分析

基于 TCP 协议的自定义协议在样本分析过程中非常常见,可以利 用其上传下载信息,发送控制命令等,在代码层次来看,一般是使用 了 socket 套接字进行实现。话不多说,直接进入正题。

一个简单的基于 TCP 协议的接收程序:

int main() {
// 创建套接字
SOCKET s = ::socket(AF_INET, SOCK_STREAM, IPPROTO_TCP); if(s == INVALID_SOCKET) {

printf("Failed socket() \n");

return 0; }

// 填写远程地址信息
sockaddr_in servAddr;
servAddr.sin_family = AF_INET;
servAddr.sin_port = htons(4567); servAddr.sin_addr.S_un.S_addr = inet_addr("127.0.0.1"); if(::connect(s, (sockaddr*)&servAddr, sizeof(servAddr)) == -1){

printf("Failed connect() \n"); return 0;

}
// 接收数据
char buff[256];
int nRecv = ::recv(s, buff, 256, 0); if(nRecv > 0) {

buff[nRecv] = '\0';

printf(" 接收到数据:%s", buff); }

// 关闭套接字 ::closesocket(s); return 0;

}

那么自定义协议又是什么呢?本身应用层的协议就是服务器与客 户端之间互相约定来进行信息交流的规范,恶意软件也可以创建一个 约定用来和被感染的机器进行交流。

一般来说,在分析通信协议,进而解析数据包内容具体含义的情 形中,僵尸网络这一类的样本是最多的,我们将以僵尸网络为例来进 行讲解。

当一个僵尸主机想要加入僵尸网络的时候,会先发送一个标志包 给僵尸网络的主控服务器,我们将其称为上线数据包,上线数据包中 一般会包含僵尸主机的一些基本信息,例如计算机名称,硬件 ID,计 算机版本信息等等内容,在传输之前,可能使用一些比较简单的自定 义算法,或者 RSA、AES 这类成熟的算法进行加密。

对于加密数据的处理,需要确定的是是否有采用已知的算法,定 位一些关键函数是非常快速的方法,以 Windows 程序为例:需要确 定是否导入了 Crypt*系列的函数。如果有,查看 CryptGenKey、 CryptImportKey 函数来截获加密类型及加密密钥信息,查看 CryptEncrypt 函数来截获要加密的内容。如果没有导入这类函数,很有可能是采用了自定义的加密算法,最快的跟踪方法是定位到发送部 分的函数,向前追溯,找到加密函数。

数据发送的方式也非常简单,只需要构造好需要发送的数据,使 用 socket 套接字提供的 send 接口函数即可。当然,在实际分析的过 程中,可能会发现无法连接到僵尸网络的主控服务器上(即 C&C 服务 器),为了让程序正常执行,并且捕获数据包,你需要对 C&C 服务器 进行模拟。此种方法对于分析失联的 C&C 通讯尤为有效,同时,在 了解整个恶意软件的运行细节之前,同样建议使用这种方式进行分析, 当对恶意软件进行了深入分析之后,再连接到真实的 C&C 服务器上, 获取其发来的指令信息。

在网络上,我们可以很简单的搜索到模拟服务器之类的软件,非 常方便,在分析恶意软件时,如果该恶意软件使用了域名作为连接的 途径,我们可以在调试的过程中发现 gethostbyname 函数,我们可以 修改其返回值为我们自己虚拟机的 IP 地址:192.168.100.1。

在虚拟机 192.168.100.1 上,我们可以运行 TCP 监听软件或者是 netcat,监听恶意程序需要连接的端口,直到其连接即可获取上线数 据包中的内容。

数据包长度 (4 字节)
命令控制字 (4 字节)
命令内容 (n 字节)
可配置选项 (n 字节)
在 IDA 中我们一般能够看到相关的命令解析部分,如下图所示:
根据 IDA 中解析命令数据包的代码来对整个命令包的数据格式进 行分析,是了解僵尸网络功能的最佳途径,采用这种方法能够获取完 整的指令表。
对于 UDP 来说,自定义协议可能是用起来不是很方便,因为攻击 者无法确定僵尸主机是否正确接收到控制主机的命令,所以,基于 UDP 的点对点通信技术(P2P)在攻击者看来非常适合传播恶意软件, 共享命令(当然基于 TCP 的也很好)。

P2P 网络(Peer to Peer 对等网络)

P2P 网络大致分为三类,集中目录式 P2P 网络,全分布无结构 P2P 网络,全分布结构化 P2P 网络。

大部分人眼中 P2P 僵尸网络的构造和下图类似,所有僵尸主机通 过 IP 地址互相连接,互相发送命令,完全不需要中心服务器或者域 名。但是,这种表述是错误的。

那些使用了防火墙,NAT 或者代理来访问网络的计算机是无法接 受连入请求的,它们只能向外发起链接,这使得大多数僵尸主机无法 被另外一个僵尸主机直接连接。所以说,建立 P2P 僵尸网络仍然是需要服务器的,只不过形式上是不相同的。

控制者将那些可以接收连入请求的僵尸主机作为一个节点,其他的无法作为节点的僵尸主机将向节点发起连接,获取指令信息。真实 环境下的 P2P 网络构造图如下:

要将一台主机加入到僵尸网络中去,它至少需要获取一个节点的 地址,这时候需要一台或者多台服务器来进行引导,服务器上应维护 了一个巨大的节点地址池,并将其中一部分发送到僵尸主机上,在病 毒文件中应硬编码了一系列可供其连接的服务器的地址,当程序第一 次在被感染的计算机上运行时,它就会连接到这些服务器。

因此,在分析 P2P 网络架构的病毒文件时,主要是找到相应的节 点地址,获取到种子,以便对整个僵尸网络有一个初步的认知。命令 执行等内容参考基于 TCP/UDP 自定义协议网络通信分析这一节内容 即可。

基于 IRC 协议的通信方式

IRC(Internet Replay Chat:互联网中继聊天)协议是基于客户服 务器(Client-Server)模型的,可以以分布式方式运行在接入网络的机 器上。由于其要求每个服务器都拥有整个网络的全局状态信息,限制 了一个网络能够达到的最大规模,故基于此协议的 botnet 的规模一 般是可控制的。

一个 IRC 网络的典型设置为:一个单一的处理器(服务器)扮演了 整个网络的中心点以供客户端(包含其他服务器)进行连接,并且实现 指定消息的传送/复用以及其他的功能。

一个 IRC 网络的组件包括:服务器,客户机(包含用户客户机,一 般指用于交流的界面程序;服务客户机,一般指可以随意使用来自与 服务器的加密数据,用于提供数据统计等服务)。

对于 IRC 来说,受感染的机器成为僵尸主机以后,首先要做的事 情就是加入预先指定的“频道“中去,以接收控制主机发来的命令及其 他内容。

上图这段代码中,会先给指定的服务器发送所谓的密码信息,接 着发送昵称以用于注册自己,当我们被服务器接受并加入到指定的聊 天频道之后,IRC 僵尸主机的上线行为就完成了。后续只需要监控接 收到的信息及逆向分析相关的处理函数逻辑,即可完整的解析命令内 容,但是我们经常会遇见无法连接到服务器的情况,在这种情况下, 我们可以临时搭建一个 IRC 服务器,在 Python 的 PyPi 网站上可以找 到 IRC 的 python 包,只需要修改 setup.py 文件中频道等相关信息, 运行起来后监听指定端口就可以了。

利用隐藏隧道传输数据

恶意软件为了保证通讯的数据在通信信道中不被检测类设备发现 和防护类设备阻断,会将数据隐藏在已知协议的保留字段或者可以更 改的信息字段中,这里以 DNS 协议为里进行分析。

DNS 在网络世界中是一个非常重要的协议,它将长串的不适合记 忆的 IP 地址映射成可读性较强的字符域名。域名的存储、解析和管 理都要通过域名服务器来实现,DNS 的记录类型有很多,大家常见的 有 A,AAAA,CNAME,MX,SOA,NS 等。DNS 隧道技术可以利用 其中的一些记录类型来传输数据。例如 A,MX,CNAME,TXT,NULL等。

DNS 的解析过程可以分为两种类型:迭代查询和递归查询。通常本机到 Local DNS Server 的过程属于递归查询,而 Local DNS Server 对查询域名的解析过程属于迭代查询。为了减轻 Local DNS Server 的 压力,提高解析速度,引入了缓存机制。缓存和 TTL 紧密相连,当 TTL 过期,Local DNS Server 则会丢弃缓存的数据,重新从权威域名服务 器上获取新的数据。

因此恶意软件在利用此技术的时候会将相应的 TTL 值设置的非常 小,或者设置多个不同的域名用于控制主机与僵尸主机的通信,迫使 发送的 DNS 请求数据能够始终传递到攻击者控制的 DNS 服务器上。

上图展示了恶意软件 Denis 的流量情况,Denis 对外发送了大 量的 DNS 查询请求,查询AAAAAAAAAAAAAAAHM8.z.teriava.com 的地址, 但是 google 的域名服务器中没有此记录项,则该请求会传 递给权威域名服务器进行查询,最后,将此 DNS 查询包发送给了黑 客控制的服务器上,也就是 z.teriava.com 这个地址。地址之前的所有 内容都是发送给攻击者的信息。

在进行样本分析的过程中,应首先到找到加密数据所使用的加 密算法,以便于获取上传的所有信息。分析时可以定位到解析域名相关的函数处,在 Windows 上,一般是使用 gethostbyname 等函数。 从此部分开始往前追溯,还原数据搜集以及加密的部分,是非常有效 且高效率的。

HTTP/HTTPS 通信内容分析

对于大多数恶意软件来说,利用 HTTP 协议进行数据上传及下载 是非常方便的,而且容易将恶意流量隐藏在大量的 web 流量中。HTTP 协议是基于 TCP 实现的,从分析角度上来说与基于 TCP 协议的自定 义协议分析没有太大差别,需要注意的是,大多数 HTTP 通信是使用 了 GET 或者 POST 方法,非常好辨别数据,但是也有很多例外,举个 特殊例子:使用 XML 文档来进行数据传输的情况。

通信方式:僵尸主机会尝试连接控制服务器,以请求一个包含有 指令的 XML 文档到本地,该 XML 文档会使用一些伪装性的标签或内 容,以隐藏真实的命令内容,如:

<?xml version="1.0"?>
<Data xmlns="http://schemas.datacontract.org/2004/07/Io" xmlns:i="http://www.w3.org/2001/XMLSchema-instance">

<Hwid>WIN-HV9TU5VPRAN-hello-283095A0</Hwid> <IoData>

<CommandResults

xmlns:a="http://schemas.datacontract.org/2004/07/System.Collections.Generic">
<a:_array xmlns:b="http://schemas.datacontract.org/2004/07/Io.Commands" /> <a:_head>0</a:_head>
<a:_size>0</a:_size>
<a:_tail>0</a:_tail>
<a:_version>0</a:_version>

</CommandResults>

<CommandsData

xmlns:a="http://schemas.datacontract.org/2004/07/Io.Commands" />

i:nil="true"

<FilesList xmlns:a="http://schemas.microsoft.com/2003/10/Serialization/Arrays" /> <FoundFiles xmlns:a="http://schemas.microsoft.com/2003/10/Serialization/Arrays" /> <Hwid>WIN-HV9TU5VPRAN-hello-283095A0</Hwid>
<KregsQueue xmlns:a="http://schemas.datacontract.org/2004/07/System.Collections.Generic">

<a:_array xmlns:b="http://schemas.datacontract.org/2004/07/Helpers" /> <a:_head>0</a:_head>
<a:_size>0</a:_size>
<a:_tail>0</a:_tail>

<a:_version>0</a:_version> </KregsQueue>

<LogsQueue xmlns:a="http://schemas.datacontract.org/2004/07/System.Collections.Generic"> <a:_array xmlns:b="http://schemas.datacontract.org/2004/07/Helpers" /> <a:_head>0</a:_head>
<a:_size>0</a:_size>

<a:_tail>0</a:_tail>

<a:_version>0</a:_version> </LogsQueue>

<ScreenshotsQueue

xmlns:a="http://schemas.datacontract.org/2004/07/System.Collections.Generic">
<a:_array xmlns:b="http://schemas.datacontract.org/2004/07/Io.Commands.ScreenShots"

/>

<a:_head>0</a:_head> <a:_size>0</a:_size> <a:_tail>0</a:_tail> <a:_version>0</a:_version>

</ScreenshotsQueue>
<SysInfo i:nil="true" xmlns:a="http://schemas.datacontract.org/2004/07/Helpers" /> <TasksList xmlns:a="http://schemas.microsoft.com/2003/10/Serialization/Arrays" /> <TransferFilesQueue

xmlns:a="http://schemas.datacontract.org/2004/07/System.Collections.Generic">
<a:_array xmlns:b="http://schemas.datacontract.org/2004/07/Helpers.Files" /> <a:_head>0</a:_head>
<a:_size>0</a:_size>

<a:_tail>0</a:_tail>

<a:_version>0</a:_version> </TransferFilesQueue>

</IoData> <RequestType>ResponseGetCommands</RequestType> <Time>2017-10-16T11:21:16.520113Z</Time>

</Data>

僵尸主机接收到此 XML 文档后,会读取其中的命令,执行后将搜集到的信息或其他内容填入 XML 文件的指定位置中,经过加密/压缩 等方式对数据进行处理,再回传给控制服务器。那么在控制服务器连 接不上的情况下如何分析此类恶意软件呢?特别的,如果采用了 HTTPS 进行通信,应该如何去分析呢?

HTTP 通信用于请求文件,上传信息,所以我们只需要搭建一个 HTTP 服务器即可接收或者提交文件供恶意软件进行下载。在 Windows 下,我们可以使用 IIS 或者下载 apache 等软件,搭建一个 简单的 HTTP 服务器。修改 host 文件,重定向原本的域名到自己虚拟 机地址上,上传恶意软件需要的文件到服务器上,使得恶意软件能正 常执行功能,从而能够继续后续功能的分析。

HTTPS 使用了证书加密,使得分析人员通过沙盒等自动化分析工 具获取发送的数据变得更加困难,但是在动态调试过程中,我们可以 在建立链接之前,将域名更改为 HTTP 协议头,来避免通信过程的加 密,同时也方便我们自己搭建 HTTP 服务器,免去证书认证的繁琐的 操作(当然你可以提前搭建这类有证书分析环境,如果这样的话,那 会非常方便)。除此之外,我们可以使用中间人攻击技术,在恶意软 件与真正的控制服务器通信的时候截获通信内容,从而免去分析恶意 软件的麻烦。

利用 Twitter 或其他开放平台进行通信

僵尸网络利用 Twitter 或者微博等公开平台传递信息已经是一个公开的方式和方法了,在 APT29 中使用的恶意软件 HAMMERTOSS 就 是基于此的。原理非常简单,利用 Twitter 提供的 API 及攻击者使用 的账号,上传信息到指定账号或者读取指定账号中的 Twitter 信息, 从中获取命令,URL 等等一系列内容。

另外,通过 Github 进行文件下载或者上传也是这类恶意软件采用 的比较新奇的方法,通过这种方式上传受害者信息,或者说下载文件 到本地,都非常容易被网络管理员忽略,从而达到隐藏自身网络流量 的目的。

对于这类恶意软件的分析,需要注意的是导入表中包含的 TwitterAPI、GithubAPI 相关的函数,定位到这部分代码后,参照这类 网站提供的 API 说明文档及示例,即可简单的对其进行逆向分析。

Spread the word. Share this post!

Meet The Author

Leave Comment