【技术分享】以Emotet为例识别C2服务器并掌握其拓扑结构

https://p2.ssl.qhimg.com/t01e8b00a8ab3fc3840.jpg

译者:shan66

预估稿费:200RMB

投稿方式:发送邮件至linwei#360.cn,或登陆网页版在线投稿

 简介

虽然现在大多数僵尸网络仍在使用基本的客户端-服务器模式,并且依赖HTTP服务器来接收命令,但是,许多著名的黑客组织已经开始利用更先进的基础设施来绕过终端黑名单,并且在关闭系统方面要更加具有弹性。 在本文中,我将以Emotet为例来介绍识别C2服务器并掌握其拓扑结构的详细过程。

  

关于Emotet

Emotet是Feodo的最新版本,其主要用途是加载模块,以及收集电子邮件地址以供将来分发垃圾邮件之用。乍一看,它好像是将C2的各个IP地址直接硬编码到二进制文件中了,但是通过进一步考察,就会发现事情远没有这么简单。

http://p9.qhimg.com/t016bdf1b3022101274.png

通过借助于免费的社区版RiskIQ 工具,我们不仅可以查看每个IP地址,甚至可以查看过去哪些域名指向该IP地址,或者现在哪些域名仍指向该IP地址。现在,让我们来考察第一个IP地址。

http://p2.qhimg.com/t01f7188b03c89aaff4.png

RiskIQ指出,该IP地址属于1&1(一家出租服务器的ISP),并且,当前有许多域名指向该地址,其中一个域名自从2009年起就一直指向这个IP地址。由于1&1 Internet 是一家正规的服务商,所以C2服务器不可能在它那里托管8年之久,再说,Emotet的存在时间也不足8年,因此这很可能是一个合法的Web服务器。

由于该服务器已经被关闭,我们拿它没招,所以不妨将注意力转向206.214.220.81

 http://p4.qhimg.com/t01c8c144c36d86c5c6.png

该服务器在80端口上运行了一个标准的Plesk HTTPd,这表明该服务器又是一个Web服务器,但是它似乎没有运行任何网站。在Emotet配置中指定的端口是8080,所以让我们来看看这个端口的情况。

http://p3.qhimg.com/t01ef98b43f7a568cac.png

它返回的是一个Nginx 404页面,这很有趣,因为服务器正在运行的是Plex。更有意思的是,如果我们向80端口和8080端口发送请求,我们可以通过Chrome Developer Tools得到相应的延迟时间。

http://p6.qhimg.com/t01d569d115c1b87282.png

根据Chrome的报告来看,这个服务器花了4毫秒的时间向80端口发送了一个6.5千字节的网页,而花了325毫秒的时间给端口8080发送了一个712字节的404页面,这完全不合逻辑。

根据下列事实,即这些服务器看起来一直在托管合法网站,并运行各种HTTP服务,同时,又始终在Emotet端口上响应Nginx 404错误,并且主端口和Emotet端口之间的延迟存在巨大的差异——我们可以得出这样一个结论:所有这些服务器都已经被入侵,并且正在副端口上运行Nginx反向代理,这会将请求转发给另一台服务器,从而导致严重的延迟。

如果我们想进一步确认Emotet端口面向的是一个反向代理,并且这不是攻击者的源端服务器,那么我们可以借助另一个简单的方法来进行计时。为此,我专门编写的一个简单的python脚本。

import socket
import datetime
import argparse
 
 
def time_request(host, request):
    s = socket.socket(socket.AF_INET, socket.SOCK_STREAM, 0)
    host = host.split(':')
    s.connect((host[0], int(host[1])))
 
    time_start = datetime.datetime.now()
    s.send(request)
    s.recv(1024)
    time_end = datetime.datetime.now()
 
    diff = time_end - time_start
    return diff.total_seconds() * 1000
 
 
parser = argparse.ArgumentParser()
parser.add_argument('--host', help="host (ip:port)", required=True)
args = parser.parse_args()
 
