9 异常

news2025/1/11 16:24:11

如果你希望在软件调试上有所突破,或者想了解如何通过异常进行反调试,或者想自己写一个调试器,那么就必须要深入了解异常,异常与调试是紧密相连的,异常是调试的基础。

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

异常记录

异常可以简单分为2类,即CPU产生的异常软件模拟产生的异常,如下两张图所示,我们可以看见第一张图中进行了除法运算,CPU检测到除数为0,就产生了异常;第二张图中使用了throw关键词,通过软件模拟主动产生了异常。

images/download/attachments/2949166/image2023-5-25_20-56-53.png

images/download/attachments/2949166/image2023-5-25_20-57-1.png

CPU的异常记录

我们先了解一个结构体_EXCEPTION_RECORD,它的格式及每个成员的意义如下:

typedef struct _EXCEPTION_RECORD 
{
	DWORD ExceptionCode; // 异常状态码,在Windows中每一种状态(包括异常)都有一个状态码
	DWORD ExceptionFlags; // 异常状态,0表示CPU异常,1表示软件模拟异常,8表示堆栈异常
	struct _EXCEPTION_RECORD *ExceptionRecord; // 通常情况下该值为空,如果发生嵌套异常(即处理异常时又出现了异常)则指向下一个异常
	PVOID ExceptionAddress; // 异常发生地址,表示异常发生时的位置
	DWORD NumberParameters; // 附加参数个数
	ULONG_PTR ExceptionInformation[EXCEPTION_MAXIMUM_PARAMETERS]; // 附加参数指针
} EXCEPTION_RECORD, *PEXCEPTION_RECORD;

Windows状态码及其对应含义,我们可以在在线文档中获取:[MS-ERREF]: NTSTATUS Values | Microsoft Learn,如下图所示我们可以看见,整数除0时的异常状态码为0xC0000094。

images/download/attachments/2949166/image2023-5-25_21-36-30.png

接着我们可以通过除0的例子来看一下CPU的异常记录过程,它的大致过程就是:CPU指令检测到异常→查IDT表执行中断处理函数→执行CommonDispatchException→执行KiDispatchException。我们可以通过IDA打开Ntoskrnl.exe先找到IDT表,通过ALT+T快捷键全局搜索_IDT,找到IDT表。

images/download/attachments/2949166/image2023-5-25_21-47-45.png

根据下图所示的中断描述符表我们可以知道除0异常对应的0号中断处理函数,因此我们就可以在IDA中进入对应的处理函数:

images/download/attachments/2949166/image2023-5-25_21-50-9.png

images/download/attachments/2949166/image2023-5-25_21-51-19.png

该函数的前面一部分代码和KiSystemService函数(系统调用API进0环)的代码一样,都是用来保存现场的:

images/download/attachments/2949166/image2023-5-25_21-54-40.png

接着向下可以看到,该中断处理函数直至执行结束都没有对异常进行处理(微软在设计时,希望程序员自己能够对异常进行处理,因此在中断处理函数中并没有对异常进行处理),反而是有多处的跳转,调用了另一个函数CommonDispatchException。

images/download/attachments/2949166/image2023-5-25_22-0-10.png

跟进CommonDispatchException函数,我们可以看见它开辟了一块大小为0x50的空间,用于存放_EXCEPTION_RECORD结构体,并且给结构体的每个成员赋值,最终执行KiDispatchException函数,该函数通常用来分发异常,目的是找到异常的处理函数。

images/download/attachments/2949166/image2023-5-25_22-8-38.png

其中异常状态码是来自上层的EAX,这点我们通过之前的流程就可以知道,接着我们来看异常发生地址(即ExceptionAddress)是来自上层的EBX,而EBX又来自[EBP+0x68],这里实际上指的是Trap_Frame结构体0x68偏移位Eip成员,它是用来记录中断发生地址的,这是因为在保存现场结束之后,ESP指向Trap_Frame的顶部,而EBP也与ESP一样

images/download/attachments/2949166/image2023-5-25_22-22-29.png

软件模拟的异常记录

我们接着来看一下throw关键词触发的软件模拟异常记录过程,在关键词处下断点,然后运行通过反汇编代码我们可以知道它调用的就是CxxThrowException函数:

images/download/attachments/2949166/image2023-5-26_12-30-18.png

跟进该函数,会发现它也是调用了另外一个函数RaiseException,并通过栈的方式压入了几个传参:

images/download/attachments/2949166/image2023-5-26_12-36-14.png

接着我们跟进RaiseException函数发现,正是这几个传参填充了_EXCEPTION_RECORD结构体,在这里我们会发现两个比较关键成员的值都与CPU异常记录时的赋值内容不一致,首先是ExceptionCode,它的值很明显是一个Windows异常状态码中没有的(即0xE06D7363),这是因为在软件模拟产生的异常场景下,ExceptionCode的值是根据不同的编译环境而生成的;其次是ExceptionAddress,如下图中我们可以看见,它的值是RasieException函数的首地址,而并不是真正产生异常的那段地址。

