概述

  Symbiote由威胁情报公司BlackBerry和Intezer命名,原因是该恶意程序能够将自己隐藏在正在运行的进程或者网络流量中,像寄生虫一样耗尽受害者的资源。
  Symbiote背后的组织在2021年11开始开发该恶意程序,主要用来攻击拉丁美洲的金融部门,包括巴西银行和Caixa银行。
  Symbiote与其他Linux恶意程序不同之处在于它利用一个名为LD_PRELOAD的linux特性通过动态链接器将其加载到所有正在运行的进程中。

2. 样本详情

文件名 liblinux.so
Md5 59033839c1be695c83a68924979fab58
文件类型 Linux64共享库

3. 详细分析

3.2 隐藏文件或进程

  在linux中,所有对象都可以看作是文件,恶意程序为了隐藏自身,拦截了多个linux系统下用于操作文件的函数,为了隐藏文件或进程拦截的函数如下,函数返回值为在对隐藏文件或进程列表中的对象进行操作时函数的返回值。

函数名 目的 函数返回值
fstatat 隐藏进程 返回-1
fstatat64 隐藏进程 返回-1
statx 隐藏进程 返回-1
stat 隐藏进程 返回-1
readdir 隐藏进程或文件 返回遍历的下一个不在隐藏列表的进程或文件
readdir64 隐藏进程或文件 返回遍历的下一个不在隐藏列表的进程或文件

  在linux下进程的路径为”/proc/[pid]”,因此只要判断是否包含字符”proc”和pid是否为数字就能判断一些函数操作的对象是进程还是文件。

1. 隐藏文件

  恶意程序将需要隐藏的文件名以RC4加密算法加密并硬编码保存在程序内。在linux函数对文件操作时将路径与要隐藏的文件匹配,如果匹配程序则根据函数不同返回对应的结果,比如readdir/readdir64遍历到要隐藏的文件时跳过该文件遍历下一个文件。

隐藏进程

恶意程序读取文件”/proc/[pid]/cmdline”获取进程的命令行参数判断加载恶意程序的进程是否是进程”strace”、”javaserverx64”、”javaclientex64”和”javanodex86”。

3.3 隐藏进程网络连接

  恶意程序采用多种不同的方式来隐藏网络流量,主要有拦截fopen/fopen64函数、添加eBPF代码到原过滤器代码头部两种。两种方式隐藏的IP或者端口如下:

1
2
3
4
5
6
7
8
9
10
IP地址:
10.123.36.58
10.123.8.187
10.123.8.33
10.123.8.23
10.123.8.50
端口号:
45345
2054
32821

拦截fopen/fopen64

  如果程序尝试打开文件”/proc/net/tcp”文件,恶意程序就会逐行匹配该文件的每一行,判断是否包含指定的IP或者端口,如果不是则将其复制到临时文件,否则匹配下一行。最后返回临时文件的文件描述符,该文件已经将需要隐藏的端口或者IP地址从tcp文件中移除了。

2. 劫持eBPF数据包过滤器

  恶意程序为了能够劫持eBPF数据包过滤器拦截函数setsockopt,并判断flags是否为SO_ATTACH_FILTER确定是否使用eBPF数据包过滤器,
如果使用了eBPF数据包过滤器,恶意程序会在原eBPF过滤代码之前添加自己的字节码用于将与自身相关的网络连接相关信息从过滤器丢弃。因此使用了eBPF过滤器的一些应用或防火墙不能够获取对应的数据包从而达到隐藏网络连接的目的。

