浅析Windows异常处理结构与实现

本文深入浅出地探讨了Windows操作系统中的异常处理机制,包括结构化异常处理(SHE)、向量化异常处理(VEH)和顶层异常处理(UEF)。文章详细阐述了异常处理的流程,如异常分发、调试器的角色,以及常见异常的处理。通过对异常处理结构的分析,读者能更好地理解Windows系统如何管理和响应程序错误。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

浅析Windows异常处理结构与实现

  Windows异常处理是操作系统处理程序错误的一种手段,一般有两种:SHE(结构化异常处理)和VEH(向量化异常处理),而UEF(TopLevalEH顶层异常处理)是基于SHE的(这之后应该还有一种VCH),下面我就从上面三方面分析一下Windows异常处理结构。

一、异常处理的个人理解简述

  当正在运行一个程序产生了一个异常后,就会利用自身的异常处理来处理这个异常,这个过程将是VEH优先于SEH的,而如果存在调试器,就会先交给调试器处理(使用shift+F7/F8/F9会把异常交还程序),若调试器不能处理再交还给程序,若仍不能处理将再交给调试器,进行第2 次处理的机会,有无调试器的存在会影响UEF的使用,这个顶层异常处理在有调试器的情况下是不会被调用的,所以我们大概能把处理过程分为:

  第一次交给调试器(进程必须被调试)->VEH->SHE->UEF(TopLevelEH 进程被调试时不会被执行)->第二次交给调试器(进程必须被调试)-> 调用异常端口通知csrss.exe

  在这里列举一下常见的系统定义的异常:

异常 描述
EXCEPTION_ACCESS_VIOLATION 0xC0000005 程序企图读写一个不可访问的地址时引发的异常。例如企图读取0地址处的内存。
EXCEPTION_BREAKPOINT 0x80000003 触发断点时引发的异常。
EXCEPTION_ILLEGAL_INSTRUCTION 0xC000001D 程序企图执行一个无效的指令时引发该异常。
EXCEPTION_INT_DIVIDE_BY_ZERO 0xC0000094 整数除法的除数是0时引发该异常。
EXCEPTION_SINGLE_STEP 0x80000004 标志寄存器的TF位为1时,每执行一条指令就会引发该异常。主要用于单步调试。
  下面就正式开始分析整个结构:

  (VEH为什么优先于SEH呐?可以从二者的作用范围出发,SEH是基于线程的(由线程创建),而VEH则是基于进程的(由进程创建)。由此来看,SHE只能处理自身线程的异常,VEH却能处理整个进程的异常,所以每当异常产生时都会先调用VEH,后调用SHE。

二、从R3出发

  说起异常的分发,那么这里故事线就稍稍有一点儿长了。因为Windows分为内核(R0)和应用层(R3),Windows的异常处理机制是内核和应用层都可以使用的。所以这里就需要进行一些区分了。因为如果内核产生了异常,那么自然内核的异常处理函数也在内核里面那么这个事情就好办了,我出现异常了我直接处理就好了。但是应用层如果出现了异常,那么一定他的处理函数是在应用层的,当产生异常的时候,异常的分发总是在内核,那么如果要处理应用层的异常,那么需要先切换到应用层然后才能去执行应用层的异常分发处理,我就只分析从R3出发的结构(太菜)。
  在进入异常处理的时候,栈中会放置EXCEPTION_RECORD(异常结构信息)和CONTEXT(线程上下文)两个结构

typedef struct _EXCEPTION_RECORD
{
DWORD ExceptionCode; //异常代码
DWORD ExceptionFlags; //标志异常是否继续,标志异常处理完成后是否接着之前有问题的代码
struct _EXCEPTION_RECORD* ExceptionRecord; //指向下一个异常节点的指针,这是一个链表结构
PVOID ExceptionAddress; //异常发生的地址
DWORD NumberParameters; //异常附加信息
ULONG_PTR ExceptionInformation[EXCEPTION_MAXIMUM_PARAMETERS]; //异常的字符串
} EXCEPTION_RECORD, *PEXCEPTION_RECORD;

  在R3中的起始位置为ntdll.dll中的KiUserExceptionDispatcher函数,由它调用ntdll!RtlDispatchException函数进行用户态的异常处理。
随后,进入VEH和SHE两种异常处理机制,其中包含SHE的顶级异常处理,但有调试器是不进行。

  1. 如果RtlDispatchException找到异常处理例程能够处理异常,则调用ZwContinue按照设置好的Context结构继续执行;
  2. 如果在调试异常时未能处理,调用ZwRaiseExcept
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值