调试与异常
没有调试器如何处理异常 VEH VCH区别 VEH位置 SEH栈中结构 成员字段
- VEH是向量化异常 属于全局,是进程相关
- SEH是结构化异常属于局部 是线程相关 结构是链表
异常分发流程
用户层异常处理流程
- KeContextFromKframs将Trap_frame备份到context为返回3环做准备
- 判断先前模式0是内核层调用1是用户层调用
- 是否是第一次调用
- 是否有内核调试器
- 发送调试信息给三环调试器 通过调试子系统 调试子系统通过SendApiMessage发送给三环调试器
- 如果三环调试器没有处理这个异常 那么准备返回三环 开始修改Trap_frame结构体里的值
- 最关键的修改 修改EIP为KiUserExceptionDispatcher即回到三环什么地方
- KiUserExceptionDispatcher函数执行结束 返回调用的位置CPU异常和模拟异常返回的地点不同
- 无论哪种方式 当线程再次回到三环时 将执行KiUserExceptionDispatcher函数
内核层异常处理流程
- 调用_KeContextFromKframes将Trap_fram备份到context为返回3环做准备
- 判断先前模式PreViousMode 0是内核调用1是用户层调用
- 判断是是否是第一次调用 不为1则跳转 为1则继续往下走 通过函数的最后一个参数
- 判断一个全局变量_KiDebugRoutine看内核调试器是否存在 有的话 这个值是非零的 如果没有内核调试器直接跳转
- 有内核调试器会先调用内核调试器 如果调用返回1说明调用成功 说明内核调试器已经处理了 就将Context再转成Trap_Frame直接返回 如果调试器没有处理 就接着让3环处理 如果内核调试器没有处理 也就是返回失败 直接跳转
- 如果没有内核调试器 或者内核调试器没有处理 会调用RtlDispatchException函数 这个函数专门负责处理异常功能是负责调用异常处理函数
- 再次判断是否有内核调试器 有调用 没有直接蓝屏