Machine Check Exceptions as a State Disruptor

▶ Watch (00:27)

Interrupt suppression is the standard defense against privilege-transition attacks. Kernel code clears the interrupt flag, clears the trap flag, clears DR7, latches NMI, latches SMIs, masks signals. Every controllable exception source gets shut off. Rafal (2012), Peterson’s pop-ss trick, and Google Project Zero’s TDX seam loader finding all exploited unexpected exceptions that slipped through exactly this kind of suppression.

Machine check exceptions bypass all of it. No flag clears them. No microcode latches them. They fire when the hardware itself reports a fault, and the CPU delivers them unconditionally. That one property makes every interrupt-suppression scheme incomplete.

Generating MCEs On Demand via North Bridge Fuzzing

▶ Watch (06:42)

The north bridge logs PCI master aborts in a machine check bank, and master aborts are software-controllable. Domas pulled 24 candidate configuration bits, flipped them individually, and got only hangs. He built a fuzzer: trigger a PCI abort, check whether the MCA banks logged a hit. The north bridge fuzzer finds MCE-triggering bit configuration (14:33) found two bits that do it.

“We’ve got a hammer, but we can only hit ourselves with it right now.” — Christopher Domas

That MCE fired on the same core that triggered it, which is useless for exploitation. Domas modified the fuzzer to search cross-core. After several hours it found three north bridge bits. The cross-core MCE delivery demo (16:12) shows core 1 originating the exception and core 0 receiving it.

System Management Mode as the Exploit Target

▶ Watch (18:59)

Ring zero sounds like the finish line. It is not. SMM, System Management Mode, sits below the kernel, below the hypervisor, invisible to all of them. It has run on x86 processors for 35 years. Microcode is the only thing that can open SM RAM, and code running there can write malware into platform firmware, surviving an OS reinstall or a hard drive wipe.

That is why it is the target. Compromising SMM means code execution at ring minus 2, with access to memory the kernel cannot read or even acknowledge exists.

The Unmodified IDTR: AMD’s Architectural Vulnerability in SMM

▶ Watch (22:33)

AMD’s SMM entry specification lists the IDTR as “unmodified.” That one word is the vulnerability. IDTR points to the interrupt descriptor table, which tells the CPU where to dispatch exceptions. When SMM fires, AMD leaves that pointer set to whatever the OS was using. Any exception inside SMM, including a divide-by-zero, goes to the attacker’s handler.

“It’s kind of like taking all your code and jamming it into the function main and then wrapping main and a try accept block where the accept block just pops a shell.” — Christopher Domas

AMD’s documentation acknowledges the risk and recommends writing firmware without bugs. EDK2 does eventually load a safe IDT, but only after re-enabling machine check handling in CR4. That ordering creates two distinct attack windows: one for any exception before the lidt instruction, and a narrower one for machine checks between the mov CR4 and lidt.

MC Hammer — Timing the Cross-Core Attack Window

▶ Watch (25:58)

The attack window opens 10,000 cycles into SMM entry and closes 100 cycles later. A compliant MMIO read takes 700 cycles. Competing traffic, underclocking, and complex PCI topologies pushed reads to 4,000 cycles. Still not enough. Then:

“I was following the specification coding requirements and that’s not what you want to do in CPU exploitation. You want to violate the requirements.” — Christopher Domas

He demonstrated the unaligned MMIO fuse instruction timing (31:03): an unaligned 8-byte MMIO read breaks into three sub-accesses totaling ~12,000 cycles. A small delay on the victim thread shifts the window to match. Cross-core MCE delivery, timed to 100 cycles during SMM entry, had a name: MC Hammer.

Live Demo, SM RAM Dump, and Mitigations

▶ Watch (36:37)

Domas ran the MC Hammer live SMM compromise demo (36:37) on stage. MC Hammer installs the malicious IDT, measures the north bridge to find the right fuse delay, poisons the master abort escalation bits, then fires the timed SMI and MCE together. With code executing inside SMM, a C2 payload copies SM RAM to kernel-readable memory. The dump shows flash access routines, USB drivers, UEFI variable storage, the lock box, S3 resume state, and PSP doorbell registers — all of it now readable from ring 0.

The EDK2 patch Domas submitted removes the MCE vector from the early IDT, closing the machine check path on pre-Zen AMD platforms. The IDTR problem stays open: any exception before SMM loads a safe IDT still hands control to the attacker. As for what comes next:

“machine checks turn out to be really powerful but they’ve never really been explored for exploitation before” — Christopher Domas

Notable Quotes

machine checks turn out to be really powerful but they’ve never really been explored for exploitation before Christopher Domas · ▶ 39:37

It’s kind of like taking all your code and jamming it into the function main and then wrapping main and a try accept block where the accept block just pops a shell. Christopher Domas · ▶ 23:34

We’ve got a hammer, but we can only hit ourselves with it right now. Christopher Domas · ▶ 15:44

I was following the specification coding requirements and that’s not what you want to do in CPU exploitation. You want to violate the requirements. Christopher Domas · ▶ 29:51

I built a hammer for machine checks. I built an MC hammer is the tool that we’ve got at our disposal now. Christopher Domas · ▶ 32:39

Key Takeaways

  • Suppress all interrupts you want — machine check exceptions bypass every defense and fire unconditionally.
  • Generate real hardware MCEs entirely from software by fuzzing north bridge configuration bits to escalate PCI master aborts.
  • Violating MMIO alignment specs creates a hardware fuse that times cross-core MCE delivery into a 100-cycle SMM attack window.