内核学习——VEH / SEH

VEH全局链表:与线程无关

全局链表结构(每个是个EXCEOTION_REGISTRATION_RECORD)
在这里插入图片描述构造除零异常

__asm
{
	xor edx,edx
	xor ecx,ecx
	mov eax.0x10
	idiv ecx //edx:eax 除以 ecx
}

用一个函数将异常处理函数挂入VEH,异常处理函数如下

LONG NTAPI VecExcepHandler( PEXCEPTION_POINTERS pExcepInfo )
{
	::MessageBoxA(NULL,"VEH异常处理函数执行了","VEH异常",MB_OK);
	//异常过滤
    if( pExcepInfo->ExceptionRecord->ExceptionCode == 0xC0000094)
    {	//异常处理
		pExcepInfo->ContextRecord->Eip = pExcepInfo->ContextRecord->Eip+2;
		//pExcepInfo->ContextRecord->Ecx = 1;
		return 已处理
	}
	return 未处理
}

SEH局部链表:在堆栈中

windows原始结构

typedef struct _EXCEOTION_REGISTRATION_RECORD{
		struct _EXCEPTION_REGISTRATION_RECORD *Next;
		PEXCEPTION_ROUTINE Handler;
}EXCEOTION_REGISTRATION_RECORD;

编译器拓展结构,扩展了3个成员是因为一个函数里无论有多少try catch都只挂一个record

struct _EXCEOTION_REGISTRATION_RECORD{
		struct _EXCEPTION_REGISTRATION *prev;
		void (*handler)(PEXCEPTION_RECORD,
			PEXCEPTION_REGISTRATION,
			PCONTEXT,PEXCEPTION_RECORD);
		struct scopetable_entry *scopetable;
		int reylevel;
		int _ebp;
};

自己实现将异常处理函数挂入SEH

DWORD temp;
MyException myException;//自己定义的EXCEOTION_REGISTRATION_RECORD
//将原FS:[0]存入temp
//将FS:[0]指向新的EXCEOTION_REGISTRATION_RECORD
//挂入链表
__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{
		mov eax,temp
		mov FS:[0],eax
}

编译器实现将异常处理函数挂入SEH
过滤表达式有 常量 (1,0)/ 表达式(exceptioncode=0x…) / 函数(GetExceptionInfo()里有context等)
过滤表达式为函数,可能在函数里涉及加密,异常处理程序也会涉及

try					//挂入链表(对应上面的代码)
{

}
except(过滤表达式)	//异常过滤
{
	异常处理程序		//异常处理
}

多个try & scopetable,trylevel分析

Example

try{
}
except(){
}
try{
	try{
	}
	except(){
	}
}
except(){
}

●每个使用try的函数,不论其内部嵌套或反复使用多少个try,都只将一个EXCEOTION_REGISTRATION_RECORD挂入当前线程的SEH(对于递归函数,每一次调用都会创建一个EXCEOTION_REGISTRATION_RECORD并挂入),以下是初始化了扩展的record

push ebp //ebp
mov ebp,esp //提升堆栈
push 0xFF //-1,trylevel
push scopetable地址
push 异常处理函数地址
mov eax,FS:[0]
push eax  //prev
mov fs:[0] ,esp //指向新结构体,即挂入链表

●对于scopetable,有几个try就有几个成员

struct scopetable_entry
{
	DWORD previousTryLevel	//上一个try{}结构编号
	PDWRD lpfnFilter		//过滤函数的起始地址,except()
	PDWRD lpgnHandler		//异常处理程序的地址,except里的
}
scopetable[0].previousTryLevel = -1 //因为前面没try
scopetable[0].lpfnFilter = 过滤函数1 //异常过滤
scopetable[0].lpgnHandler = 异常处理函数1 //异常处理
scopetable[1].previousTryLevel = -1 
scopetable[1].lpfnFilter = 过滤函数2
scopetable[1].lpgnHandler = 异常处理函数2
scopetable[2].previousTryLevel = 1	//嵌套try
scopetable[2].lpfnFilter = 过滤函数3
scopetable[2].lpgnHandler = 异常处理函数3
如果嵌套里面再嵌套一个level就是2

Example

try{
	try{
	}
	except(){
	}
}
except(){
}
try{
	try{
	}
	except(){
	}
}
except(){
}

●trylevel用于标识当前代码执行在哪个try里,是随时变化的,进入try就改变值

例子的变化过程如下:
-1(try 外),0(第一个try),1(第2个),0(恢复,在第一个try),-1(退出了第一个try)
2(第三个),3(第四个),2,-1(-1就是不在任何try里)

如果是自己throw的知识KiDispatchException前不一样except_handler3在SEH里
在这里插入图片描述

try {
可能出错的代码
}
finally{
一定要执行的代码
}
finally用在try里没发生异常且提前退出,finally的PDWRD lpfnFilter为空,局部展开(一个函数的名称)调用finally
若出现异常,一层一层的往外找except处理,然后finally,全局展开这个函数走的
在这里插入图片描述

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

q1uTruth

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值