反汇编的eBPF字节码如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
[0x00] ldabsh 0,0,c
[0x01] jeq 0,800,1a00
//判断源ip地址是否是以下四个值
///0xa7b243a, [ip]10.123.36.58
///0xa7b08bb, [ip]10.123.8.187
///0xa7b0821, [ip]10.123.8.33
///0xa7b0817, [ip]10.123.8.23
// 0xa7b0832, [ip]10.123.8.50
[0x02] ldabse 0,0,1a
[0x03] jeq 0,a7b243a,35
[0x04] jeq 0,a7b08bb,34
[0x05] jeq 0,a7b0821,33
[0x6] jeq 0,a7b0817,32
[0x07] jeq 0,a7b0832,31
//判断目标地址 如果r0寄存器等于如下IP地址跳转到偏移0x38
[0x08] ldabse 0,0,1e
[0x09] jeq 0,a7b243a,2f
[0x0a] jeq 0,a7b08bb,2e
[0x0b] jeq 0,a7b0821,2d
[0x0c] jeq 0,a7b0817,2c
[0x0d] jeq 0,a7b0832,2b
//判断协议类型
[0x0e] ldabsb 0, 0, 17
[0x0f] jeq 0,84,2 //判断是否是SCTP
[0x10] jeq 0,6,1 //判断是否是TCP协议
[0x11] jeq 0,11,2800 //判断是否是UDP协议

//ipv4 flag
[0x12] ldabsh 0,0,14
[0x13] jset 0,1fff,26// 如果if (r0&0x1FFF) goto off[0x38]
[0x14]unkown opencode 0x0000000E000000B1

//判断端口?
[0x015] ldindh 0,0,e
[0x016] jeq 0,b121,22
[0x017] jeq 0,86e7,21
[0x018] jeq 0,fc1f,20
[0x019] jeq 0,6045,1f

//使用ipv4,判断totalLen是否为固定值
[0x01a] ldindh 0,0,10
[0x01b] jeq 0,b121,1a1d //45345
[0x01c] jeq 0,806,1 //2054
[0x01d] jeq 0,8035,c00 //32821

[0x1e] ldabse 0,0,1c
[0x01f] jeq 0,a7b243a,19
[0x020] jeq 0,a7b08bb,18
[0x21] jeq 0,a7b0821,17
[0x22] jeq 0,a7b0817,16
[0x23] jeq 0,a7b0832,15
[0x24] ldabse 0,0,26
[0x25] jeq 0,a7b243a,13
[0x26] jeq 0,a7b08bb,12
[0x27] jeq 0,a7b0821,11
[0x28] jeq 0,a7b0817,10
[0x29] jeq 0,a7b0832,100f

//判断是否是IPv6
[0x2a] jeq 0,86dd,f00
[0x2b] ldabsb 0, 0, 14
[0x2c] jeq 0,84,2
[0x2d] jeq 0,6,1
[0x2e] jeq 0,11,b00
//判断TCP源端口
[0x2f] ldabsh 0,0,36
[0x30] jeq 0,b121,8 //45345
[0x31] jeq 0,86e7,7 //34535
[0x32] jeq 0,fc1f,6 //64543
[0x33] jeq 0,6045,5 //24645
//判断TCP目的端口
[0x34] ldabsh 0,0,38
[0x35] jeq 0,b121,3
[0x36] jeq 0,86e7,2
[0x37] jeq 0,fc1f,1
[0x38] jeq 0,6045,100
[0x06] unkown opencode 0x06

3.4 隐藏共享库加载

  恶意程序是通过LD_PRELOAD方式被所有程序加载,如果环境变量LD_TRACE_LOADED_OBJECTS
被设置为1会导致动态链接检查工具能够检测出恶意程序被加载。

  恶意程序判断环境变量LD_TRACE_LOADED_OBJECTS是否被设置为1,如果是则调用原execve函数获取执行结果,再从已加载共享库中将liblinux.so从结果中移除从而达到隐藏自身的目的。

3.5 keylogger

  恶意程序拦截read函数并在进程满足条件的情况下执行keylogger功能。

  恶意程序执行keylogger功能需要满足的条件为加载该恶意程序的进程为终端并且符号链接以”/ssh”或”/scp”结尾。

  恶意程序还收集受害者机器上除了local接口的所有网络接口和应用程序使用的命令行。

  每个网络接口之间使用分隔符”;”分隔;最终将所有收集到的信息以一定的格式保存后使用硬编码的RC4密钥加密保存到文件”usr/include/java.h”并通过DNS协议发送到C&C服务器。

