调试与异常

没有调试器如何处理异常 VEH VCH区别 VEH位置 SEH栈中结构 成员字段

  • VEH是向量化异常 属于全局,是进程相关
  • SEH是结构化异常属于局部 是线程相关 结构是链表

异常分发流程

用户层异常处理流程

  1. KeContextFromKframs将Trap_frame备份到context为返回3环做准备
  2. 判断先前模式0是内核层调用1是用户层调用
  3. 是否是第一次调用
  4. 是否有内核调试器
  5. 发送调试信息给三环调试器 通过调试子系统 调试子系统通过SendApiMessage发送给三环调试器
  6. 如果三环调试器没有处理这个异常 那么准备返回三环 开始修改Trap_frame结构体里的值
  7. 最关键的修改 修改EIP为KiUserExceptionDispatcher即回到三环什么地方
  8. KiUserExceptionDispatcher函数执行结束 返回调用的位置CPU异常和模拟异常返回的地点不同
  9. 无论哪种方式 当线程再次回到三环时 将执行KiUserExceptionDispatcher函数

内核层异常处理流程

  1. 调用_KeContextFromKframes将Trap_fram备份到context为返回3环做准备
  2. 判断先前模式PreViousMode 0是内核调用1是用户层调用
  3. 判断是是否是第一次调用 不为1则跳转 为1则继续往下走 通过函数的最后一个参数
  4. 判断一个全局变量_KiDebugRoutine看内核调试器是否存在 有的话 这个值是非零的 如果没有内核调试器直接跳转
  5. 有内核调试器会先调用内核调试器 如果调用返回1说明调用成功 说明内核调试器已经处理了 就将Context再转成Trap_Frame直接返回 如果调试器没有处理 就接着让3环处理 如果内核调试器没有处理 也就是返回失败 直接跳转
  6. 如果没有内核调试器 或者内核调试器没有处理 会调用RtlDispatchException函数 这个函数专门负责处理异常功能是负责调用异常处理函数
  7. 再次判断是否有内核调试器 有调用 没有直接蓝屏