Understanding How Rootkits Hide From Detection

Most people who talk about rootkits don't actually understand how they work in practice. I have spent years reversing them and building detection tooling, and the reality is far more tedious than the movies make it seem. Rootkits aren't magic. They are just code that runs at a privilege level above the anti-malware scanning your files, manipulating kernel structures to make themselves invisible. The techniques are well known, but the implementation details are where things get messy. I want to talk about The Rootkit Arsenal Escape And Evasion In The Dark Corners Of The System, because that is essentially what these tools do. They find the gaps between what the operating system reports and what is actually happening in memory.

Kernel-Level Evasion Techniques

The most effective rootkits operate in kernel mode, which gives them access to the same structures that antivirus software uses to scan the system. Direct Kernel Object Manipulation, or DKOM, is one of the most common techniques. Instead of trying to hide a process from user-mode enumeration, the rootkit simply modifies the EPROCESS or PSDOUBLE list entries so the process doesn't appear in the linked list that tools like tasklist or Process Explorer walk. The process is still running. It still has open handles. It is just missing from the lists that most monitoring tools read. I ran into this exact scenario on a Windows Server 2019 box about three years ago. The SIEM was flagging unusual network activity from a domain controller, but every process enumeration tool showed nothing suspicious. CPU usage was normal. Memory footprint was unremarkable. I ended up writing a custom routine that walked the active process list by reading the PsActiveProcessHead directly from kernel memory using a custom driver, which bypassed the standard ZwQuerySystemInformation call that the rootkit had hooked. That revealed a process named svchost.exe running under SYSTEM with a command line that didn't match any known binary. The file had been deleted from disk already, so this was a fileless execution that lived entirely in memory. Syscall hooking is another major category. When a rootkit installs a hardware breakpoint or an inline hook on NtQuerySystemInformation or NtOpenProcess, every user-mode tool that queries the system for process information gets filtered data. The rootkit presents a modified version of the kernel's own output. Detecting this requires reading the raw bytes of the function prologue and comparing them against a known good copy from a clean boot or from signed Microsoft binaries. Tools like Sysinternals' Autoruns used to do something like this, but even that approach has limitations now.

User-Mode Evasion Methods

Not all rootkits go to kernel mode. User-mode rootkits rely on different tricks. They might use API hooking through an injected DLL, or manipulate the Windows Event Log to delete entries after they are written. Some use scheduled tasks with obfuscated names that run at seemingly random intervals. These are easier to detect but harder to fully remove because the persistence mechanisms are often scattered across multiple registry keys and scheduled task definitions. I recently worked on a case where the rootkit was entirely user-mode. It had replaced the legitimate eventlog service binary with a modified version that logged events normally but silently dropped any entries containing specific strings. The hooking was done through an early-loaded DLL that used minihooks on the.ReportEventW function. What made this particularly annoying was that the rootkit also installed a second copy of itself under a slightly different name with a one-character difference in the filename. I caught it because the modified ReportEventW was writing to a circular buffer in memory, and the buffer overflowed when I tried to search for the dropped events. That overflow gave me the full list of what had been deleted.

Get the Full Details

The Rootkit Arsenal : Escape and Evasion in the Dark Corners of the ...
The Rootkit Arsenal : Escape and Evasion in the Dark Corners of the ...

Modern Defense Considerations

Things have gotten harder for both sides. Windows Defender Credential Guard, HVCI, and various forms of kernel patch protection make it significantly more difficult to install kernel-mode rootkits on modern Windows systems. If you try to load an unsigned driver on a machine with Secure Boot enabled, the kernel will reject it. This forces attackers toward user-mode techniques or exploits of vulnerable signed drivers, which is a whole different vector. Linux has its own challenges. Many rootkits target the eBPF subsystem now, using legitimate-looking eBPF programs to hook kernel functions. The kernel's own verification step is supposed to prevent malicious eBPF, but there have been cases where the verifier was tricked into accepting harmful programs through carefully crafted logic that appeared benign on the surface. I spent two days on a single eBPF rootkit that was hiding a backdoor inside what looked like a perfectly normal packet sampling program. The trick was that it was writing to a custom bpf_map that wasn't referenced anywhere in the program's visible logic, and the map was only accessible through a syscall wrapper that the rootkit had replaced with a custom implementation. The downside of relying on kernel-level defenses like HVCI is that they can break legitimate diagnostic and monitoring tools. I have seen production servers where third-party antivirus software became incompatible with the hypervisor-enforced code integrity policy, causing boot failures that required manual recovery. This is a real tradeoff. You gain protection against unsigned kernel code, but you lose the ability to use some legacy tooling that your team depends on.

Practical Detection Approaches

There is no silver bullet. The best approach combines multiple detection layers. Start with memory forensics using tools like Volatility or Rekall, which analyze raw memory dumps without relying on the potentially compromised operating system. Walk the active process list independently from the kernel's reported structures. Check for discrepancies between what the kernel says is running and what you can see by examining physical memory directly. For persistent monitoring, consider using a monitored fork or auditing the creation of new driver objects. When a new kernel module loads, log the driver path, the signing certificate, and the module base address. Compare these against a known-good baseline. If something loads that you didn't expect, that is worth investigating immediately. I usually set up a simple audit policy that triggers an alert whenever a driver is loaded outside of the standard Windows directory or from an unsigned source. Another useful technique is to monitor for anomalous system call behavior. A hooked NtQuerySystemInformation might not just filter results, it might also change the timing of the call. If you measure the execution time of process enumeration over a period and notice a consistent delay, that could indicate hooking is adding overhead to the filtering logic. This is a heuristic, not a guarantee, but it is worth tracking alongside other indicators.

I should note that none of this works perfectly against sophisticated actors. If someone has physical access to the machine and enough time, they can modify the bootloader, replace firmware, or use DMA attacks through Thunderbolt ports. At that point, forensic analysis of the memory dump becomes your primary evidence, and removal usually means rebuilding the system from known-good media rather than trying to clean an infection. I have spent entire weekends trying to surgically remove rootkits from production servers, and the answer has always been the same: a clean rebuild is faster and more reliable than any cleanup attempt.

The Rootkit Arsenal: Escape and Evasion in the Dark Corners of the ...
The Rootkit Arsenal: Escape and Evasion in the Dark Corners of the ...