CVE-2026-13043 Kernel Memory Access

Discovered by: Juan Sacco  
Vendor: Panda Antivirus Security / WatchGuard  
Component: Panda Kernel Memory Access Driver  
Driver module: pskmad.sys
CVE: 2026-13043 
CVSS Score: 9.3
Link: https://psirt.watchguard.com/CVE-2026-13043

CVE Summary

A missing authentication vulnerability in the Kernel Memory Access Driver (PSKMAD) used by WatchGuard endpoint security products allows a local, authenticated attacker to bypass the driver's access-control handshake and issue arbitrary privileged commands to the driver, resulting in disclosure of kernel and process memory.

Introduction

This advisory documents a vulnerability reported to Panda Security in the Panda Kernel Memory Access Driver, pskmad.sys used by several of their products. This vulnerability was confirmed, assigned the CVE-2026-13043 number and resolved by Panda Security in October 2026.

The affected driver exposes a kernel memory access interface that can be reached from user mode through the device object created by the driver. By abusing the driver's IOCTL interface, a local attacker, among other things.. can read virtual memory from an arbitrary process through the signed kernel driver (as shown in the poc).

The proof of concept in this advisory demonstrates:

RDMSR through the driver -> Info leak kASLR
process virtual-address mapping -> Arbitrary read of any target process
page-sized process memory transfers
process memory dumping through IOCTL requests

The affected driver:

File name:       pskmad.sys
Description:     Panda Kernel Memory Access Driver (x64)
Internal name: PSKMAD_64
Company:        Panda Security, S.L.U.
Product name: Panda Technologies
File version:     1.1.0.23
Version:           1.1.0.45
Size:                63,360 bytes
SHA256:          9bf3b737afa4d4f5e7b00ec749d4b75656ad66d9a2b402e1e81934e95ba7df5b
Signature:       Microsoft Windows Hardware Compatibility Publisher

The driver exposes the following device names:

\Device\PSMEMDriver
\Global??\PSMEMDriver

The interface is intended for memory access operations. The vulnerable behavior is in the way user-controlled requests are accepted and translated into privileged kernel operations.

Driver Capabilities

The import table shows the driver has code paths for process lookup, process attachment, MDL handling, section mapping, physical memory mapping, and system-thread execution.

Relevant imported routines include:



These routines are commonly seen in legitimate kernel components that need memory inspection features. In this case, the externally reachable IOCTL layer allows a user-mode caller to drive sensitive operations.

IOCTL Interface

The proof of concept uses the following control codes:

IOCTL_TRANSFER     0xB3702C08
IOCTL_ENTRY_MAP    0xB3702C0C
IOCTL_ENTRY_UNMAP  0xB3702C10
IOCTL_MSR          0xB3702C3C

Decoded:

TRANSFER            0xb370  0xb02     METHOD_BUFFERED  FILE_ANY_ACCESS
ENTRY_MAP         0xb370   0xb03     METHOD_BUFFERED  FILE_ANY_ACCESS
ENTRY_UNMAP    0xb370   0xb04     METHOD_BUFFERED  FILE_ANY_ACCESS
MSR                       0xb370   0xb0f      METHOD_BUFFERED  FILE_ANY_ACCESS


All four requests use METHOD_BUFFERED and FILE_ANY_ACCESS.

The IOCTL buffers use the following magic value:

0xXXXXXXXX (Hidden to avoid misusage)

Device Open Handshake

The driver has a gated open path based on an extended attribute packet named:

PsOpenPacket000

The exploit first attempts a normal NtCreateFile with an EA buffer containing the expected packet name and fields.

The handshake uses named objects:

Global\DOGPskMadSec_*
Global\DOGPskMadSignal_*
Global\DOGPskMadReply_*

The user-mode side creates:

CreateFileMappingW(Global\DOGPskMadSec_*)
CreateEventW(Global\DOGPskMadSignal_*)
CreateEventW(Global\DOGPskMadReply_*)

Then it sends the EA packet to NtCreateFile. A helper thread waits for the signal event, maps the shared section, writes the expected gate value, and signals the reply event.

The flow including the gate looks like this::

Create shared section
Create signal event
HIDDEN! Sorry :-)
HIDDEN! Sorry :-)
HIDDEN! Sorry :-)
HIDDEN! Sorry :-)
HIDDEN! Sorry :-)
Signal reply event
Receive device handle

After the handle is open, exploitation continues through DeviceIoControl.

MSR Read Primitive:

The IOCTL_MSR path allows the caller to request a model-specific register read.

The proof of concept reads `IA32_LSTAR`:

MSR index: 0xC0000082
Name:      IA32_LSTAR
The request layout used by the exploit:

offset  size  description
0x00    4     magic = 0xXXXXXXXX (HIDDEN! Sorry :-))
0x04    4     request size
0x08    4     operation flag
0x0c    8     caller PID
0x14    4     CPU index
0x18    4     MSR index
0x1c    8     output value

The decompiled IOCTL used for MSR Read 0xB3702C3C in the dispatcher:

And the function that does the actual _readmsr with the buffer:

The exploit prints the returned value:

[+] IA32_LSTAR = 0x... (We get the L_STAR)

