WinpMem: Volatility's driver that lets malware volatilize

Baptiste David (IT Security Specialist · ERNW)

REcon 2025 · Day 2 · Main Track · Reverse Engineering

Overview

When an organization detects a compromise, the first responder's instinct is to reach for memory forensics tools — capture a RAM dump, feed it to Volatility, and reconstruct what the attacker did. Thi

Watch on YouTube

Visual summary for WinpMem: Volatility's driver that lets malware volatilize by Baptiste David
Visual summary for WinpMem: Volatility's driver that lets malware volatilize by Baptiste David

Key moments

  1. 2:49 WinpMem history: from Volatility project to standalone driver
  2. 10:17 Memory mapping internals: MDL-based physical memory access
  3. 18:11 Critical insight: the most dangerous IOCTL access method
  4. 26:06 Vulnerability: arbitrary kernel memory write primitive
  5. 34:03 Privilege escalation: nullifying security descriptors
  6. 41:25 KASLR bypass: kernel address leak via NtQuerySystemInformation
  7. 48:15 Live PoC: modifying kernel memory via WinpMem

WinpMem: Volatility's Driver That Lets Malware Volatilize

Speakers: Baptiste David, IT Security Specialist, ERNW

Conference: REcon 2025

YouTube: https://www.youtube.com/watch?v=hZjPvYSxDdM

Overview

When an organization detects a compromise, the first responder's instinct is to reach for memory forensics tools — capture a RAM dump, feed it to Volatility, and reconstruct what the attacker did. This response chain depends on a kernel-mode driver called WinPmem, a memory acquisition driver used by Volatility, Velociraptor, and other forensic platforms. At REcon 2025, Baptiste David of ERNW presented a detailed vulnerability analysis of WinPmem, revealing multiple serious flaws including CVE-2024-10972, which allows an unprivileged-but-admin user to trigger a reliable Blue Screen of Death, effectively stopping the forensic investigation dead. More significantly, David demonstrated that vulnerabilities in WinPmem's I/O control dispatch logic provide a "read what/where" primitive across all of physical memory, a constrained "write zero anywhere" primitive, and a "write random value anywhere" primitive — all of which are exploitable to load unsigned kernel drivers, bypass Driver Signature Enforcement (DSE), and ultimately give malware a mechanism to evade the very tools being used to detect it.

Background

▶ Watch: WinpMem history: from Volatility project to standalone driver (2:49)

The Memory Forensics Workflow

When a machine is suspected to be compromised, incident responders typically deploy a user-mode application that silently extracts and loads a kernel-mode driver, captures a raw dump of physical memory, and passes it to an analysis framework like Volatility or Velociraptor for offline processing. The memory dump contains everything: process lists, network connections, loaded modules, injected shellcode, event objects, and encryption keys. It is the gold standard for post-compromise investigation.

WinPmem is the dominant memory acquisition driver in this ecosystem. Written originally by Michael Cohen (who has since departed the Volatility project), WinPmem is open-source. Despite being widely relied upon, it is, as David demonstrates, obsolete and carries serious vulnerabilities. An important clarification David made at the start of the talk: Volatility and WinPmem are technically separate projects. The Volatility developers were at pains to clarify that they do not maintain WinPmem, despite the two being used together almost universally in practice.

Driver Architecture in Windows

Kernel-mode drivers in Windows are represented in memory as a driver object, a large structure that contains a list of dispatch routines. The relevant routine for this research is DispatchDeviceControl — the handler for DeviceIoControl calls. User-mode applications communicate with the driver by calling DeviceIoControl with an I/O control code (IOCTL), an input buffer, and an output buffer.

There are three buffer-sharing methods between user mode and kernel mode:

  • METHOD_NEITHER (method 3): The user-mode buffer address is passed directly to the driver. This is the most dangerous method because the driver is directly manipulating memory under the control of a potentially hostile user-mode process.
  • METHOD_BUFFERED: Windows copies the user-mode buffer into kernel memory before passing it to the driver. Much safer.
  • METHOD_DIRECT (MDL): Uses a memory descriptor list to handle non-contiguous physical memory. Used in specific scenarios.

