快捷搜索:  汽车  科技

双头暗影魔龙(双头龙RotaJakiro)

双头暗影魔龙(双头龙RotaJakiro)systemd-daemonFIRST SEEN IN VTFileNAMEMD5DETECTION

概述

2021年3月25日,360 NETLAB的BotMon系统发现一个的VT 0检测的可疑ELF文件(MD5=64f6cfe44ba08b0babdd3904233c4857),它会与4个业务类型截然不同的域名进行通信,端口均为TCP 443(HTTPS),但流量却并非TLS/SSL类型,这个异常行为引起了我们的兴趣,进一步分析发现它是一个针对Linux X64系统的后门木马,该家族至少已经存在3年但目前还是0检测。基于该家族使用rotate加密,并且运行后对root/non-root账户有不同的行为,犹如一只双头龙,一体双向,我们将它命名为RotaJakiro。

RotaJakiro隐蔽性较强,对加密算法使用比较多,包括:使用AES算法加密样本内的资源信息;C2通信综合使用了AES,XOR,ROTATE加密和ZLIB压缩算法。指令方面,RotaJakiro支持12种指令码,其中3种是和特定plugin相关的,遗憾的是目前我们并没有捕获到这类payload,因此并不知道它的真正目的。从广义的后门角度来看,RotaJakiro支持的功能可以归纳成以下4类:

  • 上报设备信息
  • 窃取敏感的信息
  • 文件/Plugin管理(查询,下载,删除)
  • 执行特定的Plugin

当所有分析结束后,我们尝试对RotaJakiro进行溯源,根据解密后的资源以及编码的风格的相似性,我们推测它是Torii Botnet作者的又一作品。

潜伏了多少?

我们从捕获的样本出发,寻找RotaJakiro同源者,最终发现了以下4个样本,它们在VT上都是0检测,从VT的First Seen时间来看,RotaJakiro至少已经存在了3年

FileNAME

MD5

DETECTION

FIRST SEEN IN VT

systemd-daemon

1d45cd2c1283f927940c099b8fab593b

0/61

2018-05-16 04:22:59

systemd-daemon

11ad1e9b74b144d564825d65d7fb37d6

0/58

2018-12-25 08:02:05

systemd-daemon

5c0f375e92f551e8f2321b141c15c48f

0/56

2020-05-08 05:50:06

gvfsd-helper

64f6cfe44ba08b0babdd3904233c4857

0/61

2021-01-18 13:13:19

这批样本都内嵌了以下4个C2,目前它们在VT上也是0检测。这4个C2域名有非常接近的Crteated Updated Expired时间,我们推测它们一直以来用于同一个业务,从这个角度来看,RotaJakiro背后的团伙至少已经活动了6年

DOMAIN

DETECTION

CREATED

LAST UPDATED

EXPIRED

news.thaprior.net

0/83

2015-12-09 06:24:13

2020-12-03 07:24:33

2021-12-09 06:24:13

blog.eduelects.com

0/83

2015-12-10 13:12:52

2020-12-03 07:24:33

2021-12-10 13:12:52

cdn.mirror-codes.net

0/83

2015-12-09 06:24:19

2020-12-03 07:24:32

2021-12-09 06:24:19

status.sublineover.net

0/83

2015-12-09 06:24:24

2020-12-03 07:24:32

2021-12-09 06:24:24

逆向分析

4个RotaJakiro样本,时间分布从2018到2021,它们的功能非常接近,本文选取2021年的样本为分析对象,它的基本信息如下:

MD5:64f6cfe44ba08b0babdd3904233c4857 ELF 64-bit LSB executable x86-64 version 1 (SYSV) dynamically linked (uses shared libs) for GNU/Linux 2.6.32 stripped Packer:No

从编码层面来说,RotaJakiro采用了动态AES,双层加密的通信协议等技术来对抗安全人员的二进制&网络流量分析。

从功能层面来说,RotaJakiro运行时首先会判断当时用户是root,还是non-root,不同的账户有不同的执行策略,然后使用AES&ROTATE解密出相关的敏感资源供后续的持久化,进程守护和单一实例使用,最后和C2建立通信,等待执行C2下发的指令。

下文将从上述角度出发剖析RotaJakiro具体实现。

样本对抗技巧
  • 动态生成AES加密算法所需的常量表,防止算法被直接识别
  • 使用stack strings obfuscation技术存储加密的敏感资源信息
  • 使用双层加密的网络通信
加密算法

