异常记录(CPU产生的异常和软件模拟产生的异常)

前奏

当API函数3环进0环时,第一件事就是保存现场,保存到_Trap_Frame
在这里插入图片描述
在这里插入图片描述

异常的分类

CPU产生的异常

在这里插入图片描述
错误首先肯定被CPU先发现,然后CPU就会执行相应的错误处理程序

软件模拟产生的异常

throw 1

异常产生

CPU异常的产生

CPU指令检测到异常(例:除0)------>查IDT表,执行中断处理函数--------->CommonDispatchException------>KiDispatchException

在跳转CommonDispatchException之前,还传了两个参数
在这里插入图片描述
ebp+68h也就是上图Trap结构体的Eip
在这里插入图片描述
0x0c0000094h也就是ExceptionCode
在这里插入图片描述
传了两个参数后调用CommonDispatchException,

CommonDispatchException函数分析

该函数构造一个_EXCEPTION_RECORD结构体,并赋值
在这里插入图片描述
CommonDispatchException函数的作用也就是把一些值赋值给一个_EXCEPTION_RECORD结构体

type struct _EXCEPTION_RECORD
{
    
    
DWORD ExceptionCode;//异常代码(异常类型)
DWORD	ExceptionFlags;//异常状态
Struct _EXCEPTION_RECORD* ExceptionRecord;//下一个异常
PVOID	ExceptionAddress;		//附加发生地址(异常发生地址)
DWORD NumberParameters;		//附加参数个数
ULONG_PTR	ExceptionInformation
[EXCEPTION_MAXIMUM_PARAMETERS];//附加参数指针
}

结构体作用就是用来记录异常信息

ExceptionFlags(给后面的处理程序所用,辨别异常状态)

Struct _EXCEPTION_RECORD* ExceptionRecord(通常为空,当发生嵌套异常(当异常处理程序里面又发生异常时)这个指针会指向下一个异常)

总结:

CPU异常执行的流程:

  1. CPU指令检测到异常
  2. 查IDT表,执行中断处理函数(往往并不真正处理异常,而是调用函数)
  3. 调用CommonDispatchException(构造_EXCEPTION_RECORD)
  4. KiDispatchException(分发异常:目的是找到异常处理函数)

软件模拟异常

在这里插入图片描述
在这里插入图片描述
模拟异常的产生:
CxxThrowException------->(KERNEL32.DLL)RaiseException(DWORD dwException,DWORD dwExceptionFlags,DWORD nNumberOfArguments,const of ULONG_PTR *IPArguments)--------->NTDLL.DLL!RtIRaiseException()------->NT!NtRaiseException---->NT!KiRaiseException

填充ExceptionRecord结构体

type struct _EXCEPTION_RECORD 
{
    
     
DWORD ExceptionCode;//异常代码(异常类型) 
DWORD ExceptionFlags;//异常状态 
Struct _EXCEPTION_RECORD* ExceptionRecord;//下一个异常
 PVOID ExceptionAddress; //附加发生地址(异常发生地址)
  DWORD NumberParameters; //附加参数个数
   ULONG_PTR ExceptionInformation
    [EXCEPTION_MAXIMUM_PARAMETERS];//附加参数指针
     }

在这里插入图片描述
软件模拟异常这个ExceptionCode是固定的,值取决于编译环境,编译环境不同,ExceptionCode也不同
在这里插入图片描述
这个ExceptionAddress并不是抛出异常的位置,而是存了一个固定的值,这个值就是函数RaiseException地址

(以上两点就是CPU产生的异常和软件模拟产生的异常之间的区别)

KiRaiseException函数分析

  1. EXCEPTION_RECORD.ExceptionCode最高位清零,用于区分CPU异常
  2. 调用KiDispatchException 开始分发异常

总结:

CPU异常:
CPU指令检测到异常------>查IDT表,执行中断处理函数--------->CommonDispatchException(填充ExceptionRecord结构体)------>KiDispatchException

模拟异常:throw关键词(依赖编译器)---->CxxThrowException------->(KERNEL32.DLL)RaiseExceptionDWORD dwException,DWORD dwExceptionFlags,DWORD nNumberOfArguments,const of ULONG_PTR *IPArguments)(作用:填充ExceptionRecord结构体)--------->NTDLL.DLL!RtIRaiseException()------->NT!NtRaiseException(ExceptionCode最高位清零)---->NT!KiRaiseException

CPU异常和模拟异常类型不同,仅仅异常记录时不同,但是等到异常分发时,就没法区分了

猜你喜欢

转载自blog.csdn.net/CSNN2019/article/details/113836112