当前位置: 首页 > 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.xdnf.cn/news/1203175.html

相关文章:

  • C++ 内存管理
  • 图像轮廓与凸包
  • 数据赋能(345)——数据整合——全面集成原则
  • 《 服务注册发现原理:从 Eureka 到 Nacos 的演进》
  • Vue、微信小程序、Uniapp 面试题整理最新整合版
  • 博士申请 | 荷兰阿姆斯特丹大学 招收计算机视觉(CV)方向 全奖博士生
  • JAVA后端开发——用 Spring Boot 实现定时任务
  • Spring与SpringBoot:从手动挡到自动挡的Java开发进化论
  • JAVA:Spring Boot 集成 Protobuf 的技术指南
  • Office-PowerPoint-MCP-Server – 基于MCP的开源PPT生成与编辑工具
  • 基于AFLFast的fuzz自动化漏洞挖掘(1)
  • 【Linux系统】Ext2文件系统 | 软硬链接
  • 6种将iPhone照片传输到Windows 10电脑的方法
  • 最小二乘法拟合椭圆
  • 《Linux服务与安全管理》| samba服务器配置匿名模式
  • 嵌入式基础知识复习(7.28)
  • 未授权访问
  • C++ list 容器全解析:从构造到模拟实现的深度探索----《Hello C++ Wrold!》(16)--(C/C++)
  • window显示驱动开发—Direct3D 11 视频设备驱动程序接口 (DDI)
  • OpenLayers 综合案例-信息窗体-弹窗
  • 对于ui=f(state)的理解(react)
  • python毕业设计案例:基于python django的抖音数据分析与可视化系统,可视化有echarts,算法包括lstm+朴素贝叶斯算法
  • 【Datawhale夏令营】端侧Agent开发实践
  • 【Unity笔记】Unity Camera.cullingMask 使用指南:Layer 精准控制、XR 多视图与性能提升
  • [机缘参悟-236]:通过AI人工神经网络理解人的思维特征:惯性思维、路径依赖、适应性、不同场合不同言行、经验、概率、常规与特殊情形(正态分布)、环境适应性
  • 【linux】md5文件相似校验介绍与实战示例
  • 零基础学习性能测试第九章:全链路追踪-项目实操
  • 设计模式(十七)行为型:迭代器模式详解
  • react前端样式如何给元素设置高度自适应
  • debian系统分卷是不会影响系统启动速度?