How can I debug x64 windows exceptions?

442 Views Asked by At

I'm curious how Windows handles exceptions. More exactly, how Windows find the catch block of a try / catch. I saw that the compiler makes a separate function in assembly for catch block. Since the catch block was represented by another function in assembly, I couldn't find any correlation between the instruction that was generating the exception and the RUNTIME_FUNCTION entries from .pdata section.

I tried to put a breakpoint on RaiseException, RtlRaiseException and RtlVirtualUnwind but all I could find was the address after the RaiseException call. Tried to debug a divide by 0 exception, but it looks like the debugger has some additional exception handlers and the message in the catch block was not printed.

Any additional information about Stack Unwinding on Windows 64bit are welcome :D.

2

There are 2 best solutions below

0
On

The exceptions are handled by exception handler routines. When you add a try/catch block to your C++ code you will see that the compiler added __CxxFrameHandler3 to your import table (providing that the MSVCRT is not statically linked). So this is your exception handler that will be called when an exception occurs in the try block. Another one __C_specific_handler is imported when you add __try/__except block to your C or C++ code. There are a few others but these two are used in the C/C++ code.

To answer your question, the best way is to hook (replace the import table pointer with a pointer to your local routine) one of these functions and see how your "handler" will be called when an exception is thrown.

0
On

With the goal of finding C++ catch you can set Vectored Exception Handler and set a breakpoint in it. VEH goes before frame-based handlers, so it it not too late:

LONG NTAPI vh(EXCEPTION_POINTERS* ExceptionInfo)
{
    return EXCEPTION_CONTINUE_SEARCH;
}

AddVectoredExceptionHandler(TRUE, vh);

Alternatively, if you want to set breakpoint closer to catch block, have __try...__except deeper in call stack than target catch block, in __except expression return EXCEPTION_CONTINUE_SEARCH and have your breakpoint there.