Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

WinDBG - Finding the actual (unmanaged) exception

I'm trying to find the actual exception in a managed-unmanaged mixed code.

The problem is that I have a .Net class that catches all unhandled exceptions and then creates a dump, so when i look at the dump there's mixed managed-unmanaged code, and i can't really get to the actual unmanaged exception.
And to make things worse, the .Net seems to have its own exception so !analyze -v gives me that exception.

So, here is what I have:

I can find where the exception happened (by finding the 1003f word), then do .cxr to get to that actual place in the code.

When I do a !dumpstack I get something like:

//My module stuff and then:
122bf71c 08bf5242 (MethodDesc 0x4bf71ac +0x5a <Module>.dbg.NativeExceptionHandler())
122bf734 08bf5242 (MethodDesc 0x4bf71ac +0x5a <Module>.dbg.NativeExceptionHandler())
122bf73c 08bf51ce (MethodDesc 0x4bf71dc +0x6 <Module>.dbg.OnUnhandledNativeException(_EXCEPTION_POINTERS*)), calling (MethodDesc 0x4bf71ac +0 <Module>.dbg.NativeExceptionHandler())
122bf75c 08bf51ce (MethodDesc 0x4bf71dc +0x6 <Module>.dbg.OnUnhandledNativeException(_EXCEPTION_POINTERS*)), calling (MethodDesc 0x4bf71ac +0 <Module>.dbg.NativeExceptionHandler())
122bf760 3944bf15 3944bf15
122bf778 7c35f0c3 msvcr71!__CxxUnhandledExceptionFilter+0x46, calling 091f15a2
122bf784 7c864191 kernel32!UnhandledExceptionFilter+0x1c7
122bf7ac 7c812afb kernel32!RaiseException+0x53, calling ntdll!RtlRaiseException
122bf7f4 7857df60 msvcr90!_CxxThrowException+0x48 [f:\prebuild\eh\throw.cpp:161], calling kernel32!RaiseException
122bf828 785436c5 msvcr90!__set_flsgetvalue+0xf [f:\src\tidtable.c:256], calling kernel32!TlsGetValue
122bf834 785438b3 msvcr90!_getptd_noexit+0x74 [f:\src\tidtable.c:616], calling ntdll!RtlSetLastWin32Error
122bf844 785438c5 msvcr90!_getptd+0x8 [f:\src\tidtable.c:641], calling msvcr90!_getptd_noexit [f:\src\tidtable.c:566]
122bf84c 7857c98c msvcr90!__FrameUnwindToState+0xd9 [f:\prebuild\eh\frame.cpp:1161], calling msvcr90!_getptd [f:\src\tidtable.c:640]
122bf850 7857c972 msvcr90!__FrameUnwindToState+0xbf [f:\prebuild\eh\frame.cpp:1182], calling msvcr90!__SEH_epilog4
122bf860 785436c5 msvcr90!__set_flsgetvalue+0xf [f:\src\tidtable.c:256], calling kernel32!TlsGetValue
122bf870 785436c5 msvcr90!__set_flsgetvalue+0xf [f:\src\tidtable.c:256], calling kernel32!TlsGetValue
122bf87c 785438b3 msvcr90!_getptd_noexit+0x74 [f:\src\tidtable.c:616], calling ntdll!RtlSetLastWin32Error
122bf88c 785438c5 msvcr90!_getptd+0x8 [f:\src\tidtable.c:641], calling msvcr90!_getptd_noexit [f:\src\tidtable.c:566]
122bf894 7857d06a msvcr90!CallCatchBlock+0x148 [f:\prebuild\eh\frame.cpp:1503], calling msvcr90!_getptd [f:\src\tidtable.c:640]
122bf898 7857d03c msvcr90!CallCatchBlock+0x11a [f:\prebuild\eh\frame.cpp:1520], calling msvcr90!__SEH_epilog4
122bf8e8 7857d03c msvcr90!CallCatchBlock+0x11a [f:\prebuild\eh\frame.cpp:1520], calling msvcr90!__SEH_epilog4
122bf8ec 7857d486 msvcr90!CatchIt+0x5e [f:\prebuild\eh\frame.cpp:1275], calling msvcr90!CallCatchBlock [f:\prebuild\eh\frame.cpp:1433]
122bf91c 7857d576 msvcr90!FindHandlerForForeignException+0xdb [f:\prebuild\eh\frame.cpp:976], calling msvcr90!CatchIt [f:\prebuild\eh\frame.cpp:1219]
122bf950 785436c5 msvcr90!__set_flsgetvalue+0xf [f:\src\tidtable.c:256], calling kernel32!TlsGetValue
122bf95c 785438b3 msvcr90!_getptd_noexit+0x74 [f:\src\tidtable.c:616], calling ntdll!RtlSetLastWin32Error
122bf96c 785438c5 msvcr90!_getptd+0x8 [f:\src\tidtable.c:641], calling msvcr90!_getptd_noexit [f:\src\tidtable.c:566]
122bf974 7857d8c8 msvcr90!FindHandler+0x334 [f:\prebuild\eh\frame.cpp:879], calling msvcr90!_getptd [f:\src\tidtable.c:640]
122bf988 785436c5 msvcr90!__set_flsgetvalue+0xf [f:\src\tidtable.c:256], calling kernel32!TlsGetValue
122bf994 785438b3 msvcr90!_getptd_noexit+0x74 [f:\src\tidtable.c:616], calling ntdll!RtlSetLastWin32Error
122bf998 7c910323 ntdll!RtlpImageNtHeader+0x56, calling ntdll!_SEH_epilog
122bf9b0 7c90d98a ntdll!NtQueryVirtualMemory+0xc
122bf9b4 7c880b54 kernel32!_ValidateEH3RN+0xb6, calling ntdll!ZwQueryVirtualMemory
122bf9f4 7c83ab50 kernel32!BaseThreadStart+0x4d, calling kernel32!UnhandledExceptionFilter
122bf9fc 7c839b39 kernel32!_except_handler3+0x61
122bfa24 7c9032a8 ntdll!ExecuteHandler2+0x26
122bfa48 7c90327a ntdll!ExecuteHandler+0x24, calling ntdll!ExecuteHandler2
122bfa6c 7c92aa0f ntdll!RtlDispatchException+0xb1, calling ntdll!RtlpExecuteHandlerForException
122bfa98 78591795 msvcr90!_except_handler3+0x69
122bfac0 7c9032a8 ntdll!ExecuteHandler2+0x26
122bfae4 7c90327a ntdll!ExecuteHandler+0x24, calling ntdll!ExecuteHandler2
122bfaf8 7c90e48a ntdll!KiUserExceptionDispatcher+0xe, calling ntdll!RtlDispatchException
122bfdf8 064fdd84 MyModule!Class::MyFunction::Update+0xe4 [c:\MyCode.cpp:12345] ====> Exception cxr@122bfb2c
122bfb60 7c910222 ntdll!RtlpAllocateFromHeapLookaside+0x42, calling ntdll!_SEH_epilog