This confirms that the driver executes the privileged MSR read and returns the result to the caller.

Process Memory Read Primitive

The arbitrary process memory read is built from three IOCTLs:

ENTRY_MAP
TRANSFER
ENTRY_UNMAP

The exploit provides:

target PID
target virtual address
read size

The map request uses this layout:

offset  size  description
0x00    4     magic = 0xXXXXXXXX (HIDDEN! Sorry :-))
0x04    4     request size
0x0c    4     operation flag
0x10    8     target PID
0x18    8     target virtual address
0x24    4     requested size
0x28    4     output flags
0x30    4     output entry count
0x3c    4     map flag

If the map operation succeeds, the driver returns entry metadata. The exploit copies that metadata into a transfer request and sends a simple IOCTL_TRANSFER.

The transfer request copies bytes from the target process virtual address into the caller-controlled output buffer. In the following screenshot the IOCTL used for the transfer: 0xB3702C08

And inside the function sub_13D90 (following references) we land into the interesting transfer mechanism, as shown in the screenshot below:

The primitive exposed by the exploit is:

read_process_va(handle, pid, va, size) -> bytes

In the following screenshot the IOCTLs used to Map/Unmap a process: IOCTL_ENTRY_MAP    0xB3702C0C
IOCTL_ENTRY_UNMAP  0xB3702C10

And following the 0xB3702C0C (map a process) we can see the interesting, but expected, behavior from a driver module used by an Antivirus software:

And if we follow the function we can see it obtains the Current Process ID by walking the KProcess (part of the EPROCESS structure) this handle is later used to map the process memory.

And in the following screenshot, the interesting part where via the selected process it maps the VA of that arget:

After each transfer, the exploit calls IOCTL_ENTRY_UNMAP (0xB3702C10) to release the mapped entries, as shown in the screenshot below:

Dumping a Process:

The proof of concept enumerates readable user-mode memory ranges with VirtualQueryEx.

The target process is opened with query rights:

PROCESS_QUERY_INFORMATION
PROCESS_QUERY_LIMITED_INFORMATION

SeDebugPrivilege` is enabled when available.

For every committed readable region, the exploit reads memory in chunks up to one page:

for each VirtualQueryEx region:
    if State == MEM_COMMIT:
        if Protect is not PAGE_NOACCESS and not PAGE_GUARD:
            read 0x1000 bytes through pskmad.sys
            print hexdump

The read operation is performed by the driver itself. As expected. the resulting output is a hexdump of the target process memory.

Exploit Sequence:

1. We create and start the pskmad kernel service if needed. Meaning, Panda Security has not been installed on the target machine.
2. Open \\.\PSMEMDriver
3. Complete the PsOpenPacket000 handshake.
4. Send IOCTL_MSR to read IA32_LSTAR.
5. Set the target PID: Example LSASS
6. Enumerate committed readable user-mode regions with VirtualQueryEx.
7. For each page:
   - send IOCTL_ENTRY_MAP
   - send IOCTL_TRANSFER
   - send IOCTL_ENTRY_UNMAP
8. Print the target process memory as a hexdump.

In the screenshot below a proof of concept running in a fully patched Windows 11 25h2 with VBS/HVCI/kCET enabled, dumping the memory of LSASS PID: 1020 process:

Impact:

A malicious user can make use of the driver features for malicious purposes, in example dump any process VA, read L_STAR via RDMSR (leads to nt_base infoleak)

The affected driver exposes a kernel memory access interface that can be reached from user mode through the device object created by the driver. By abusing the driver's IOCTL interface, a local attacker can read virtual memory from an arbitrary process through the signed kernel driver. A local attacker with access to the vulnerable driver interface can read memory from another process by supplying a PID and virtual address to the driver.

Depending on the target process, this can expose:

credentials
tokens
session material
private keys
application secrets
browser data
security product process memory
other sensitive process-resident data

The MSR path also exposes privileged CPU state to the caller. In the proof of concept, it is used to read IA32_LSTAR. This could be abuse, in example to obtain the Kernel Base and defeat kASLR.

Recommended mitigations:

Update Panda / WatchGuard products to a fixed release.
Restrict the device ACL to trusted product processes.
Validate caller identity before allowing memory or MSR operations.
Apply normal Windows process access checks to target PIDs.
Validate all virtual address, size, flags, and entry-count fields.
Remove user-controllable MSR access from production builds.
Block vulnerable driver hashes where the driver is not required.
Monitor unexpected access to \\.\PSMEMDriver

Previous public research has documented vulnerabilities in related Panda memory access drivers, including older issues tracked as CVE-2015-1438, CVE-2017-8339, CVE-2023-6330, CVE-2023-6331, and CVE-2023-6332.

References:

[Sophos X-Ops: Multiple vulnerabilities discovered in widely used security driver](https://www.sophos.com/en-us/blog/multiple-vulnerabilities-discovered-in-widely-used-security-driver)

[NVD: CVE-2017-8339](https://nvd.nist.gov/vuln/detail/CVE-2017-8339)

[CVE: CVE-2015-1438](https://www.cve.org/CVERecord?id=CVE-2015-1438)

Back to blog