8-BitQuest
菜单
[安全研究]

Symbiote: 几乎不可能被检测到的 Linux Rootkit 深度分析

· 6 分钟阅读 · @admin

Symbiote Linux rootkit 像素封面

Symbiote 是由威胁情报公司 BlackBerry 和 Intezer 发现并命名的高级 Linux rootkit。之所以命名为 “Symbiote”(共生体),是因为该恶意程序能够将自己隐藏在正在运行的进程和网络流量中,像寄生虫一样潜伏在受害者系统中。

根据研究报告,Symbiote 背后的威胁组织在 2021 年 11 月开始开发该恶意程序,主要攻击目标是拉丁美洲的金融机构,包括巴西银行(Banco do Brasil)和 Caixa 银行。

Symbiote 与其他 Linux 恶意程序最显著的不同之处在于:它利用 Linux 的 LD_PRELOAD 环境变量特性,通过动态链接器将自身注入到系统中所有正在运行的进程中,从而实现深度隐藏和持久化控制。

2. 样本详情

分析样本的基本信息如下:

属性 值
文件名 liblinux.so
MD5 哈希值 59033839c1be695c83a68924979fab58
文件类型 ELF 64-bit LSB shared object (动态链接库)
架构 x86-64
功能描述 恶意共享库,通过 LD_PRELOAD 加载

3. 详细分析

3.1 文件和进程隐藏机制

在 Linux 系统中,所有对象都可以抽象为文件。为了隐藏自身存在,Symbiote 拦截了多个 Linux 系统调用函数,特别是用于文件和目录操作的函数。当对这些隐藏对象进行操作时,函数会返回特定的值来掩盖其存在。

3.1.1 拦截的系统调用函数

函数名 目的 隐藏行为
fstatat 隐藏进程 返回 -1,模拟文件不存在
fstatat64 隐藏进程 返回 -1,模拟文件不存在
statx 隐藏进程 返回 -1,模拟文件不存在
stat 隐藏进程 返回 -1,模拟文件不存在
readdir 隐藏进程或文件 跳过隐藏列表中的对象,返回下一个合法条目
readdir64 隐藏进程或文件 跳过隐藏列表中的对象,返回下一个合法条目

3.1.2 进程识别机制

在 Linux 系统中,进程的路径格式为 /proc/[pid]。Symbiote 通过以下方式判断函数操作的对象类型:

  • 检查路径是否包含字符串 “proc”
  • 验证路径中的 PID 部分是否为数字

如果满足上述条件,则认为操作对象为进程,否则视为普通文件。这种精确识别使得 Symbiote 能够有选择地隐藏特定的进程或文件。

3.1.3 文件隐藏实现

恶意程序将需要隐藏的文件名使用 RC4 加密算法加密后硬编码在程序内部。当 Linux 函数进行文件操作时,会将路径与待隐藏的文件列表进行匹配:

  • 对于 readdir/readdir64 函数:当遍历到要隐藏的文件时,直接跳过该文件,继续返回下一个文件
  • 对于 stat 系列函数:返回错误码,模拟文件不存在

3.1.4 进程隐藏实现

Symbiote 通过读取 /proc/[pid]/cmdline 文件获取进程的命令行参数,判断是否为以下特定进程名称:

  • strace
  • javaserverx64
  • javaclientex64
  • javanodex86

这些很可能是恶意程序自身或相关组件的伪装名称。当检测到这些进程时,Symbiote 会隐藏其在系统进程列表中的存在。

3.2 网络连接隐藏机制

Symbiote 采用多种技术手段来隐藏网络连接,主要包括:

  1. 拦截 fopen/fopen64 函数进行文件内容过滤
  2. 注入 eBPF 代码到现有的数据包过滤器中

这两种方式隐藏的 IP 地址和端口如下:

3.2.1 隐藏的网络标识

IP 地址列表:

  • 10.123.36.58
  • 10.123.8.187
  • 10.123.8.33
  • 10.123.8.23
  • 10.123.8.50

