05 SEH(结构化异常处理)

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中查找

猜你喜欢

转载自blog.csdn.net/lifeshave/article/details/87540165