## https://sploitus.com/exploit?id=C3D90422-8858-5EAC-A8E5-588AF315EA86
# CVE-2026-42978 PoC & Research — Windows Push Notifications Use-After-Free
Race condition in Windows Push Notifications service (`WpnService`) that runs as `NT AUTHORITY\SYSTEM`. An attacker with local access can trigger a use-after-free during platform shutdown and potentially elevate privileges.
- **CVE:** [CVE-2026-42978](https://msrc.microsoft.com/update-guide/vulnerability/CVE-2026-42978)
- **BDU:** [BDU:2026-08249](https://pm.gov.ru/vul/2026-08249)
- **Type:** CWE-362 (Race Condition), Use-After-Free
- **CVSS:** 7.8 (High)
- **Affected:** Windows 10, Windows 11, Windows Server 2016/2019/2022/2025
- **Patched:** June 10, 2026 (Patch Tuesday)
- **Status:** Fixed. This repo is for defensive research only.
## How It Works
`WpnService` is the Windows Push Notification service. It runs in session 0 as LocalSystem inside `svchost.exe -k netsvcs -p`. All notification delivery — toasts, tiles, badges — goes through it.
The vulnerability sits in `wpncore.dll`, specifically in the `PresentationEndpointFacade` class. This class wraps all notification API calls (toast delivery, session management, settings queries, etc.) and delegates to `PresentationEndpointImpl`.
The bug: during platform shutdown, the `NotificationPlatform` object gets destroyed. But the Facade methods don't check if shutdown is in progress — they grab a pointer to the platform, the platform gets freed by the shutdown thread, and the Facade uses a dangling pointer. Classic use-after-free race.
### Vulnerable code (decompiled from wpncore.dll build 26100.8521)
```c
// PresentationEndpointFacade::ToastUnblockAll โ VULNERABLE
long ToastUnblockAll(PresentationEndpointFacade *this) {
// No lock. No shutdown check. Just grab the platform pointer and go.
NotificationPlatformHandle::Get(this + 0x50);
if (platform == NULL) Throw_Hr(...);
// If shutdown frees the platform right here โ use-after-free
return PresentationEndpointImpl::UnblockToastsForEachApp(...);
}
```
Ghidra: vulnerable ToastUnblockAll — no synchronization before accessing the platform
### Patched code (wpncore.dll build 26100.8655)
```c
// PresentationEndpointFacade::ToastUnblockAll โ PATCHED
long ToastUnblockAll(PresentationEndpointFacade *this) {
if (Feature_4097557817::IsEnabled()) {
AcquireSRWLockShared(&Wns::s_platformLock); // 1. shared lock
if (Wns::s_platformShutdown) // 2. shutdown guard
Throw_Hr(E_APPLICATION_EXITING);
NotificationPlatformHandle::Get(this + 0x50);
// ... do work ...
ReleaseSRWLockShared(&Wns::s_platformLock); // 3. RAII release
} else {
// feature flag off โ old behavior preserved for rollback
}
}
```
The fix adds three things:
1. **`AcquireSRWLockShared`** — shared readers-writer lock. Multiple API calls can run concurrently, but shutdown takes an exclusive lock and blocks them all.
2. **`s_platformShutdown` check** — if shutdown already started, bail out immediately with `E_APPLICATION_EXITING`.
3. **RAII lock release** — the lock is held in a `wil::unique_storage` wrapper, so it gets released even if an exception is thrown.
The feature flag `Feature_4097557817` is for staged rollout via WIL (Windows Internal Library). It lets Microsoft enable the fix gradually and disable it if something breaks.
Ghidra: vulnerable build (left tab) vs patched build (right tab)
### Scale of the fix
This isn't a one-function bug. The same lock+guard pattern was added to **49 functions** in `wpncore.dll`:
| Category | Functions |
|----------|-----------|
| Toast operations | `ToastUnblockAll`, `ToastCreateSession`, `ToastCloseSession`, `ToastRequestAllNotifications`, `ToastSuppress` |
| Tile operations | `TileCreateSession`, `TileCloseSession`, `TileRequestResourceForeground` |
| Registration | `RegisterApplication`, `UnregisterApplication`, `RegisterHandler`, `UpdateRegistration`, `RegisterSystemApplication` |
| Settings | `ChangeAppSetting`, `QueryAppSetting`, `QueryGlobalSetting`, `RegisterSettingCallback`, `UnregisterSettingCallback` |
| Delivery | `Deliver`, `GetPayloadForNotificationId`, `Submit`, `PostScheduledNotification` |
| Queries | `GetRegisteredHandler`, `GetRegisteredHandlersFromParent`, `GetSettingsFromHandler`, `GetAssetsFromHandler` |
Every `PresentationEndpointFacade::*` method that touches the platform got the same fix. The `PresentationEndpointImpl::*` methods underneath are unchanged — the issue was only at the facade layer.
## Impact
WpnService runs as SYSTEM. If the race is won:
1. The freed `NotificationPlatform` object's memory can be reclaimed and filled with attacker-controlled data (heap spray)
2. A subsequent virtual method call on the dangling pointer jumps to an attacker-controlled address
3. Code execution as `NT AUTHORITY\SYSTEM`
The actual exploitation — heap spray, vtable hijacking, achieving code execution — is outside the scope of this research. This repo focuses on **understanding the root cause** and **building detection**.
## TOCTOU Race Condition Lab
The `lab/` directory contains a standalone C demo that reproduces the class of bug without touching WpnService. It uses a named pipe + shared memory architecture similar to WpnService.
**How it works:**
- `vulnerable_service.exe` reads a message length from shared memory, validates it, sleeps for 50ms, then reads the length **again** (double-fetch).
- `race_attacker.exe` sets a safe length, triggers the service, then immediately flips the shared memory to an overflow value.
- If timing is right, the service reads the overflow value on the second fetch — buffer overflow.
Run `vulnerable_service.exe --patched` to see the fix: single-fetch capture into a local variable.
Left: service detects race (5/5). Right: attacker flipping shared memory values.
### Build and run
Requires GCC (MinGW). From the `lab/` directory:
```bat
build.bat
```
Terminal 1:
```bat
vulnerable_service.exe
```
Terminal 2:
```bat
race_attacker.exe 5
```
Then compare with `vulnerable_service.exe --patched` — same attack, zero races detected.
## Detection
### ETW Monitor (`detection/etw_wpn_monitor.ps1`)
PowerShell script that checks 7 indicators:
1. WpnService state and PID
2. Crash/restart history (failed exploitation leaves crash traces)
3. Push Notifications Platform event log burst detection
4. WPN-related named pipes
5. Patch verification (checks wpncore.dll date)
6. Processes with WPN modules loaded
7. Symlink/junction audit in notification data paths
```powershell
powershell -ExecutionPolicy Bypass .\detection\etw_wpn_monitor.ps1
```
ETW monitor: WpnService running (PID 6432), no crashes, 100 events/hour, system patched
### Sysmon Rules (`detection/sysmon_wpn_race_detect.xml`)
Six rule groups for continuous monitoring:
| Rule | What it catches |
|------|----------------|
| `WPN_EoP_ChildProcess` | svchost (netsvcs) spawning cmd/powershell/wscript |
| `WPN_PipeAccess` | Connections to WPN-related named pipes |
| `WPN_FileCreation` | File creation in notification data directories |
| `WPN_RegistryTampering` | Registry writes to PushNotifications keys |
| `WPN_ProcessAccess` | `PROCESS_ALL_ACCESS` handles to svchost |
| `WPN_ThreadInjection` | `CreateRemoteThread` into svchost |
Install:
```bat
sysmon64.exe -accepteula -i detection\sysmon_wpn_race_detect.xml
```
### Event Viewer
WpnService activity is logged in `Microsoft-Windows-PushNotifications-Platform/Operational`. Key events to watch:
- Event 1225: transport-level WPN commands
- Rapid event bursts (>20/min) — possible race spray
- Error/Critical events — possible crash from failed exploitation
Event Viewer: PushNotifications-Platform operational log, Event ID 1225
## Patch Diffing
Key findings from diffing `wpncore.dll`:
- `.text` section grew by **18,432 bytes** (new lock/guard code across 49 functions)
- `.data` section grew by **96 bytes** (new `Wns::s_platformLock` and `Wns::s_platformShutdown` globals)
- No new imports added — `AcquireSRWLockShared`/`ReleaseSRWLockShared` were already in the import table
- New RAII destructor: `~unique_any_t` confirms lock wrapper addition
Full reports are in `reports/`.
## Related CVEs
CVE-2026-42978 is part of a cluster of 9 WPN-related vulnerabilities fixed in June 2026:
| CVE | Type | CWE |
|-----|------|-----|
| CVE-2026-42977 | EoP | Race Condition |
| **CVE-2026-42978** | **EoP** | **Race Condition** |
| CVE-2026-42979 | EoP | Race Condition |
| CVE-2026-42991 | EoP | Race Condition |
| CVE-2026-42969 | Info Disclosure | Race Condition |
| CVE-2026-42970 | Info Disclosure | Race Condition |
| CVE-2026-42973 | Info Disclosure | Race Condition |
| CVE-2026-26167 | EoP | — |
| CVE-2026-32160 | EoP | — |
## Project Structure
```
CVE-2026-42978/
โโโ README.md
โโโ lab/
โ โโโ vulnerable_service.c # mock WpnService with double-fetch bug
โ โโโ race_attacker.c # attacker that exploits the double-fetch
โ โโโ build.bat # GCC build script
โโโ detection/
โ โโโ etw_wpn_monitor.ps1 # 7-check PowerShell detector
โ โโโ sysmon_wpn_race_detect.xml # Sysmon rule config
โโโ reports/
โ โโโ PE_DIFF_REPORT.txt # PE section/import diff results
โ โโโ FUNCTION_DIFF_REPORT.txt # function-level diff (49 changed)
โโโ img/ # screenshots for this README
```
## Requirements
- Windows 10/11 (for running the lab and detection tools)
- GCC / MinGW (for building the C lab)
- Python 3.9+ (for diffing scripts)
- Ghidra 11+ (for headless decompilation, optional)
- Sysmon (for detection rules, optional)
## Disclaimer
This project is for **defensive security research**. The vulnerability is patched. No weaponized exploit code is included. The TOCTOU lab demonstrates the class of bug on a standalone mock service — it does not interact with WpnService or any system component.
Make sure your Windows is up to date. If `etw_wpn_monitor.ps1` reports your system as unpatched — install the June 2026 cumulative update immediately.
## Contributing
If you have something to add — better detection rules, sploit PoC, a Ghidra Version Tracking session, YARA signatures, or analysis of the related CVEs in this cluster — PRs are welcome.
Ideas for contributions:
- Sigma rules for the SIEM side of detection
- Deeper analysis of CVE-2026-42977/42979/42991 (same WPN race family)
- WinDbg-based heap analysis of the use-after-free
- Improved ETW monitor with real-time ALPC burst detection
- Windows Defender ASR rule recommendations
Open an issue if you have questions or want to discuss the research.
## License
MIT