Flag: Tornado! Hurricane!

Blogs >> omeg's Blog

Created: Tuesday, July 13 2010 19:21.10 CDT  
Printer Friendly ...
Kernel debugger vs user mode exceptions
Author: omeg # Views: 60576

Kernel debugger is a nice and nifty tool allowing us to do things not otherwise possible. Total control over debugged OS and all processes is the main reason to use it. However, there are some hiccups and obstacles that may disrupt our work. One of the most common is the case of intercepting user-mode exceptions with kernel-mode debugger.

Let's assume we have windbg connected to the debuggee OS as a kernel mode debugger. What can we do to catch user-mode exceptions that interest us? First, there is the 'Debug | Event Filters' menu (or sx* commands) that controls debugger's behavior when it does encounter an exception in debugged code. In short, 'Execution - Enabled' option tells the debugger to break on the specific exception. There is a catch though - it only works for kernel mode code 'out of the box'. That is, if we enable breaks on 'Illegal instruction' and run some user-mode program on the debugged OS that generates it, windbg won't break. Why? Well, we're in the kernel debug mode after all.

How to make it work then? It's pretty simple. All NT-based Windows systems support 'Global Flags' debugging mechanism in the kernel, which is a collection of system-wide debugging flags. From within windbg we can access it using '!gflag' extension command. And one of the flags is 'Break on exceptions' - which means kernel debugger will be notified not only of kernel-mode exceptions, but also user-mode ones. Neat. To activate it, use '!gflag +soe' windbg command.

Now all is well, we can see that windbg breaks on every exception in user-mode code. Or does it? There is still one special case that evades our cleverly laid traps. If the user-mode program A is being debugged (using user-mode Debug API) by user-mode program B, we (windbg running as a kernel-mode debugger) won't get exceptions coming from program A - program B will get them instead. It's a bit counter-intuitive, as one would think that a kernel-mode debugger should receive every exception before user-mode debuggers. That isn't the case though, and it seems to be the design decision by Microsoft. All is not lost though - we can still force windbg to receive every and all exceptions before they get to any user-mode debugger in the debugged OS.

To learn how to do that, we need to dive deep into the Windows' kernel function responsible for kernel-mode exception dispatching - KiDispatchException. This is the 'main' code responsible for deciding what to do with an exception that was encountered. It services both kernel-mode and user-mode exceptions, first- and second-chance ones, and most importantly - decides whether to notify kernel debugger about the event or not. Not all events are forwarded to kd (kernel debugger), as we've learned before. But because we are in control of the target system, we can modify the KiDispatchException routine to do our bidding - or routing ALL exceptions to kernel debugger first.

The exact details of the patch vary between systems, but structure of KiDispatchException function is pretty much the same. Using IDA to reverse engineer the kernel, studying Windows Research Kernel or ReactOS sources certainly helps. Disassembly of original KiDispatchException function along with the patch point from two Windows systems is provided below - 32-bit Windows XP Pro and 64-bit Windows 7 with all updates as of 2010-07-14. Modifying other kernels is left as an exercise to the reader. :)

XP 32-bit
7 64-bit

Blog Comments
j00ru Posted: Wednesday, July 14 2010 00:17.33 CDT
Hey, interesting post!

One thing that should be noted, is that your modification can only work correctly, if the KD is attached right at the boot-time in case of 64-bit system versions. This is caused by the specific way of how PatchGuard is initialized:

"This means that if a debugger is attached to the system prior to the indirect initialization of the PatchGuard protections, then the protections will not be initialized because the divide error fault will not be triggered. (...) However, this only works if the debugger is attached to the system during boot. If a developer subsequently attaches a debugger after PatchGuard has initialized, then the act of setting breakpoints or performing other actions may loead to a bluscreen as a result of PatchGuard detecting the alterations."
(via Bypassing PatchGuard on Windows x64, Uninformed)

Otherwise, you end up with the CRITICAL_STRUCTURE_CORRUPTION bugcheck (verified in practice).

Besides that, cool idea.

acel Posted: Friday, November 14 2014 08:44.52 CST
Besides the PatchGuard issue on 64-bit system, is it better by simple patch nt!KdIsThisAKdTrap to return TRUE always? This makes all user mode exception to pretend as KD trap and will be delivered to KD at first.

djnemo Posted: Monday, November 17 2014 03:22.11 CST
Check ExcpHookMonitor from, http://gynvael.coldwind.pl/?id=148
it does same thing!

Add New Comment

There are 31,317 total registered users.

Recently Created Topics
[help] Unpacking VMP...
Reverse Engineering ...
let 'IDAPython' impo...
set 'IDAPython' as t...
GuessType return une...
About retrieving the...
How to find specific...
How to get data depe...
Identify RVA data in...

Recent Forum Posts
Finding the procedur...
Question about debbu...
Identify RVA data in...
let 'IDAPython' impo...
How to find specific...
Problem with ollydbg
How can I write olly...
New LoadMAP plugin v...
Intel pin in loaded ...
OOP_RE tool available?

Recent Blog Entries
Breaking IonCUBE VM

Anatomy of a code tracer

IAT Patcher - new tool for ...

CryptoShark: code tracer ba...

Build a debugger in 5 minutes

More ...

Recent Blog Comments
nieo on:
IAT Patcher - new tool for ...

djnemo on:
Kernel debugger vs user mod...

acel on:
Kernel debugger vs user mod...

pedram on:
frida.github.io: scriptable...

capadleman on:
Using NtCreateThreadEx for ...

More ...

SoySauce Blueprint
Jun 6, 2008

[+] expand

View Gallery (11) / Submit