.. /blog
2026-02-06 // 11 min

SmmInfect: Launching a Hypervisor from Ring -2

smmfirmwarering-2

I flashed a custom SMM module into my motherboard firmware. It runs before the OS boots, before Secure Boot checks anything, before the kernel even exists in memory. Ring -2. The deepest privilege level on the machine. And from there, I launch a hypervisor.

The idea is simple. System Management Mode has its own protected memory region -- SMRAM -- that the OS cannot read, cannot write, cannot even address. If I can get code running in SMM, I have a persistence mechanism that survives OS reinstalls, disk wipes, everything short of reflashing the BIOS chip itself.

This post is about SmmInfect -- a standalone C hypervisor compiled as an edk2 DXE_SMM_DRIVER, flashed into the UEFI firmware image, that detects the Windows kernel at runtime and virtualizes the machine from underneath it.

Getting into SMRAM

Consumer AMD boards don't fuse Platform Secure Boot (PSB). This means modified BIOS images boot just fine -- the CPU doesn't verify the firmware signature. I extracted the stock BIOS with UEFITool, inserted my DXE_SMM_DRIVER module into the firmware volume, rebuilt the image, and flashed it with Q-Flash Plus. Q-Flash Plus doesn't even need the board to POST -- you rename the file to GIGABYTE.bin, stick the USB drive in the designated port, and press a button. If anything goes wrong, I reflash stock the same way. Zero risk of a brick.

SMRAM on my board is 8MB. That's tight, but it's enough for a minimal hypervisor -- the VMCB is 4KB, the host save area is 4KB, NPT tables take maybe 2MB for identity mapping, and my code + data fits in under 1MB. The rest is buffer space for the MSR permission bitmap and stack.

The SMM entry point

An SMM driver registers a callback that fires on a specific System Management Interrupt. But I don't want to rely on software-triggered SMIs -- I want my code to run automatically on a timer. The UEFI spec gives me PeriodicTimerDispatch -- a hardware timer that fires an SMI every N ticks. I set it to ~64ms.

// register a periodic SMI -- fires every ~64ms
PeriodicSmiDispatch->Register(
    PeriodicSmiDispatch,
    PeriodicTimerCallback,
    &TimerContext,
    &PeriodicTimerHandle
);

// inside the callback:
if (DetectWindowsKernel()) {
    VirtualizeCore();
}

Every 64 milliseconds, the CPU drops everything, enters SMM, and runs my callback. The entire OS freezes during this -- SMM is non-maskable, non-interruptible, completely invisible to the operating system. The OS literally cannot know it's happening.

Detecting the Windows kernel

The tricky part is knowing when to virtualize. My SMI fires from the moment the board powers on, long before any OS is loaded. I can't just call VirtualizeCore() on every tick -- there's nothing to virtualize during POST.

I use a CR3/RIP heuristic. When the SMI fires, I read the interrupted context's CR3 (page table base) and RIP (instruction pointer). The Windows kernel's CR3 is always in a recognizable physical address range, and ntoskrnl.exe loads at a predictable virtual address range. Once both match, I know the kernel is up and running.

static BOOLEAN DetectWindowsKernel(void) {
    UINT64 cr3 = ReadSaveStateCr3();
    UINT64 rip = ReadSaveStateRip();

    // kernel CR3 is always below 4GB on Windows
    if (cr3 > 0x100000000) return FALSE;

    // ntoskrnl loads in the 0xFFFFF800`00000000 range
    if ((rip & 0xFFFFF80000000000) != 0xFFFFF80000000000)
        return FALSE;

    // additional check: read MZ header at kernel base
    return ValidateKernelImage(cr3, rip);
}
This heuristic has a false positive rate of effectively zero. No other code runs with CR3 below 4GB and RIP in the kernel address range during early boot. Once I detect the kernel, I set a flag and never check again -- VirtualizeCore() runs once and the periodic timer unregisters itself.

VirtualizeCore from SMM

Once I know the kernel is live, I build a VMCB right there in SMRAM, enable SVM via EFER.SVME, set up the host save area, and call VMRUN. The interrupted context becomes the guest. The CPU resumes executing exactly where it was before the SMI -- except now it's running as a guest inside my hypervisor.

The code is pure C with inline NASM for the VMRUN instruction. No Rust here -- edk2's build system wants C, and honestly for a 2000-line SMM module the language doesn't matter much. What matters is that every byte fits in SMRAM and I don't touch any memory the OS might be watching.

The 8MB constraint

SMRAM is small. I can't use ExAllocatePool -- there is no kernel memory manager in SMM. I can't call any OS API. Everything is statically allocated or comes from a fixed-size bump allocator I wrote in about 40 lines. The NPT tables are the biggest consumer -- 2MB pages keep the table small, but I still need a PML4, a few PDPTs, and the PD entries. I pre-allocate all of it in a single contiguous block.

The upside of this constraint is that the entire hypervisor state lives in SMRAM, which the OS cannot address. I don't need NPT tricks to hide my memory -- SMM hiding is done in hardware by the memory controller. The SMRAM region simply doesn't exist from the OS's perspective.

Recovery and Q-Flash Plus

I bricked the board twice during development. Not real bricks -- Q-Flash Plus recovered both times in under 90 seconds. The first time I had a size overflow in the firmware volume that corrupted the SEC phase. The second time I accidentally nuked the NVRAM volume. Both times: USB drive with stock BIOS, press button, wait for LED to stop blinking, reboot. Back to stock. This is why I specifically chose a Gigabyte board for this project -- Q-Flash Plus is the best firmware recovery mechanism on consumer hardware.

PSB (Platform Secure Boot) is AMD's hardware firmware verification. If fused, the CPU checks the BIOS signature against a key burned into the processor itself. Consumer desktop CPUs ship with PSB unfused -- the OTP bits are all zeros. Server EPYC parts are typically fused. I verified my Ryzen 7 5800XT has PSB disabled by reading MSR 0xC00110A2. All clear.

Why SMM matters

The Rust blue-pill from post 01 is powerful, but it has a weakness -- it loads after the OS. Secure Boot can block the driver. PatchGuard can detect the virtualization. Anti-cheats that run early enough might see the transition.

SmmInfect flips that entirely. My code runs before the OS exists. By the time Windows boots, it's already a guest. There's no "before" state to compare against. No transition to catch. The machine was virtualized from the start.

First successful launch was March 9th, 2026. I booted into Windows, opened Task Manager, and there it was -- a hypervisor detected, zero trace of how it got there. Nothing in the event log. No driver loaded. No service registered. Just a machine that was born virtualized.