If you are working on a custom unhandled exception filter (perhaps to implement your own crash dump / error reporting mechanism), then you have probably run into the frustrating situation where you can’t debug the filter itself in case there is a crash bug in it.
The symtoms are that when a crash occurs, your crash reporting logic doesn’t work at all and the process just silently disappears. When you attach a debugger and reproduce the crash to figure out what went wrong, the debugger keeps getting the exceptions (even if you continue after the first chance exception), and your unhandled exception filter is just never called.
Well, the reason for this is that UnhandledExceptionFilter tries to be clever and hides any last chance exception filter handling when a debugger is active. Here’s why: the default implementation of the unhandled exception filter launches the JIT debugger and then restarts the exception. When the JIT debugger attaches itself and the exception is restarted, you clearly want the exception to go to the debugger and not the unhandled exception filter, which would try to launch the JIT debugger again.
If, however, you have a custom unhandled exception filter that is crashing, then you probably don’t want this behavior so that you can debug the problem with the exception filter. To disable this behavior and let the exception filter be called even if there is a debugger attached, you will need to patch kernel32!UnhandledExceptionFilter in a debugger. If you unassemble it, you should eventually see a call to NtQueryInformationProcess that looks like this:
NtQueryInformationProcess(GetCurrentProcess(), 7, &var, 4, 0)
…followed by a comparison of that local variable passed in to NtQueryInformationProcess against 0. You will need to patch the comparison to treat the local set by NtQueryInformationProcess as if it were zero, perhaps turning it into an unconditional jmp with the “eb” or “a” commands.
This comparison is checking for something called the “process debug port”, which is a handle to an LPC port that is used to communicate with the debugger attached to the current process. The kernel returns a null handle value if there is no debugger attached, which is how UnhandledExceptionFilter knows whether to work its magic and forward the exception on to the debugger or call the registered unhandled exception filter.
After patching out the check, then exceptions should be forwarded to your unhandled exception filter as if no debugger were there, giving you a chance to inspect the operation of your crash handling code.
[…] Previously, I had discussed some techniques for debugging unhandled exception filters. There are some more gotchas relating to unhandled exception filters than just debugging them, though. […]
[…] [Skywing] Debugging a custom UEF. […]
[…] [Skywing] Debugging a custom UEF. […]