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