T1014

Rootkit

Defense Evasion Last updated:

Adversaries may use rootkits to hide the presence of programs, files, network connections, services, drivers, and other system components. Rootkits intercept and modify operating system API calls to conceal malware activity and can reside at user-space, kernel-space, or firmware levels. Real-world deployments include Drovorub (GRU-attributed Linux kernel rootkit using LKMs), Skidmap (cryptocurrency miner with kernel-mode hooking), TeamTNT's Diamorphine (open-source LKM), Ebury (SSH userland rootkit), Rocke (ld.so.preload hijacking), Umbreon (libc hooking), and Windows-based rootkits from Carberp and Stuxnet. Linux kernel rootkits typically leverage loadable kernel modules (LKMs) or shared library preloading via /etc/ld.so.preload. Windows kernel rootkits abuse driver loading mechanisms. Detection is most effective at installation and loading time — once active, rootkits actively conceal themselves from OS-level enumeration.

What is T1014 Rootkit?

Rootkit (T1014) maps to the Defense Evasion tactic — the adversary is trying to avoid being detected in MITRE ATT&CK.

This page provides production-ready detection logic for Rootkit, covering the data sources and telemetry it touches: Driver: Driver Load, File: File Creation, File: File Modification, Process: Process Creation, Windows Security Event Log, Microsoft Defender for Endpoint. The queries below are rated critical severity at medium confidence, and ship for 7 SIEM platforms — KQL, SPL, Elastic, QRadar, Sumo, YARA-L, LogScale.

MITRE ATT&CK

Tactic
Defense Evasion
Technique
T1014 Rootkit
Canonical reference
https://attack.mitre.org/techniques/T1014/
Microsoft Sentinel / Defender
kusto
// T1014 Rootkit — Multi-signal, multi-platform detection
// Signal 1: Windows kernel driver service installation from suspicious path (Security Event ID 4697)
let KernelDriverInstall = SecurityEvent
| where TimeGenerated > ago(24h)
| where EventID == 4697
| extend ServiceName = extract(@'<Data Name="ServiceName">([^<]+)</Data>', 1, EventData)
| extend ServiceFileName = extract(@'<Data Name="ServiceFileName">([^<]+)</Data>', 1, EventData)
| extend ServiceType = extract(@'<Data Name="ServiceType">([^<]+)</Data>', 1, EventData)
| where ServiceType in~ ("0x00000001", "0x1", "Kernel Driver")
| extend IsSuspiciousPath = (
    ServiceFileName has_any (@"\\Temp\\", @"\\tmp\\", @"\\Users\\Public\\", @"\\AppData\\", @"\\Downloads\\", @"\\ProgramData\\")
    or not(ServiceFileName startswith @"C:\\Windows\\"))
| where IsSuspiciousPath
| project TimeGenerated, Host = Computer, Account,
          DetectionType = "KernelDriverInstall",
          Indicator = ServiceName,
          Detail = ServiceFileName;
// Signal 2: Driver (.sys) file loaded from non-standard filesystem path (MDE DeviceImageLoadEvents)
let SuspiciousDriverLoad = DeviceImageLoadEvents
| where Timestamp > ago(24h)
| where FileName endswith ".sys"
| where not(FolderPath has_any (
    @"C:\\Windows\\System32\\",
    @"C:\\Windows\\SysWOW64\\",
    @"C:\\Windows\\WinSxS\\",
    @"C:\\Program Files\\",
    @"C:\\Program Files (x86)\\",
    @"C:\\Windows\\servicing\\"
  ))
| project TimeGenerated = Timestamp, Host = DeviceName, Account = AccountName,
          DetectionType = "SuspiciousDriverLoad",
          Indicator = FileName,
          Detail = FolderPath;
