avatar

Catalog
软件模拟异常记录

前言

在上一篇介绍了CPU异常记录的过程,本篇介绍软件模拟异常的记录过程。并比对两者之间的区别。

分析软件模拟异常

本次用一个小实验,分析软件模拟异常的流程

测试代码

编译并运行如下代码(环境:Windows XP,IDE:VC++6.0)

c
1
2
3
4
5
6
7
8
9
#include "stdafx.h"

int main(int argc, char* argv[])
{
throw 1;

getchar();
return 0;
}

查看反汇编

在”throw 1”处下断点,运行程序,进入反汇编查看。

可以看到,它调用了函数_CxxThrowException

_CxxThrowException

接下来步入_CxxThrowException

发现_CxxThrowException又调用了RaiseException函数,这是一个Kernel32.dll中的导出函数

RaiseException

RaiseException函数,又调用了RtlRaiseException函数,这是一个Ntdll.dll中的函数

RtlRaiseException

RtlRaiseException会先调用ZwRaiseException,然后通过系统服务调用机制,调用内核函数NtRaiseException,进入内核

NtRaiseException

NtRaiseException又调用了另一个内核函数KiRaiseException

KiRaiseException

KiRaiseException最终调用了用于异常分发的函数KiDispatchException

小结

根据软件模拟异常的执行流程,可以看出最终也会调用KiDispatchException函数,和CPU异常是一样的。所以可以认为,进入异常分发的步骤后,CPU异常与软件模拟异常就没有明显的区别了。接下来,将会对部分函数进行分析,了解软件模拟异常是如何填充和构建ExceptionRecord结构体的。

ExceptionRecord结构体填充

学习完CPU异常记录了解到,异常记录的核心步骤,是对_EXCEPTION_RECORD结构体的构建和初始化。这里先回顾一下该结构。

其中最重要的是ExceptionCode与ExceptionAddress两个字段的赋值。接下来,将会重新分析软件模拟异常执行流程中的一些函数,观察赋值的细节。

ExceptionAddress

再来看这个RaiseException函数,这是_CxxThrowException调用的一个3环函数,可以看到,该函数主要就是初始化ExceptionRecord结构体,其中ExceptionAddress填入的并不是发生异常处的地址,而是RaiseException函数的地址。

ExceptionCode

ExceptionCode是状态异常码,其实它已在RaiseException函数的参数中出现,所以我们得单步到_CxxThrowException调用RaiseException前传递参数的位置。

通过观察反汇编,可以看到,传给RaiseException的第一个参数值(ExceptionCode)为0xE06D7363,与Windows提供的异常状态码的值并不相符。原因是在软件模拟异常的情况下,ExceptionCode的值是根据不同的编译环境而设定的调用RaiseException函数的CxxThrowException也是如此。例如Visual C++程序抛出的异常,会通过CxxThrowException调用RaiseException函数,ExceptionCode的值固定为0xE06D7363,但是在别的编译环境下(例如.NET程序)会通过其它函数调用RaiseException函数,ExceptionCode的值则为0xE0434F4D。

KiRaiseException

这里为啥还要重提一下这个函数呢。该函数在调用前还做了一件比较关键的事,将_EXCEPTION_RECORD.ExceptinCode的最高位清零,用于区分CPU异常。

总结

CPU异常与软件模拟异常,最终都要调用KiDispatchException,在对异常记录这部分的流程有所不同。其中ExceptionCode与ExceptionAddress两个字段尤为关键。

参考资料

参考书籍:

  • 《软件调试 卷2:Windows平台调试》p243~p244 —— 张银奎

参考教程:

  • 海哥中级预习班课程

参考链接:

  1. https://blog.csdn.net/qq_41988448/article/details/104989318 (CSDN-lyzddf学习笔记,他的笔记止步于此,之后的文章就不会有他笔记的引用了)
  2. https://blog.csdn.net/qq_38474570/article/details/104346316 (CSDN-鬼手56学习笔记)
  3. https://blog.csdn.net/weixin_42052102/article/details/83501391 (CSDN-My classmates学习笔记)
Author: cataLoc
Link: http://cata1oc.github.io/2020/08/19/%E8%BD%AF%E4%BB%B6%E6%A8%A1%E6%8B%9F%E5%BC%82%E5%B8%B8%E8%AE%B0%E5%BD%95/
Copyright Notice: All articles in this blog are licensed under CC BY-NC-SA 4.0 unless stating additionally.
Donate
  • 微信
    微信
  • 支付寶
    支付寶