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:
Arbitrary read → leak
ntoskrnlbase → defeat KASLR → resolve symbols.Arbitrary write → data-only edits: token theft, callback removal, DSE flip.
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.
PsInitialSystemProcessis 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:
System = kread64(PsInitialSystemProcess)→ SYSTEM's EPROCESS.Follow the
ActiveProcessLinksdoubly-linked list untilUniqueProcessId == GetCurrentProcessId()to find our own EPROCESS.sysTok = kread64(System + Token) & ~0xF(mask the low reference-count bits of theEX_FAST_REF).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!_EPROCESSin 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
0xFFFFFFFFFFFFFFFFintoToken->Privileges.Present/Enabledto grant every privilege without swapping tokens (stealthier — the token still "belongs" to you).Integrity level downgrade removal: raise your process integrity to System.
Protectionfield flip: setEPROCESS.Protectionto make your process a PPL (Protected Process Light), frustrating EDR that respects PP/PPL.ImageFileNamespoof: 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
PsSetCreateProcessNotifyRoutinetelemetry 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.
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)
Enable HVCI / Memory Integrity. The single highest-impact control. Blocks code execution and DSE-flip, and enables the vulnerable-driver blocklist.
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.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
.sysis denied even if it's freshly signed and not on any blocklist. Blocklists are deny-lists (reactive); allow-lists are proactive.Remove
SeLoadDriverPrivilegefrom accounts that don't need it and enforce least privilege so an attacker can't reach the loading step.
Detection (assume something loads anyway)
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
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
LOLDrivers —
loldrivers.io(catalog, hashes, IOCTLs, detections)Microsoft — Recommended 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+0xE0and its IOCTLswitchare the whole attack surface;METHOD_NEITHER+FILE_ANY_ACCESS+ an unvalidatedMmMapIoSpace/__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