端口号列表:

  • 45345
  • 2054
  • 32821

这些网络标识很可能是 C&C 服务器地址或恶意程序使用的通信端口。

3.2.2 拦截文件操作函数

当任何程序尝试打开 /proc/net/tcp 文件时,Symbiote 会拦截该操作并执行以下流程:

  1. 逐行读取原文件内容
  2. 检查每一行是否包含待隐藏的 IP 地址或端口号
  3. 如果不包含隐藏标识,则将该行复制到临时文件
  4. 如果包含隐藏标识,则跳过该行
  5. 最后返回临时文件的文件描述符

通过这种方式,调用程序获得的是一个经过过滤的 TCP 连接列表,其中所有与恶意程序相关的网络连接都已被移除。

3.2.3 劫持 eBPF 数据包过滤器

Symbiote 通过拦截 setsockopt 函数来劫持 eBPF 数据包过滤器。当检测到 flags 参数为 SO_ATTACH_FILTER 时,恶意程序会:

  1. 在原有 eBPF 过滤代码的前面插入自己的字节码
  2. 这些自定义字节码会将与恶意程序相关的网络连接数据包直接丢弃
  3. 将修改后的过滤器应用到套接字上

这种技术的高级之处在于,即使用了 eBPF 过滤器的应用程序或防火墙也无法获取到被隐藏的数据包,从而实现更深层的网络隐藏。

3.2.4 eBPF 字节码分析

反汇编后的 eBPF 字节码如下:

[0x00] ldabsh 0,0,c              // 加载EtherType字段
[0x01] jeq 0,800,1a00            // 判断是否为IPv4

// 检查源IP地址是否为以下值
// 0xa7b243a = 10.123.36.58
// 0xa7b08bb = 10.123.8.187
// 0xa7b0821 = 10.123.8.33
// 0xa7b0817 = 10.123.8.23
// 0xa7b0832 = 10.123.8.50
[0x02] ldabse 0,0,1a             // 加载源IP地址
[0x03] jeq 0,a7b243a,35          // 匹配10.123.36.58
[0x04] jeq 0,a7b08bb,34          // 匹配10.123.8.187
[0x05] jeq 0,a7b0821,33          // 匹配10.123.8.33
[0x06] jeq 0,a7b0817,32          // 匹配10.123.8.23
[0x07] jeq 0,a7b0832,31          // 匹配10.123.8.50

// 检查目标IP地址
[0x08] ldabse 0,0,1e             // 加载目标IP地址
[0x09] jeq 0,a7b243a,2f          // 匹配10.123.36.58
[0x0a] jeq 0,a7b08bb,2e          // 匹配10.123.8.187
[0x0b] jeq 0,a7b0821,2d          // 匹配10.123.8.33
[0x0c] jeq 0,a7b0817,2c          // 匹配10.123.8.23
[0x0d] jeq 0,a7b0832,2b          // 匹配10.123.8.50

// 检查协议类型
[0x0e] ldabsb 0, 0, 17           // 加载协议字段
[0x0f] jeq 0,84,2                // 判断是否为SCTP
[0x10] jeq 0,6,1                 // 判断是否为TCP
[0x11] jeq 0,11,2800             // 判断是否为UDP

// 检查IPv4分片标志
[0x12] ldabsh 0,0,14             // 加载IPv4标志字段
[0x13] jset 0,1fff,26            // 检查是否为分片包

// 检查源端口(IPv4)
[0x15] ldindh 0,0,e              // 加载源端口
[0x16] jeq 0,b121,22             // 匹配端口45345
[0x17] jeq 0,86e7,21             // 匹配端口34535
[0x18] jeq 0,fc1f,20             // 匹配端口64543
[0x19] jeq 0,6045,1f             // 匹配端口24645

// 检查总长度
[0x1a] ldindh 0,0,10             // 加载IP总长度
[0x1b] jeq 0xb121,1a1d           // 匹配长度45345
[0x1c] jeq 0,806,1               // 匹配长度2054
[0x1d] jeq 0,8035,c00            // 匹配长度32821

