Jan 22, 2026·7 min read·183 visits
CVE-2026-20805 is a local info-leak in `dwm.exe` that reveals kernel memory addresses. While it doesn't execute code on its own, it allows attackers to bypass Kernel Address Space Layout Randomization (KASLR), a primary defense mechanism in Windows. It is currently listed in the CISA KEV catalog, meaning ransomware groups and APTs are actively chaining it with other exploits to achieve privilege escalation.
A seemingly benign information disclosure vulnerability in the Windows Desktop Window Manager (dwm.exe) serves as a critical KASLR bypass primitive. By querying system handle information, unprivileged local attackers can leak raw kernel virtual addresses associated with ALPC ports, effectively de-randomizing the kernel memory layout.
In the modern exploit development landscape, memory corruption is only half the battle. You might have a perfectly good buffer overflow or a Use-After-Free (UAF), but if you don't know where you are in memory, you are firing blind. This is thanks to Kernel Address Space Layout Randomization (KASLR), which shuffles the kernel's furniture every time the system boots. To win, an attacker first needs a map. Enter CVE-2026-20805.
This vulnerability resides in the Desktop Window Manager (dwm.exe), the process responsible for the pretty visual effects, window composition, and transparency in Windows. Because DWM needs to talk to practically everything on the screen, it holds a massive number of handles to system objects. It sits at a privileged intersection between user-land and kernel-land.
Security researchers discovered that dwm.exe is a bit of a blabbermouth. When asked politely via specific Windows Native APIs, it inadvertently hands over the raw 64-bit virtual addresses of its kernel objects. For an attacker, this is like finding the blueprints to the bank vault taped to the front door. It transforms a 'guess-and-pray' exploit attempt into a calculated, deterministic strike.
The root cause of this vulnerability is a failure to sanitize kernel metadata before returning it to user mode. The Windows kernel tracks resources using 'Objects' (Files, Processes, Threads, etc.), and user-mode applications reference these via 'Handles'.
When a process calls NtQuerySystemInformation with the SystemExtendedHandleInformation class, the kernel generates a list of all open handles on the system. Historically, Microsoft has hardened this API. For standard users, the Object pointer field (which contains the actual kernel memory address) is supposed to be redacted—usually zeroed out or obfuscated—to prevent exactly this kind of mapping.
However, the logic handling Asynchronous Local Procedure Call (ALPC) ports and Section Objects within the context of dwm.exe missed a spot. The specific structures initialized for DWM's ALPC communication channels fail to apply the necessary mask when enumerated. This means that when the handle table is traversed, the kernel says, 'Here is the handle ID, and oh, here is the exact 64-bit memory address where the ALPC port object lives in the kernel pool.'
> [!NOTE]
> Technical Nuance: This isn't a corruption bug. The code works exactly as written; it just shares too much. It is a logic error in the boundary between SystemExtendedHandleInformation reporting and the specific object type attributes of DWM's resources.
To understand the gravity of the situation, we have to look at how an attacker views the system. They aren't looking at source code; they are looking at structures returned by the Windows Native API. The critical structure involved is SYSTEM_HANDLE_TABLE_ENTRY_INFO_EX.
Below is a reconstruction of the data leak. A secure implementation (Before the exploit is known) assumes the kernel sanitizes the pointer. The vulnerable reality allows the Object field to pass through untouched.
// Definition of the handle information structure
typedef struct _SYSTEM_HANDLE_TABLE_ENTRY_INFO_EX {
PVOID Object; // <--- THE LEAK. Should be NULL/Obfuscated for low-priv users.
ULONG_PTR UniqueProcessId; // We look for DWM's PID here
ULONG_PTR HandleValue;
ULONG GrantedAccess;
USHORT CreatorBackTraceIndex;
USHORT ObjectTypeIndex; // We look for ALPC Port (24/25) or Section (36)
ULONG HandleAttributes;
ULONG Reserved;
} SYSTEM_HANDLE_TABLE_ENTRY_INFO_EX, *PSYSTEM_HANDLE_TABLE_ENTRY_INFO_EX;In a simplified pseudo-code representation of the kernel's handle enumeration routine, the failure looks something like this:
// Pseudo-code of the kernel logic handling the query
foreach (Handle in SystemHandles) {
Entry.UniqueProcessId = Handle.OwnerPid;
Entry.HandleValue = Handle.Value;
// Security Check: Should we hide the kernel address?
if (RequesterMode == UserMode && !HasDebugPrivilege) {
// The Fix would ensure ALL object types are scrubbed here.
// The Bug: Specific ALPC objects owned by DWM bypass this or
// are incorrectly classified, leaking the raw pointer.
Entry.Object = NULL; // Expected behavior
} else {
Entry.Object = Handle.KernelObjectAddress; // Vulnerable path taken
}
CopyToUserBuffer(UserBuffer, &Entry);
}Because of the oversight in CVE-2026-20805, the Entry.Object is populated with a value like 0xFFFFD58F80C0E5E0. Since the attacker knows the offset of the ALPC Port object relative to the Kernel Base (or can use the object to fingerprint the heap), KASLR is defeated.
Exploiting this vulnerability is trivial for any code running on the machine, even with low privileges. The attack does not require a race condition or complex heap grooming. It is a deterministic read.
dwm.exe. This is standard behavior for any tool.NtQuerySystemInformation with the SystemExtendedHandleInformation (64) class.UniqueProcessId == DWM_PID.ObjectTypeIndex corresponding to ALPC Ports (typically index 24 on modern Windows versions, though this varies slightly by build).Object pointer. By subtracting known offsets for the specific Windows version (which can be determined dynamically), the attacker calculates the ntoskrnl.exe base address.Once the KASLR slide is known, the attacker can adjust their ROP (Return Oriented Programming) gadgets in a secondary exploit (e.g., a vulnerable driver or another kernel bug) to achieve reliable code execution.
You might ask, 'So what? It's just an address.' In the world of high-tier exploitation, an information leak is often more valuable than a crash. A crash denies service; a leak enables control.
This vulnerability carries a CVSS score of 5.5, which feels deceptively low. However, its inclusion in the CISA Known Exploited Vulnerabilities (KEV) catalog tells the real story. Threat actors are using this right now.
Many kernel vulnerabilities (like integer overflows or pool corruptions) are 'unreliable' because hitting the wrong memory address causes a Blue Screen of Death (BSOD), killing the attack and alerting defenders. By using CVE-2026-20805 to peek at the memory layout first, attackers turn 10% reliability exploits into 100% reliability weapons.
This vulnerability is particularly dangerous because it affects all modern versions of Windows, from Windows 10 up to Server 2025. It serves as the skeleton key for ransomware operators looking to escalate from a compromised user account to full NT AUTHORITY\SYSTEM control.
The remediation is straightforward but requires a system restart. Microsoft has patched the kernel logic to ensure that queries targeting DWM handles properly sanitize the Object field, regardless of the object type.
NtQuerySystemInformation originating from non-administrative processes. While legitimate software uses this API, repeated calls followed by memory probing are indicative of an exploit attempt.CVSS:3.1/AV:L/AC:L/PR:L/UI:N/S:U/C:H/I:N/A:N| Product | Affected Versions | Fixed Version |
|---|---|---|
Windows 10 1809 Microsoft | < 10.0.17763.8276 | 10.0.17763.8276 |
Windows 11 23H2 Microsoft | < 10.0.22631.6491 | 10.0.22631.6491 |
Windows Server 2025 Microsoft | < 10.0.26100.7623 | 10.0.26100.7623 |
| Attribute | Detail |
|---|---|
| CWE ID | CWE-200 |
| Attack Vector | Local (AV:L) |
| CVSS Score | 5.5 (Medium) |
| EPSS Score | 5.86% (High Percentile) |
| Impact | Kernel Address Space Layout Randomization (KASLR) Bypass |
| Exploit Status | Active Exploitation (CISA KEV) |
The product exposes sensitive information to an actor that is not explicitly authorized to have access to that information.
CVE-2026-128087 (GHSA-9264-jvgf-6w2f) is an incorrect behavior order (CWE-696) and improper authorization (CWE-863) vulnerability in the russh Rust SSH library, affecting versions 0.55.0 through 0.65.0. During the initial SSH key exchange (KEX) handshake, the client state machine invokes the client::Handler::kex_done() callback—providing the negotiated raw shared secret bytes—prior to validating the remote server's host key or certificate via check_server_key(). Consequently, an untrusted or rogue SSH server can complete cryptographic key agreement and force a connecting client to execute side-effecting application logic inside kex_done() before the server's identity is checked and rejected.
CVE-2026-128082 (GHSA-6vhm-j9h7-f9gh) is an uncontrolled recursion vulnerability (CWE-674) in AutoMapper, a convention-based object-object mapper for .NET. When mapping nested or self-referential types into destination models that rely on parameterized constructors, C# positional records, or recursive ConstructUsing expressions, AutoMapper evaluates child constructor arguments prior to incrementing the parent's recursion depth counter. This ordering flaw bypasses both explicit MaxDepth limits and the default depth limit of 64. An unauthenticated remote attacker can supply deeply nested input payloads to affected endpoints, exhausting the thread call stack and triggering an uncatchable System.StackOverflowException that terminates the hosting .NET process.
An information exposure vulnerability in the @opentelemetry/instrumentation-http package for OpenTelemetry JavaScript versions 0.204.0 prior to 0.222.0 causes incoming HTTP server spans to record raw, unredacted query string parameters under the url.query attribute. While outgoing client spans applied built-in and user-configured query parameter redaction, incoming server spans bypassed this sanitization completely, resulting in the transmission of sensitive credentials such as pre-signed cloud URLs and API tokens to external observability backends.
CVE-2026-128089 is an uncontrolled resource consumption vulnerability in the dnspython toolkit for Python, affecting all versions prior to 2.9.2. When parsing Well-Known Service (WKS) records from text via dns.rdtypes.IN.WKS.WKS.from_text(), the parser fails to validate that numeric service port identifiers fall within the RFC 1035 valid range of 0 through 65535. An attacker capable of supplying untrusted zone files or RDATA text strings containing an arbitrarily large service port integer can force the parser to allocate an unbounded bitmap array using an inefficient linear append loop, resulting in severe CPU exhaustion, application hangs, or Out-Of-Memory (OOM) process termination.
CVE-2026-126347 (GHSA-5cjw-f85j-cv6r) is an open redirect vulnerability (CWE-601) in Tornado, an asynchronous Python networking library and web framework. The flaw resides in tornado.web.RedirectHandler when dynamic URL redirection templates incorporate unvalidated user input. Due to a parser differential between RFC 3986 (used by Python's urllib.parse.urlsplit) and the WHATWG URL Standard (used by modern web browsers), inputs containing three or more leading slashes bypass Tornado 6.6.0's validation logic, allowing unauthenticated attackers to redirect users to arbitrary external domains.
A Denial of Service (DoS) vulnerability exists in @sveltejs/adapter-node versions 5.5.7 and 6.0.0-next.0 through 6.0.0. When a SvelteKit server route returns a direct response from a fetch() call with a Content-Type of text/event-stream, the Node.js adapter attempts to mutate the response headers to disable proxy buffering. Because headers returned directly by the WHATWG Fetch API carry an immutable guard, this mutation throws an unhandled TypeError, terminating the underlying Node.js process and denying service to all active and subsequent clients.