Windows异常学习笔记(二)—— 内核异常处理流程&用户异常的分发

用户层与内核层异常

描述

  1. 异常可以发生在用户空间,也可以发生在内核空间
  2. 无论是CPU异常还是模拟异常,是用户层异常还是内核异常,都要通过 KiDispatchException 函数进行分发,理解这个函数是学好异常的关键

内核异常

分析 KiDispatchException

声明:

VOID KiDispatchException(
	ExceptionRecord,
	ExceptionFrame,
	TrapFrame,
	PreviousMode,
	FirstChance);

处理逻辑

  1. 调用 _KeContextFromKframes,由于操作系统不知道分发的异常到底是3环的异常还是0环的异常,如果是3环的异常,进0环前的环境会被备份到Trap_Frame中,如果要在中途回到3环的话,就需要将 Trap_frame 备份到 context,为返回3环做准备
    在这里插入图片描述
  2. 判断先前模式,0是内核调用,1是用户层调用,此时能够知道要分发的异常来自哪里。
  3. 是否是第一次调用
  4. 是否有内核调试器
    在这里插入图片描述
  5. 如果没有或者内核调试器不处理,调用RtlDispatchException,寻找异常处理函数
    在这里插入图片描述
  6. 如果RtlDispatchException返回FALSE,也就是0
  7. 再次判断是否有内核调试器,有就调用,没有会直接蓝屏
    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述

分析 RtlDispatchException

作用

  1. 遍历异常链表,调用异常处理函数,如果异常被正确处理了,该函数返回
  2. 如果当前异常处理函数不能处理该异常,那么调用下一个,以此类推
  3. 如果到最好也没有人处理这个异常,返回0

反汇编
在这里插入图片描述
在这里插入图片描述
可以发现,RtlDispatchException 调用了 RtlpGetRegistrationHead,RtlpGetRegistrationHead的唯一作用就是获取fs寄存器的值给eax
当程序位于0环是,FS寄存器指向KPCR,而KPCR的第一个成员又指向_EXCEPTION_REGISTRATION_RECORD这样一个结构体

_EXCEPTION_REGISTRATION_RECORD

声明

typedef struct _EXCEPTION_REGISTRATION_RECORD {
	struct _EXCEPTION_REGISTRATION_RECORD *Next;
	PEXCEPTION_ROUTINE Handler;
} EXCEPTION_REGISTRATION_RECORD;

描述

  1. _EXCEPTION_REGISTRATION_RECORD位于当前线程的堆栈中
  2. Next指向下一个结构体,Handler指向异常处理函数,是一个链表结构
  3. 当调用RtlDispatchException时,按顺序执行异常处理函数,若其中一个异常处理函数返回结果为真,就不再继续向下执行
  4. 若执行完所有异常处理函数后,异常仍然没有被处理,那么就返回FALSE
    在这里插入图片描述

用户异常的分发

描述

  1. 异常如果发生在内核层,处理起来比较简单,因为异常处理函数也在0环,不用切换堆栈,但是如果异常发生在3环,就意味着必须要切换堆栈,回到3环执行处理函数

  2. 切换堆栈的处理方式与用户APC的执行过程几乎是一样的,惟一的区别就是执行用户APC时返回3环后执行的函数是KiUserApcDispatcher,而异常处理时返回3环后执行的函数是KiUserExceptionDispatcher

  3. 理解用户APC的执行过程是理解3环异常处理的关键

用户异常

描述:当异常发生时,无论是CPU异常还是模拟异常,最终在0环都要通过一个函数进行分发处理,这个函数就是KiDispatchException

VOID KiDispatchException(
	ExceptionRecord,
	ExceptionFrame,
	TrapFrame,
	PreviousMode,
	FirstChance);

注意:需先掌握用户APC执行过程

分析 KiDispatchException

  1. Trap_frame被分到context为返回3环做准备,因为目前不确定是从0环进来还是从3环进来
    在这里插入图片描述
  2. 判断先前模式,0是内核调用,1是用户层调用
    在这里插入图片描述在这里插入图片描述
    在这里插入图片描述3. 从loc_42590B向下分析,是在为TRAP_FRAME结构体赋值,准备结束
    在这里插入图片描述在这里插入图片描述

总结:用户异常处理流程

  1. _KeContextFromKframes将Trap_frame被分到context为返回3环做准备
  2. 判断席安全模式,0是内核调用,1是用户层调用
  3. 是否都是第一次机会
  4. 是否有内核调试器
  5. 发送给3环调试
  6. 如果3环调试器没有处理这个异常,修正EIP为KiUserExceptionDispatcher
  7. KiUserExceptionDispatcher函数执行结束:CPU异常与模拟异常返回地点不同
    CPU异常:
    	CPU检测到异常
    	→查IDT执行处理函数
    	→CommonDispatchException
    	→KiDispatchException通过IRETD返回3环
    模拟异常:
    	CxxThrowException
    	→RaiseException
    	→RtlRaiseException
    	→NT!NtRaiseException
    	→NT!KiRaiseException
    	→KiDispatchException通过系统调用返回3环
    
  • 2
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值