如何知道80000003断点后面是否隐藏了另一个异常(WER对话框)

Rah*_*ngh 3 windows exe windbg

我的应用程序(可执行文件)在远程计算机上崩溃.我无法访问该计算机,因此我请求通过任务管理器生成的转储.使用WinDbg,在执行命令时!analyze -v,我可以看到以下文本和许多其他文本

EXCEPTION_RECORD:  (.exr -1)
ExceptionAddress: 0000000000000000
ExceptionCode: 80000003 (Break instruction exception)
ExceptionFlags: 00000000
NumberParameters: 0
Run Code Online (Sandbox Code Playgroud)

我如何知道是否应对坠机负责?如果不是,我该如何确定真正的原因?

Tho*_*ler 7

INT3断点是根本原因吗?

TLDR:如果!findstack kernel32!WerpReportFault产生结果,那么它可能不是根本原因.

长版:

当您的应用程序因未处理的异常而崩溃时,操作系统将使用名为Windows错误报告的功能进行选择.这导致了一些技术性的事情:

  1. 异常调度程序ntdll启动一个新线程.
  2. 在新线程中,触发断点
  3. 异常调度程序还调用未处理的异常处理程序
  4. 如果你的应用程序没有这样的处理程序,它会将处理转发到kernel32显示对话框的Windows错误报告(in )

如果您当时采用崩溃转储,您将看到以下内容:

  1. 您问题中提到的断点异常

    0:002> .exr -1
    ExceptionAddress: 775f000c (ntdll!DbgBreakPoint)
       ExceptionCode: 80000003 (Break instruction exception)
      ExceptionFlags: 00000000
    NumberParameters: 1
       Parameter[0]: 00000000
    
    Run Code Online (Sandbox Code Playgroud)
  2. 一个除了断点之外什么都没有的线程

    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
    
    Run Code Online (Sandbox Code Playgroud)
  3. 具有前面提到的相关操作的调用堆栈

    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
    
    Run Code Online (Sandbox Code Playgroud)

要识别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
Run Code Online (Sandbox Code Playgroud)

我希望方法名称不会改变.

如何确定根本原因?

由于堆栈的创建方式,这适用于x86(32位).它在x64(64位)上不能很好地工作,因为kb命令不可靠.在x64上,参数在寄存器而不是堆栈中传递,但该kb命令仅适用于堆栈.

也就是说,异常指针WerpReportFault()作为第二个参数传递给它.您可以使用该异常指针创建一个带有该异常的新转储作为主要异常,如下所示:

.dump /ma /xp <exception pointer> c:\path\to\newdump.dmp
Run Code Online (Sandbox Code Playgroud)

接下来,关闭源转储,打开新转储并再次分析,例如使用以下4个命令作为起点:

.symfix
.reload
.exr -1
!analyze -v
Run Code Online (Sandbox Code Playgroud)