Win32程序发生异常时处理的流程


一、程序没有被调试

  1. 线程建立时,系统安装一个系统线程异常处理例程。
  2. 异常发生时,Win2K/XP控制权转移给NTDLL.KiUserExceptionDispatcher。
  3. 如果你安装了线程相关的异常处理例程,系统就把异常发送给你的处理例程,交由其处理。
  4. 每个线程相关的异常处理例程可以处理或者不处理这个异常,如果他不处理并且安装了多个线程相关的异常处理例程,可交由链起来的其他例程处理。
  5. 如果这些例程均选择不处理异常,系统线程异常处理例程将起作用,调用ZwQueryInformationProcess判断是否被调试,没有调试并且你调用SetUnhandledExceptionFilter安装了最后异常处理例程的话,系统转向对它的调用。
  6. 如果你没有安装最后异常处理例程或者他没有处理这个异常,系统会调用默认的系统处理程序,通常显示一个对话框,你可以选择关闭或者最后将其附加到调试器上的调试按钮。如果没有调试器能被附加于其上或者调试器也处理不了,系统就调用ExitProcess终结程序。
  7. 不过在终结之前,系统仍然对发生异常的线程异常处理句柄来一次展开,这是线程异常处理例程最后清理的机会。一般只用来释放资源,不要试图修复什么。注意只对线程异常有展开。

二、程序被调试

  1. 线程建立时,系统安装一个系统线程异常处理例程。
  2. 异常发生时,系统挂起程序并向调试器发送。EXCEPTION_DEBUG_EVENT消息。
  3. 调试器未能处理异常(比如我们在OD里按Shift+F7),控制权转移给 NTDLL。KiUserExceptionDispatcher如果你安装了线程相关的异常处理例程,系统就把异常发送给你的程序seh处理例程,交由其处理。
  4. 每个线程相关的异常处理例程可以处理或者不处理这个异常,如果他不处理并且安装了多个线程相关的异常处理例程,可交由链起来的其他例程处理。
  5. 如果这些例程均选择不处理异常,系统线程异常处理例程将起作用,调用ZwQueryInformationProcess判断是否被调试。
  6. 由于被调试,操作系统仍会再次挂起程序通知debugger。

文章作者: Kiba Amor
版权声明: 本博客所有文章除特別声明外,均采用 CC BY-NC-ND 4.0 许可协议。转载请注明来源 Kiba Amor !
  目录