1、RtlDispatchException函数式执行流程
SEH是线程相关的
2、SEH测试
#include <stdio.h>
#include "windows.h"
//0环异常处理时遇到的结构体
/*
typedef struct _EXCEPTION_REGISTRATION_RECORD{
struct _EXCEPTION_REGISTRATION_RECORD *Next;
PEXCEPTION_ROUTINE Handler;
}EXCEPTION_REGISTRATION_RECORD;
*/
struct MyException{
struct MyException *prev;
DWORD handle;
};
EXCEPTION_DISPOSITION _cdecl MyException_handler(
struct _EXCEPTION_RECORD *ExceptionRecord, //ExceptionRecord 存储异常信息,什么类型,异常产生位置
void* EstablisherFrame, //MyException 结构体地址
struct _CONTEXT *RecordContext, //_CONTEXT结构体,存储异常发生时的各种寄存器值,堆栈位置等
void *DispatcherContext)
{
::MessageBox(NULL, "SEH异常处理函数执行了", "SEH异常", MB_OK);
//除0异常对应的编号是0xC0000094
if (ExceptionRecord->ExceptionCode == 0xC0000094){
//函数返回如果想跳过idiv ecx指令执行printf则将Eip+2,idiv ecx 硬编码两个字节
//RecordContext->Eip = RecordContext->Eip + 2;
RecordContext->Ecx = 1;
return ExceptionContinueExecution;
}
return ExceptionContinueSearch;
}
void TestException()
{
DWORD temp;
MyException myException;
//插入异常,必须在当前的堆栈中
_asm{
mov eax, fs:[0]
mov temp, eax
lea ecx, myException
mov fs : [0], ecx
}
myException.prev = (MyException *)temp;
myException.handle = (DWORD)&MyException_handler;
//创造异常
_asm{
xor edx, edx
xor ecx, ecx
mov eax, 0x10
idiv ecx //edx:eax除ecx
}
//摘掉异常
_asm{
lea ecx, temp
mov fs : [0], ecx
}
printf("函数正常执行\n");
}
int main()
{
TestException();
getchar();
return 0;
}
3、总结:SEH异常的流程
<1>FS:[0]指向SEH链表的第一个成员
<2>SEH的异常处理函数必须在当前线程的堆栈中
<3>只有当VEH中的异常函数不存在或者不处理,才会在SEH中查找