// Signal 3: Linux kernel module loading outside package manager context (MDE for Linux)
let LinuxKernelModuleLoad = DeviceProcessEvents
| where Timestamp > ago(24h)
| where FileName in~ ("insmod", "modprobe")
| where not(InitiatingProcessFileName in~ (
    "systemd", "apt-get", "apt", "dpkg", "rpm", "yum", "dnf",
    "snap", "pacman", "zypper", "kmod", "update-initramfs", "dracut"
  ))
| project TimeGenerated = Timestamp, Host = DeviceName, Account = AccountName,
          DetectionType = "LinuxKernelModuleLoad",
          Indicator = FileName,
          Detail = ProcessCommandLine;
// Signal 4: Modification of /etc/ld.so.preload — userland rootkit hook point (Rocke, Umbreon, Ebury TTP)
let LdPreloadModification = DeviceFileEvents
| where Timestamp > ago(24h)
| where FolderPath =~ "/etc" and FileName =~ "ld.so.preload"
| where ActionType in~ ("FileCreated", "FileModified")
| project TimeGenerated = Timestamp, Host = DeviceName, Account = AccountName,
          DetectionType = "LdPreloadModification",
          Indicator = FileName,
          Detail = InitiatingProcessCommandLine;
// Combine all signals
union KernelDriverInstall, SuspiciousDriverLoad, LinuxKernelModuleLoad, LdPreloadModification
| sort by TimeGenerated desc

Multi-signal detection for rootkit installation and loading across Windows and Linux platforms using MDE and Sentinel. Combines four signals: (1) Windows kernel driver service installation (Security Event ID 4697) where the binary resides outside C:\Windows\, detecting rootkits staged in user-writable paths; (2) Driver (.sys) loading from non-standard paths via DeviceImageLoadEvents, catching kernel rootkits dropped outside the system driver store; (3) Linux kernel module loading via insmod/modprobe initiated outside known package manager processes, targeting LKM rootkits like Diamorphine, Drovorub, and Skidmap; (4) Writes to /etc/ld.so.preload via DeviceFileEvents, detecting userland rootkit hook injection as used by Rocke and Umbreon. Detection confidence is medium because rootkits by design evade OS-level telemetry once active — these signals catch the installation phase before evasion is established.

critical severity medium confidence

Data Sources

Driver: Driver Load File: File Creation File: File Modification Process: Process Creation Windows Security Event Log Microsoft Defender for Endpoint

Required Tables

SecurityEvent DeviceImageLoadEvents DeviceProcessEvents DeviceFileEvents

False Positives

  • Legitimate third-party kernel drivers (VPN clients, hardware manufacturers, security software) installed from staging directories before being moved to C:\Windows\System32\drivers\
  • Linux infrastructure provisioning via configuration management tools (Ansible, Puppet, Chef) loading expected kernel modules such as nf_tables, overlay, or br_netfilter on new nodes
  • Containerization and virtualization software (Docker, VirtualBox, VMware) loading kernel modules (vboxdrv.ko, vmwgfx.ko, overlay.ko) during service startup outside package manager context
  • Security hardening and compliance scanning tools that inspect or recreate /etc/ld.so.preload as part of CIS benchmark enforcement or file integrity verification workflows
  • Custom in-house kernel modules loaded on specialized appliances, HPC systems, or network gear where non-standard module paths are expected by design

Sigma rule & cross-platform mapping

The detection logic for Rootkit (T1014) above is provided in a vendor-neutral form so you can deploy it on any SIEM. The same logic is shipped here as native KQL (Microsoft Sentinel / Defender), SPL (Splunk), Elastic (Elastic Security (EQL)), QRadar (IBM QRadar (AQL)), Sumo (Sumo Logic CSE), YARA-L (Google Chronicle / SecOps), LogScale (CrowdStrike LogScale (CQL)) queries. In Sigma terms, this detection targets the following logsource:

logsource:
  category: process_creation
  product: windows

Browse the community-maintained Sigma rules for this technique:


Testing Methodology