valid_request = 'GET /aaaaaaaa HTTP/1.1rnHost: {}rnrn'.format(args.host)
invalid_request = 'GET /aaaaaaaa HTTP/1.1rnMost: {}rnrn'.format(args.host)
 
valid_time = time_request(args.host, valid_request)
invalid_time = time_request(args.host, invalid_request)
 
print('valid request took {} msninvalid request took {} ms'.format(valid_time, invalid_time))

它的工作原理是发送两个HTTP请求:一个请求用于触发404错误(找不到页面),另一个是用于触发400错误(无效请求)的HTTP请求,并记录每个请求的响应时间。正常情况下,404页和400页应该具有相似的响应时间;但是,如果我们当前使用了反向代理的话,则响应时间就会出现明显得差异。因为第一个请求将被转发到源端服务器,它发现页面不存在后,才会返回一个404。第二个请求是无效的,所以反向代理不会转发,而是直接返回400错误。所以,如果正在使用反向代理的话,由于有效的请求被转发到源端,但是无效的请求不会进行转发,所以,无效的请求的响应时间会比有效请求快得多。

http://p8.qhimg.com/t01f59a489c1405f4b8.png

当我们运行脚本对对可疑的反向代理进行检测时,可以看到无效请求比有效请求快4倍以上,所以完全可以肯定,这就是一个代理。

现在的问题是,我们能够找出正在向其转发请求的服务器的IP地址吗?如果可以的话,我们就有可能联系到服务器的所有者并向其咨询一些信息,但是服务器几乎总是在所有者作出响应之前就被关闭了(即使他们愿意做出响应)。假设服务器真的遭到黑客入侵,那我们该如何处理?一种可能的方法是通过黑客手段入侵一个服务器进行相应的调查,然而,这不仅是非法的,而且也是非常不道德的,因为这些服务器都是个人网站,而不是黑客控制的C2(这是我不支持“黑回去”的原因之一,因为这些服务器仅仅看起来像是一个C2服务器,但是并不意味着它就是一个C2服务器)。

我个人的做法是,查看Emotet配置中的IP地址列表,并找到了一个托管在我可以跟他们说得上话的ISP那里的服务器,然后咨询该ISP是否可以查看Emotet端口上的IP地址的入站流量,并查看它是否与其他IP的出站流量相关。他们告诉我,由于隐私的原因,只有当我能够证明该服务器正在从事恶意活动,并且待检查的流量来自我的电脑的时候,他们才能进行这种流量检查,所以我在虚拟机上跑了一个Emotet,并捕获了该虚拟机与可疑IP之间的一些流量。当我向ISP提供这些数据后,他们很快将来自我的IP的流量与其内部网络流量数据进行了匹配,并发现每当我的电脑向被黑客入侵的服务器发送请求时,被黑客入侵的服务器就会将该请求转发到另一台服务器(可能是真正的C2)。

令人遗憾的是,这家ISP为我提供了这个上游服务器的IP,但是却不允许我对外公布;然而TechHelpList最近发现的一个IP(217.147.92.31)的行为与我发现的IP的行为完全一致。

如果我们通过Shodan来检查这个地址的话,会得到以下结果。

 http://p4.qhimg.com/t0106ba64d844911f44.png

我们可以看到,端口80返回的通用404错误与被黑客入侵的服务器在Emotet端口上返回的完全一致,所以很可能这就是流量转发的目标端口。下一个问题是,这是源端服务器还是另一个反向代理?

 http://p9.qhimg.com/t019553f4da19b3abf7.png

不过,这个时间比运行上面Python脚本时看到的无效的请求的时间要长得多,从这一点来看,我们好像已经找到了他们一个后端服务器。


小结

 现在,通过被入侵的网站来代理C2服务器的做法已经变得非常流行,因为这样能够为攻击者增加一道防线,以防止研究人员轻易发现和关闭实际的C2服务器;另外的好处就是,安全公司通常不会将这些服务器标记为恶意服务器,毕竟这些服务器实际上是运行了多年的合法网站,而不是用前一天才购买的域名搭建的服务器。

(完)