images/download/attachments/2949166/image2023-5-26_12-45-24.png

RaiseException函数之后的流程是这样的:RtlRaiseException→NtRaiseException→KiRaiseException,在最后执行到KiRaiseException函数时,会将ExceptionCode的最高位清0,便于区分CPU/软件模拟异常

images/download/attachments/2949166/image2023-5-26_12-53-55.png

虽然模拟异常与CPU异常有一定的差异,但是在最后,两者都会去调用KiDispatchException函数,用于异常分发

images/download/attachments/2949166/image2023-5-26_12-56-19.png

异常分发与处理

异常可以发生在用户空间,也可以发生在内核空间。无论是CPU异常还是模拟异常,无论是用户空间异常还是内核空间异常,最终都要通过KiDispatchException函数进行分发,理解这个函数是学好异常的关键,这个函数比较复杂,我们以内核、用户两个角度来分析学习。

内核异常

本章我们主要分析内核异常是如何分发,如何处理的。首先我们需要来了解一下KiDispatchException函数的格式,及每个参数的作用:

VOID KiDispatchException (
	PEXCEPTION_RECORD ExceptionRecord, // 异常记录结构体
	PKEXCEPTION_FRAME ExceptionFrame, // X86系统下,该值为NULL
	PKTRAP_FRAME TrapFrame, // 3环进0环保存现场所用的结构体
	KPROCESSOR_MODE PreviousMode, // 先前模式,表示调用来自什么模式,0表示内核模式,1表示用户模式
	BOOLEAN FirstChance // 判断是否是第一次分发这个异常,对于同一个异常,Windows最多分发两次
	// 该值为1表示第一次分发,为0表示第二次分发
)

通过IDA直接打开Ntoskrnl.exe模块,找

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2274986.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

springBoot整合ELK Windowsb版本 (elasticsearch+logstash+kibana)

springBoot整合ELK Windowsb版本 【elasticsearchlogstashkibana】 下载软件启动服务1、elasticsearch2、kibana3、logstash 集成springboot1、添加依赖2、在logback.xml添加相关配置3、修改logstash 配置4、重启logstash 最后测试 下载软件 elasticsearch 官网 https://www.…

详解Sonar与Jenkins 的集成使用!

本文阅读前提 本文假设读者熟悉Jenkins和SonarQube的基础操作。 核心实现功能 Jenkins中运行的job来调用SonarScanner,最后可实现测试结果与SonarQube中同步查看。 Jenkins中安装Sonar相关插件 配置Sonarqube Dashboard>Manage Jenkins>Systems 指定son…

鸿蒙面试 2025-01-10

写了鉴权工具,你在项目中申请了那些权限?(常用权限) 位置权限 : ohos.permission.LOCATION_IN_BACKGROUND:允许应用在后台访问位置信息。 ohos.permission.LOCATION:允许应用访问精确的位置信息…

php 使用simplexml_load_string转换xml数据格式失败

本文介绍如何使用php函数解析xml数据为数组。 <?php$a <xml><ToUserName><![CDATA[ww8b77afac71336111]]></ToUserName><FromUserName><![CDATA[sys]]></FromUserName><CreateTime>1736328669</CreateTime><Ms…

【多空资金博弈】综合副图指标,资金做多线,短线做多雷达,中长线共振,大资金进场会涨等技术信号

如上图&#xff0c;副图指标【多空资金博弈】&#xff0c;红线做多资金线&#xff0c;绿色线为做空资金线&#xff0c;紫色柱线为短线做多雷达信号&#xff0c;紫色圆柱叠加文字为大资金进场信号&#xff0c;堆量柱线和紫色空心柱线为底部吸筹建仓信号&#xff0c;三条横向虚线…

Win11家庭版转专业版

Win11家庭版转专业版&#xff08;亲测有效&#xff09; 第一步 【断网】输入这个密钥&#xff1a; R8NJ8-9X7PV-C7RCR-F3J9X-KQBP6 第二步 点击下一步会自动重启 第三步 【联网】输入这个密钥&#xff1a; F3NWX-VFMFC-MHYYF-BCJ3K-QV66Y 注意 两次输入密钥的地方一致 …

【云商城】高性能门户网构建

第3章 高性能门户网构建 网站门户就是首页 1.OpenResty 百万并发站点架构 ​ 1).OpenResty 特性介绍 ​ 2).搭建OpenResty ​ 3).Web站点动静分离方案剖析 2.Lua语法学习 ​ 1).Lua基本语法 3.多级缓存架构实战 ​ 1).多级缓存架构分析 用户请求网站&#xff0c;最开始…

上海亚商投顾:沪指探底回升微涨 机器人概念股午后爆发

上海亚商投顾前言&#xff1a;无惧大盘涨跌&#xff0c;解密龙虎榜资金&#xff0c;跟踪一线游资和机构资金动向&#xff0c;识别短期热点和强势个股。 一.市场情绪 市场全天探底回升&#xff0c;沪指盘中跌超1.6%&#xff0c;创业板指一度跌逾3%&#xff0c;午后集体拉升翻红…

