For the complete documentation index, see llms.txt. This page is also available as Markdown.

Weaponization, PoCs & Defense

Part 3 — Weaponization, PoCs & Defense

In this part: we take the arbitrary read/write primitive from Part 2 and build a working kernel R/W engine, leak ntoskrnl, walk the EPROCESS list, steal the SYSTEM token (full C PoC), then cover DSE downgrade and callback removal, walk through real CVE case studies, and finish with the detection and defensive engineering that actually stops this.

⚠️ VM only. Every code path below can bugcheck a live system. The PoCs teach the mechanics; they are not drop-in tooling.


3.1 The primitive ladder — where we're going

A single "map arbitrary physical memory" or "read/write arbitrary virtual address" IOCTL is enough to climb the entire ladder:

  1. Arbitrary read → leak ntoskrnl base → defeat KASLR → resolve symbols.

  2. Arbitrary write → data-only edits: token theft, callback removal, DSE flip.

  3. On non-HVCI hosts, optionally → control-flow hijack / kernel code execution.

3.2 Building a kernel read/write engine

Wrap the driver's raw IOCTLs into clean kread/kwrite helpers. The snippet below uses a RTCore64-style virtual R/W (Class 2 from Part 2): each call moves up to 4 bytes at an arbitrary virtual address, and we compose those into arbitrary-size transfers.

Now kread/kwrite reach into any kernel virtual address. Everything after this is Windows-internals plumbing, not driver-specific.

3.3 Defeating KASLR — leaking the ntoskrnl base

To edit kernel structures you need their addresses, which KASLR randomizes each boot. The cleanest leak from a medium-integrity admin process is NtQuerySystemInformation(SystemModuleInformation, ...), which returns the load address of every kernel module — including ntoskrnl.exe at index 0.

From the base you resolve exported symbols (PsInitialSystemProcess, PsLoadedModuleList) by parsing ntoskrnl's export table — either from the on-disk copy at %SystemRoot%\System32\ntoskrnl.exe (mapped read-only) added to the leaked base, or by reading the export directory through kread.

PsInitialSystemProcess is a pointer symbol: kread64(resolve_export(base, "PsInitialSystemProcess")) gives the EPROCESS of the SYSTEM process (PID 4).

3.4 The payoff — EPROCESS token theft (full PoC)

Every process's security context is a pointer — EPROCESS.Token (an EX_FAST_REF). Steal SYSTEM's token pointer, write it over your own process's Token, and your process is SYSTEM. No shellcode, no code execution, nothing PatchGuard or HVCI objects to — this is the canonical data-only attack and it works even on HVCI-enabled systems.

The walk:

  1. System = kread64(PsInitialSystemProcess) → SYSTEM's EPROCESS.

  2. Follow the ActiveProcessLinks doubly-linked list until UniqueProcessId == GetCurrentProcessId() to find our own EPROCESS.

  3. sysTok = kread64(System + Token) & ~0xF (mask the low reference-count bits of the EX_FAST_REF).

  4. kwrite(self + Token, &sysTok, 8).

Hardening note: modern Windows adds token robustness checks in some paths, and offsets drift every build — this is why real tooling resolves offsets dynamically (via the PDB / dt nt!_EPROCESS in WinDbg) rather than hardcoding. The technique is unchanged since Windows XP; only the numbers move.

Alternative data-only payloads

Once you hold kread/kwrite, token theft is just the friendliest option:

  • Privilege bit-flip: OR 0xFFFFFFFFFFFFFFFF into Token->Privileges.Present/Enabled to grant every privilege without swapping tokens (stealthier — the token still "belongs" to you).

  • Integrity level downgrade removal: raise your process integrity to System.

  • Protection field flip: set EPROCESS.Protection to make your process a PPL (Protected Process Light), frustrating EDR that respects PP/PPL.

  • ImageFileName spoof: cosmetic, but complicates naive detection.

3.5 Attacking the security stack (non-HVCI hosts)

DSE downgrade — loading an unsigned rootkit

With arbitrary write and no HVCI, flip Code Integrity's policy variable and the kernel will load unsigned drivers. Historically this is ci!g_CiOptions (older: nt!g_CiEnabled). Resolve it (pattern-scan CI.dll/ntoskrnl or use symbols), read the current value, zero the enforcement bits, load your driver, then restore.