WinPmem uses METHOD_NEITHER — the most dangerous method — for its I/O control codes. This is the first systemic red flag.

Correct secure practice for kernel drivers receiving user-mode buffers requires: checking that the buffer address falls within user-mode address space, validating alignment, using ProbeForRead / ProbeForWrite inside a __try/__except block before accessing the buffer, and performing all subsequent accesses within that same try/except. Microsoft's documentation is explicit on this.

Key Findings

▶ Watch: Critical insight: the most dangerous IOCTL access method (18:11)

David identified three principal vulnerability classes in WinPmem:

  1. Time-of-Check / Time-of-Use (TOCTOU) race condition in IRP_MJ_GET_INFO IOCTL — enabling a reliable BSOD (CVE-2024-10972).
  2. Missing kernel/user-mode address boundary check in IOCTL_REVERSE_SWITCH_QUERY — enabling a "write zero anywhere in kernel memory" or "write random physical address anywhere" primitive.
  3. "Read what/where" primitive — WinPmem's core purpose of reading all physical memory provides a complete kernel memory read capability usable as a stepping stone for privilege escalation.

Technical Deep Dive

▶ Watch: Vulnerability: arbitrary kernel memory write primitive (26:06)

IOCTL Dispatch and the METHOD_NEITHER Problem

WinPmem's IOCTL handler implements a switch/case over several control codes: get info, set mode, memory read operations, and what the driver calls "reverse switch query" (translating virtual addresses to physical addresses). All of these use METHOD_NEITHER, meaning the driver directly receives raw user-mode buffer pointers.

When the driver initializes, it creates a device named WinPmem using IoCreateDeviceSecure. The security descriptor embedded in that call uses the GA (generic all) access specifier for SY (System) and BA (Built-in Administrators). This means administrator access is the only access control. In the incident response context, this is often acceptable — the assumption is that you're running on an already-compromised machine where the attacker likely already has admin rights. David acknowledges this and frames the rest of the talk accordingly.

CVE-2024-10972: TOCTOU BSOD in GET_INFO

The IRP_MJ_GET_INFO IOCTL handler performs the following sequence:

  1. Checks that the output buffer exists and has a minimum size.
  2. Performs a ProbeForWrite inside a __try/__except block — this validates the buffer is writable at the time of the check.
  3. Outside the try/except, proceeds to write results into the output buffer.

The critical mistake: the ProbeForWrite check occurs inside the try/except, but the actual buffer writes occur after the try/except block exits. This creates a classic TOCTOU race. In the window between the probe (check) and the write (use), an attacker can use VirtualProtect from a separate thread to change the output buffer's memory protection from read/write to read-only. The driver then attempts to write to read-only memory outside a protected region, causing a kernel exception and a Blue Screen of Death.

The exploit is straightforward: spin up a thread that continuously alternates the target page between PAGE_READWRITE and PAGE_READONLY using VirtualProtect. From the main thread, repeatedly invoke the IOCTL. With sufficient parallelism, the race is won — the probe passes when the page is writable, but the write fires when the page is read-only. The BSOD arrives reliably.

The impact on incident response is severe: a sophisticated attacker who detects that forensic tools are being run can simply crash the investigator's machine, destroying volatile memory evidence and interrupting the investigation. David performed this as a live demo at REcon.

IOCTL_REVERSE_SWITCH_QUERY: Write Zero / Write Random Anywhere

The IOCTL_REVERSE_SWITCH_QUERY IOCTL translates a user-supplied virtual address to a physical address. The implementation:

  1. Accepts a user-mode input buffer and copies it inside a try/except — this part is correctly implemented, no TOCTOU here.
  2. Calls vfindPTE, which reconstructs the page table entry (PTE) chain step by step to resolve the physical address.
  3. On success, stores the physical address result in output_physical_address and writes this value to the caller's output buffer inside a ProbeForWrite / try/except block — also correctly done.

