欢迎访问 生活随笔!

生活随笔

当前位置: 首页 > 编程资源 > 编程问答 >内容正文

编程问答

SEH处理异常

发布时间:2023/12/1 编程问答 55 豆豆
生活随笔 收集整理的这篇文章主要介绍了 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,stdcalloption casemap:none ;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> include windows.inc include user32.inc includelib user32.lib include kernel32.inc includelib kernel32.libL macro var:VARARGLOCAL @lbl.const@lbl db var,0.codeexitm <offset @lbl> endm ;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> ;Code Segment ;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>.code ;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> ;SEH Handler ;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> _Handler proc C _lpExceptionRecord,_lpSEH,_lpContext,_lpDispatcherContextLOCAL @szBuffer[256]:BYTEpushadmov esi,_lpExceptionRecordmov edi,_lpContextassume esi:ptr EXCEPTION_RECORD,edi:ptr CONTEXTinvoke wsprintf,addr @szBuffer,L("异常位置:%08x,异常代码:%08x,异常标志:%08x"),[edi].regEip,[esi].ExceptionCode,[esi].ExceptionFlagsinvoke MessageBox,NULL,addr @szBuffer,L("---"),MB_OKmov eax,_lpSEHpush [eax + 8]pop [edi].regEippush [eax + 0ch]pop [edi].regEsp ;这个是属于当前线程的-而不是当前的栈指针assume esi:nothing,edi:nothingpopadmov eax,ExceptionContinueExecution ;这个会先返回到内核里面去ret_Handler endp start:assume fs:nothingpush ebp ;添加的自定义数据push offset _SafePlace ;添加的自定义数据......push offset _Handlerpush fs:[0]mov fs:[0],espxor eax,eaxmov dword ptr [eax],0_SafePlace:invoke MessageBox,NULL,L("----"),L("----"),MB_OKpop fs:[0]add esp,0ch ;恢复栈平衡invoke ExitProcess,NULL end start </span>


 

总结

以上是生活随笔为你收集整理的SEH处理异常的全部内容,希望文章能够帮你解决所遇到的问题。

如果觉得生活随笔网站内容还不错,欢迎将生活随笔推荐给好友。