SEH处理异常

Win32为每个线程定义了一个线程信息块,其中保存了线程的一些属性数据,线程信息块的属性被定义为NT_TIB结构

typedef struct _NT_TIB {

    struct _EXCEPTION_REGISTRATION_RECORD *ExceptionList;

    PVOID StackBase;

    PVOID StackLimit;

    PVOID SubSystemTib;

    union {

        PVOID FiberData;

        ULONG Version;

    };

    PVOID ArbitraryUserPointer;

    struct _NT_TIB *Self;

} NT_TIB;

ExceptionList指向一个EXCEPTION_REGISTRATION结构-也就是SEH链的入口地址

 

EXCEPTION_REGISTRATION STRUCT

  prev           dd       ?                       ;前一个EXCEPTION_REGISTRATION结构的地址

 handler     dd       ?                        ;异常处理回调函数的地址

EXCEPTION_REGISTRATION ends

 所以  一系列的EXCEPTION_REGISTRATION结构  就组成了一个SEH链...

 

TIB是放在fs段寄存器指向的数据段的0偏移处  所以 fs;[0]指向TIB结构的ExceptionList字段,由于同一个进程中 有不同的线程,所以不同线程中的fs段寄存器可以使用不同的值,这种特性使得每个线程都可以设置不同的回调函数

 

如果内存是从高到低构建...栈则也是从高到低构建....那么对于栈而言

push offset _Handler           ;异常处理程序的回调函数地址

push fs:[0]                               ;上一个EXCEPTION_REGISTRATION结构的地址

mov   fs:[0],esp                       ;设置当前EXCEPTION_REGISTRATION结构的地址

esp此时 正好指向你构建的EXCEPTION_REGISTRATION结构体

 

SEH异常处理回调函数的参数定义与筛选器器的回调函数的参数定义有所不同,其定义如下,其调用约定为C格式,

_Handler proc C _lpExceptionRecord,_lpSEH,_lpContext,_lpDispatcherContext

_lpExceptionRecord  指向EXCEPTION_RECORD结构(保存异常的相关信息)

_lpContext                   指向一个Thread Context结构-保存线程上下文

_lpSEH                         指向注册回调函数时EXCEPTION_REGISTRATION结构的首地址--利用这个字段可以用栈来传递一些自定义数据如SafeCode地址

 

回调函数的返回值:

ExceptionContinueExecution(等于0):回调函数返回后,系统将线程环境设置为_lpContext参数指定的CONTEXT结构并继续执行

ExceptionContinueSearch(等于1):回调函数拒绝处理这个异常,系统将通过 EXCEPTION_REGISTRATION结构的prev字段得到前一个回调函数的地址并调用他

ExceptionNestedException(等于2):回调函数执行过程中,又发生了新的异常,即触发了嵌套异常

ExceptionCollidedUnwind(等于3):发生了嵌套展开操作

 

代码:

<span style="font-family:Microsoft YaHei;font-size:13px;">		.386
		.model flat,stdcall
		option casemap:none
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
include	windows.inc
include	user32.inc
includelib	user32.lib
include	kernel32.inc
includelib	kernel32.lib

L macro var:VARARG
	LOCAL @lbl
	.const
	@lbl db var,0
	.code
	exitm <offset @lbl>
endm
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
;Code Segment
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
		.code
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
;SEH Handler
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
_Handler proc C _lpExceptionRecord,_lpSEH,_lpContext,_lpDispatcherContext
	LOCAL	@szBuffer[256]:BYTE
	
	pushad
	mov	esi,_lpExceptionRecord
	mov	edi,_lpContext
	assume esi:ptr EXCEPTION_RECORD,edi:ptr CONTEXT
	invoke	wsprintf,addr @szBuffer,L("异常位置:%08x,异常代码:%08x,异常标志:%08x"),[edi].regEip,[esi].ExceptionCode,[esi].ExceptionFlags
	invoke	MessageBox,NULL,addr @szBuffer,L("---"),MB_OK
	mov		eax,_lpSEH
	push		[eax + 8]
	pop		[edi].regEip
	push		[eax + 0ch]
	pop		[edi].regEsp					;这个是属于当前线程的-而不是当前的栈指针
	assume esi:nothing,edi:nothing
	popad
	mov	eax,ExceptionContinueExecution		;这个会先返回到内核里面去
	ret

_Handler endp
start:
		assume fs:nothing
		push		ebp						;添加的自定义数据
		push		offset _SafePlace			;添加的自定义数据......
		push		offset _Handler
		push		fs:[0]
		mov		fs:[0],esp
		
		xor		eax,eax
		mov		dword ptr [eax],0
		
_SafePlace:
		invoke	MessageBox,NULL,L("----"),L("----"),MB_OK
		pop 		fs:[0]
		add		esp,0ch					;恢复栈平衡
		invoke	ExitProcess,NULL
end start
</span>


 

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值