异常处理之 CPU/模拟异常的记录及初步分发

226 阅读1分钟

异常的处理流程

异常记录,异常分发,异常处理

异常的分类

1)CPU检测到的异常(例:除零) 2)软件模拟产生的异常(例:try catch)

1)发生在内核空间的内核异常 2)发生在用户空间的用户异常

一、CPU检测到的异常的记录和分发(可用ida打开ntoskrnl.exe分析)
  • CPU检测到异常(例:除零)
  • 查IDT表,执行中断处理函数
  • CommonDispatchException把异常相关的信息写入EXCEPTION_RECORD结构体,并未处理异常,可理解为异常的记录
  • KiDispatchException分发异常,寻找异常的处理函数,可理解为异常的初步分发

type struct _EXCEPTION_RECORD{ DWORD ExceptionCode //异常代码,就像一个ID DWORD ExceptionFlags//异常状态,可用来区分是CPU异常还是软件模拟异常 struct _EXCEPTION_RECORD* ExceptionRecord//下一个异常,嵌套异常时会使用 PVOID ExceptionAddress//异常发生地址 DWORD NumberParameters//附加参数个数,一般不关注 ULONG_PTR ExceptionInformation [EXCEPTION_MAXIMUM_PARAMETERS]//附加参数指针,一般不关注 }

二、软件模拟产生的异常的记录和分发
  • throw了异常
  • CxxThrowException(vc6里的,不同语言该函数可能不同)
  • KERNEL32.DLL的RaiseException,作用同CommonDispatchException
  • NTDLL.DLL!RtlRaiseException
  • NT!NtRaiseException
  • NT!KiRaiseException
  • KiDispatchException同上

一些值得注意的点

  1. 两种异常的共同点为最后都调用了KiDispachException
CPU产生的异常软件模拟的异常
异常的记录RaiseExceptionCommonDispatchException
异常的初步分发KiDispatchExceptionKiDispatchException
  1. 两种异常在填充EXCEPTION_RECORD结构体时的不同点
CPU产生的异常软件模拟的异常
ExceptionCode固定不固定
ExceptionAddress存了真实的地址存了RaiseException函数的地址