异常如果发生在内核层,处理起来比较简单,因为异常处理函数也在0环,不用切换堆栈,但是如果异常发生在3环,就意味着必须要切换堆栈,回到3环执行处理函数。
切换堆栈的处理方式与用户APC的执行过程几乎是一样的,唯一的区别就是执行用户APC时返回3环后执行的函数是KiUserApcDispatcher,而异常处理时返回3环后执行的函数是KiUserExceptionDispatcher.
所以,理解用户APC的执行过程是理解3环异常处理的关键。
VOID KiDispatchException
(
ExceptionRecord,
ExceptionFrame,
TrapFrame,
PreviousMode,
FirstChance
)
用户异常跳转
这些都是修改Ktrap_Frame回准备回3环操作
修改Ktrap_Frame.eip
- KeContextFromKframes将Trap_frame备份到context为返回3环做准备
- 判断先前模式0是内核调用1是用户层调
- 是否是第一次机会
- 是否有内核调试器
- 发送给3环调试
- 如果3环调试器没有处理这个异常修正EIP为KiUgerExceptionDispatcher
- 如果3环调试器没有处理这个异常修正EIP为KiUgerExceptionDispatcher
- 无论通过那种方式,但线程再次回到3环时,将执行KiUserExceptionDispatcher函数