Back
Game Security Research

Breaking the MmCopyMemory Bypass

April 2026
windows-internalskerneldetectionhardwaremca

What's This About

A few weeks ago, someone posted on UnknownCheats about breaking MmCopyMemory by flipping the ParityError bit in the PFN database. The idea is straightforward, if you mark your driver pages as having parity errors, MmCopyMemory fails with STATUS_HARDWARE_MEMORY_ERROR and anti-cheats can't dump your code. I've actually known about this method for ages, but it seems to have just surfaced publicly now. The problem with this approach is that while it blocks memory dumping, it creates a detection surface that anti-cheats can exploit during execution checks.

The Original Technique

The method exploits the MMPFNENTRY3 structure sitting at offset 0x23 in each PFN entry. By setting bit 7 (the ParityError bit), you make MiCopySinglePage return STATUS_HARDWARE_MEMORY_ERROR whenever MmCopyMemory tries to read that page. Pretty clean bypass for memory scanning on the surface, but there's a fundamental problem that becomes obvious once you understand how anti-cheats can detect it during execution.

struct _MMPFNENTRY3 {
    UCHAR Priority:3;
    UCHAR OnProtectedStandby:1;
    UCHAR InPageError:1;
    UCHAR SystemChargedPage:1;
    UCHAR RemovalRequested:1;
    UCHAR ParityError:1;  // bit 7
};

The technique assumes that anti-cheats will just check if MmCopyMemory succeeds or fails, and if it fails with a hardware error, they'll assume the memory is legitimately faulty and move on. The problem is that this creates an obvious detection vector during execution checks that I initially overlooked.

Initial Analysis: MCA Registers and NVRAM

When I first analyzed this technique, I looked into how Windows handles real hardware parity errors. ECC memory or the memory controller detects corrupted bits in physical RAM, the CPU generates a Machine Check Exception (Exception 18), and the hardware logs the error in Intel's Machine Check Architecture registers before Windows even gets notified. These MCA registers (IA32_MCi_STATUS and IA32_MCi_ADDR) are Model-Specific Registers that log hardware errors at the microarchitecture level.

I initially thought cross-referencing PFNs with ParityError against MCA registers would be a solid detection method. However, this has a critical timing problem. Windows clears MCA registers immediately after processing via HalpMcaClearError as mandated by the Intel SDM. By the time an anti-cheat scans, both legitimate old hardware errors and fake ParityError manipulations would show no MCA records, creating false positives.

I then considered NVRAM persistence as an alternative. During my Windows internals trace, I noticed WheapPersistPageForMemoryError calls HalSetEnvironmentVariableEx to save bad PFN numbers to NVRAM under "UncorrectedBadMemoryPage". I thought this could be used for detection since many cheat implementations don't update NVRAM. However, my good friend 0AVX corrected me on this approach and pointed out why it doesn't work.

Why NVRAM Detection Doesn't Work

As 0AVX explained, the NVRAM variable only exists to carry a single page frame number across a reboot boundary when the kernel is about to die due to a fatal bugcheck and cannot write to disk. Looking at when WheapPersistPageForMemoryError is called, both call sites in the WHEA error processing path terminate in a bugcheck. The function only runs on the fatal error path, not for corrected or recoverable errors.

There are three outcomes when the operating system detects a memory error. Corrected errors are fixed transparently by ECC hardware, if the same page accumulates too many corrections, WHEA proactively retires it through MmMarkPhysicalMemoryAsBad on the live system. Uncorrectable but recoverable errors are cases where the data is corrupted but the processor's internal state is still intact, handled by WheapAttemptErrorRecovery. If recovery succeeds, the page is offlined and persisted to BCD or the registry by the live system. Fatal errors are cases where either the processor's own internal state is corrupted, or recovery was attempted and failed. The handler must signal the operating system to reset, leading directly to WheapPersistPageForMemoryError followed by a bugcheck.

The NVRAM variable exists only for the last case, where the kernel is about to bugcheck and cannot safely write to disk. On the next boot, WheapCheckForAndReportErrorsFromPreviousSession runs during early kernel initialization. It reads the NVRAM variable, copies the page frame number to BCD via WheaPersistBadPageToBcd, and then deletes the NVRAM variable by calling HalSetEnvironmentVariableEx with NULL data. This means the NVRAM variable is transient and won't exist during normal anti-cheat scanning, making it useless for detection.

The Real Detection Method

Now, this was originally a research excercise but I want to demonstrate an actual way to detect this, so I will go to the root of the truth, being execution. Anti-cheats don't need to scan memory looking for ParityError bits or cross-reference against hardware state. Instead, detection happens during execution checks when using NMIs or any interrupt-based mechanism to examine what code is currently running.

When an anti-cheat fires an NMI or interrupt and captures the current instruction pointer, it can resolve that address to its corresponding PFN and check two things: does this PFN have the ParityError bit set, or/and is this PFN in the system's bad page list?

If code is actively executing from a page marked as having parity errors, that's an immediate detection. Windows would never execute code from a page it believes has hardware faults. The entire point of marking pages as bad is to retire them from service, not to continue using them for critical operations like code execution.

This is significantly simpler and more reliable than trying to validate against MCA registers or NVRAM. The detection happens in real-time during execution checks that anti-cheats are already performing. There's no timing window, no false positives from legitimate past hardware errors, and no reliance on transient NVRAM variables.

Wrapping Up

The ParityError bit technique blocks memory dumping via MmCopyMemory, but it creates an obvious detection surface during execution checks. While my initial analysis focused on static validation against MCA registers and NVRAM, the real detection method is much simpler: when anti-cheats check what's executing via NMIs or interrupts, they can simply verify that the executing code isn't from a page marked as bad. Executing from a ParityError page is impossible under legitimate Windows operation, making it a reliable detection signal.