Blinding EDR — removing kernel callbacks

EDRs subscribe to kernel notifications via PsSetCreateProcessNotifyRoutine, PsSetCreateThreadNotifyRoutine, PsSetLoadImageNotifyRoutine, and object callbacks (ObRegisterCallbacks). These live in exported callback arrays (PspCreateProcessNotifyRoutine, etc.). With kwrite you can locate the array, find the EDR's callback entry, and zero it — the sensor goes deaf without crashing. This is the core of "EDR killer" BYOVD tools (Terminator, AuKill, Spyboy).

Detection pivot for blue teams: a drop in a sensor's kernel callbacks, or a gap in PsSetCreateProcessNotifyRoutine telemetry immediately after a driver load, is a high-fidelity BYOVD signal. Tamper-protection watchdogs that re-register callbacks and alert on their removal defeat this.

3.6 Case studies — real vulnerable drivers

Each of these is worth reversing yourself; they map one-to-one onto the vulnerability classes from Part 2.

RTCore64.sys — MSI Afterburner (CVE‑2019‑16098)

The reference BYOVD driver. Ships with the wildly popular MSI Afterburner overclocking utility, signed by Micro-Star. Exposes IOCTLs that read/write arbitrary virtual memory (0x80002048 / 0x8000204C) and MSRs. Because it grants a direct virtual R/W with no page-table math, it's the "hello world" of kernel R/W primitives and the driver most EDR-killer tools historically bundled. Class 2 + Class 3.

dbutil_2_3.sys — Dell (CVE‑2021‑21551)

Shipped inside Dell's firmware update utilities for ~12 years across hundreds of millions of machines. An IOCTL exposes arbitrary read/write; the device had a permissive DACL, so even non-privileged users could reach it on many configs. Discovered by SentinelOne. A textbook "trusted-vendor driver, catastrophic DACL + primitive" combination. Class 1/2.

gdrv.sys — GIGABYTE (CVE‑2018‑19320 and friends)

GIGABYTE's system utility driver. Arbitrary physical memory read/write and MSR write. Famously weaponized by the RobbinHood ransomware crew to disable endpoint protection before encryption — one of the first widely-reported criminal BYOVD-for-EDR-kill campaigns. Class 1 + Class 3.

Capcom.sys — game anti-tamper

The archetype of Class 5. Exposes an IOCTL that takes a user-supplied pointer and calls it in kernel mode, even briefly clearing SMEP so the callee can be a user-mode address. One IOCTL = ring-0 code execution. Neutered on SMEP+HVCI systems but immortal as a teaching example.

WinRing0.sys / AsrDrv / iqvw64e — the OEM long tail

WinRing0.sys (OpenLibSys) underpins a huge number of hardware-monitoring and RGB-lighting tools; it grants MSR and physical R/W and is signed and widespread. AsrDrv* (ASRock) and Intel's iqvw64e.sys are similar. iqvw64e.sys was used by RobbinHood; the sheer number of these OEM "system access" drivers is why the BYOVD supply is effectively inexhaustible.

procexp.sys — Sysinternals Process Explorer

Not a memory-R/W bug but a handle/kill primitive (Class 4): the driver will open protected processes with strong access on the caller's behalf. Tools like Backstab abuse it to terminate or strip handles from EDR/AV processes without any memory corruption at all.

Driver
CVE
Class
Primitive
Famous abuse

RTCore64.sys

2019‑16098

2/3

Virtual R/W + MSR

Generic EDR killers

dbutil_2_3.sys

2021‑21551

1/2

Arb R/W (+weak DACL)

LPE, EDR kill

gdrv.sys

2018‑19320

1/3

Phys R/W + MSR

RobbinHood ransomware

Capcom.sys

5

Ring‑0 pointer call

PoC / red team

iqvw64e.sys

1/3

Phys R/W + MSR

RobbinHood

procexp.sys

4

Handle/kill

Backstab

3.7 Defense — detecting and blocking BYOVD

The exploit runs in the kernel and is nearly invisible while executing. The good news for defenders: the loading and setup are noisy, and the effects (callback removal, token swaps) are observable. Defense is layered.

