01 模拟异常

1、模拟异常产生
首先,我们用下面的代码来演示用软件抛出模拟异常时的情况

#include <stdio.h>

void Test()
{
	throw 1;
}

int main(int arg, char* args[])
{
	Test();
	getchar();
	return 0;
}

我们断点调试该程序,进入反汇编查看汇编代码我们发现有如下片段:

5:        throw 1;
00401038   mov         dword ptr [ebp-4],1
0040103F   push        offset __TI1H (00421558)
00401044   lea         eax,[ebp-4]
00401047   push        eax
00401048   call        __CxxThrowException@8 (00401290)

由上可见其调用了CxxThrowException函数,不同语言不同环境调用的函数可能不同。
接下来我们跟进这个函数里面去看一下是什么情况,发现如下代码片段:

004012B3   lea         edx,[ebp-0Ch]
004012B6   push        edx
004012B7   mov         eax,dword ptr [ebp-10h]
004012BA   push        eax
004012BB   mov         ecx,dword ptr [ebp-1Ch]
004012BE   push        ecx
004012BF   mov         edx,dword ptr [ebp-20h]
004012C2   push        edx
004012C3   call        dword ptr [__imp__RaiseException@16 (0042614c)]

发现其调用了一个kernel32里的函数RaiseException
所以我们通过软件模拟产生异常路线如下:
CxxThrowException—>(KERNEL32.DLL)void WINAPI RaiseException(
__in DWORD dwExceptionCode,
__in DWORD dwExceptionFlags,
__in DWORD nNumberOfArguments,
__in const ULONG_PTR *lpArguments );---->NTDLL.DLL!RtlRaiseException()
—>NT!NtRaiseException()—>NT!KiRaiseException()

2、(KERNEL32.DLL)RaiseException函数分析
<1>填充ExceptionRecord结构体
kd> dt _EXCEPTION_RECORD
ntdll!_EXCEPTION_RECORD
+0x000 ExceptionCode : Int4B //异常代码
+0x004 ExceptionFlags : Uint4B //异常状态
+0x008 ExceptionRecord : Ptr32 _EXCEPTION_RECORD //下一个异常
+0x00c ExceptionAddress : Ptr32 Void //异常发生地址
+0x010 NumberParameters : Uint4B //附加参数个数
+0x014 ExceptionInformation : [15] Uint4B //附加参数指针
调用Ntdll.dll!RtlRaiseException()函数
我们跟进CxxThrowException后查看模拟异常时ExceptionCode填的什么,CPU异常对应的一个确定的值,软件模拟异常跟编译环境有关在这里插入图片描述
我们用IDA查看RaiseException函数,发现ExceptionAddress存的是一个函数地址值

.text:7C812AC7                 mov     [ebp+ExceptionRecord.ExceptionFlags], eax ; 为ExceptionRecord.ExceptionFlags赋值,CPU异常是0,模拟异常是1
.text:7C812ACA                 mov     [ebp+ExceptionRecord.ExceptionAddress], offset _RaiseException@16 ; 为ExceptionRecord.ExceptionAddress赋值,CPU异常是异常发送位置

3、KiRaiseException()函数分析
<1>EXCEPTION_RECORD.ExceptionCode最高位清0,用于区分CPU异常
<2>调用KiDispatchException开始分发异常

4、总结:
在这里插入图片描述
异常分发后无法区分是CPU异常还是模拟异常

猜你喜欢

转载自blog.csdn.net/lifeshave/article/details/87524765
01
#01