Mirai属于经典的物联网僵尸网络,产生时间比较久,因此在github上有其泄露的源码。接下来内容我将按照源码进行分析。另外还有一个正在流行的僵尸网络样本Gafgyt,也将在本文后半部分分析。这也是我第一次分析恶意软件。
Mirai分析
Mirai属于经典的物联网僵尸网络,产生时间比较久,因此在github上有其泄露的源码。接下来内容我将按照源码进行分析。
Mirai主要由三个部分组成。其中dlr部分为不同架构下,黑客所投放的病毒实施远程下载的编译好的二进制文件。loader部分运行在黑客主机上,主要进行telnet爆破,并进行弱口令猜测攻击目标路由器或者暴露的IOT设备。bot是在loader运行成功之后,发送到远程僵尸主机上的病毒文件,其主要工作是接受黑客指令创建用户,完成DDoS攻击。
接下来对这三部分做详细分析。
loader部分
loader部分主要完成远程IOT设备的telnet密码爆破,权限获取,以及远程传递病毒文件。
在loader的main.c中,可以看到一共调用了以下几种重要函数。
binary init
实际上就是把所有下载器文件读取到本地栈变量上,用一个数据结构保存下来。后续会用echo将这些下载器传给受控制的IOT设备上,用来下载真正的病毒。
dlr
dlr中没有main()只有run()函数。这个文件做的事情非常简单,连接黑客服务器并通过HTTP请求的方式获取病毒文件。黑客在这个过程中会发送0x0d0a0d0a用来表示何时开始发送正真的病毒本体。这种下载方式只有在使用wget或者tftp命令无法下载文件时才会使用。
server create
生成一个具有固定IP的server,用来测试被攻击者是否能够正常使用wget或者tftp来接受远程文件。这个固定IP是100.200.100.100,当然在开源软件中可能是伪造的。源代码显示这属于一种比较经典的多线程服务器的初始化工作。有多个工作线程(CPU核数个),然后支持的最多连接数量是1024*64个。
在worker()函数中调用了handle_event()。这里是在与目标设备成功建立telnet连接之后尝试爆破密码的地方。首先服务器会判断连接状态,是否能够读取数据,然后根据连接回显的内容判断连接处于的状态。之后根据回显的提示符,输入用户名或者口令,然后根据回显结果判断是否弱口令爆破成功。这里的弱口令是黑客提供的,记录的内容是(ip:端口 用户名:密码 架构)。
成功之后首先通过kill杀死所有包含init以及pid>400的进程,并找到一段内存中的可读写空间,如果找到就生成一个可写文件夹。之后根据用户输入或者主机种ELF文件格式来判断目标主机架构。
如果成功则用busybox通过wget,tftp或者echo下载自身(mirai病毒)。其中前两者都是从黑客服务器下载,echo则是通过黑客提供的下载器下载病毒。之后尝试运行病毒并获取其输出,验证有效性。这是server.c中handle_event线程的主要工作。
cnc
cnc下的文件主要用于接受黑客的指令。包括新建用户(估计这个是给暗网上用户使用的),以及攻击的配置
cnc文件夹下的文件用来编译生成mirai病毒。在main.go中,可以看到mirai通过在端口23以及端口101上进行tcp监听。其中api端口为101,tel端口为23。
tel handler
23号端口的tel handler用于接受黑客指令,包括用户名、用户口令,它可以用来创建一个新的bot或者一个新的用户。分别对应NewBot以及NewAdmin函数。其中23号端口用来接受添加用户,获取僵尸主机相关参数,101号端口用来接收实际的攻击指令,包括设置攻击类型,构造payload数据包。
对于NewAdmin主要控制部分在admin.go中。有以下几种命令,主要是添加一个管理僵尸主机的用户,显示bot连接状态信息,并设置攻击参数。
命令名称 | 命令用途 |
---|---|
adduser | 设置用户名、密码、bot数量、攻击持续时间、攻击冷却时间 |
botcount | 显示bot状态信息 |
- | 指定多少僵尸网络发起攻击 |
@ | 指定发送的payload |
对于NewBot,只是为一个Bot结构体初始化。设置其连接信息,名称等。
api handler
api handler主要接受用户对bot输入的用户名/密码,之后调用NewAttack执行用户输入的命令。
在attack.go中,通过对一些参数组合进行设置,达到不同的攻击效果。这些参数用来把TCP数据包中不同部分设置为用户指定的值,修改其对应位置完成数据包payload编写。用户可以指定,也可以通过默认的方式输入。输入之后将会通过build()构建一个完整的攻击数据包。
有一些现成的组合。达到不同的攻击效果。
Bot
bot部分主要是完成攻击以及发送心跳包等信息,最主要的函数是attack_init以及killer_init。
bot部分首先完成一些环境的清理。包括对watchdog进程发送防止重启的信号,隐藏自身进程名、argv[0]的行为,确保自己单进程运行。
attack_init
接下来的attack_init和killer_init函数中完成的是真正的攻击部分。在attack_init中,初始化了一系列攻击函数。这部分攻击函数主要是根据我们上面的输入,构造真正的数据包。
下面是一个例子。进行UDP攻击的过程。首先是从之前设置的内容中获取包中ttl、协议、源地址、目的地址等信息
之后组装完整的数据包,并发送。
其余的数据包构造方法大致类似,这里不再赘述。
killer_init
killer部分用于关闭一些进程,包括原先23号端口的telnet,22号端口的ssh,80端口的http。主要是为了维持自身的存在。
在main.c的最后,bot会定时发送心跳信息,向黑客主机报告自身的存活。
这次分析的是一个僵尸网络样本。原先的mirai样本因为架构过于奇怪u,无法正常分析,于是分析的市另一个ARM架构的文件。
Gafgyt分析
这里给的样本应该是一个僵尸网络样本。样本架构为32位arm,ELF文件格式。
首先在main()中,可以看到fork()出来一个子进程,并在子进程中进行连接。
病毒会选择一个全局数组中的IP进行连接。如果没有初始设置端口,则默认链接6982端口。
在样本中,数组中只有一个IP,连接到的是23号端口
查询结果发现是越南的一个IP
连接之后,病毒通过recvline()接受发来的命令,并做简单的修正(取最前面空格和最后面空格之间的内容作为命令)。命令开始的标记为”!”。之后病毒按照感叹号之后的内容将命令按照空格分割,保存在本地,并进入process_cmd中。
在process_cmd中,可以看到一共有五种类型的攻击,分别是TCP、UDP、HTTP、VSE、STDHEX。病毒根据黑客的指令,在指令中找到上述五种字符串,以及IP地址,端口号、攻击事件、攻击次数信息,并分别fork()出子进程进行攻击。下面是TCP攻击部分。在攻击中,会采用随机IP地址的方法,自己构造IP数据包进行攻击。
UDP数据包也是类似的行为。和TCP基本一致,不在说明了。接下来是HTTPSTOMP攻击。参数和上述UDP,TCP攻击时不同,是(HTTP行为,ip,端口,攻击次数,攻击时间)这里比较有意思的时他的payload,发送给/cdn-cgi/l/chk_captcha。是为了绕过cloud flare的captcha检查的。在这里,user_agent时一个随机内容,防止被过滤。
HTTPpayload如下所示
1 | unsigned char http_payload[] = |
随机的user_agent内容
1 | Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/60.0.3112.113 Safari/537.36 |
对于VSE攻击,发送了一串很有意思的payload。VSE攻击是针对VSE服务器的一种请求,它被用来去攻击一些游戏中心。它的作用是不停的像游戏中心发送连接请求,导致其中断服务。下面的payload是用于针对此类服务器的。这一段payload能够引起DrDoS攻击,也即分布式反射性拒绝服务攻击,会导致许多受害者及其在不知情的情况下参与到DDoS攻击当中。
1 | TSource Engine Query + |
最后一个攻击在样本中的字符串为”STDHEX”。他的内容仅仅是发送一串固定payload。经过网上搜索,这是一串没有意义的payload,不过可以根据此payload搜索到很接近本样本的开源代码
总结
本样本的功能比较单一,是远控样本,能够接受攻击者发来的命令,通过fork出子进程,进行HTTP、TCP、UDP、VSE以及发送固定无意义内容的攻击。其中攻击者可以指定攻击的目的IP,目的端口,攻击时间,数据包大小等信息。
C2回连信息存在于样本中。IP为103.195.237.238
。域名来自越南胡志明市。样本不存在横向扩展功能,不存在持久化功能。也不存在反调试、反沙箱的手段。