Anyway, so the thing is, I can't get the actual exception. I know it's an std exception, but I'm not sure which one (in that line of code there isn't a custom exception, and a number of things could have gone wrong).

like image 883
Yochai Timmer Avatar asked Feb 24 '23 02:02

Yochai Timmer


2 Answers

Switching the context should've brought you to the RaiseException() invocation. If you look it up, it accepts an exception code and a bunch of application/compiler-specific parameters in the parameters block. Visual studio compiler will passes exception object as one of the parameters, i.e.:

0:003:x86> .cxr <addr-of-context-record>
0:003:x86> dds 2bffb28 la
02bffb28  02bffb60
02bffb2c  7222872d MSVCR100!CxxThrowException+0x45  ; this is the RaiseException() call
02bffb30  e06d7363 ; c++ exception code
02bffb34  00000001 ; flags
02bffb38  00000003 ; number of parameters
02bffb3c  02bffb54 ; parameters
...

0:003:x86> dpp 02bffb54 l3
02bffb54  19930520 ; compiler magic
02bffb58  02bffb70 0016c8b0 mymodule!std::bad_alloc::`vftable'
02bffb5c  0016f088 ; exception descriptor area (compiler-specific)
...

Then, you can use dt 02bffb70 mymodule!std::bad_alloc to inspect the exception object

like image 65
deemok Avatar answered Mar 02 '23 16:03

deemok


You may try this to look for a context signature in the process memory:

s -d 0 L10000000/4 0001003f

with some luck this will return a memory address where the context was found, you can then set the current context to this location with .cxr.

This works because the CONTEXT structure in windows, created when an exception is raised, always begins with the 0001003f value (only valid for X86!)

(tip taken from the Advanced Windows Debugging book)

like image 26
floyd73 Avatar answered Mar 02 '23 18:03

floyd73