Validate this detection against 4 adversary techniques from Atomic Red Team. Each test below lists the behaviour to exercise and the telemetry you should expect to see. Executable commands and cleanup steps are available with Pro.

  1. Test 1Linux: Load a Benign Kernel Module from Non-Standard Path

    Expected signal: auditd SYSCALL record with syscall=init_module, exe=/sbin/insmod, auid=<current_user>. DeviceProcessEvents (MDE for Linux): FileName=insmod, ProcessCommandLine containing '/tmp/testmodule/test_rootkit_sim.ko', InitiatingProcessFileName=bash/sh. dmesg shows 'argus_test: rootkit simulation module loaded'. lsmod shows 'test_rootkit_sim' in module list.

  2. Test 2Linux: Userland Rootkit Hook via ld.so.preload Injection

    Expected signal: auditd PATH record: type=PATH name=/etc/ld.so.preload nametype=NORMAL with associated SYSCALL record showing write/openat syscall, exe=/usr/bin/tee. DeviceFileEvents (MDE for Linux): FolderPath=/etc, FileName=ld.so.preload, ActionType=FileModified or FileCreated. File integrity monitoring (if deployed) triggers on /etc/ld.so.preload change.

  3. Test 3Windows: Install a Kernel Driver Service from Suspicious Path

    Expected signal: Security Event ID 4697 in Security Log: ServiceName=ArgusTestRootkit, ServiceFileName=C:\Users\Public\argus_test_driver.sys, ServiceType=0x00000001 (Kernel Driver), AccountName=<current_admin_user>. Sysmon Event ID 6 (Driver Loaded): ImageLoaded=C:\Users\Public\argus_test_driver.sys, Signed=true (null.sys is signed). System Event Log 7045: same service details. The file is legitimately signed but the path is suspicious.

  4. Test 4Linux: Enumerate Running Processes to Detect Rootkit-Induced Discrepancies

    Expected signal: On a clean system: proc_pids.txt and ps_pids.txt should differ only by kernel threads and very short-lived processes, and the final comm output should be empty or show only expected kernel thread PIDs. Module comparison should show no discrepancies on a clean system. During active rootkit incident: hidden PIDs and module names would appear in the discrepancy output. This test generates no detection alerts on a clean system — it is a verification tool for the investigation phase.


Response Playbook

Triage

  1. Identify the specific detection signal that fired: KernelDriverInstall, SuspiciousDriverLoad, LinuxKernelModuleLoad, or LdPreloadModification — each has a different initial triage path and urgency level
  2. For Windows driver events (7045/4697 or Sysmon EventCode 6): check the driver binary path, file hash, and digital signature. Run: Get-AuthenticodeSignature '<driver_path>' — an unsigned driver from a temp directory is high-confidence malicious
  3. For Linux kernel module loads: examine the .ko file using modinfo <module_path> to check author, description, and license fields. Legitimate modules show expected kernel version and module author. Run lsmod and compare to /proc/modules — discrepancies indicate active rootkit concealment
  4. For /etc/ld.so.preload modification: immediately cat /etc/ld.so.preload to identify the injected library path. Verify the library exists, then run nm -D <library_path> to identify which libc functions it hooks (read, getdents, write, connect are common rootkit targets)
  5. Check for process visibility discrepancies: compare 'ps aux' output against /proc entries using: ls /proc | grep -E '^[0-9]+$' | while read pid; do [ ! -d /proc/$pid/exe ] 2>/dev/null && echo "Hidden: $pid"; done — hidden PIDs indicate an active rootkit
  6. Review the initiating process and user context: was the module load/driver install initiated by a privileged user, a compromised service account, or an unexpected binary such as a web server or database process?
  7. Check dmesg output and /var/log/kern.log for kernel module load events and any ERROR or WARNING messages from the loaded module that may indicate rootkit activity or kernel tainting