RotaJakiro中所有的敏感资源都是加密的,在IDA中我们可以看出解密方法dec_proc调用了60次,它是由AES,Rotate俩部分组成。

双头暗影魔龙(双头龙RotaJakiro)(1)

AES解密入口如下所示:

双头暗影魔龙(双头龙RotaJakiro)(2)

其中aes_dec的采用的是AES-256 CBC模式,key&iv都是硬编码。

  • key
  • 14 BA EE 23 8F 72 1A A6 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
  • iv
  • 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00

Rotate解密入口如下所示:

双头暗影魔龙(双头龙RotaJakiro)(3)

所谓Rotate即循环移位,可以看出此处使用的循环左移,其中移位的次数由plain_len(明文长度)&7的值决定。

以解密以下C2密文为例:

ff ba a2 3b cd 5b 7b 24 8c 5f e3 4b fc 56 5b 99 ac 91 cf e3 9a 27 d4 c9 6b 39 34 ce 69 ce 18 60

其与解密相关的各种参数如下图所示,密文长度为32字节,明文长度为26字节

双头暗影魔龙(双头龙RotaJakiro)(4)

首先使用AES解密后得到以下“次级密文”:

双头暗影魔龙(双头龙RotaJakiro)(5)

然后从次级密文中取出有效密文,其中有效密文从第8字节开始,长度为明文长度减8,此处即为26-8=18字节。

98 1B DB D9 8B 59 19 5D 59 1B 59 D8 1D DC 8B D8 DB 5B

最后通过明文长度26可以计算26&7=2,得到移位的次数,将上述有效密文逐字节左移2位,就能得到C2明文。

blog.eduelects.com 持久化

RotaJakiro在实现持久功能时,对root/non-root用户做了区分,不同的账号采用了不同的技术。

针对root账号的持久化实现
  • 根据不同Linux系统发行版本,创建相应的自启动脚本/etc/init/systemd-agent.conf或者/lib/systemd/system/systemd-agent.service。
  • Content of systemd-agent.conf ----------------------------- #system-daemon - configure for system daemon #This service causes system have an associated #kernel object to be started on boot. description "system daemon" start on filesystem or runlevel [2345] exec /bin/systemd/systemd-daemon respawn Content of systemd-agent.service ----------------------------- [Unit] Description=System Daemon Wants=network-online.target After=network-online.target [Service] ExecStart=/usr/lib/systemd/systemd-daemon Restart=always [Install]
  • 用于伪装的文件名,俩者2选1
  • /bin/systemd/systemd-daemon /usr/lib/systemd/systemd-daemon
针对non-root账号的持久化实现
  • 创建桌面环境的自启动脚本$HOME/$.config/autostart/gnomehelper.desktop
  • [Desktop Entry] Type=Application Exec=$HOME/.gvfsd/.profile/gvfsd-helper
  • 修改.bashrc文件,创建shell环境的自启动脚本
  • # Add GNOME's helper designed to work with the I/O abstraction of GIO # this environment variable is set gvfsd will not start the fuse filesystem if [ -d ${HOME} ]; then ${HOME}/.gvfsd/.profile/gvfsd-helper fi
  • 用于用于伪装的文件名,俩者同时存在
  • $HOME/.dbus/sessions/session-dbus $HOME/.gvfsd/.profile/gvfsd-helper
进程守护

RotaJakiro实现了进程守护以保护自身的运行,和持久化一样,对root/non-root用户有不同的实现方式。

针对root账号的进程守护实现

在root账号下运行时,根据不同Linux系统发行版本,通过向服务的配置文件中写入Restart=always或者respawn,当服务进程被结束时,会自动创建新进程。

双头暗影魔龙(双头龙RotaJakiro)(6)

实际效果如下图所示,可以看到systemd-daemon进程被结束后,立马就生成了新进程。

双头暗影魔龙(双头龙RotaJakiro)(7)

针对non-root账号的进程守护实现

在non-root账号下运行时,RotaJakiro生成session-dbus和gvfsd-helper俩个进程,它们监控着彼此的存活,当其中一方被结束时,另一方将其恢复,这是非常典型的双进程保护。

RotaJakiro的双进程保护是如何实现的呢?首先以shmget API创建一片共享内存,session-dbus和gvfsd-helper通过这片共享内存实现进程间通信,告诉对方的自己的PID。然后通过/proc/[PID]目录,动态地获取进程的存活情况。当发现对方进程死亡时,通过execvp创建进程,帮助死亡一方“复活”,大致流程如下图所示:

