Symbiote: 几乎不可能被检测到的 Linux Rootkit 深度分析
· 6 分钟阅读 · @admin

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 文件获取进程的命令行参数,判断是否为以下特定进程名称:
stracejavaserverx64javaclientex64javanodex86
这些很可能是恶意程序自身或相关组件的伪装名称。当检测到这些进程时,Symbiote 会隐藏其在系统进程列表中的存在。

3.2 网络连接隐藏机制
Symbiote 采用多种技术手段来隐藏网络连接,主要包括:
- 拦截
fopen/fopen64函数进行文件内容过滤 - 注入 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 会拦截该操作并执行以下流程:
- 逐行读取原文件内容
- 检查每一行是否包含待隐藏的 IP 地址或端口号
- 如果不包含隐藏标识,则将该行复制到临时文件
- 如果包含隐藏标识,则跳过该行
- 最后返回临时文件的文件描述符
通过这种方式,调用程序获得的是一个经过过滤的 TCP 连接列表,其中所有与恶意程序相关的网络连接都已被移除。

3.2.3 劫持 eBPF 数据包过滤器
Symbiote 通过拦截 setsockopt 函数来劫持 eBPF 数据包过滤器。当检测到 flags 参数为 SO_ATTACH_FILTER 时,恶意程序会:
- 在原有 eBPF 过滤代码的前面插入自己的字节码
- 这些自定义字节码会将与恶意程序相关的网络连接数据包直接丢弃
- 将修改后的过滤器应用到套接字上
这种技术的高级之处在于,即使用了 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 拦截相关系统调用并执行以下操作:
- 检测
LD_TRACE_LOADED_OBJECTS环境变量是否被设置为 1 - 如果是,则调用原始的
execve函数获取执行结果 - 从已加载共享库列表中移除
liblinux.so - 返回经过过滤的结果,从而隐藏自身的存在

这种技术使得即使用户使用 ldd 等工具检查程序依赖关系,也无法发现 Symbiote 的存在。
3.4 键盘记录器(Keylogger)
3.4.1 键盘记录触发条件
Symbiote 拦截 read 系统调用,并在满足特定条件时启用键盘记录功能:

键盘记录功能的触发条件包括:
- 加载恶意程序的进程必须是终端进程
- 进程的符号链接路径必须以
/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 拦截此函数的目的是:
- 获取用户通过 PAM 身份验证时输入的密码
- 将密码保存到全局变量
pampassword中 - 该变量后续会与硬编码密码进行比较,根据比较结果执行不同操作

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 采用以下策略:
- 使用密钥
suporte42caixa32对要泄露的数据进行 RC4 加密 - 将加密后的数据按 32 字节(0x20)大小分割成多个数据块
- 依次通过 DNS A 记录查询发送到 C&C 服务器
- 数据块索引从 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
远程命令执行流程:
- 首先向
0.x4206.caixa.cx发送 DNS TXT 查询,从 TXT 记录中获取 Ed25519 私钥签名 - 按照同样方式递增 DNS 域名序号,依次从 TXT 记录中读取脚本内容数据块
- 验证 Ed25519 签名是否正确,确保命令来自合法的 C&C 服务器
- 签名验证通过后,生成 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,其主要特点包括:
- 深度隐藏:通过 LD_PRELOAD 注入所有进程,劫持系统调用隐藏文件、进程和网络连接
- PAM 后门:植入万能密码后门,同时窃取合法用户凭证
- 隐蔽通信:利用 DNS 协议进行 C2 通信,绕过传统防火墙检测
- 持久化强:通过环境变量修改实现开机自启动和进程注入
- 多重加密:使用 RC4 加密保护配置和窃取的数据
- eBPF 滥用:劫持 eBPF 过滤器,在内核层面隐藏网络流量
防御建议:
- 定期检查
/etc/environment、/etc/profile等文件中的 LD_PRELOAD 配置 - 监控异常的 DNS 查询行为,特别是长域名和高频查询
- 使用文件完整性监控工具检测 PAM 模块的异常加载
- 部署 EDR 解决方案检测异常的系统调用拦截行为
- 定期审计系统中的可疑共享库文件

