在 Linux 安全研究领域,rootkit 技术一直是攻防对抗的前沿阵地。近期开源的 Singularity rootkit 以其先进的 ftrace hooking 技术和全面的隐身能力引起了广泛关注。本文将从技术实现角度深入分析 Singularity 的架构设计、核心功能模块以及其对抗现代安全检测的机制。
1. Singularity 概述:现代内核 rootkit 的新范式
Singularity 是一个针对 Linux 6.x 内核设计的开源内核模块(LKM)rootkit,由 MatheuZSecurity 开发。与传统的 rootkit 不同,Singularity 采用了基于 ftrace 基础设施的系统调用劫持技术,而非直接修改系统调用表(sys_call_table)。这种设计选择使其在对抗基于内存完整性检查的安全工具时具有显著优势。
根据项目文档,Singularity 的设计目标是回答一个问题:"如果一个 rootkit 成功渗透并加载到系统中,它能隐藏到什么程度?" 为此,它实现了全面的隐身功能,包括:
- 进程隐藏:使任何进程对系统完全不可见
- 文件与目录隐藏:基于模式匹配隐藏文件和目录
- 网络隐身:隐藏 TCP/UDP 连接、端口和连接跟踪条目
- 权限提升:多种即时获取 root 权限的方法
- 日志清理:实时过滤内核日志和系统日志
- 自我隐藏:从模块列表和系统监控中移除自身
- 远程访问:ICMP 触发的反向 shell,自动隐藏
- 反检测:阻止 eBPF 工具、io_uring 操作,防止模块加载
2. Ftrace Hooking 实现机制
2.1 Ftrace 基础架构利用
Ftrace 是 Linux 内核内置的跟踪框架,原本用于性能分析和调试。Singularity 巧妙地利用 ftrace 的 function tracer 功能来劫持系统调用。与传统的 sys_call_table 修改相比,ftrace hooking 具有以下优势:
- 无需修改内核内存布局:ftrace 提供了合法的 hook 接口
- 绕过内存完整性检查:不直接修改关键数据结构
- 动态 hook 管理:可以动态添加和移除 hook
- 内核版本兼容性:ftrace 接口相对稳定
Singularity 的 ftrace hooking 实现位于ftrace_helper.h中,通过定义HOOK宏来简化 hook 的创建和管理。每个 hook 包含三个关键字段:name(函数名)、function(hook 函数)和original(原始函数指针)。
2.2 多架构支持
Singularity 支持 x86_64 和 ia32 两种架构,通过条件编译处理不同架构的系统调用约定:
#if defined(CONFIG_X86_64) && (LINUX_VERSION_CODE >= KERNEL_VERSION(4,17,0))
#define PTREGS_SYSCALL_STUBS 1
#endif
对于 x86_64 架构,它使用 ptregs 风格的参数传递;对于 ia32 架构,则使用传统的参数传递方式。这种设计确保了在不同架构上的兼容性。
2.3 Hook 保护机制
为了防止递归调用和 hook 被意外移除,Singularity 实现了 hook 保护机制:
- 递归检测:在 hook 函数中检查调用上下文,避免无限递归
- ftrace 控制保护:拦截所有尝试禁用 ftrace 的操作
- 智能缓存:对频繁操作使用 PID 缓存,减少性能开销
3. 核心功能模块分析
3.1 进程隐藏实现
进程隐藏是 rootkit 最基本也是最关键的功能之一。Singularity 通过多个层次的 hook 实现了全面的进程隐藏:
目录列表过滤:hook getdents和getdents64系统调用,从目录列表中过滤隐藏进程的 PID 目录。当用户执行ls /proc或相关命令时,隐藏进程的目录条目被移除。
进程信息隐藏:hook stat、lstat、statx、newfstatat等系统调用,当查询隐藏进程的信息时返回ENOENT错误。这包括:
kill信号 0 检查(返回 ESRCH)getsid、getpgid、getpgrp(返回 ESRCH)sched_getaffinity、sched_getparam等调度相关调用pidfd_open(返回 ESRCH)
进程计数调整:hook sysinfo系统调用,调整报告的总进程数,使其与实际可见进程数一致。
子进程跟踪:通过sched_process_fork tracepoint hook 自动跟踪隐藏进程的子进程,确保整个进程树都被隐藏。
3.2 文件系统隐藏
文件隐藏采用模式匹配机制,用户可以在include/hiding_directory_def.h中配置要隐藏的文件和目录模式。实现机制包括:
目录列表过滤:与进程隐藏类似,hook getdents和getdents64过滤匹配模式的文件和目录。
文件访问阻止:hook openat系统调用,阻止对隐藏文件的访问尝试。
目录切换阻止:hook chdir系统调用,防止用户切换到隐藏目录。
符号链接解析阻止:hook readlinkat系统调用,阻止对隐藏文件符号链接的解析。
3.3 网络连接隐藏
网络隐身是 Singularity 的亮点功能之一,它从多个层次隐藏网络连接:
/proc/net 接口过滤:hook tcp4_seq_show、tcp6_seq_show、udp4_seq_show、udp6_seq_show等函数,从/proc/net/tcp、/proc/net/tcp6、/proc/net/udp、/proc/net/udp6中过滤隐藏的连接。
原始数据包过滤:hook tpacket_rcv函数,在原始套接字层面丢弃与隐藏连接相关的数据包。
连接跟踪过滤:hook read系统调用,过滤/proc/net/nf_conntrack中的连接跟踪条目。
Netlink 消息过滤:hook recvmsg系统调用,过滤 SOCK_DIAG 和 NETFILTER netlink 消息,这些消息被ss、conntrack等工具使用。
3.4 日志清理机制
Singularity 实现了全面的日志清理功能,从多个接口过滤敏感信息:
内核日志接口:
/proc/kmsg:通过 read hook 过滤 dmesg 输出do_syslog:hook 内核的 syslog 实现,过滤 klogctl () 输出journalctl -k:通过 write hook 过滤 journald 的内核日志输出
系统日志文件:通过 read hook 过滤/var/log/kern.log、syslog、auth.log等文件中的敏感内容。
调试接口:过滤/sys/kernel/debug/tracing/*、/proc/kallsyms、/proc/kcore、/proc/vmallocinfo等调试接口的输出。
过滤的关键词包括:taint、journal、singularity、Singularity、matheuz、zer0t、kallsyms_lookup_name、obliviate、hook、hooked_、constprop、clear_taint、ftrace_helper、fh_install、fh_remove等。
3.5 权限提升机制
Singularity 提供了两种权限提升方法:
环境变量触发:设置MAGIC=mtz环境变量后执行 bash,自动获得 root 权限。
信号触发:向进程发送信号 59(kill -59 <PID>),触发权限提升。
权限提升的实现基于commit_creds(prepare_kernel_cred(0)),将当前进程的凭证设置为 root 凭证。
4. ICMP 触发反向 shell 与 SELinux 绕过
4.1 ICMP 触发机制
Singularity 实现了一个隐蔽的远程访问机制:ICMP 触发的反向 shell。当收到特定的 ICMP 数据包时,rootkit 会启动一个反向 shell 连接到攻击者控制的服务器。
实现要点:
- ICMP 处理 hook:hook
icmp_rcv函数,检查接收到的 ICMP 数据包 - 触发条件:特定的 ICMP 类型和代码组合
- 自动隐藏:反向 shell 进程自动被隐藏
- 子进程跟踪:shell 创建的所有子进程自动被跟踪和隐藏
4.2 SELinux 绕过技术
在 SELinux 强制模式下,Singularity 能够自动绕过 SELinux 限制:
- SELinux 模式检测:检查当前 SELinux 模式(强制、宽容、禁用)
- 临时模式切换:在 ICMP 触发时临时切换到宽容模式
- 权限恢复:执行完特权操作后恢复原始模式
- 审计日志过滤:过滤 SELinux 相关的审计消息
这种设计使得 Singularity 即使在严格的安全策略下也能执行特权操作。
5. 反检测与自我保护
5.1 eBPF 检测阻止
Singularity 通过 hook bpf系统调用阻止 eBPF-based 检测工具:
BPF_PROG_LOAD:阻止 tracepoint、kprobe、tracing、LSM 等类型的 eBPF 程序加载BPF_ITER_CREATE、BPF_PROG_GET_NEXT_ID、BPF_MAP_GET_NEXT_ID:阻止 eBPF 迭代器和信息查询BPF_RAW_TRACEPOINT_OPEN、BPF_LINK_CREATE:阻止原始 tracepoint 和链接创建- 所有来自隐藏进程的 BPF 操作都被阻止
5.2 io_uring 保护
io_uring 是 Linux 的异步 I/O 接口,可能被用于绕过 ftrace 控制。Singularity 通过 hook io_uring_enter系统调用,并实现智能的 PID 缓存(1 秒缓存)来防止 io_uring bypass。
5.3 模块加载阻止
通过 hook init_module和finit_module系统调用,阻止新的内核模块加载,防止安全工具加载检测模块。
5.4 自我隐藏机制
加载后,Singularity 自动从以下位置隐藏自身:
lsmod输出/proc/modules/sys/module- 内核 taint 标志被清除
6. 性能优化与架构设计
6.1 智能缓存机制
为了减少性能开销,Singularity 实现了多个缓存机制:
PID 缓存:对频繁检查的操作(如 io_uring 保护)使用 1 秒的 PID 缓存,避免重复的进程扫描。
连接跟踪缓存:网络连接隐藏使用缓存来加速连接匹配。
文件模式缓存:文件隐藏模式被缓存以提高匹配速度。
6.2 多版本内核支持
Singularity 支持多个 Linux 6.x 内核版本,包括:
- 6.8.0-79-generic(Ubuntu 22.04/24.04)
- 6.12.0-174.el10.x86_64(CentOS Stream 10)
- 6.12.48+deb13-amd64(Debian 13)
- 6.17.8-300.fc43.x86_64(Fedora 43)
- 6.17.0-8-generic(Ubuntu 25.10)
通过条件编译和版本检测,确保在不同内核版本上的兼容性。
7. 安全影响与防御建议
7.1 检测挑战
Singularity 的先进设计给安全检测带来了多重挑战:
- 内存完整性检查绕过:不修改 sys_call_table,传统的内存完整性检查可能失效
- 行为隐蔽性:全面的日志过滤和进程隐藏使行为分析困难
- 网络隐身:多层次的网络连接隐藏使网络监控失效
- 反检测机制:主动阻止 eBPF 和 io_uring 等检测工具
7.2 防御建议
基于 Singularity 的技术特点,建议采取以下防御措施:
内核完整性监控:
- 监控 ftrace 配置的异常修改
- 检查内核函数指针的异常跳转
- 使用硬件支持的完整性测量(如 TPM、Secure Boot)
行为异常检测:
- 监控进程计数的异常变化
- 检测网络连接统计的异常
- 分析系统调用模式的异常
深度检测技术:
- 使用基于硬件的内存扫描
- 实施定期的离线内存分析
- 部署基于虚拟化的安全监控
安全配置强化:
- 限制内核模块加载权限
- 启用 SELinux 强制模式并定期审计
- 配置严格的网络过滤规则
8. 研究意义与伦理考量
Singularity 作为一个开源研究项目,具有重要的安全研究价值:
- 技术探索:展示了现代 rootkit 可能达到的隐身水平
- 防御演进:推动安全社区开发更先进的检测技术
- 教育价值:为安全研究人员提供内核安全的学习资源
然而,必须强调伦理和法律边界:
- 仅用于授权的安全研究和教育目的
- 在隔离的测试环境中使用
- 遵守相关法律法规和道德准则
结论
Singularity 代表了 Linux 内核 rootkit 技术的新高度,其基于 ftrace 的 hook 实现、全面的隐身功能和先进的反检测机制展示了现代恶意软件可能达到的复杂程度。对于安全研究人员来说,深入理解这类工具的实现机制是开发有效防御措施的前提。对于系统管理员和安全工程师,了解这些技术有助于更好地保护系统安全。
正如项目作者所言,Singularity 的存在是为了回答 "一个 rootkit 能隐藏到什么程度" 的问题。这个问题的答案不仅关乎攻击技术,更关乎防御能力的持续演进。在攻防对抗的永恒循环中,只有不断深入理解对手的技术,才能构建更强大的防御体系。
资料来源: