Windows Kernel Exploits: WRMSR (Model Specific Registers)

Model Specific Registers (MSR) are CPU control registers that are specific for a CPU family. Their original purpose was to introduce experimental new features and functionality, but some of them proved useful enough to be retained across CPU models and are not expected to change in future processors. Intel refers to these as Architectural MSRs.

One example of such a register is the Long-mode System call Target Address Register (LSTAR) MSR. This register provides support to the operating system for handling system calls. The OS can store the address of the system call handler in the LSTAR MSR. When the syscall assembly instruction is executed, it switches the CPU to ring 0 mode (kernel mode) and sets the instruction pointer (RIP) to the value stored in the LSTAR register. As a result, the CPU effectively jumps to the system call handler, enabling the OS to process the system call.

If you can write to IA32_LSTAR (via WRMSR), you effectively control the syscall entry point: Redirect every syscall to your own code or a ROP gadget.

That gives arbitrary kernel execution the next time a Syscall runs. In a nutshell, abusing a vulnerable driver through WRMSR you can: 

  • Save original IA32_LSTAR.,
  • Write gadget address into IA32_LSTAR.,
  • Trigger a syscall (NtYieldExecution, etc.).,
  • CPU jumps to gadget and exploit code executes with kernel privileges.,
  • Restore original IA32_LSTAR for stability and avoid BSOD,

I have extended the msrexec project with an improved Syscall Wrapper and added automation to execute the ROP gadgets and the Kernel functions as Payloads with a wrapper.

  • KVA Shadowing detection and bypass,
  • SMEP bypass using ROP gadgets,
  • Sycall wrapper pointing to LSTAR ROP gadget,
  • Arguments instead of hardcoded driver,
  • Arguments for IOCTLs,
  • Library Injection into Kernel (ring0),
  • System 4 token shellcode (Implemented in C++)

On this screenshot, the vulnerable WRSMR, discovered using Driver Buddy reloaded:

And the code decompiled using Hex-Rays decompiler, no filter, no protections:

And if we follow the xrefs of this function we will end up finding the vulnerable IOCTL code that will lead us to that function from user-mode.

The following screenshot shows the tool IOCTL++ capturing the Kernel Debug messages coming from the exploit itself, and Control Pack agent has been injected as a .DLL in Kernel Space giving us a full agent of Control Pack running with Kernel privileges.

 

And on this last screenshot, as a proof of concept, the same exploit has been used but instead we have replaced the token of the current process with the token of PID 4 (System)

Back to blog