Uninformed: Informative Information for the Uninformed

Vol 8» 2007.Sep

KeBugCheckEx Protection

One of the first bypass mechanisms proposed for PatchGuard 1 was to hook the code responsible for bugchecking the system[4]. From there, an attacker would simply resume normal system execution.

There are several defensive mechanisms in place to prevent this. In the the current version of PatchGuard, the entire contents of the thread stack are filled with zeros, making it difficult to resume execution of whichever thread was responsible for calling into PatchGuard. Furthermore, PatchGuard appears to make a copy of KeBugCheckEx at system initialization time, and copy this version over the actual code residing within the kernel at runtime just before bringing down the system in a bug check. This is clearly visible by making a modification to KeBugCheckEx in the debugger just as one enters the PatchGuard check context, and then setting a breakpoint on the internal function in the PatchGuard context to call KeBugCheckEx after clearing the stack and all registers. If one then examines KeBugCheckEx, any modifications that have been made will have vanished.

Additionally, PatchGuard appears to disable DbgPrint (patching it out with a "ret" opcode) before calling KeBugCheckEx. This may have been a (failed) attempt to prevent easy access to execution within KeBugCheckEx without actually patching KeBugCheckEx itself, which would circumvent the aformentioned protection on modifications to the bugcheck code itself. (KeBugCheckEx ordinarily utilizes DbgPrintEx to display a banner to the debugger when a bug check occurs. However, because PatchGuard only patches DbgPrint, there is no little to no effect in terms of what ends up happening when the bug check finally does happen.)

This code can be seen in the PatchGuard check routine, just before a call to the KeBugCheckEx wrapper is made. The pointer to DbgPrint is established during PatchGuard initialization at boot time.

mov     rax, [rbx+PATCHGUARD_CONTEXT.DbgPrint]
mov     byte ptr [rax], 0C3h ; '+' ; ret