3.6 PAM后门

  PAM是一种认证模块,是Linux系统上用于用户身份验证的机制。恶意程序通过劫持PAM中的三个函数来修改身份验证逻辑,这三个函数分别是pam_set_item、pam_authenticate和pam_acct_mgmt。

  函数pam_set_item用于设置PAM相关项的信息,当传入函数的额第二个参数值为PAM_AUTHTOK(6)时,表示设置设置身份验证的密码。恶意程序拦截该函数的目的是为了获取受害者机器使用PAM身份验证的密码并将其保存到全局变量pampassword,该变量的值主要用于与硬编码的密码进行比较,恶意程序会根据比较结果执行不同的操作。

  函数pam_authenticate为PAM身份验证函数,恶意程序将受害者使用的认证与硬编码的密码suporte42caixa32进行比较,如果匹配成功则返回身份验证成功的返回值,即对于任何使用PAM作为身份验证的程序或者服务,攻击者只需要指定验证密码为suporte42caixa32和使用任意用户名就能够绕过验证而成功登录。

  如果与硬编码的密码匹配失败但是成功通过PAM身份验证,则获取受害者机器服务名、主机名、用户名和通过PAM身份验证的密码。
  恶意程序使用RC4算法加密收集到的信息并保存到文件”/usr/include/java.h”。加密信息使用的RC4加密密钥通过使用硬编码的密钥对”suporte42caixa32”加密后得出。

收集到的信息未加密前保存格式如下:

1
pam |{服务名}|{主机名}|{用户名}|{pam身份验证密码}

  函数pam_acct_mgmt用于确定用户是否有效,恶意程序为了能够使用任意用户名通过PAM服务验证,修改该函数的验证逻辑。当使用该函数来验证密码为suporte42caixa32的用户时总是返回验证成功。

3.7 DNS后门

1. 泄露信息

  恶意程序在执行PAM后门和keylogger功能时利用DNS地址A记录来泄露收集到的信息到C&C服务器而不必担心防火墙和流量规则。恶意程序调用函数uname获取操作系统相关信息,然后通过一系列运算得到hash值作为DNS地址A记录的一部分来标识受害者机器。

  恶意程序使用密钥suporte42caixa32对要泄露的数据使用RC4算法加密,由于DNS域A记录有着长度限制,只能在域名中携带少量数据。

  恶意程序采用将要发送的数据以0x20的大小分成多个数据块,然后依次拼接DNS域A记录并发送数据到C&C服务器,直接所有数据发送完。DNS域A记录中第一部分用来标识数据块的索引,索引从11111开始计数。C&C服务器通过索引再将接收的数据通过索引组合然后解密。
DNS域A记录使用的格式如下:

1
{数据库索引}.{机器标识}.{要发送的数据块}.x3206.caixi.cx

数据泄露到C&C服务器代码如下:

2. 执行shell脚本

  在受害者使用pam身份验证服务登录成功后,除了泄露收集的密码信息外,还会通过向C&C服务器发送DNS TXT记录请求来接收要执行的shell脚本。
  恶意程序将标准输入文件、标准输出文件和标准出错文件三个文件描述符重定向到空设备”/dev/null”,这样在执行脚本时不会输出任何数据。

恶意软件向C&C服务器发送的DNS TXT格式如下:

1
{机器标识}.x4206.caixa.cx

  恶意程序首先向”0.x4206.caixa.cx”获取从TXT 记录中获取ed25519
私钥签名,然后按照同样方式递增DNS域依次从TXT记录中读取数据,最后在验证ed25519签名是否正确,验证通过后使用生成的bash进程来执行shell脚本。

4. IOC

59033839c1be695c83a68924979fab58
usr/include/java.h
suporte42caixa32
x3206.caixi.cx

5. ATT&CK矩阵

Tactic ID Name Description
Execution T1059.004 Command and Scripting Interpreter: Unix Shell 执行shell脚本
Persistence T1556.003 Modify Authentication Process: Pluggable Authentication Modules 拦截PAM证模块修改认证逻辑
Privilege Escalation T1548.001 Abuse Elevation Control Mechanism: Setuid and Setgid 提权为root用户
Defense Evasion T1564.001 Hidden Files and Directories 隐藏文件
2023-11-01

⬆︎TOP