计算机毕业设计Python机器学习农作物健康识别系统 人工智能 图像识别 机器学习 大数据毕业设计 算法

温馨提示&#xff1a;文末有 CSDN 平台官方提供的学长联系方式的名片&#xff01; 温馨提示&#xff1a;文末有 CSDN 平台官方提供的学长联系方式的名片&#xff01; 温馨提示&#xff1a;文末有 CSDN 平台官方提供的学长联系方式的名片&#xff01; 作者简介&#xff1a;Java领…

游戏语音的历史是什么样的?

游戏中&#xff0c;离不开游戏社交。 无社交&#xff0c;不游戏&#xff0c;大家都深知社交在游戏体验中的重要性。 游戏语音的发展史是怎么样的&#xff1f;问了下AI&#xff0c;给我的回答是 早期阶段 1970年代&#xff1a;1970年代出现了第一个语音游戏“尤瓦尔的冒险”&am…

《解锁图像的语言密码:Image Caption 开源神经网络项目全解析》

《解锁图像的语言密码&#xff1a;Image Caption 开源项目全解析》 一、开篇&#xff1a;AI 看图说话时代来临二、走进 Image Caption 开源世界三、核心技术拆解&#xff1a;AI 如何学会看图说话&#xff08;一&#xff09;深度学习双雄&#xff1a;CNN 与 RNN&#xff08;二&a…

毕业设计选题

你是不是正在纠结毕业设计该如何完成&#xff1f;不知道该如何选题?同时又觉得定制太昂贵&#xff1f;你是不是还在为毕业论文不会写而苦恼&#xff1f; 当你看到这儿&#xff0c;就不用再纠结再苦恼了&#xff0c;周哥为你提供了计算机专业各个方向的选题&#xff0c;包括Jav…

linux RT-Preempt spin lock实现

一、spin_lock概述 Spinlock是linux内核中常用的一种互斥锁机制&#xff0c;和mutex不同&#xff0c;当无法持锁进入临界区的时候&#xff0c;当前执行线索不会阻塞&#xff0c;而是不断的自旋等待该锁释放。正因为如此&#xff0c;自旋锁也是可以用在中断上下文的。也正是因为…

Ubuntu 22.04 桥接配置

1. 网卡配置文件备份 sudo cp /etc/netplan/01-network-manager-all.yaml /etc/netplan/01-network-manager-all.yaml.bak 1.1 静态ip配置 1.1.3 解释 network: version: 2 ethernets: # 网卡名称 使用ifconfig查看 ens33: dhcp4: false dhcp6: false …

PHP多功能投票小程序源码

多功能投票小程序&#xff1a;全方位打造专属投票盛宴的得力助手 &#x1f389; &#x1f527; 基于先进的ThinkPHP框架与Uniapp技术深度融合&#xff0c;我们匠心独运&#xff0c;精心雕琢出一款功能全面、操作便捷的投票小程序&#xff0c;旨在为您带来前所未有的投票体验。…

[fastadmin] 第三十四篇 FastAdmin 商城模块标签使用详解

FastAdmin 商城模块标签使用详解 一、标签基本语法 1.1 基础语法格式 {shop:goodslist flag"参数值" id"变量名" row"数量"}<!-- 循环内容 --> {/shop:goodslist}1.2 常用参数说明 flag: 商品标记筛选id: 循环变量名row: 显示数量 1.…

二维数组-

定义&#xff1a;二维数组本质上也就是一维数组&#xff0c;只不过每个元素又是一个一维数组 基本语法&#xff1a; 数据类型[][] 数组名称 new 数据类型 [行数][列数] {}初始化数据; 示例&#xff1a; public class Test {public static void main(String[] args) {int[]…

软件测试预备知识④—NTFS权限管理、磁盘配额与文件共享

在软件测试的实际环境搭建与管理过程中&#xff0c;了解和掌握NTFS权限管理、磁盘配额以及文件共享等知识至关重要。这些功能不仅影响系统的安全性和稳定性&#xff0c;还对测试数据的存储、访问以及多用户协作测试有着深远的影响。 一、NTFS权限管理 1.1 NTFS简介 NTFS&am…

自动控制原理初识

文章目录 1.引言2.自动控制原理2.1方框图的案例2.2方框图里面的相关符号2.3闭环控制系统的特点2.4三种基础控制方式2.5对于控制系统的基本要求2.6自动控制原理的体系架构 3.控制系统的数学模型3.1为什么建模3.2建模的方法3.3什么是线性系统3.4线性or非线性系统判断3.5时变or定常…

计算机网络(二)——物理层和数据链路层

一、物理层 1.作用 实现相信计算机节点之间比特流的透明传输&#xff0c;尽可能屏蔽具体传输介质和物理设备的差异。 2.数据传输单位 比特。 3.相关通信概念 ①信源和信宿&#xff1a;即信号的发送方和接收方。 ②数据&#xff1a;即信息的实体&#xff0c;比如图像、视频等&am…