zoukankan      html  css  js  c++  java
  • SEH异常处理

    SEH是应用最为广泛,却没有被微软公开技术之一,所有不同windows版本,SEH可能有所不同。

    SEH链表位置:fs:[0]->线程信息块TIB,TIB.ExceptionList->SEH链表

    一)有关SEH链表结构:

    1)线程信息块TIB结构

    kd> dt _NT_TIB
    nt!_NT_TIB
       +0x000 ExceptionList    : Ptr32 _EXCEPTION_REGISTRATION_RECORD            ;SEH链表头
       +0x004 StackBase        : Ptr32 Void
       +0x008 StackLimit       : Ptr32 Void
       +0x00c SubSystemTib     : Ptr32 Void
       +0x010 FiberData        : Ptr32 Void
       +0x010 Version          : Uint4B
       +0x014 ArbitraryUserPointer : Ptr32 Void
       +0x018 Self             : Ptr32 _NT_TIB

    2)链表节点

    _EXCEPTION_REGISTRATION struc

        prev           dd ?                   ;下一个_EXCEPTION_REGISTRATION结构

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

    _EXCEPTION_REGISTRATION ends

    3)异常处理函数约定

    _Exception_Handler proc C _lpExceptionRecord,_lpSEH,_lpContext,_lpDispatcherContext

      ret

    _Exception_Handler endp

    3.1)异常处理函数为系统回调,调用方式不是stdcall而是C方式调用。

    3.2)参数说明

    参数类型分别为:(一般只用前3个参数)

    struct _EXCEPTION_RECORD * pExceptionRecord,

    struct EXCEPTION_REGISTRATION * pRegistrationFrame,

    struct _CONTEXT *pContextRecord,

    void * pDispatcherContext

    第一个参数

    kd> dt _EXCEPTION_RECORD
    nt!_EXCEPTION_RECORD
       +0x000 ExceptionCode    : Int4B                                    ;异常代码
       +0x004 ExceptionFlags   : Uint4B                                    ;异常标志
       +0x008 ExceptionRecord  : Ptr32 _EXCEPTION_RECORD
       +0x00c ExceptionAddress : Ptr32 Void                             ;产生异常的地址
       +0x010 NumberParameters : Uint4B
       +0x014 ExceptionInformation : [15] Uint4B

     第二参数

    为新插入到SEH链表的新节点,利用此参数,既可恢复ebp、esp寄存器,也可通过堆栈传递数据。如:

    线程代码为:

    _Test  proc

    ;********************************************************************
    ; 在堆栈中构造一个 EXCEPTION_REGISTRATION 结构
    ;********************************************************************
      assume fs:nothing
      push ebp
      push offset _SafePlace
      push offset _Handler
      push fs:[0]
      mov fs:[0],esp
    ;********************************************************************
    ; 会引发异常的指令
    ;********************************************************************
      pushad
      xor ebp,ebp
      xor eax,eax
      mov dword ptr [eax],0
      popad  ;这一句将无法被执行
    _SafePlace:
      invoke MessageBox,NULL,addr szSafe,addr szCaption,MB_OK
    ;********************************************************************
    ; 恢复原来的 SEH 链
    ;********************************************************************
      pop fs:[0]
      add esp,0ch
      ret

    _Test  endp

    异常处理函数为:

    _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,addr szMsg,\
       [edi].regEip,[esi].ExceptionCode,[esi].ExceptionFlags
      invoke MessageBox,NULL,addr @szBuffer,NULL,MB_OK
    ;********************************************************************
    ; 将 EIP 指向安全的位置并恢复堆栈
    ;********************************************************************
      mov eax,_lpSEH
      push [eax + 8]
      pop [edi].regEip
      push [eax + 0ch]
      pop [edi].regEbp
      push eax
      pop [edi].regEsp
      assume esi:nothing,edi:nothing
      popad
      mov eax,ExceptionContinueExecution
      ret

    _Handler endp

     第三个参数,cpu寄存器状态值

    kd> dt _CONTEXT
    nt!_CONTEXT
       +0x000 ContextFlags     : Uint4B
       +0x004 Dr0              : Uint4B
       +0x008 Dr1              : Uint4B
       +0x00c Dr2              : Uint4B
       +0x010 Dr3              : Uint4B
       +0x014 Dr6              : Uint4B
       +0x018 Dr7              : Uint4B
       +0x01c FloatSave        : _FLOATING_SAVE_AREA
       +0x08c SegGs            : Uint4B
       +0x090 SegFs            : Uint4B
       +0x094 SegEs            : Uint4B
       +0x098 SegDs            : Uint4B
       +0x09c Edi              : Uint4B
       +0x0a0 Esi              : Uint4B
       +0x0a4 Ebx              : Uint4B
       +0x0a8 Edx              : Uint4B
       +0x0ac Ecx              : Uint4B
       +0x0b0 Eax              : Uint4B
       +0x0b4 Ebp              : Uint4B
       +0x0b8 Eip              : Uint4B
       +0x0bc SegCs            : Uint4B
       +0x0c0 EFlags           : Uint4B
       +0x0c4 Esp              : Uint4B
       +0x0c8 SegSs            : Uint4B
       +0x0cc ExtendedRegisters : [512] UChar

     3.3)返回值

    EXCEPTION_CONTINUE_SEARCH表示本异常处理函数不处理,系统将沿着链表查找下一个异常处理函数。

    ExceptionContinueExecution表示返回到_lpContext.Eip指定的安全位置继续运行程序。

    二)SEH链表图解

     

    三)SEH调试

    OD调试方法:在异常处理函数下断,当执行到异常指令的时候,根据状态栏提示按F9,就可以调试到达异常处理函数断点处。

  • 相关阅读:
    spring bean的生命周期
    02-MySQL主要配置文件
    01-MySQL Linux安装
    spring自动装配
    JVMGC+Spring Boot生产部署和调参优化
    java面试-生产环境出现CPU占用过高,谈谈你的分析思路和定位
    java面试-G1垃圾收集器
    java面试-垃圾回收器谈谈你的理解
    java面试-谈谈你对OOM的理解
    RPC介绍以及编程
  • 原文地址:https://www.cnblogs.com/guanlaiy/p/2469297.html
Copyright © 2011-2022 走看看