当用户异常产生后,内核函数KiDispatchException并不是像处理内核异常那样在0环直接进行处理,而是修正3环EIP为KiUserExceptionDispatcher函数后就结束了。
这样,当线程再次回到3环时,将会从KiUserExceptionDispatcher函数开始执行。
(ntdll.dll) KiUserExceptionDispatcher函数分析
- 调用 RtIDispatchException 查找并执行异常处理函数
- 如果 RtIDispatchException 返回真,调用 ZwContinue 再次进入0环,但线程再次返回3环时,会从修正后的位置开始执行。
- 如果 RtIDispatchException 返回假,调用 ZwRaiseException 进行第二轮异常分发
RtlDispatchException是个库函数,内核调用与用户调用的是不一样的。
RtIDispatchException函数分析
- 查找VEH链表 (全局链表) ,如果有则调用0
- 查找SEH链表 (局部链表,在堆栈中) ,如果有则调用
无论那一条线程出现了异常都会先找VEH因为他是全局的,如果VEH链表中没有才会找SEH。
VEH异常的处理流程
- CPU捕获异常信息
- 通过KiDispatchException进行分发(EIP=KiUserExceptionDispatcher)
- KiUserExceptionDispatcher调用RtIDispatchException.
- RtIDispatchException查找VEH处理函数链表并调用相关处理函数
- 代码返回到KiUserExceptionDispatcher
- 调用ZwContinue再次进入0环(ZwContinue调用NtContinue,主要作用就是恢复 TRAPFRAME然后通过_KiServiceExit返回到3环)。
- 线程再次返回3环后,从修正后的位置开始执行 </