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

相关文章:

  • 计算机视觉---Halcon概览
  • 暑期自学嵌入式——Day10(C语言阶段)
  • 生成器和迭代器的区别
  • 【65 Pandas+Pyecharts | 山东省2025年高考志愿投档数据分析可视化】
  • MCP架构:模型上下文协议的范式革命与工程实践
  • JSBridge原理与实现全解析
  • 嵌入式单片机中位带操作控制与实现
  • flutter使用firebase集成谷歌,苹果登录
  • C++20实战FlamingoIM开发
  • 和豆包玩的AI文字冒险游戏(可以当小说看)
  • 大模型推理框架基础概述
  • 4.应用层自定义协议与序列化
  • 【OS】真题 2015
  • k8s中Nvidia节点驱动的配置问题
  • Item18:让接口容易被正确使用,不易被误用
  • 设计模式(十五)行为型:命令模式详解
  • 计算机毕业设计java在线二手系统的设计与实现 基于Java的在线二手交易平台开发 Java技术驱动的二手物品管理系统
  • 低代码可视化AR远程协助、巡检、装配、质检新平台-元境智搭平台
  • MySQL高级配置与优化实战指南
  • 网站劫持是什么?如何防御?一篇简单科普
  • windows clion远程连接ubuntu运行调试nginx-1.22.1版本
  • MySQL有哪些“饮鸩止渴”提高性能的方法?
  • Linux应用程序架构与软件包管理
  • 在Windows下读写Linux EXT文件系统文件
  • VMWARE -ESXI-ntp时间同步无法启动异常处理
  • 用 Python 获取电脑电池电量的各种案例
  • ubuntu资源共享samba 安装与配置 mac/windows共享ubuntu文件资源
  • 暴雨服务器更懂人工智能+
  • 【GaussDB】内存资源告急:深度诊断一起“memory temporarily unavailable“故障
  • 虚拟面孔,真实革命