Prevention (stop the driver loading at all)

  1. Enable HVCI / Memory Integrity. The single highest-impact control. Blocks code execution and DSE-flip, and enables the vulnerable-driver blocklist.

  2. Enable Microsoft's vulnerable driver blocklist explicitly (it isn't on for every SKU/upgrade path). bcdedit/WDAC or via Windows Security → Device Security → Core Isolation.

  3. Deploy WDAC (App Control) in enforced mode with an allow-list. This is the gold standard: only your approved, current drivers load — an unknown vulnerable .sys is denied even if it's freshly signed and not on any blocklist. Blocklists are deny-lists (reactive); allow-lists are proactive.

  4. Remove SeLoadDriverPrivilege from accounts that don't need it and enforce least privilege so an attacker can't reach the loading step.

Detection (assume something loads anyway)

Signal
Source
Notes

Known-bad driver hash / signer

AV, EDR, LOLDrivers feed

Cheap, but only catches known drivers

.sys written outside System32\drivers

Sysmon 11 (FileCreate)

Staging in %TEMP%, user dirs

Kernel service created

Event 4697, Sysmon 13 (...\Services\*\ImagePath), 7045

type=1 + odd path = strong signal

Driver load event

Sysmon 6 (DriverLoad), ETW Threat-Intel

Check signer + reputation

New handle to a rare \Device\*

ETW / EDR

Unusual device opens by unexpected processes

Kernel callback removed

EDR self-integrity / tamper watchdog

High fidelity — sensor notices its own callback vanish

Sensor heartbeat loss right after a driver load

EDR cloud correlation

The "blinding" tell

Token/PPL field mutation

EDR kernel sensor

Detects the data-only payload effect

Hunting queries (conceptual)

Response & resilience

  • Tamper protection with re-registration: an EDR that re-adds and verifies its kernel callbacks, and alerts on removal, defeats the blinding step.

  • Cloud-side heartbeat: detect the absence of expected telemetry, not just its presence — BYOVD's whole goal is to make signals disappear.

  • Isolate & re-image on confirmed kernel compromise. Once ring‑0 is owned, the host cannot be trusted; a rootkit may survive user-mode cleanup.

3.8 Mitigation summary

If you are…
Do this

A defender / IT

HVCI on, blocklist on, WDAC allow-list drivers, strip SeLoadDriverPrivilege, monitor 4697/Sysmon 6/13

An EDR vendor

Kernel callback self-integrity, re-registration watchdog, cloud heartbeat, detect token/PPL mutation

A driver developer

IoCreateDeviceSecure + tight SDDL, avoid METHOD_NEITHER, validate every physical/virtual address & length, never expose MSR/phys-map/pointer-call IOCTLs to user mode

A researcher

Work in snapshotted VMs, disclose responsibly, feed hashes/IOCTLs to LOLDrivers

3.9 References & further reading

  • LOLDriversloldrivers.io (catalog, hashes, IOCTLs, detections)

  • MicrosoftRecommended driver block rules and Memory Integrity (HVCI) documentation

  • CVE‑2019‑16098 (RTCore64), CVE‑2021‑21551 (Dell dbutil, SentinelOne write-up), CVE‑2018‑19320 (GIGABYTE gdrv)

  • hfiref0x/KDU — Kernel Driver Utility (research framework)

  • Windows Internals (Russinovich, Allievi et al.) — I/O manager, IRPs, EPROCESS

  • EDR-killer analyses — AuKill, Terminator/Spyboy, Backstab public reports

  • MITRE ATT&CK — T1068 (Exploitation for Privilege Escalation), T1543.003 (Windows Service), T1562.001 (Impair Defenses)


Series recap

  • Part 1: BYOVD defeats DSE/WHQL/PatchGuard because the driver is genuinely signed; HVCI is the one control that really constrains it.

  • Part 2: the dispatch handler at DriverObject+0xE0 and its IOCTL switch are the whole attack surface; METHOD_NEITHER + FILE_ANY_ACCESS + an unvalidated MmMapIoSpace/__writemsr/pointer-call is the bug.

  • Part 3: one arb R/W primitive → leak ntoskrnl → walk EPROCESS → steal the SYSTEM token (data-only, HVCI-proof). Defenders win at the loading and effect stages, not the (invisible) exploit stage.

Last updated