Windows使用筛选器来处理异常

 

很久木有管博客了   最近也没有学什么   


Dos系统下发生异常后,系统会调用int 24h服务例程,然后根据中断的返回值决定下一步要做什么,他会在屏幕上显示ignore Retry Fail Abort  让用户选择进而进行下一步操作

这样的话  只要应用程序截取int 24h中断,就可以随意的"胡作非为"了

 

Windows操作系统对异常的处理流程相对复杂,其依靠80x86的保护模式机制来主动捕获异常.

 

用SetUnhandledExceptionFilter函数设置异常处理回调函数

<span style="font-family:Microsoft YaHei;font-size:13px;">invoke SetUnhandledExceptionFilter,addr _Handler

mov   lpOldHandler,eax

</span>


函数返回的是原回调函数的地址

 

筛选器回调函数的格式如下

_Handler proc lpExceptionInfo

lpExceptionInfo  指向一个EXCEPTION_POINTERS结构

<span style="font-family:Microsoft YaHei;font-size:13px;">EXCEPTION_POINTERS STRUCT

      pExceptionRecord   DWORD  ?     ;指向一个EXCEPTION_RECORD结构

       ContextRecord      DWORD  ?     ;指向一个CONTEXT结构

EXCEPTION_POINTERS ENDS

</span>

 (1)EXCEPTION_RECORD结构

<span style="font-family:Microsoft YaHei;font-size:13px;">typedef struct _EXCEPTION_RECORD { 
  DWORD ExceptionCode;                                             //异常事件代码
  DWORD ExceptionFlags;                                            //异常标志    
  struct _EXCEPTION_RECORD *ExceptionRecord;                       //下一个Exception_Record结构地址
  PVOID ExceptionAddress; 
  DWORD NumberParameters; 
  ULONG_PTR ExceptionInformation[EXCEPTION_MAXIMUM_PARAMETERS];
} EXCEPTION_RECORD, *PEXCEPTION_RECORD; 
</span>

ExceptionCode指定了一系列的错误代码,说明了错误的原因

ExceptionFlags说明了错误的标志 ,由一系列的数据位组成

位0:代表发生的异常是否允许被恢复执行,当位0被复位的时候,表示回调函数在对异常进行处理后可以指定让程序继续运行,置位时候表示这个异常是不可恢复的,,这个时候程序最好进行退出前的扫尾工作,并选择终止应用程序,如果这个时候非要指定让程序继续执行的话,Windows会再次以EXCEPTION_NONCONTINUABLE_EXCEPTION异常代码调用回调函数.为了程序的可读性,可以通过2个预定义值来测试这个位,EXCEPTION_CONTINUABLE(定义为0)和EXCEPTION_NONCONTINUABLE(定义为1)

位1:EXCEPTION_UNWINDING标志.表示回调函数被调用的原因是进行了展开操作

位2:EXCEPTION_UNWINDING_FOR_EXIT标志,表示回调函数被调用的原因是进行最终退出前的展开操作

当异常处理函数的代码设计得不完善而在运行中引发新的异常时,回调函数会被嵌套调用,在这种情况下EXCEPTION_RECORD结构中的pExceptionRecord字段会指向下一个EXCEPTION_RECORD结构....如果没有发生嵌套异常,这个值为NULL
 (2)CONTEXT 线程上下文

