The Emulators Gambit: Executing Code from Non-Executable Memory

The Emulators Gambit: Executing Code from Non-Executable Memory

The article demonstrates debugging a technique where a VEH handler emulates execution of shellcode stored in non-executable .data memory using chained hardware breakpoints so the memory protection never changes. #Win32HWBPs #MyExceptionHandler

Keypoints

  • Shellcode resides in the .data section at address 0x00007FF7D71C5080 with bytes 0x90 0x90 0x90 0x90 0x90 0xC3 visible in the debugger.
  • Memory protection for the region is PAGE_READWRITE (0x04) with no execute permission, confirming NX is enforced.
  • A VEH (Vectored Exception Handler) named MyExceptionHandler is used and a breakpoint is set there to observe exception handling flow.
  • Hardware breakpoint DR0 is set to the shellcode address and DR7 enables the breakpoint, causing EXCEPTION_SINGLE_STEP (0x80000004) before any instruction fetch.
  • The handler emulates each instruction (five NOPs and a RET), updates RIP, and sets the next hardware breakpoint to create a chain of single-step exceptions.
  • After emulating the RET, the handler reads the return address from the stack, updates RIP to return to main, increments RSP, clears the hardware breakpoints, and returns EXCEPTION_CONTINUE_EXECUTION.
  • Throughout execution the memory protection never changes, no VirtualProtect calls are made, and the program confirms β€œ[+] Returned cleanly from emulated code”.

MITRE Techniques

  • [T1218 ] System Binary Proxy Execution – Using a legitimate debug mechanism (hardware breakpoints and VEH) to execute code from non-executable memory by emulating instructions: β€œthe hardware breakpoint triggered before the CPU attempted to fetch the instruction from non-executable memory.”
  • [T1595 ] Active Scanning – Observing and verifying memory and register state via debugger to confirm protections and behavior: β€œwe can examine the shellcode buffer in memory… the Memory Map window with our .data section highlighted.”
  • [T1106 ] Native API – Manipulating low-level CPU debug registers (DR0, DR7) and exceptions to alter control flow without changing page protections: β€œDR0 contains 0x00007FF7D71C5081… DR7 contains 0x0000000000000401.”
  • [T1055 ] Process Injection – Emulating instructions and chaining hardware breakpoints to run code located in a writable non-executable region instead of creating executable pages: β€œthe handler emulates the current instruction (incrementing RIP for a NOP), sets the next hardware breakpoint at the updated RIP address.”

Indicators of Compromise

  • [Memory Address ] shellcode location in demo – 0x00007FF7D71C5080, 0x00007FF7D71C5085 (RET address)
  • [Register Values ] debug registers context – DR0=0x00007FF7D71C5081, DR7=0x0000000000000401 (hardware breakpoint enabled)
  • [File/Program Name ] demo executable – Win32HWBPs.exe (used for the walkthrough)
  • [Console Output ] execution confirmation – β€œ[+] Returned cleanly from emulated code”


Read more: https://redops.at/en/blog/the-emulators-gambit-executing-code-from-non-executable-memory