The bug: there is no check that the output buffer address is in user-mode address space. A caller can pass a kernel-mode address as the output buffer pointer. Because METHOD_NEITHER is in use and the "correct" probe checks only validate writability but not user/kernel boundary, the driver will write the computed physical address value directly into an arbitrary kernel memory location of the attacker's choice.

This gives two distinct primitives:

  • Write random physical address to any kernel memory location: If the virtual address supplied resolves successfully, the output is the corresponding physical address — a value that is never zero and essentially random from the attacker's perspective but is nonetheless a non-zero write to an arbitrary kernel address.
  • Write zero to any kernel memory location: If the virtual address does not resolve (e.g., because the page is not present in memory), the driver's error-handling path sets output_physical_address = 0 and still writes that zero to the output buffer address. An attacker who controls a virtual address that fails PTE resolution gets a reliable write-zero primitive anywhere in kernel memory.

Combined with WinPmem's inherent "read all physical memory" capability (its designed purpose), an attacker gains a read-everything primitive for free.

Exploitation: Bypassing Driver Signature Enforcement

David explored what can be accomplished with write-zero-anywhere and write-random-anywhere in kernel memory, targeting Driver Signature Enforcement (DSE) — the mechanism that requires all Windows drivers to be digitally signed since Windows XP 64-bit.

Target: ci.dll and g_CiOptions

The traditional DSE bypass involves patching g_CiOptions (formerly g_CiEnabled) in ci.dll — a boolean (or flag word) that controls whether code integrity checking is active. Setting it to zero disables signature verification. However, this has been blocked since Windows 8.1 because PatchGuard monitors protected kernel data structures and triggers a BSOD if they are modified. Furthermore, modern Windows with Virtualization-Based Security (VBS) uses HVCI (Hypervisor-Protected Code Integrity) to enforce code integrity from within the VTL1 secure kernel, making ci.dll patching impossible even with kernel write access.

Alternative: Callback Pointer Replacement

A technique from the 2022 paper "Swan Song for Driver Signature Enforcement Tampering" targets a different approach. When Windows loads a driver, it calls a set of callbacks to validate the signature. One key callback, CiValidateImageHeader, is a complex cryptographic function that returns STATUS_SUCCESS (zero) on success. The technique replaces this callback pointer in the NT kernel's callback list with a pointer to an existing kernel function that always returns zero — effectively making every signature check pass. This requires a write-what/where primitive, which WinPmem does not cleanly provide.

Write-Zero Approach: Security Descriptor Nullification

With only write-zero-anywhere, the most viable documented technique is nullifying the security descriptor pointer of a target process in its EPROCESS structure. In Windows, the EPROCESS object carries a security descriptor; when that descriptor pointer is null, the kernel assumes the object was created with a null DACL, granting access to anyone. By writing zero to the security descriptor field of a highly privileged process's EPROCESS, an attacker can then use OpenProcess, ReadProcessMemory, and WriteProcessMemory to access that process's memory arbitrarily — including the kernel's mapped sections. However, this technique stopped working reliably around Windows 10 build 16007.

Write-Random Approach: CI Policy Structure

The write-random (physical address value) primitive offers more possibilities because any non-zero value evaluates as true in a boolean context. CI's internal structures include policy flags that control enforcement behavior. Writing a non-zero (even random) value to the right structure member can potentially disable enforcement checks. David acknowledged this is inherently risky since writing random values to kernel memory can trigger BSODs, but noted "no risk, no fun."

The fundamental insight is that WinPmem's vulnerabilities, though not trivially exploitable for full code execution, provide meaningful leverage for an attacker to escape the forensic process that is actively trying to detect them.

Demo / Proof of Concept

▶ Watch: KASLR bypass: kernel address leak via NtQuerySystemInformation (41:25)