// IPv6协议检查
[0x2a] jeq 0,86dd,f00            // 判断是否为IPv6
[0x2b] ldabsb 0, 0, 14           // IPv6协议字段
[0x2c] jeq 0,84,2                // IPv6 SCTP
[0x2d] jeq 0,6,1                 // IPv6 TCP
[0x2e] jeq 0,11,b00              // IPv6 UDP

// 检查TCP源端口(IPv6)
[0x2f] ldabsh 0,0,36             // 加载IPv6 TCP源端口
[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目的端口(IPv6)
[0x34] ldabsh 0,0,38             // 加载IPv6 TCP目的端口
[0x35] jeq 0,b121,3              // 匹配45345
[0x36] jeq 0,86e7,2              // 匹配34535
[0x37] jeq 0,fc1f,1              // 匹配64543
[0x38] jeq 0,6045,100            // 匹配24645

这些 eBPF 字节码会在数据包到达用户空间应用程序之前就将其过滤掉,实现了深层的网络隐藏。

3.3 共享库加载隐藏

3.3.1 LD_PRELOAD 检测绕过

Symbiote 通过 LD_PRELOAD 环境变量被所有程序加载,但这也带来一个问题:当环境变量 LD_TRACE_LOADED_OBJECTS 被设置为 1 时,动态链接检查工具(如 ldd)能够检测到恶意程序的存在。

为了绕过这种检测,Symbiote 拦截相关系统调用并执行以下操作:

  1. 检测 LD_TRACE_LOADED_OBJECTS 环境变量是否被设置为 1
  2. 如果是,则调用原始的 execve 函数获取执行结果
  3. 从已加载共享库列表中移除 liblinux.so
  4. 返回经过过滤的结果,从而隐藏自身的存在

这种技术使得即使用户使用 ldd 等工具检查程序依赖关系,也无法发现 Symbiote 的存在。

3.4 键盘记录器(Keylogger)

3.4.1 键盘记录触发条件

Symbiote 拦截 read 系统调用,并在满足特定条件时启用键盘记录功能:

键盘记录功能的触发条件包括:

  1. 加载恶意程序的进程必须是终端进程
  2. 进程的符号链接路径必须以 /ssh 或 /scp 结尾

这意味着 Symbiote 主要针对通过 SSH 或 SCP 连接的会话进行键盘记录,而非本地终端会话。

3.4.2 信息收集与存储

除了键盘记录外,Symbiote 还会收集以下信息:

  • 受害者机器上除本地接口(lo)外的所有网络接口信息
  • 应用程序使用的命令行参数

收集到的信息格式化后:

  • 网络接口之间使用分号 ; 分隔
  • 使用硬编码的 RC4 密钥进行加密
  • 保存到文件 /usr/include/java.h
  • 通过 DNS 协议发送到 C&C 服务器

这种多渠道的信息泄露方式确保了即使某个通道被阻断,攻击者仍能获取收集到的数据。

3.5 PAM 后门机制

3.5.1 PAM 函数劫持概述

PAM(Pluggable Authentication Modules)是 Linux 系统上用于用户身份验证的模块化机制。Symbiote 通过劫持 PAM 中的三个关键函数来修改身份验证逻辑:

  • pam_set_item:设置 PAM 相关项信息
  • pam_authenticate:执行用户身份验证
  • pam_acct_mgmt:管理用户账户

3.5.2 密码窃取机制

劫持 pam_set_item 函数:

该函数用于设置 PAM 相关项的信息。当传入的第二个参数值为 PAM_AUTHTOK(值为 6)时,表示正在设置身份验证密码。Symbiote 拦截此函数的目的是:

  1. 获取用户通过 PAM 身份验证时输入的密码
  2. 将密码保存到全局变量 pampassword 中
  3. 该变量后续会与硬编码密码进行比较,根据比较结果执行不同操作

3.5.3 万能密码后门

劫持 pam_authenticate 函数:

这是 PAM 身份验证的核心函数。Symbiote 将用户输入的密码与硬编码密码 suporte42caixa32 进行比较:

  • 匹配成功:直接返回身份验证成功,攻击者可以使用密码 suporte42caixa32 和任意用户名绕过验证
  • 匹配失败:继续执行正常的 PAM 身份验证流程

这种设计使得攻击者可以绕过任何使用 PAM 进行身份验证的程序或服务,包括 SSH、login、sudo 等。

3.5.4 合法密码窃取

如果用户密码与硬编码密码不匹配,但通过正常的 PAM 身份验证,Symbiote 会收集以下信息:

  • 服务名称
  • 主机名
  • 用户名
  • 通过 PAM 验证的密码

收集到的信息使用 RC4 算法加密后保存到文件 /usr/include/java.h。RC4 加密密钥是通过对硬编码密码 suporte42caixa32 进行加密处理得出的。

信息收集格式:

pam |{服务名}|{主机名}|{用户名}|{PAM验证密码}

3.5.5 账户管理绕过

劫持 pam_acct_mgmt 函数:

该函数用于确定用户账户是否有效。Symbiote 修改了其验证逻辑,当检测到密码为 suporte42caixa32 时,无论用户名是什么,都直接返回验证成功。

这进一步强化了万能密码后门的功能,确保攻击者可以使用任意用户名和硬编码密码成功登录系统。

3.6 DNS 后门通信

3.6.1 DNS 信息泄露机制

Symbiote 利用 DNS 协议的 A 记录查询来泄露收集到的敏感信息到 C&C 服务器。这种方法的显著优势是可以绕过大多数防火墙和网络流量检测规则,因为 DNS 查询在大多数网络环境中都是被允许的。

受害者机器标识生成:

恶意程序调用 uname() 函数获取操作系统相关信息,然后通过一系列哈希运算生成一个唯一标识符,作为 DNS 查询域名的一部分来标识特定的受害者机器。

数据加密与分块:

由于 DNS 域名存在长度限制,无法在单次查询中传输大量数据,Symbiote 采用以下策略:

  1. 使用密钥 suporte42caixa32 对要泄露的数据进行 RC4 加密
  2. 将加密后的数据按 32 字节(0x20)大小分割成多个数据块
  3. 依次通过 DNS A 记录查询发送到 C&C 服务器
  4. 数据块索引从 11111 开始计数,C&C 服务器通过索引重新组装数据

DNS 查询格式:

{数据块索引}.{机器标识}.{数据块内容}.x3206.caixi.cx

3.6.2 执行远程 Shell 脚本

在受害者使用 PAM 身份验证服务成功登录后,除了泄露收集的密码信息外,Symbiote 还会通过向 C&C 服务器发送 DNS TXT 记录请求来接收要执行的 shell 脚本。

为了隐蔽执行,恶意程序将标准输入(stdin)、标准输出(stdout)和标准错误(stderr)三个文件描述符全部重定向到空设备 /dev/null,确保在执行脚本时不会产生任何可见输出。

DNS TXT 请求格式:

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

远程命令执行流程:

  1. 首先向 0.x4206.caixa.cx 发送 DNS TXT 查询,从 TXT 记录中获取 Ed25519 私钥签名
  2. 按照同样方式递增 DNS 域名序号,依次从 TXT 记录中读取脚本内容数据块
  3. 验证 Ed25519 签名是否正确,确保命令来自合法的 C&C 服务器
  4. 签名验证通过后,生成 bash 子进程执行接收到的 shell 脚本

这种机制为攻击者提供了灵活的远程控制能力,可以动态下发各种恶意指令,同时通过签名验证防止命令被劫持或篡改。

4. 威胁指标(IOCs)

本节汇总了 Symbiote rootkit 相关的威胁指标(Indicators of Compromise),可用于检测和防御此类威胁。

4.1 文件哈希值

MD5:    59033839c1be695c83a68924979fab58
SHA256: [如有可补充]

4.2 可疑文件路径

/usr/include/java.h          # 存储窃取的凭证和键盘记录
liblinux.so                  # 恶意共享库主体

4.3 硬编码凭证

万能后门密码:     suporte42caixa32
RC4 加密密钥:     suporte42caixa32

4.4 网络威胁指标

C&C 域名:

x3206.caixi.cx               # 用于数据泄露
x4206.caixa.cx               # 用于远程命令执行

隐藏的 IP 地址:

10.123.36.58
10.123.8.187
10.123.8.33
10.123.8.23
10.123.8.50

隐藏的端口号:

45345
2054
32821

4.5 伪装进程名称

Symbiote 可能会伪装成以下进程名称:

strace              # 系统调用跟踪工具伪装
javaserverx64       # Java 服务器伪装
javaclientex64      # Java 客户端伪装
javanodex86         # Java 节点伪装

5. MITRE ATT&CK 框架映射

下表将 Symbiote 的恶意行为映射到 MITRE ATT&CK 框架,便于安全团队理解其攻击模式并制定相应的防御策略。

战术 (Tactic) 技术 ID 技术名称 (Technique Name) 在 Symbiote 中的实现
执行 (Execution) T1059.004 Command and Scripting Interpreter: Unix Shell 通过 DNS TXT 记录接收并执行远程 Shell 脚本
持久化 (Persistence) T1574.006 Hijack Execution Flow: LD_PRELOAD 利用 LD_PRELOAD 环境变量实现自动加载
T1556.003 Modify Authentication Process: Pluggable Authentication Modules 劫持 PAM 认证模块,植入后门
权限提升 (Privilege Escalation) T1548.001 Abuse Elevation Control Mechanism: Setuid and Setgid 需要 root 权限进行 LD_PRELOAD 注入
防御规避 (Defense Evasion) T1564.001 Hide Artifacts: Hidden Files and Directories 隐藏恶意文件、进程和网络连接
T1070.006 Indicator Removal: Hide Network Traffic 通过 eBPF 和文件过滤隐藏网络流量
T1112 Modify Registry (类似机制) 修改 LD_PRELOAD 环境变量实现进程注入
T1027 Obfuscated Files or Information 使用 RC4 加密算法加密收集的数据和配置信息
T1014 Rootkit 实现完整的 Linux rootkit 功能
凭证访问 (Credential Access) T1056.001 Input Capture: Keylogging 记录 SSH/SCP 会话的键盘输入
T1556.003 Modify Authentication Process: PAM 窃取通过 PAM 认证的用户密码
命令与控制 (C&C) T1071.004 Application Layer Protocol: DNS 使用 DNS A 记录和 TXT 记录进行 C2 通信
T1573.001 Encrypted Channel: Symmetric Cryptography 使用 RC4 算法加密 C2 通信数据
T1008 Fallback Channels 同时使用文件存储和 DNS 通道确保数据传输
数据窃取 (Exfiltration) T1041 Exfiltration Over C2 Channel 通过 DNS 协议泄露收集的凭证和键盘记录

总结

Symbiote 是一个技术复杂、隐蔽性极强的 Linux rootkit,其主要特点包括:

  1. 深度隐藏:通过 LD_PRELOAD 注入所有进程,劫持系统调用隐藏文件、进程和网络连接
  2. PAM 后门:植入万能密码后门,同时窃取合法用户凭证
  3. 隐蔽通信:利用 DNS 协议进行 C2 通信,绕过传统防火墙检测
  4. 持久化强:通过环境变量修改实现开机自启动和进程注入
  5. 多重加密:使用 RC4 加密保护配置和窃取的数据
  6. eBPF 滥用:劫持 eBPF 过滤器,在内核层面隐藏网络流量

防御建议:

  • 定期检查 /etc/environment、/etc/profile 等文件中的 LD_PRELOAD 配置
  • 监控异常的 DNS 查询行为,特别是长域名和高频查询
  • 使用文件完整性监控工具检测 PAM 模块的异常加载
  • 部署 EDR 解决方案检测异常的系统调用拦截行为
  • 定期审计系统中的可疑共享库文件

更多文章