双头暗影魔龙(双头龙RotaJakiro)(8)

实际效果如下图所示,可以看到session-dbus和gvfsd-helper被kill -9结束后,新进程立马就创建了。

双头暗影魔龙(双头龙RotaJakiro)(9)

单一实例

RotaJakiro通过文件锁来实现单一实例,具体实现如下所示:

双头暗影魔龙(双头龙RotaJakiro)(10)


其中用到的lockfile在root/non-root账号下有所不同。

  • root下的lockfile,2选1
  • /usr/lib32/.X11/X0-lock /bin/lib32/.X11/X0-lock
  • non-root下的lockfile,同时存在
  • $HOME/.X11/X0-lock $HOME/.X11/.X11-lock

以实际中non-root账号为例,通过/proc/locks可以将进程以及文件锁对应起来,此时再执行对应的RotaJakiro的样本,可以看到并不会有对应的新进程创建。

双头暗影魔龙(双头龙RotaJakiro)(11)

网络通信

RotaJakiro通过以下代码片段和C2建立通信,等待执行后续指令:

双头暗影魔龙(双头龙RotaJakiro)(12)

这个过程可以分成2个阶段

  • Stage 1,初始化阶段:解密出C2列表,和C2建立连接,发送上线信息,接回并解密C2返回的信息。
  • Stage 2,业务阶段:验证C2的返回信息,若通过验证,执行C2后续下发的指令。
Stage 1:初始化

通过前文所述的解密算法解密出C2列表,目前样本中内置了以下4个C2:

news.thaprior.net blog.eduelects.com cdn.mirror-codes.net status.sublineover.net

RotaJakiro首先会尝试和它们建立连接,然后通过以下代码片段构造上线信息,

双头暗影魔龙(双头龙RotaJakiro)(13)

接着将上线信息加密并发送给C2

双头暗影魔龙(双头龙RotaJakiro)(14)

最后接收C2的回包,解密并校验其合法性,若通过校验,进入Stage 2。

双头暗影魔龙(双头龙RotaJakiro)(15)

Stage 2:具体业务

通过以下代码片段接收并执行C2下发的指令:

双头暗影魔龙(双头龙RotaJakiro)(16)

目前RotaJakiro一共支持12条指令,指令码与功能的对应关系如下表所示:

CMDID

FUNCTION

0x138E3E6

Exit

0x208307A

Test

0x5CCA727

Heartbeat

0x17B1CC4

Set C2 timeout time

0x25360EA

Streal Senstive Info

0x18320e0

Upload Device Info

0x2E25992

Deliver File/Plugin

0x2CD9070

Query File/Plugin Status

0x12B3629

Delete File/Plugin Or Dir

0x1B25503

Run Plugin_0x39C93E

0x1532E65

Run Plugin_0x75A7A2

0x25D5082

Run Plugin_0x536D01

其中Run Plugin功能复用相同的代码,通过以下逻辑实现函数调用:

双头暗影魔龙(双头龙RotaJakiro)(17)

我们目前被没有捕获到这类payload,因此用Plugin_“参数”的形式来表示不同的任务。

RotaJakiro的网络通信包如下图所示,由head,key,payload三部分组成,其中header是必须的,长度为82字节,而body&payload部分是可选的。head&key采用的XOR&Rotate加密,payload采用AES&ZLIB加密压缩。

双头暗影魔龙(双头龙RotaJakiro)(18)


下面我们将通过BOT与C2的一轮交互,来说明网络流量head&key&payload的组成以及解密过程。

C2 -> BOT

双头暗影魔龙(双头龙RotaJakiro)(19)

读取前0x52字节,就是head的内容。head如何解密呢?方法很简单,逐字节左移3位,然后和0x1b异或即可,解密后得下以内容:

00000000 16 11 10 b9 03 b1 0c fb 04 20 00 00 00 08 00 e0 |...¹.±.û. .....à| 00000010 20 83 01 c2 20 64 20 01 e2 00 00 00 00 c2 0c 00 | .. d .â....Â..| 00000020 00 00 32 42 36 39 33 33 34 46 38 34 31 44 30 44 |..2B69334F841D0D| 00000030 39 46 41 30 36 35 38 45 43 33 45 32 39 46 41 44 |9FA0658EC3E29FAD| 00000040 34 39 c8 53 e6 9c 48 c4 8b 77 24 2e 02 1c 96 d9 |49ÈSæ.HÄ.w$....Ù| 00000050 81 28 ------------filed parse------------------ offset 0x09 4 bytes--->payload length offset 0x0d 2 bytes--->body length offset ox0f 4 bytes--->cmdid

