Search code examples
64-bitwindbg

How to Find the context record for user mode exception on X64


I have a user mode dump from Win 8.1/64, the dump was taken by attaching Windbg when the Wer dialogue. The .ecxr shows then ntdll!DbgBreakPoint for the Windbg injected thread. (As normal)

I have identified the thread by examine all stack, and finding the one which has :

# Call Site
00 ntdll!NtWaitForMultipleObjects
01 KERNELBASE!WaitForMultipleObjectsEx
02 kernel32!WerpReportFaultInternal
03 kernel32!WerpReportFault
04 KERNELBASE!UnhandledExceptionFilter
05 ntdll!RtlUserThreadStart$filt$0
06 ntdll!_C_specific_handler
07 ntdll!RtlpExecuteHandlerForException
08 ntdll!RtlDispatchException
09 ntdll!KiUserExceptionDispatch
10 <My faulty code which generated the exception>

The kvn aslo dispays a TrapFrame @ 00000000`0379ed28)

09 00000000`0379e900 00000000`00250bc8 : 00000000`00000000 00000000`0026ca09 00000000`0379f160 00000000`0379f168 : ntdll!KiUserExceptionDispatch+0x2e (TrapFrame @ 00000000`0379ed28)

Is there a way to use the trap frame to get the context record to feed into .cxr ? Or is it other possibilities to find the exception context?


Solution

  • I see a KERNELBASE!UnhandledExceptionFilter on the stack. That seems like a good thing to focus on.

    If this were x86, you could easily get an EXCEPTION_POINTERS struct out of the first parameter to KERNELBASE!UnhandledExceptionFilter. From there, you would have access to the EXCEPTION_RECORD and CONTEXT. The procedure is described in this KB article.

    The same method works for x64 processes with one caveat. Due to the nature of the x64 calling convention, it is harder to retrieve the actual argument to KERNELBASE!UnhandledExceptionFilter since it is stored in a register rather than on the stack.

    I recently found a debugger extension called CMKD that automates the task of hunting for the first 4 args in the x64 calling convention rather than blindly displaying stack values like kb and kv. This can be done by hand but it is a rather lengthy and error-prone process -- better to let an extension take a crack at it first.

    With it, you can do something like this:

    0:000> !cmkd.stack -p
    Call Stack : 15 frames
    ## Stack-Pointer    Return-Address   Call-Site       
    [...]
    03 000000aea3dae7e0 00007fff1e906b14 KERNELBASE!UnhandledExceptionFilter+196 
        Parameter[0] = 000000aea3dae930
        Parameter[1] = (unknown)       
        Parameter[2] = (unknown)       
        Parameter[3] = (unknown)       
    [...]
    

    And, now we have an EXCEPTION_POINTERS* in Parameter[0].

    0:000> dt 000000ae`a3dae930 EXCEPTION_POINTERS
    ConsoleApplication2!EXCEPTION_POINTERS
       +0x000 ExceptionRecord  : 0x000000ae`a3daf850 _EXCEPTION_RECORD
       +0x008 ContextRecord    : 0x000000ae`a3daf240 _CONTEXT
    

    We can see in my example that a C++ exception was thrown...

    0:000> .exr 000000ae`a3daf850
    ExceptionAddress: 00007fff1bfeab78 (KERNELBASE!RaiseException+0x0000000000000068)
       ExceptionCode: e06d7363 (C++ EH exception)
      ExceptionFlags: 00000001
    NumberParameters: 4
       Parameter[0]: 0000000019930520
       Parameter[1]: 000000aea3daf9b0
       Parameter[2]: 00007ff6f50024a8
       Parameter[3]: 00007ff6f5000000
      pExceptionObject: 000000aea3daf9b0
      _s_ThrowInfo    : 00007ff6f50024a8
    

    Hopefully this helps. Good luck. :)