Ghosts no longer haunt the shell — they reside in the kernel.
A stealth-loaded, signal-driven LKM rootkit for total control beneath the surface.
Click to collapse/expand
"In a system without borders, even the kernel can be haunted."
GhostInTheKernel is a stealthy and modular Loadable Kernel Module (LKM) rootkit for Linux, written in C.
It was designed as a proof-of-concept for advanced kernel-level concealment, command and control (C2), and privilege escalation — all controlled through POSIX signals.
Inspired by cyberpunk philosophy and systems introspection, this project explores how far one can manipulate visibility, authority, and persistence in a post-userland environment.
GhostInTheKernel offers a covert presence inside the Linux kernel.
From syscall hijacking and selective process hiding to persistent module loading and signal-driven privilege escalation, it provides a foundation for red teaming, kernel experimentation, and low-level offensive research.
The rootkit interacts silently with its environment via signals, remaining invisible to common tools like ps, lsmod, netstat, and dmesg. Its modular architecture and clean API make it extendable and maintainable — even under scrutiny.
GhostInTheKernel hooks a wide array of Linux syscalls across multiple files:
- File access:
access,faccessat,faccessat2 - Permissions & ownership:
chmod,chown,fchmodat,fchownat,chdir,chroot - Execution:
execve,execveat,uselib - Directory listing:
getdents,getdents64 - Kernel accounting:
acct,quotactl,syslog - Process signals:
kill,tkill,tgkill,pidfd_open - Module loading:
init_module,finit_module - Mounting:
mount,umount2,pivot_root,move_mount, etc. - File management:
open,unlink,rename,mknod,mkdir,truncate, etc.
| Signal | Code | Purpose |
|---|---|---|
SIGROOT |
42 | Grants root privileges to the calling process (with correct PID) |
SIGHIDE |
43 | Hides the calling process from userland tools |
SIGSHOW |
44 | Unhides a previously hidden process |
SIGAUTH |
45 | Marks a process as authorized to bypass hiding |
SIGMODHIDE |
46 | Removes the rootkit from /proc/modules and dmesg |
SIGMODSHOW |
47 | Makes the rootkit module visible again |
SIGPORTHIDE |
48 | Adds a port to the hidden port list |
SIGPORTSHOW |
49 | Removes a port from the hidden list |
The function is_process_authorized() uses a linked list (authorized_pids_list) to determine which processes can bypass the rootkit's hiding mechanisms.
The hide_module() function removes the rootkit from kernel module lists and obfuscates any traceable taints or dependencies.
Intercepting getdents64 allows selective hiding of entries in /proc/, including those related to the rootkit itself.
Using net hooks like tcp4_seq_show_hooked, the rootkit hides C2-related open ports from /proc/net and similar entries.
The list hidden_pids_list and the function is_pid_hidden() ensure that select processes remain invisible to userland.
GhostInTheKernel ensures persistence via:
- Copying the module to
/lib/modules/rootkit_mod.ko - Creating a script at
/etc/local.d/rootkit_load.startwith the commandinsmod /lib/modules/rootkit_mod.ko
This is fully compatible with OpenRC-based systems.
- Support for
systemdunit persistence - Firmware-level persistence exploration
The SIGROOT signal triggers give_root(), which uses prepare_creds() and commit_creds() to set UID/GID = 0 for the calling process.
- On load:
rootkit_init()installs syscall/net hooks and hides the module - On unload:
rootkit_exit()restores everything and clears hidden state
"In a system without borders, even the kernel can be haunted."
kill -42 <pid> # Gain root privileges
kill -43 <pid> # Hide a process
kill -44 <pid> # Unhide a process
kill -45 <pid> # Authorize a process (bypass hiding)
kill -46 <pid> # Hide the rootkit module
kill -47 <pid> # Reveal the rootkit module
kill -48 <pid> # Hide a port
kill -49 <pid> # Unhide a port| Signal Command | Code | Purpose |
|---|---|---|
kill -42 <pid> |
42 | Grants root privileges to the calling process (requires authorized PID) |
kill -43 <pid> |
43 | Hides the specified process |
kill -44 <pid> |
44 | Reveals the specified hidden process |
kill -45 <pid> |
45 | Authorizes a process to bypass visibility filters |
kill -46 <pid> |
46 | Hides the rootkit module from /proc/modules and dmesg |
kill -47 <pid> |
47 | Reveals the previously hidden rootkit module |
kill -48 <pid> |
48 | Adds a TCP/UDP port to the hidden port list |
kill -49 <pid> |
49 | Removes a port from the hidden list |
We truly appreciate and welcome community involvement. Your contributions, feedback, and suggestions play a crucial role in improving the project for everyone. If you're interested in contributing or have ideas for enhancements, please feel free to open an issue or submit a pull request on our GitHub repository. Every contribution, no matter how big or small, is highly valued and greatly appreciated!
Explore the star history of this project and see how it has evolved over time:
Your support is greatly appreciated. We're grateful for every star! Your backing fuels our passion. ✨
This project is licensed under the GNU Affero General Public License, Version 3.0. For more details, please refer to the LICENSE file in the repository: Read the license on GitHub