Home BlogThe Phantom Pointer — Decoding Invalid Memory Access (0x50 & 0x7E)

The Phantom Pointer — Decoding Invalid Memory Access (0x50 & 0x7E)

by dnaadmin

In our previous articles, we covered timing and resource deadlocks. Now, we return to the most frequent “bread and butter” of Windows debugging: The Access Violation.

When a driver tries to read or write to a memory address that doesn’t exist, is protected, or has already been freed, the CPU throws an exception. If the kernel doesn’t have a specific handler for that exception, it triggers Bug Check 0x50: PAGE_FAULT_IN_NONPAGED_AREA or 0x7E: SYSTEM_THREAD_EXCEPTION_NOT_HANDLED.


1. The Architecture of a Memory Fault

Windows uses a virtual memory system. Every address a driver sees is “Virtual.” The Hardware Management Unit (MMU) translates this into a “Physical” address using Page Tables.

A crash happens when:

  1. NULL Pointer: The driver tries to access address 0x00000000 (the most common bug).
  2. Use-After-Free: The driver accesses memory it already released back to the Pool.
  3. Instruction Corruption: The CPU tries to execute data as if it were code.

2. Real Use Case: The Race Condition Pointer

Scenario: A high-speed imaging driver crashes randomly during device initialization. The BSOD shows 0x50.

Step 1: Analyze the Faulting Address

Run !analyze -v.

  • Arg1: ffffa00012345678 (The memory address referenced)
  • Arg2: 0x00 (Read operation) or 0x01 (Write operation)

Step 2: Context is King

With a 0x7E or 0x50, the stack trace might look “garbage” if the instruction pointer (RIP) itself is corrupted. Use the Trap Frame to restore the registers to the exact state at the crash:

Plaintext

kd> .trap ffff8001`5521a000

Step 3: Disassembling the Failure

Now, look at the exact instruction that failed using u . (unassemble at current IP):

Plaintext

MyCameraDriver!StartCapture+0x7b:
fffff801`4a22047b 488b01          mov     rax,qword ptr [rcx]

The Insight: The CPU tried to move data from the address held in the RCX register into RAX.

If we check the registers:

kd> r rcx

rcx=0000000000000020

The Diagnosis: 0x20 is a “near-NULL” pointer. It usually means the driver has a structure pointer that is NULL, and it tried to access a member at offset 0x20.


3. Debugging “Use-After-Free” with PageHeap

Standard memory pools are recycled quickly. If Driver A frees memory and Driver B immediately allocates it, Driver A might still have a “dangling pointer” and overwrite Driver B’s data without a crash.

To catch this, use Verifier /flags 0x1 (Special Pool).

  • Windows will place the allocation at the very end of a page.
  • When the driver frees it, the page is marked “Invalid” immediately.
  • Any subsequent access by the dangling pointer triggers an immediate 0x50, catching the bug at the source rather than miles down the road.

4. Pro-Tips for the Blog

  • Initialize Your Pointers: Always set pointers to NULL after calling ExFreePool.
  • Check for NULL: Never assume ExAllocatePool succeeded. Always if (Pointer == NULL) return STATUS_INSUFFICIENT_RESOURCES;.
  • Understand the “Non-Paged” Requirement: If you are at DISPATCH_LEVEL, your code and data must be in non-paged memory. If the OS has to “page in” your code from the disk while you are at a high IRQL, you get a 0x50.

Summary Table: Access & Exception Bug Checks

CodeNameDescription
0x50PAGE_FAULT_IN_NONPAGED_AREAAccessing invalid memory at an IRQL that forbids page faults.
0x7ESYSTEM_THREAD_EXCEPTION_NOT_HANDLEDA general “catch-all” for kernel-mode exceptions (like divide-by-zero).
0xD1DRIVER_IRQL_NOT_LESS_OR_EQUAL(Recall Article 1) Specifically a page fault at high IRQL.
0x3BSYSTEM_SERVICE_EXCEPTIONAn exception happened while transitioning from User mode to Kernel mode.

With this, you have the foundational toolkit for 90% of the BSODs you will encounter in your career. Which of these scenarios have you seen most often in your labs?

You may also like

Leave a Comment