07 编译器扩展

1、_try _except自动挂入链表
手动挂入链表:
_asm{
mov eax, fs:[0]
mov temp, eax
lea ecx, myException
mov fs : [0], ecx
}
我们用上篇的简单测试代码下断点查看反汇编得到代码片段如下:

0040102A   push        offset __except_handler3 (00401320)
0040102F   mov         eax,fs:[00000000]
00401035   push        eax
00401036   mov         dword ptr fs:[0],esp

可见异常处理函数固定为_except_handler3 (00401320),编译器不同地址不同

2、_try _except嵌套,重复
每个使用_try _except的函数,不管内部嵌套或反复多次_try _except,只注册一遍,即只将一个_EXCEPTION_REGISTRATION_RECORD挂入当前线程的异常链表中(对于递归函数每一次调用都会创建_EXCEPTION_REGISTRATION_RECORD,并挂入线程的异常链表中)
typedef struct _EXCEPTION_REGISTRATION_RECORD{
struct _EXCEPTION_REGISTRATION_RECORD *Next;
PEXCEPTION_ROUTINE Handler;
}EXCEPTION_REGISTRATION_RECORD;
验证代码:

#include <windows.h>
#include <stdio.h>

void TestException()
{
	_try{
		_try{
	
		}
		_except(1){
		}
	
	}
	_except(1){
	}

	_try{
	
	}
	_except(1){
	}
}

int main()
{
	TestException();
	getchar();
	return 0;
}

对应反汇编

4:    void TestException()
5:    {
00401020   push        ebp
00401021   mov         ebp,esp
00401023   push        0FFh
00401025   push        offset string "_filbuf.c"+0FFFFFFD4h (00420020)
0040102A   push        offset __except_handler3 (0040127c)
0040102F   mov         eax,fs:[00000000]
00401035   push        eax
00401036   mov         dword ptr fs:[0],esp
0040103D   add         esp,0B8h
00401040   push        ebx
00401041   push        esi
00401042   push        edi
00401043   mov         dword ptr [ebp-18h],esp
00401046   lea         edi,[ebp-58h]
00401049   mov         ecx,10h
0040104E   mov         eax,0CCCCCCCCh
00401053   rep stos    dword ptr [edi]
6:        _try{
00401055   mov         dword ptr [ebp-4],0
7:            _try{
0040105C   mov         dword ptr [ebp-4],1
8:
9:            }
00401063   mov         dword ptr [ebp-4],0
0040106A   jmp         $L42199+0Ah (0040107c)
10:           _except(1){
0040106C   mov         eax,1
$L42200:
00401071   ret
$L42199:
00401072   mov         esp,dword ptr [ebp-18h]
11:           }
00401075   mov         dword ptr [ebp-4],0
12:
13:       }
0040107C   mov         dword ptr [ebp-4],0FFFFFFFFh
00401083   jmp         $L42195+0Ah (00401095)
14:       _except(1){
00401085   mov         eax,1
$L42196:
0040108A   ret
$L42195:
0040108B   mov         esp,dword ptr [ebp-18h]
15:       }
0040108E   mov         dword ptr [ebp-4],0FFFFFFFFh
16:
17:       _try{
00401095   mov         dword ptr [ebp-4],2
18:
19:       }
0040109C   mov         dword ptr [ebp-4],0FFFFFFFFh
004010A3   jmp         $L42203+0Ah (004010b5)
20:       _except(1){
004010A5   mov         eax,1
$L42204:
004010AA   ret
$L42203:
004010AB   mov         esp,dword ptr [ebp-18h]
21:       }
004010AE   mov         dword ptr [ebp-4],0FFFFFFFFh
22:   }
004010B5   mov         ecx,dword ptr [ebp-10h]
004010B8   mov         dword ptr fs:[0],ecx
004010BF   pop         edi
004010C0   pop         esi
004010C1   pop         ebx
004010C2   mov         esp,ebp
004010C4   pop         ebp
004010C5   ret

从上可以看到就一次该了fs:[0],那他是怎么实现的直挂一次就能解决问题的

3、编译器拓展_EXCEPTION_REGISTRATION_RECORD结构体

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

4、堆栈中形成的_EXCEPTION_REGISTRATION结构体
在这里插入图片描述
对比下面汇编代码分析

00401020   push        ebp
00401021   mov         ebp,esp
00401023   push        0FFh
00401025   push        offset string "_filbuf.c"+0FFFFFFD4h (00420020)
0040102A   push        offset __except_handler3 (0040127c)
0040102F   mov         eax,fs:[00000000]
00401035   push        eax

猜你喜欢

转载自blog.csdn.net/lifeshave/article/details/87610317
07
今日推荐