如何知道80000003断点后是否隐藏了其他异常(WER对话框)
我的应用程序,一个可执行文件,正在远程计算机上崩溃。我没有访问那台机器的权限,所以我请求了一个转储,通过任务管理器生成。使用WEBBG,在执行命令!analyze -v
时,我可以看到许多其他的文本
EXCEPTION_RECORD: (.exr -1)
ExceptionAddress: 0000000000000000
ExceptionCode: 80000003 (Break instruction exception)
ExceptionFlags: 00000000
NumberParameters: 0
我怎么知道它是不是对坠机事件负责?如果不是,我如何确定真正的原因?
tldr:如果!findstack kernel32!WerpReportFault
产生一个结果,那么它可能不是根本原因。
长版本:
当应用程序由于未处理的异常而崩溃时,操作系统将使用名为windows错误报告的功能来获取它。这会导致一些技术问题:ntdll
中的异常分派器启动一个新线程。
在新线程中,会触发断点
异常分派器还调用未处理的异常处理程序
如果应用程序没有这样的处理程序,它将把处理转发到显示对话框的windows错误报告(inkernel32
)
如果您在那个时候进行崩溃转储,您将看到以下内容:
问题中提到的断点异常
0:002> .exr -1
ExceptionAddress: 775f000c (ntdll!DbgBreakPoint)
ExceptionCode: 80000003 (Break instruction exception)
ExceptionFlags: 00000000
NumberParameters: 1
Parameter[0]: 00000000
一个线程,其内部只有一个断点
0:002> k
ChildEBP RetAddr
02e2ff58 7767f926 ntdll!DbgBreakPoint
02e2ff88 75b3338a ntdll!DbgUiRemoteBreakin+0x3c
02e2ff94 77619f72 kernel32!BaseThreadInitThunk+0xe
02e2ffd4 77619f45 ntdll!__RtlUserThreadStart+0x70
02e2ffec 00000000 ntdll!_RtlUserThreadStart+0x1b
包含前面提到的相关操作的调用堆栈
0:001> k
ChildEBP RetAddr
01aff904 770715f7 ntdll!NtWaitForMultipleObjects+0x15
01aff9a0 75b319f8 KERNELBASE!WaitForMultipleObjectsEx+0x100
01aff9e8 75b34200 kernel32!WaitForMultipleObjectsExImplementation+0xe0
01affa04 75b580a4 kernel32!WaitForMultipleObjects+0x18
01affa70 75b57f63 kernel32!WerpReportFaultInternal+0x186
01affa84 75b57858 kernel32!WerpReportFault+0x70
01affa94 75b577d7 kernel32!BasepReportFault+0x20
01affb20 776574ff kernel32!UnhandledExceptionFilter+0x1af
01affb28 776573dc ntdll!__RtlUserThreadStart+0x62
01affb3c 77657281 ntdll!_EH4_CallFilterFunc+0x12
01affb64 7763b499 ntdll!_except_handler4+0x8e
01affb88 7763b46b ntdll!ExecuteHandler2+0x26
01affbac 7763b40e ntdll!ExecuteHandler+0x24
01affc38 775f0133 ntdll!RtlDispatchException+0x127
01affc38 6f8c20ce ntdll!KiUserExceptionDispatcher+0xf
要识别WER断点,可以检查这三个条件。对于后者,可以使用!findstack
命令,因为它可能发生在任何线程上。
0:001> !findstack kernel32!WerpReportFault
Thread 001, 2 frame(s) match
* 04 01affa70 75b57f63 kernel32!WerpReportFaultInternal+0x186
* 05 01affa84 75b57858 kernel32!WerpReportFault+0x70
我希望方法名不会更改。
如何找出根本原因?
这适用于x86(32位),因为堆栈是如何创建的。它在x64(64位)上不能很好地工作,因为kb
命令不可靠。在x64上,参数在寄存器而不是堆栈中传递,但是kb
命令只对堆栈有效。
也就是说,异常指针作为第二个参数传递给WerpReportFault()
。可以使用该异常指针创建一个新转储,将该异常作为主要异常,如下所示:
.dump /ma /xp <exception pointer> c:\path\to\newdump.dmp
接下来,关闭源转储,打开新转储并再次分析,例如,以以下4个命令作为起点:
.symfix
.reload
.exr -1
!analyze -v