<span style="font-family:Microsoft YaHei;font-size:13px;">typedef struct _CONTEXT {  
  
    //   
    // The flags values within this flag control the contents of   
    // a CONTEXT record.   
    //   
    // If the context record is used as an input parameter, then   
    // for each portion of the context record controlled by a flag   
    // whose value is set, it is assumed that that portion of the   
    // context record contains valid context. If the context record   
    // is being used to modify a threads context, then only that   
    // portion of the threads context will be modified.   
    //   
    // If the context record is used as an IN OUT parameter to capture   
    // the context of a thread, then only those portions of the thread's   
    // context corresponding to set flags will be returned.   
    //   
    // The context record is never used as an OUT only parameter.   
    //   
  
    DWORD ContextFlags;  
  
    //   
    // This section is specified/returned if CONTEXT_DEBUG_REGISTERS is   
    // set in ContextFlags.  Note that CONTEXT_DEBUG_REGISTERS is NOT   
    // included in CONTEXT_FULL.   
    //   
  
    DWORD   Dr0;  
    DWORD   Dr1;  
    DWORD   Dr2;  
    DWORD   Dr3;  
    DWORD   Dr6;  
    DWORD   Dr7;  
  
    //   
    // This section is specified/returned if the   
    // ContextFlags word contians the flag CONTEXT_FLOATING_POINT.   
    //   
  
    FLOATING_SAVE_AREA FloatSave;  
  
    //   
    // This section is specified/returned if the   
    // ContextFlags word contians the flag CONTEXT_SEGMENTS.   
    //   
  
    DWORD   SegGs;  
    DWORD   SegFs;  
    DWORD   SegEs;  
    DWORD   SegDs;  
  
    //   
    // This section is specified/returned if the   
    // ContextFlags word contians the flag CONTEXT_INTEGER.   
    //   
  
    DWORD   Edi;  
    DWORD   Esi;  
    DWORD   Ebx;  
    DWORD   Edx;  
    DWORD   Ecx;  
    DWORD   Eax;  
  
    //   
    // This section is specified/returned if the   
    // ContextFlags word contians the flag CONTEXT_CONTROL.   
    //   
  
    DWORD   Ebp;  
    DWORD   Eip;  
    DWORD   SegCs;              // MUST BE SANITIZED   
    DWORD   EFlags;             // MUST BE SANITIZED   
    DWORD   Esp;  
    DWORD   SegSs;  
  
    //   
    // This section is specified/returned if the ContextFlags word   
    // contains the flag CONTEXT_EXTENDED_REGISTERS.   
    // The format and contexts are processor specific   
    //   
    BYTE    ExtendedRegisters[MAXIMUM_SUPPORTED_EXTENSION];  
  
} CONTEXT;  
typedef CONTEXT *PCONTEXT;  
</span>

(3)异常处理程序的返回值

回调函数返回后,Windows执行默认的异常处理程序,这个程序会根据回调函数的返回值决定如何进行下一步动作

回调函数的返回值可以有3种取值:EXCEPTION_EXECUTE_HANDLER(定义为1),EXCEPTION_CONTINUE_SEARCH(定义为0)和EXCEPTION_CONTINUE_EXECUTION(定义为-1)

当返回值为1时,进程将被终止,但是在终止之前,系统不会显示出错提示对话框;当返回值为0时,系统同样将终止程序,但是在终止之前会显示出错的提示对话框.使用这2种返回值的时候,异常处理程序完成的工作一般是退出前的扫尾工作.

当返回值为-1时,系统将CONTEXT设置回去的并继续执行程序..

 

当异常的标志位为EXCEPTION_NONCONTINUABLE的标志位时候,不应该设置EXCEPTION_CONTINUE_EXECUTION返回值,这样只会引发一个新的异常

 

一个异常处理的小程序  ...

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

L macro var:VARARG
	LOCAL @lbl
	.const
	@lbl db var,0
	.code
	exitm <offset @lbl>
endm
.data?
lpOldHandler	dd	?
.code
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
;功能: 筛选器   ---全局的   Handler ---------  异常处理程序
;参数: 指向一个EXCEPTION_POINTERS
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
_Handler	proc	_lpExceptionPoint
	LOCAL	@szBuffer[256]:byte
	
	pushad
	;关联esi到EXCEPTION_POINTERS结构体
	mov	esi,_lpExceptionPoint
	assume esi:ptr EXCEPTION_POINTERS
	mov	edi,[esi].ContextRecord			;指向一个EXCEPTION_RECORD结构
	mov	esi,[esi].pExceptionRecord 		;指向一个Thread Context结构
	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		[edi].regEip,offset _SafePlace
	
	assume edi:nothing,esi:nothing
	popad
	mov		eax,EXCEPTION_CONTINUE_EXECUTION
	ret
_Handler endp

start:
	invoke	SetUnhandledExceptionFilter,addr _Handler
	mov		lpOldHandler,eax
	;下面是引发异常的指令
	xor	eax,eax
	mov	dword ptr [eax],0
	;这里的代码没有被执行哦
	invoke	MessageBox,NULL,L("这里没有被执行哦"),L("------"),MB_OK
	;安全地方
_SafePlace:
	invoke	MessageBox,NULL,L("哈哈 到安全地方啦"),L("成功"),MB_OK
	invoke	SetUnhandledExceptionFilter,lpOldHandler	
	invoke	ExitProcess,NULL
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
end start</span>


 

 

 


 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值