David conducted a live demo at REcon — on the same VM as two demonstrations, adding to the challenge. The BSOD demo showed:

  1. Starting the WinPmem driver via sc start winpmem.
  2. Launching a user-mode exploit binary that races VirtualProtect against the IOCTL calls.
  3. A reliable Blue Screen of Death, confirming CVE-2024-10972.

The demo had some technical difficulties (recompilation required mid-demo, initial timing issues), which David handled with good humor, noting it was "the only time in my life I've asked for a BSOD to appear during a demo."

Defensive Implications

▶ Watch: Live PoC: modifying kernel memory via WinpMem (48:15)

For Incident Responders:

  • WinPmem should be treated as a vulnerable component, not a trusted forensic primitive. Do not assume that running memory acquisition on a live compromised machine is safe — a sophisticated attacker can detect the acquisition and crash the host.
  • Consider offline or cold-boot memory acquisition methods where possible, bypassing the need to load a driver into a running compromised system.
  • Monitor for attempts to race-condition kernel I/O operations — unusual VirtualProtect calls in tight loops from unprivileged processes interacting with forensic driver IOCTLs is suspicious.

For Forensic Tool Developers:

  • Replace METHOD_NEITHER with METHOD_BUFFERED for all IOCTLs that do not have a compelling reason for direct pointer passing.
  • Perform all buffer accesses — not just the initial probe checks — within the __try/__except block that contains ProbeForRead/ProbeForWrite.
  • Validate that output buffer addresses fall within user-mode address ranges (MmIsAddressValid and explicit user-mode range checks) before writing results.
  • Implement anti-tamper monitoring: if the driver detects rapid memory protection changes on its output buffers, log and alert.

For the Security Community:

  • The broader lesson is that forensic tooling occupies a privileged position in the security stack and is rarely subjected to the same scrutiny as the malware it hunts. WinPmem is open-source — it deserves security audits commensurate with its critical role.
  • The WinPmem project and Volatility project are now explicitly separate. The responsible disclosure of CVE-2024-10972 should drive updates to both, but the ecosystem of tools that embed WinPmem must also update.

Key Takeaways

  • WinPmem uses METHOD_NEITHER for all IOCTL communication — the most dangerous kernel/user buffer sharing method — creating a systemic vulnerability class across all its control codes.
  • CVE-2024-10972 is a straightforward TOCTOU race: perform probe checks inside try/except, then access the buffer outside it. Reversing the order would eliminate the bug.
  • Missing user/kernel address space validation in IOCTL_REVERSE_SWITCH_QUERY creates write-zero-anywhere and write-random-anywhere primitives in kernel memory.
  • Combined with WinPmem's inherent purpose — reading all physical memory — these primitives provide a capable attacker with the tools to neutralize the forensic investigation that seeks to expose them.
  • Memory forensics tooling must be held to the same security standards as any other privileged kernel component. Security tools are high-value targets, and vulnerabilities in them undermine the entire defensive posture they are meant to support.

About the Speaker

Baptiste David is an IT Security Specialist at ERNW, a security consulting firm based in Germany. A regular speaker at major security conferences including DEF CON, Troopers, and ZeroNights, David's research focuses on Windows kernel internals, driver security, and low-level exploitation. He also contributed to the analysis of Windows' Smart App Control feature presented at Troopers the year prior to this talk. At the time of REcon 2025, he had recently returned from Troopers, which concluded the day before his REcon presentation — he presented despite jet lag, having taken the first available flights to Montreal to be present.

Reviews

Dr. Zero (Offensive Security Researcher) — MUST SEE

A forensic tool trusted to investigate compromised machines has kernel write primitives — this is exactly the kind of research that makes the security industry uncomfortable, and that's the point.

Heather Calloway (CISO) — WEAK

A well-executed kernel vulnerability disclosure against forensic tooling that raises a real governance question — are incident responders inadvertently giving sophisticated attackers a weapon — but doesn't develop that question far enough to be actionable for the teams who most need it.

→ Top-rated talks at REcon 2025

All talks from REcon 2025