通过字段解析,可知key的长度为0x8字节,payload的长度为0x20字节,要执行的指令码为0x18320e0,即上报设备信息。

从偏移0x52读取8字节就得到了keyea 9a 1a 18 18 44 26 a0,使用和head一样的解密方法,得到4c cf cb db db 39 2a 1e,它是作为AES的密钥来解密payload。

从偏移0x5a读取32字节,就得到了下面的payload:

54 c1 c3 69 00 18 31 e4 a2 5b 10 7f 67 ab d1 4b b2 7b 3d 3f b3 bc 66 6a 26 f6 f6 b3 f7 2e 66 6d

使用解密后的key做为AES-256的密钥,以CBC模式解密以上数据得下以下内容:

3b c7 f8 9b 73 2b d1 04 78 9c e3 60 60 60 d8 df d9 c1 71 56 f7 6f 00 00 13 80 04 28

第8字节起即为ZLIB压缩数据,解压得到如下内容:

08 00 00 00 bf 89 88 08 cd 2d fd 50 ------------filed parse------------------ offset 0 4 bytes--->length

解压后的payload有什么用呢?它是做为新的AES密钥,用来解密部分敏感资源信息
例如Bot在收集设备信息时,有一项是当前操作系统发行版本的信息,它是通过cat /etc/*release | uniq命令实现的。

root@debian:~# cat /etc/*release | uniq PRETTY_NAME="Debian GNU/Linux 9 (stretch)" NAME="Debian GNU/Linux" VERSION_ID="9" VERSION="9 (stretch)" ID=debian HOME_URL="https://www.debian.org/" SUPPORT_URL="https://www.debian.org/support" BUG_REPORT_URL="https://bugs.debian.org/"

cat /etc/*release | uniq这条命令正是以下密文通过新的AES密钥配合下图中的参数解密而来。

cmd ciphertxt --------------------------- 74 00 dd 79 e6 1e aa bb 99 81 7e ca d9 21 6b 81 6b d9 9d 14 45 73 6a 1c 61 cc 28 a3 0f 2b 41 5a 6b 33 8c 37 25 89 47 05 44 7e f0 6b 17 70 d8 ca

双头暗影魔龙(双头龙RotaJakiro)(20)

Bot -> C2

当BOT接收到C2的“上报设备信息”指令后,会向C2发送以下数据,可以看出key部分的值依然是ea 9a 1a 18 18 44 26 a0。

双头暗影魔龙(双头龙RotaJakiro)(21)

从上文已知解密后key值为4c cf cb db db 39 2a 1e,通过这个值将Bot发往C2的payload解密解压后,得到如下数据,正是设备的各种信息,其中有前文提到的通过cat /etc/*release | uniq获取的信息,验证了我们的分析是正确的。

双头暗影魔龙(双头龙RotaJakiro)(22)

与Torii Botnet团伙的关系

Torii僵尸网络于2018年9月20日被友商Avast曝光,对比RotaJakiro,俩者的相似之处体现在以下3方面:

1:字符串相似性

RotaJakiro&Torii的敏感资源解密后,我们发现它们复用了大量相同的命令。

1:semanage fcontext -a -t bin_t '%s' && restorecon '%s' 2:which semanage 3:cat /etc/*release 4:cat /etc/issue 5:systemctl enable 6:initctl start ... 2:流量相似性

在构造流量的过程中,大量使用常数,构造方式非常接近。

双头暗影魔龙(双头龙RotaJakiro)(23)

3:功能相似性

从安全研究人员进行逆向工程的角度来说,RotaJakiro&Torii有着相常相似的风格:使用加密算法隐藏敏感资源,都实现了相当old-school式的持久化,结构化的网络流量等。

基于这些考量,我们推测RotaJakiro和Torii出自同一个团伙之手。

冰山一角

至此RotaJakiro的逆向与溯源告一段落,但真正的工作远没结束,有许多问题依然没有答案:“RotaJakiro是怎么传播的 它的目的是什么?”,“RotaJakiro是否有特定的攻击目标,是不是APT?”,“RotaJakiro与Torii背后的黑手是谁?”......由于我们的视野有限,目前只能向安全社区分享这么多。如果社区有相关的线索,欢迎与我们联系,让我们一起Make Cyber Security Great Again。

猜您喜欢: