0-Day MSR Kernel Exploit for Windows 11 25H2
Share
New 0-day Windows Kernel Exploit, working in Windows 11 25h2 fully patched.
It took me 2 weeks of endless coffee cups!
MSRs control where the CPU jumps for privileged transitions, they are a sensitive part of system state. Operating systems carefully them during boot to point to legitimate kernel entry routines.The OS uses WRMSR to set up the IA32_LSTAR MSR so that the CPU knows where to jump on a SYSCALL.
If an attacker somehow gains kernel-mode execution (for example, by exploiting a driver bug or a mis-signed kernel module), then those instructions become available. In that scenario, malicious code could modify MSRs to redirect control flow, alter CPU protections, or conceal malicious activity.
That’s why modern defenses such as exist:
- Secure Boot
- Driver Signature Enforcement
- Supervisor Mode Execution Prevention (SMEP)
- Kernel Patch Protection (PatchGuard)
They make it extremely difficult for arbitrary code to reach a state where it could misuse these privileged instructions.
They configure privileged features like:
- System call entry points (
IA32_LSTAR,IA32_SYSENTER_EIP) - CPU feature enables (
IA32_EFER,CR4bits) - Segment base addresses (
IA32_FS_BASE,IA32_GS_BASE) - Performance monitoring and debugging controls
These registers can only be read or written in ring 0 (kernel mode).
They are not accessible to user-mode code attempting to use RDMSR or WRMSR from user mode causes a #GP (General Protection) fault.
WRMSR: Writing to model specific registers is done via the WRMSR instruction. ECX contains the register, EDX contains the high 32bits of data, and ECX contains the lower 32bits of data.
RDMSR |
Reads a 64-bit value from a Model-Specific Register (MSR) | Ring 0 only (CPL 0) | Returns value in EDX:EAX
|
WRMSR |
Writes a 64-bit value to a Model-Specific Register (MSR) | Ring 0 only (CPL 0) | Uses EDX:EAX as source |

RDMSR: Read from model specific register is done via RDMSR. ECX contains the register index (the MSR number) to read from. After execution, the CPU places the 64-bit value from that MSR into EDX:EAX, where EDX contains the high 32 bits of the value and EAX contains the low 32 bits.
| Register |
RDMSR (Read) |
WRMSR (Write) |
|---|---|---|
| ECX | MSR index to read | MSR index to write |
| EAX | Receives low 32 bits of MSR value | Supplies low 32 bits of value to write |
| EDX | Receives high 32 bits of MSR value | Supplies high 32 bits of value to write |

What this exploit achieves? Arbitrary Windows Kernel ROP execution in Windows 11 25h2 to subvert control of the KiSystemCall64 entry point via the IA32_LSTAR model-specific register.
Preparation steps:
All offsets and gadgets are calculated during runtime using as starting point an infoleak from a separate vulnerability on a second driver, this is optional for stealth.
And if available for simplicity, Enumdevicedrivers, but yes, more noisy.
Protections:
LSTAR: Holds the address of KiSystemCall64 inside ntoskrnl.exe; after KVA-shadowing patches were applied, LSTAR instead points to KiSystemCall64Shadow.
SMEP: Is a bit in control register CR4; you can check CPU support for it with CPUID (set EAX = 7). When enabled, SMEP prevents attempts to make the CPU execute kernel code from user-space pages for example, it blocks writing LSTAR to point at a user-controlled page.
SMAP: The AC flag in EFLAGS disables SMAP when set. Although the STAC instruction (which sets AC) is privileged, a user-mode context can still load a crafted EFLAGS value from the stack using POPFQ, thereby setting the AC bit and disabling SMAP.
Check smep/smap in WinDBG: .printf "CR4=%p SMEP=%u SMAP=%u\n", @cr4, ((@cr4 & 0x00100000)!=0), ((@cr4 & 0x00200000)!=0)
Return-Oriented Programming (ROP) is an exploitation technique that allows an attacker to execute arbitrary code without injecting new code. Instead, it chains together short instruction sequences called gadgets that already exist in executable memory, each ending with a RET instruction.
In the Windows kernel (ntoskrnl.exe), these gadgets are small fragments of legitimate kernel code that can be repurposed to manipulate registers, control flow, or system state.
By carefully arranging them on the stack, a ROP chain can perform complex privileged actions while bypassing certain memory protections like non-executable (NX) memory.
The core components of this ROP chain include a MOV CR4 gadget, a POP RCX gadget, and finally a SYSRET gadget.
Initially static ROP gadgets were used for this exploit, with rp-win tool, but then wanted to make it more universal as this will only work for one specific Kernel version:
.\rp-win.exe --va 0 --rop 3 -f C:\Windows\System32\ntoskrnl.exe > rop.txt

And thanks to find_gadget() (credits: backengineering) we can find these gadgets during runtime, allowing this exploit to work in Windows 10, and Windows 11 as these gadgets are available in both windows version, but different offsets of course.
Driver bootstrap : Starts with the exploit VA at a signed but vulnerable ring‑0 driver. It opens an existing device or temporarily installs one, two if using an infoleak.
Through that driver we get arbitrary MSR read/write primitives.
Exploitation: While still in user land it leaks the IA32_LSTAR value, the kernel’s usermode-kernelmode syscall bridge, then recovers the ntoskrnl base. that, or an infoleak, is the starting point, that we use to locate the offset of the ROP gadgets inside ntoskrnl (pop rcx, mov cr4, rcx, sysret) and discover KPCR offsets needed to rebuild the kernel stack after hijacking the syscall path.
Hijacking MSR: We write the IA32_LSTAR MSR to point at the gadget chain instead of the legit KiSystemCall64, offset of KiSystemCall64, was obtained using MSR_READ. The handler pivots into the ROP sequence, disables SMEP by momentarily switching CR4, and then jumps into the payload in user VA that runs with full kernel privileges, thanks to the MSR.
Payload: Not just a shellcode! The payload uses RtlFindExportedRoutineByName (resolved at runtime) to call whatever kernel APIs we want (e.g., enumerate processes, fire IPIs to read CR4 on every core, whatever we want!). After finishing, we restore the original KiSystemCall64 address in IA32_LSTAR, re-enables SMEP, and drops back to user mode.
After changing the ROP gadgets I decided to change my ROP Payload from a hardcoded chain of bytes to dynamic exports. That would make the exploit much more powerful, it was tricky, but at the end it was worth it.
The payload went from this:

The kroutine get_system_routine resolves the function offsets we want to call, during runtime, using as a base the Kernel Base address and RtlFindExportedRoutineByName.

After that the payload, looks like this instead:

Here is where I have re-implement in code the token swap shellcode, looking for the current process, and the system process with PID 4, search for the eprocess structure and swap the tokens with the current process.

And here is the token swap section, and as I wanted this exploit to work in Windows 10 and Windows 11, the eprocess structure changes between these versions and the offset for the token has to change. 0x248 Windows 11 and 0x4b8 for Windows 10
In WinDBG you can see the token value assuming you already know the eprocess address:


And to achieve this I have used RtlGetVersion that give us the build number, this function has also been resolved using get_system_routine via RtlFindExportedRoutineByName during runtime.

Then, to actually proof the concept, the mandatory NT/System shell:

What is coming next?
As we can resolve functions during runtime instead of using an arbitrary chain of bytes, the possibilities are endless, disabling ETW, driver signature check, calling NtLoadDriver and load your own unsinged driver like KDMapper, then put it back together and keep your Kernel access? But prior of implementing this I'm currently working on a Physical Memory Mapping primitive exploit, so I have an skeleton working for these two exploit classes in Windows 11 25h2, then the Payload execution with these features could be shared among both. Stay tunned!
TL;DR: I found a 0-day exploit, combined it with an infoleak, and made it work in a fully patched Windows 11. It’s a privilege-escalation that turns any MSR read/write primitive into reliable kernel execution: leak the syscall target, hijack the trampoline with a minimal gadget chain, run arbitrary ring‑0 code, then put everything back so the system keeps behaving as if nothing happened.