Listen to this Post

Introduction:
Kernel‑mode driver analysis often intimidates reverse engineers, but the rigid structure of Windows drivers actually makes them more predictable than user‑mode malware. Using Ghidra and emulation, we can dissect a rootkit like Poison X—which kills processes and hides network requests—even when it relies on undocumented API calls and custom structures.
Learning Objectives:
- Set up a safe kernel‑driver analysis environment with Ghidra and emulation frameworks.
- Identify and annotate undocumented driver structures by referencing open‑source examples on GitHub.
- Trace rootkit behaviors such as process termination and network request filtering using emulation and dynamic analysis.
You Should Know:
1. Building Your Kernel‑Driver Analysis Lab
Start by isolating your analysis environment. Use a Windows virtual machine (VM) for execution traces and a Linux host for static analysis with Ghidra. Install the following tools:
- Ghidra (latest version) with the Windows kernel extension (SLEIGH).
- Unicorn Engine or QEMU for emulating driver entry points.
- WinDbg for live kernel debugging (optional).
- IDA Free as an alternative for driver signatures.
Step‑by‑step guide to configure the lab:
- Set up the VM: Install Windows 10/11 (any build) on VMware or VirtualBox. Disable network adapters or use a host‑only network.
- Install Ghidra: Download from ghidra‑sre.org, extract, and run
ghidraRun. Add the `windows_x86_64` language module if not present.
3. Download Unicorn: On Linux, run:
pip install unicorn git clone https://github.com/unicorn-engine/unicorn.git cd unicorn/bindings/python && sudo python setup.py install
4. Extract the Poison X driver: Use `dumpbin /exports` or `strings` on the `.sys` file to identify exported functions (e.g., DriverEntry).
To emulate a driver’s `DriverEntry` without a full VM, write a small Unicorn script that loads the driver binary and executes its entry point. Example skeleton:
from unicorn import
from unicorn.x86_const import
def hook_code(mu, address, size, user_data):
print(f"Executing code at 0x{address:x}")
mu = Uc(UC_ARCH_X86, UC_MODE_64)
Load driver image base at 0x140000000 (typical for 64‑bit)
mu.mem_map(0x140000000, 0x100000)
with open("poison_x.sys", "rb") as f:
mu.mem_write(0x140000000, f.read())
mu.hook_add(UC_HOOK_CODE, hook_code)
mu.emu_start(0x140001000, 0) start at DriverEntry
2. Handling Undocumented Structures with GitHub Mining
Rootkits like Poison X often rely on undocumented kernel structures (e.g., `_EPROCESS` offsets, _TCPT_OBJECT). Instead of reversing from scratch, search GitHub for similar driver code.
Step‑by‑step guide to find and adapt undocumented structures:
- Identify unknown fields in Ghidra: Look for disassembly that accesses large offsets (e.g.,
mov rax, [rcx+0x4B8]). Note the offset.
2. Search GitHub using targeted queries:
– `”_EPROCESS” “0x4B8″ Windows`
– `”PsLookupProcessByProcessId” + offset`
– `”Poison X” rootkit` (limited results; try generic rootkit process hiding)
3. Clone a reference driver (e.g., from https://github.com/ionescu007/SpecuCheck` orhttps://github.com/namazso/physmem_drivers`) that uses similar patterns.
4. Cross‑reference offsets with Microsoft public symbols (use `live.sysinternals.com/tools/dbghelp.dll` and symchk).
5. Apply to Ghidra: Create a custom data type for the undocumented structure:
– Right‑click in Ghidra’s Data Type Manager → New → Structure.
– Add fields based on the discovered offsets (e.g., DWORD Unknown1; BYTE[0x4B8-4] Padding; PVOID HideField;).
– Relabel the code references with your new structure.
For Poison X, which hides network requests, look for hooks in `Tcpip.sys` or nsiproxy.sys. A common technique is to replace the `IRP_MJ_DEVICE_CONTROL` dispatch routine. Use Ghidra to find cross‑references to `IoGetDeviceObjectPointer` and then trace the returned device object.
3. Emulation‑Based Tracing of Rootkit Behaviors
Emulation lets you trace the rootkit’s logic without triggering anti‑analysis tricks (e.g., checking for debuggers). Poison X kills processes by calling `ZwTerminateProcess` (or an undocumented variant). We can emulate the driver from its `DriverEntry` to its dispatch routines.
Step‑by‑step guide to trace process killing and network hiding:
- Locate the dispatch table in Ghidra: The `DriverEntry` function sets `DriverObject->MajorFunction` array. Find the handler for `IRP_MJ_DEVICE_CONTROL` (index 0x0E) and `IRP_MJ_CREATE` (0x00).
- Extract the IOCTL codes used by Poison X. Look for `IoGetCurrentIrpStackLocation` followed by a comparison with a constant (e.g.,
0x222000). Those constants are the control codes. - Emulate the IOCTL handler with Unicorn, passing crafted input buffers:
Inside emulation, after mapping the driver process_id = 1234 target PID to kill input_buffer = struct.pack("<I", process_id) Set up fake IRP and call the handler (Simplified – real emulation requires defining IRP structures) - Log system calls made during emulation. Poison X likely calls
ZwTerminateProcess,ObReferenceObjectByHandle, and `NtSetInformationFile` (for network filtering). Hook these with Unicorn’s `UC_HOOK_INTR` or use a dynamic binary instrumentation tool like `DynamoRIO` for more complete traces. - Analyze network hiding: The driver might filter `IRP_MJ_INTERNAL_DEVICE_CONTROL` for `AFD.sys` or patch
Tcpip!TdiSendDatagram. Use emulation to log every call to `memcpy` between the driver and network structures. Look for checks on destination IP or port.
If the driver uses undocumented APIs (e.g., SeSetAuditParameter), search GitHub for samples. One effective query: "SeSetAuditParameter" driver filetype:cpp. You will often find open‑source rootkit prototypes that reveal parameter meanings.
4. Reversing Process Termination Logic in Poison X
Process killing is often implemented by locating the target `_EPROCESS` and calling `PspTerminateProcess` or ZwTerminateProcess. Poison X may hide its activity by first removing the process from the system’s handle table.
Step‑by‑step guide to identify and mitigate this technique:
- In Ghidra, find all calls to `ZwOpenProcess` and
ZwTerminateProcess. Note that a stealthy rootkit might directly call `PspTerminateProcess` (offset known from public symbols). - Extract the “process killing” code block and note any preceding loop that enumerates active processes (using
PsActiveProcessHead). This is how Poison X locates PIDs by name. - To defend against such drivers, a blue‑team analyst can:
– Block unknown kernel drivers via Windows Defender Application Control (WDAC).
– Enable Hypervisor‑protected Code Integrity (HVCI) to prevent unsigned driver loads.
– Monitor for `DriverEntry` callbacks using a kernel‑mode anti‑rootkit like `GMER` or `WinDbg` with the `!drvobj` command.
– Use Windows Event ID 7045 (service installation) and 4697 (driver installation) to detect new `.sys` files.
Example PowerShell detection script for suspicious kernel services:
Get-WinEvent -FilterHashtable @{LogName='System'; ID=7045} | Where-Object {$_.Message -match "Poison|Rootkit|Hidden"}
5. Hiding Network Requests: Analysis and Detection
Poison X’s ability to hide network requests suggests it hooks the NDIS (Network Driver Interface Specification) layer or patches the TDI (Transport Driver Interface) call table. Emulation helps us trace which hooks are installed.
Step‑by‑step guide to simulate and detect network hiding:
- Identify the rootkit’s hooking mechanism in Ghidra: look for `KeServiceDescriptorTable` (SSDT) modifications or inline hooks inside `tcpip.sys` code sections. A common pattern is reading the `IA32_LSTAR` MSR to get the `KiSystemCall64` address and then overwriting syscall entries.
- Build a small emulation script that loads Poison X and a dummy network driver stub. Trigger a fake `NtDeviceIoControlFile` call and see which functions get redirected.
- Extract hidden requests: If the driver hides outgoing connections to a C2 server, it will intercept `TdiSend` and compare the destination IP. Use a debugger to set breakpoints on `memcmp` after the driver copies the IP address.
4. Detection strategy:
– Compare the SSDT before and after driver load using WinDbg: `!ssdt` and !ssdt2.
– Use `Volatility` (memory forensics) to dump the kernel’s `ntoskrnl.exe` and scan for inline hooks with `apihooks` plugin.
– Deploy Sysmon event collection (ID 10 for process access, ID 13 for registry changes) and correlate with network logs from Windows Filtering Platform (WFP).
Linux command to scan Windows memory dump for hidden processes (using Volatility 3):
vol -f memory.dump windows.pslist.PsList vol -f memory.dump windows.malfind.Malfind
What Undercode Say:
– Kernel driver analysis is less intimidating than it seems because of the rigid IRP dispatching model; focus on `DriverEntry` and the MajorFunction table.
– Emulation (Unicorn) and GitHub mining for undocumented structures dramatically reduce the need for live kernel debugging.
– The Poison X rootkit exemplifies how small, single‑purpose drivers can kill processes and filter network traffic without raising immediate alarms, but their limited functionality also makes them easier to signature and detect via SSDT hooks.
Analysis: The rootkit leverages well‑known persistence through a kernel service (.sys loaded via SCM). Process killing is implemented via standard `ZwTerminateProcess` but wrapped in a secret IOCTL that only activates when a magic value is passed. Network hiding is more sophisticated—it likely patches the `Tcpip!TdiSendDatagram` routine to drop packets destined for security vendors. Emulation proves essential because the driver checks for a debugger by reading KdDebuggerEnabled; in an emulated environment this check always fails. By using Ghidra’s markup and Unicorn, we can bypass anti‑debugging and trace the real logic. Defenders should focus on kernel code integrity (HVCI) and periodic SSDT comparison, as most commodity rootkits cannot defeat those protections.
Prediction:
– +1 Emulation‑based driver analysis will become a standard step in malware triage, reducing reliance on expensive kernel debugging hardware.
– -1 Rootkit authors will increasingly abuse undocumented processor features (like Intel CET shadow stack bypasses) to hide hooking mechanisms from emulators.
– +1 Open‑source sharing of driver structure offsets on GitHub accelerates both offensive and defensive research, democratizing kernel‑level security knowledge.
– -1 The rise of AI‑generated kernel drivers with randomized structure offsets will make pattern matching in Ghidra less effective, requiring dynamic analysis of every new sample.
▶️ Related Video (82% Match):
🎯Let’s Practice For Free:
🎓 Live Courses & Certifications:
Join Undercode Academy for Verified Certifications
🚀 Request a Custom Project:
Secure, high-velocity infrastructure and disruptive technological engineering. Contact our engineering team for high-tier development and proprietary systems:
[email protected]
💎 Smart Architecture | 🛡️ Secure by Design | ⭐ Trusted by Thousands
IT/Security Reporter URL:
Reported By: Karsten Hahn – Hackers Feeds
Extra Hub: Undercode MoN
Basic Verification: Pass ✅


