当前位置: 首页 > news >正文

windows内核研究(异常-CPU异常记录)

异常


CPU异常记录

CPU的异常基本围绕这几个点展开

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

异常产生后,首先要记录异常信息(异常的类型、异常发生的位置等),然后要寻找异常的处理函数,我们称为异常的分发,最后找到异常处理函数并调用,我们称为异常处理

CPU异常的产生

CPU检测到异常 -> 查IDT表执行中断处理函数 -> CommonDispatchException -> KiDispatchException

异常的分类

  1. CPU产生的异常(除零异常)
  2. 软件模拟产生的异常(由高级语言C++,JAVA等throw抛出的异常)

Windows的异常代码

Windows 常见的 IDT 相关异常

中断号名称触发原因
0x00#DE (Divide Error)除零错误
0x06#UD (Invalid Opcode)非法指令
0x0D#GP (General Protection Fault)内存访问越权
0x0E#PF (Page Fault)页错误(访问无效内存)
0x2D#BP (Breakpoint)int 3 断点

在这里插入图片描述
但是处理异常并不是_KiTrap00这个函数去处理的,而是由CommonDispatchException(我这里是KiDispatchTrapException表示这个异常是由硬件触发的)处理

在这里插入图片描述
在这里插入图片描述

CommonDispatchException结构体

type struct _EXCEPTION_RECORD{DWORD ExceptionCode,		// 异常代码DWORD ExceptionFlags,		// 异常状态struct _EXCEPTION_RECORD *ExceptionRecord,	// 下一个异常PVOID ExceptionAddress,		// 发生异常的地址DWORD NumberParameters,		// 附加参数个数ULONG _PTR ExceptionInformation,[EXCEPTION_MAXIMUM_PARAMETERS]		// 附加参数指针
}

模拟异常记录

模拟代码

#include <iostream>void test() {// 模拟抛出异常throw 1;
}int main() {test();system("pause");return 0;
}

在这里插入图片描述

当我们使用软件模拟去调用异常时的调用链

CxxThrowException -> RaiseException(Kernel32.dll) -> NTDLL.DLL!RtlRaiseException() -> NTDLL!NtRaiseException -> NT!KiRaiseException

在这里插入图片描述

软件模拟异常和CPU异常的不同点

  1. 在CPU异常中都有对应的一个值(异常代码),而在软件模拟异常中这个值和当前的编译环境有关(在当前的编译环境中这个值是固定的)
  2. ExceptionAddress中存储的值是_RaiseException的地址,而CPU异常中存储的是异常的地址

总结:

  • CPU异常
    1. CPU检测到错误
    2. 查IDT表,执行中断处理函数
    3. CommonDispatchException(填充ExceptionRecord结构体)
    4. KiDispatchException
  • 模拟异常
    1. throw关键字(依赖编译器)
    2. CxxThrowException
    3. NTDLL.DLL!RtlRaiseException(填充ExceptionRecord结构体)
    4. NTDLL!NtRaiseException
    5. NT!KiRaiseException
    6. KiDispatchException

内核异常的处理流程

用户异常与内核异常

发生在用户空间的就是用户异常,发生在内核空间的就是内核异常

无论是CPU异常还是模拟异常,是用户层还是内核层异常,都要通过KiDispatchException函数进行分发,理解好这个函数是学好异常的关键

KiDispatchException执行流程

  1. _KeContextFromKframes 将Trap_frame备份到context为返回3环做准备
  2. 判断先前模式 0内核调用,1用户层调用
  3. 判断是否是第一次调用
  4. 判断是否有内核调式器
  5. 如果没有或者内核调试器不处理
  6. 调用RtlDispatchException
  7. 如果返回FALSE
  8. 再次判断是否有内核调试器,没有和有调用不处理就直接蓝屏

用户异常的分发

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

KiDispatchException执行流程

  1. _KeContextFromKframes 将Trap_frame备份到context为返回3环做准备
  2. 判断先前模式 0是内核调用,1是用户层调用
  3. 判断是否是次一次调用
  4. 判断是否有内核调式器
  5. 发送给3环调试器
  6. 如果3环调式器没有处理这个异常 修正EIP为KiUserExceptionDispatcher
  7. KiDispatchException函数执行结束
    • CPU异常:CPU检测到异常 -> 查IDT执行处理函数 -> CommonDispatchException -> KiDispatchException通过IRETD返回3环
    • 模拟异常:CxxThrowException -> RaiseException -> RtlRaiseException -> NT!NtRaiseException -> NT!KiRaiseException -> KiDispatchException 通过系统调用返回3环
  8. 无论通过哪种方式,线程再次回到3环时,将执行KiUserExceptionDispatcher
http://www.dtcms.com/a/303580.html

相关文章:

  • 嵌入式分享合集186
  • STM32时钟源
  • JavaScript手录09-内置对象【String对象】
  • 第一章:Go语言基础入门之函数
  • wrk 压力测试工具使用教程
  • 屏幕晃动机cad【4张】三维图+设计说明书
  • 多信号实采数据加噪版本
  • 详解 Electron 应用增量升级
  • 轻量级远程开发利器:Code Server与cpolar协同实现安全云端编码
  • 2. 编程语言-JAVA-Spring Security
  • 记录自己第n次面试(n>3)
  • JavaScript手录08-对象
  • 深入解析IPMI FRU规范:分区结构与字段标识详解
  • 10_opencv_分离颜色通道、多通道图像混合
  • Nuxt3 全栈作品【通用信息管理系统】修改密码
  • OpenLayers 综合案例-热力图
  • 在虚拟机ubuntu上修改framebuffer桌面不能显示图像
  • C++进阶—C++11
  • 5G 便携式多卡图传终端:移动作业的 “实时感知纽带”
  • 【unitrix】 6.19 Ord特质(ord.rs)
  • 【灰度实验】——图像预处理(OpenCV)
  • 2025年7月28日训练日志
  • 【三桥君】如何解决后端Agent和前端UI之间的交互问题?——解析AG-UI协议的神奇作用
  • 排水管网实时监测筑牢城市安全防线
  • 线程间-数据缓存机制(线程邮箱)
  • CDN架构全景图
  • STM32 usb HOST audio USB 音频设备 放音乐
  • springCloudAlibaba集成Dubbo
  • 【版本更新】火语言 0.9.94.0 更新
  • 虚拟面孔,真实革命