Containment

  1. If active Linux kernel rootkit confirmed: do NOT attempt to clean the live system — the rootkit may have hooked syscalls making all output unreliable. Isolate the host from the network immediately using firewall rules or hypervisor-level network disconnection
  2. For Windows kernel rootkit confirmed: isolate the endpoint using EDR network isolation. Boot from external media (WinPE or forensic live USB) to examine the filesystem and driver store without loading potentially compromised kernel components
  3. If /etc/ld.so.preload is compromised: the rootkit library is injected into every new process. Do not spawn additional shells or processes on the compromised host until the preload is removed from a trusted context (single-user mode or external boot)
  4. Identify and block the C2 infrastructure: extract network IOCs from the rootkit binary if accessible from a clean context and block at perimeter. Drovorub and Skidmap used specific ports and protocols documented in their threat intelligence reports
  5. Preserve volatile memory before any remediation: if forensic capability exists, take a memory dump (LiME for Linux, DumpIt for Windows) from a trusted kernel or external tool — this is the most reliable artifact for rootkit analysis
  6. Revoke credentials used on the compromised host: all credentials (SSH keys, service account passwords, API keys, certificates) that were accessible on the system should be treated as compromised and rotated immediately

Evidence Collection

  1. Memory dump: For Linux use LiME (Linux Memory Extractor) — insmod lime-$(uname -r).ko 'path=/mnt/external/memory.lime format=lime' — this captures a full memory image from a known-clean module before the rootkit can intercept
  2. Kernel module artifacts: copy all .ko files from /lib/modules/$(uname -r)/ to external storage; hash each file and compare against known-good package checksums using rpm -V kernel or dpkg --verify linux-image-$(uname -r)
  3. File system artifacts: run an offline scan using a live boot to enumerate all files without the rootkit's getdents hook — compare against the live system's 'ls' output to identify hidden files
  4. Windows driver store: collect C:\Windows\System32\drivers\*.sys hashes; query the service registry at HKLM\SYSTEM\CurrentControlSet\Services for entries with ServiceType=1 (kernel driver) where ImagePath points outside the driver store
  5. Network artifacts: capture pcap from a network tap or external sensor (not the compromised host's tcpdump, which may be hooked) to identify C2 communication patterns — Drovorub used port 443 with custom TLS fingerprints
  6. Audit log review: Linux — /var/log/auth.log, /var/log/kern.log, journalctl -k for kernel messages, ausearch -k rootkit for auditd events; Windows — System Event Log for Event ID 7045, Security Log for 4697
  7. Rootkit-specific IOC comparison: hash the suspicious module/driver and compare against known rootkit signatures from VirusTotal, YARA rules for Diamorphine, Drovorub, Skidmap, Ebury, and vendor threat intelligence reports
  8. Timeline reconstruction: use filesystem timestamps (mtime, atime, ctime) on the .ko or .sys file — discrepancies between install time in logs and filesystem timestamps may indicate timestamp manipulation by the attacker

Escalation Criteria

  • ! Any confirmed kernel-mode rootkit — escalate immediately to incident response; kernel rootkits can intercept and manipulate all OS-level security telemetry, making the entire system untrusted
  • ! Evidence of syscall hooking or process hiding (discrepancy between /proc entries and ps output, or between netstat and /proc/net/ entries) — this indicates the rootkit is actively concealing attacker presence
  • ! Rootkit found on a domain controller, authentication server, PKI system, or privileged access workstation — blast radius includes credential theft at scale
  • ! /etc/ld.so.preload found containing an unknown library — all processes spawned on this host since the modification may have executed attacker-controlled code
  • ! Rootkit binary or driver matches a known threat actor tool (Drovorub = APT28/GRU, Skidmap = cryptomining campaigns, Diamorphine = TeamTNT) — threat intelligence escalation required
  • ! Evidence of lateral movement from the rootkit-infected host to other systems — SSH private keys, Kerberos tickets, or credential material may have been stolen via the hooked authentication functions

Investigation Guide

Forensic Artifacts

  • > Linux /proc/modules and lsmod output: compare against known-good module list; rootkits may hide themselves from both but leave traces in /sys/module/
  • > Linux /etc/ld.so.preload: if present and non-empty, contains the path to injected shared libraries — should normally be empty on production systems
  • > Linux /sys/module/<module_name>/: even when lsmod is hooked, kernel sysfs entries for loaded modules may persist — enumerate with ls /sys/module/ from a trusted context
  • > Linux dmesg / /var/log/kern.log: kernel module load events appear as 'module: <name>' entries; rootkits that taint the kernel generate 'kernel tainted' messages
  • > Windows Registry HKLM\SYSTEM\CurrentControlSet\Services: kernel drivers (ServiceType=0x1) registered here; compare against known-good service baseline
  • > Windows C:\Windows\System32\drivers\: unexpected .sys files not present in a clean baseline or not signed by a trusted CA indicate kernel rootkit presence
  • > Windows Prefetch C:\Windows\Prefetch\: execution traces for tools used to install the rootkit (sc.exe, bcdedit.exe, devmgmt.exe) may persist even if logs are cleared
  • > Memory artifacts: kernel rootkits are visible in memory dumps via Volatility plugins (linux_check_syscall, linux_check_idt for Linux; ssdt, callbacks for Windows) which compare in-memory kernel structures against expected values

Tuning Guidance

Rootkit detection has an inherent signal quality challenge: once active, rootkits modify the OS telemetry that detection queries rely on, making the installation phase the highest-confidence detection window. Focus tuning efforts on the pre-execution and loading phase. For Windows kernel driver detections (4697/Sysmon EventCode 6), build a vetted allowlist of known driver binary paths for each device class in your environment — security software, VPN clients, and hardware vendors often have consistent driver paths. Never allowlist by service name alone since rootkits commonly masquerade as legitimate service names. For Linux kernel module detections, establish a baseline of expected modules per server role using lsmod output from known-clean systems — database servers should not load WiFi drivers, web servers should not load bluetooth modules. The most reliable Linux auditd rule set for this technique requires these rules in /etc/audit/rules.d/rootkit.rules: '-a always,exit -F arch=b64 -S init_module -S finit_module -S delete_module -k rootkit' and '-w /etc/ld.so.preload -p wa -k rootkit'. Without these auditd rules, the linux_auditd SPL query produces no output. For environments with heavy legitimate kernel module activity (HPC, specialized hardware), add a whitelist of expected module names to filter from the LinuxKernelModuleLoad signal. Consider deploying file integrity monitoring (FIM) on /etc/ld.so.preload, /etc/ld.so.conf.d/, and /lib/modules/ as a complementary control. The SuspiciousDriverLoad KQL signal can be noisy during software deployments — consider time-bounding alerts to exclude known maintenance windows.


Hunting Queries

Hunt for rare unsigned kernel drivers loaded from non-standard paths across the fleet over the past 7 days. Rootkit drivers tend to appear on very few systems (low prevalence) unlike legitimate vendor drivers which load consistently across many managed endpoints. Low count combined with non-standard path is a high-signal indicator.

Hunting — KQL
kql
// Hunt for unsigned kernel drivers loaded in the past 7 days across the fleet
DeviceImageLoadEvents
| where Timestamp > ago(7d)
| where FileName endswith ".sys"
| where not(FolderPath has_any (
    @"C:\\Windows\\System32\\",
    @"C:\\Windows\\SysWOW64\\",
    @"C:\\Windows\\WinSxS\\",
    @"C:\\Program Files\\",
    @"C:\\Program Files (x86)\\"
  ))
| summarize Count = count(), Devices = dcount(DeviceName), FirstSeen = min(Timestamp), LastSeen = max(Timestamp), DeviceList = make_set(DeviceName, 10) by FileName, FolderPath, SHA1
| where Count < 5  // Rare drivers are more suspicious than prevalent ones
| sort by Count asc
Hunting — SPL
spl
sourcetype="XmlWinEventLog:Microsoft-Windows-Sysmon/Operational" EventCode=6
NOT (ImageLoaded="C:\\Windows\\System32\\*" OR ImageLoaded="C:\\Windows\\SysWOW64\\*" OR ImageLoaded="C:\\Windows\\WinSxS\\*" OR ImageLoaded="C:\\Program Files\\*")
earliest=-7d
| stats count as Count, dc(host) as Devices, values(Signed) as Signed, earliest(_time) as FirstSeen, latest(_time) as LastSeen by ImageLoaded, Hashes
| where Count < 5
| sort + Count

Hunt for systems with unusually high frequency of kernel module operations or module loads from many different parent processes. Rootkit deployment often involves multiple load/unload cycles during testing or redeployment. High module operation counts or diverse parent processes on a single host are behavioral anomalies worth investigating.

Hunting — KQL
kql
// Hunt for Linux systems where insmod/modprobe has been called by non-root or unexpected parents
DeviceProcessEvents
| where Timestamp > ago(7d)
| where FileName in~ ("insmod", "modprobe", "rmmod")
| summarize Count = count(), UniqueParents = dcount(InitiatingProcessFileName), ParentList = make_set(InitiatingProcessFileName, 10), ModuleList = make_set(ProcessCommandLine, 20) by DeviceName, AccountName
| where UniqueParents > 3 or Count > 10
| sort by Count desc
Hunting — SPL
spl
sourcetype="linux_auditd" type=SYSCALL (syscall="init_module" OR syscall="finit_module" OR syscall="delete_module") earliest=-7d
| stats count as Count, dc(ppid) as UniquePPIDs, values(exe) as Executables, values(comm) as Commands by host, auid
| where Count > 5 OR UniquePPIDs > 3
| sort - Count

Hunt for any writes to /etc/ld.so.preload over the past 30 days. This file is rarely modified on production Linux systems — any write event warrants immediate investigation. Used by Rocke to hijack libc calls and hide cryptomining activity, and by Umbreon to intercept authentication and system calls. Even a single event here is significant.

Hunting — KQL
kql
// Hunt for any process that wrote to /etc/ld.so.preload — should be near-zero in production
DeviceFileEvents
| where Timestamp > ago(30d)
| where FolderPath =~ "/etc" and FileName =~ "ld.so.preload"
| project Timestamp, DeviceName, AccountName, ActionType, InitiatingProcessFileName, InitiatingProcessCommandLine, InitiatingProcessParentFileName
| sort by Timestamp desc
Hunting — SPL
spl
sourcetype="linux_auditd" type=PATH name="/etc/ld.so.preload" earliest=-30d
| join type=left auid [search sourcetype="linux_auditd" type=SYSCALL earliest=-30d | rename auid as auid, exe as exe | table auid, exe, comm, ppid]
| table _time, host, auid, exe, comm, ppid, nametype, name
| sort - _time

Atomic Red Team Tests

Test 1 Linux: Load a Benign Kernel Module from Non-Standard Path
linux

Simulates LKM rootkit installation by loading a simple kernel module from /tmp rather than the standard module directory. Uses the 'hello' example module (compiled from kernel headers) or the 'dummy' network driver that ships with many Linux distributions. This generates auditd init_module syscall events and Sysmon-for-Linux process events without deploying actual malicious functionality. Requires root privileges and kernel headers.

Command

bash
# Step 1: Create a minimal benign kernel module
mkdir -p /tmp/testmodule
cat > /tmp/testmodule/test_rootkit_sim.c << 'EOF'
#include <linux/module.h>
#include <linux/kernel.h>
MODULE_LICENSE("GPL");
static int __init test_init(void) { printk(KERN_INFO "argus_test: rootkit simulation module loaded\n"); return 0; }
static void __exit test_exit(void) { printk(KERN_INFO "argus_test: rootkit simulation module unloaded\n"); }
module_init(test_init);
module_exit(test_exit);
EOF
# Step 2: Build module (requires kernel headers: apt install linux-headers-$(uname -r))
echo -e 'obj-m += test_rootkit_sim.o\nall:\n\tmake -C /lib/modules/$(uname -r)/build M=$(PWD) modules\nclean:\n\tmake -C /lib/modules/$(uname -r)/build M=$(PWD) clean' > /tmp/testmodule/Makefile
make -C /tmp/testmodule
# Step 3: Load from non-standard path (key detection trigger)
sudo insmod /tmp/testmodule/test_rootkit_sim.ko

Cleanup

bash
sudo rmmod test_rootkit_sim 2>/dev/null; rm -rf /tmp/testmodule

Expected Telemetry

auditd SYSCALL record with syscall=init_module, exe=/sbin/insmod, auid=<current_user>. DeviceProcessEvents (MDE for Linux): FileName=insmod, ProcessCommandLine containing '/tmp/testmodule/test_rootkit_sim.ko', InitiatingProcessFileName=bash/sh. dmesg shows 'argus_test: rootkit simulation module loaded'. lsmod shows 'test_rootkit_sim' in module list.

Expected Detection

SPL: auditd SYSCALL record matches syscall=init_module trigger. KQL: LinuxKernelModuleLoad fires on insmod with ProcessCommandLine containing '/tmp/'. from_pkg_manager=0 because parent is bash. Alert: DetectionType=LinuxKernelModuleLoad.

Test 2 Linux: Userland Rootkit Hook via ld.so.preload Injection
linux

Simulates the Rocke and Umbreon userland rootkit technique by writing a shared library path to /etc/ld.so.preload. Uses a benign test library that only logs a message to demonstrate the hook mechanism. Once set, every newly spawned process will load the injected library before any other — this is how Rocke hid cryptominers and Umbreon intercepted authentication. Requires root privileges.

Command

bash
# Step 1: Create a benign preload library
cat > /tmp/argus_preload_test.c << 'EOF'
#include <stdio.h>
__attribute__((constructor)) void init(void) {
    fprintf(stderr, "[argus-test] ld.so.preload hook active\n");
}
EOF
gcc -shared -fPIC -o /tmp/argus_preload_test.so /tmp/argus_preload_test.c
# Step 2: Write to /etc/ld.so.preload (key detection trigger — auditd watches this file)
echo '/tmp/argus_preload_test.so' | sudo tee /etc/ld.so.preload
# Step 3: Verify hook is active (every new process loads the library)
whoami

Cleanup

bash
sudo rm -f /etc/ld.so.preload; rm -f /tmp/argus_preload_test.so /tmp/argus_preload_test.c

Expected Telemetry

auditd PATH record: type=PATH name=/etc/ld.so.preload nametype=NORMAL with associated SYSCALL record showing write/openat syscall, exe=/usr/bin/tee. DeviceFileEvents (MDE for Linux): FolderPath=/etc, FileName=ld.so.preload, ActionType=FileModified or FileCreated. File integrity monitoring (if deployed) triggers on /etc/ld.so.preload change.

Expected Detection

SPL: auditd PATH record matches name=/etc/ld.so.preload with nametype=CREATE or NORMAL. KQL: LdPreloadModification fires with ActionType=FileModified/FileCreated. Hunting query returns this event in 30-day lookback. Alert: DetectionType=LdPreloadModification, severity=critical.

Test 3 Windows: Install a Kernel Driver Service from Suspicious Path
windows

Simulates Windows kernel rootkit installation by registering a kernel driver service with its binary path pointing to a user-writable directory (AppData\Local\Temp). Uses a legitimate, benign .sys file (null.sys — the Windows null device driver) copied to a suspicious location. This triggers Security Event ID 4697 and Sysmon EventCode 6 without loading actual malicious code. Requires administrator privileges.

Command

powershell
# Copy a legitimate benign .sys to a suspicious path
copy C:\Windows\System32\drivers\null.sys C:\Users\Public\argus_test_driver.sys
# Register as kernel driver service (ServiceType=1 = kernel driver)
sc create ArgusTestRootkit type= kernel binPath= "C:\Users\Public\argus_test_driver.sys" DisplayName= "Argus Rootkit Simulation Test"
# Start the service to trigger driver load event (optional — registration alone triggers 4697)
sc start ArgusTestRootkit

Cleanup

powershell
sc stop ArgusTestRootkit; sc delete ArgusTestRootkit; del C:\Users\Public\argus_test_driver.sys

Expected Telemetry

Security Event ID 4697 in Security Log: ServiceName=ArgusTestRootkit, ServiceFileName=C:\Users\Public\argus_test_driver.sys, ServiceType=0x00000001 (Kernel Driver), AccountName=<current_admin_user>. Sysmon Event ID 6 (Driver Loaded): ImageLoaded=C:\Users\Public\argus_test_driver.sys, Signed=true (null.sys is signed). System Event Log 7045: same service details. The file is legitimately signed but the path is suspicious.

Expected Detection

KQL: KernelDriverInstall fires on Event ID 4697 with ServiceType=0x00000001 and ServiceFileName containing C:\Users\Public\. SPL: WinEventLog:System EventCode=7045 matches ServiceType=Kernel Driver. Alert: DetectionType=KernelDriverInstall, is_suspicious_path=1.

Test 4 Linux: Enumerate Running Processes to Detect Rootkit-Induced Discrepancies
linux

Simulates the forensic technique used to detect active process-hiding rootkits. Compares PIDs visible in /proc against those returned by the ps command. On a clean system these should match exactly. When a kernel rootkit (Diamorphine, Drovorub) is active, getdents-hooked ps will miss PIDs that are still visible in /proc. This atomic test establishes a clean baseline and demonstrates the detection methodology used during incident response.

Command

bash
# Method 1: Compare /proc PID list against ps output
echo '=== PIDs in /proc (direct kernel view) ==='
ls /proc | grep -E '^[0-9]+$' | sort -n > /tmp/proc_pids.txt
cat /tmp/proc_pids.txt | wc -l
echo '=== PIDs from ps (potentially hooked) ==='
ps -eo pid --no-headers | sort -n > /tmp/ps_pids.txt
cat /tmp/ps_pids.txt | wc -l
echo '=== PIDs in /proc but NOT in ps output (potential hidden processes) ==='
comm -23 /tmp/proc_pids.txt /tmp/ps_pids.txt
# Method 2: Check for kernel module hiding (compare /proc/modules vs lsmod)
echo '=== Modules in /proc/modules ==='
cat /proc/modules | awk '{print $1}' | sort > /tmp/proc_modules.txt
echo '=== Modules from lsmod ==='
lsmod | awk 'NR>1 {print $1}' | sort > /tmp/lsmod_modules.txt
echo '=== Modules in /proc/modules but NOT in lsmod (potential hidden modules) ==='
comm -23 /tmp/proc_modules.txt /tmp/lsmod_modules.txt

Cleanup

bash
rm -f /tmp/proc_pids.txt /tmp/ps_pids.txt /tmp/proc_modules.txt /tmp/lsmod_modules.txt

Expected Telemetry

On a clean system: proc_pids.txt and ps_pids.txt should differ only by kernel threads and very short-lived processes, and the final comm output should be empty or show only expected kernel thread PIDs. Module comparison should show no discrepancies on a clean system. During active rootkit incident: hidden PIDs and module names would appear in the discrepancy output. This test generates no detection alerts on a clean system — it is a verification tool for the investigation phase.

Expected Detection

No alert fires on a clean system — this is an IR verification technique. If running during an active incident with a rootkit present, the discrepancy output identifies hidden processes/modules. Analyst action: if comm -23 output shows non-kernel PIDs (above 1000) or module names that cannot be explained, escalate immediately as active rootkit concealment is occurring.

Related Detections