zoukankan      html  css  js  c++  java
  • 从TEB到PEB再到SEH(二)

    什么是SEH?

    SEH( Structured Exception Handling , 结构化异常处理 )

    结构化异常处理(SEH)是Windows操作系统提供的强大异常处理功能。而Visual C++中的__try{}/__finally{}和__try{}/__except{}结构本质上是对Windows提供的SEH的封装

    我们知道SEH是基于线程的异常处理,我们利用 __try{}/__except{}来模拟一下SEH的异常处理:

    在这里可以看到我们把EAX的值置为空指针,然后向空指针里写入值,引发 STATUS_ACCESS_VIOLATION(内存访问异常) ,然后在异常处理里面把
    EAX的值设置为 变量dwTest的地址,然后返回 EXCEPTION_CONTINUE_EXECUTION 表示异常被处理,从异常处继续执行,这里是MSDN
    对于异常处理( Exception Handling )返回值的定义:
    1
    2
    3
    #define EXCEPTION_EXECUTE_HANDLER       1        //表示异常被处理,从下一条指令开始执行
    #define EXCEPTION_CONTINUE_SEARCH       0        //表示异常未被处理,交由下一个SEH
    #define EXCEPTION_CONTINUE_EXECUTION    -1    //表示异常被处理,从异常处开始执行
    对于上面这段定义,很多人给出的注释不同,以上注释是我对他们的实验结果和理解。
     

    Windows下各种异常处理的优先级 

    平时我们听说过很多异常处理术语:VEH SEH VCH UEF等等,下面我们用实验整理它们先后的处理顺序;
    • VEH(向量化异常处理,最顶端的异常处理)
    1
    2
    3
    4
    PVOID WINAPI AddVectoredExceptionHandler(
      _In_  ULONG FirstHandler,
      _In_  PVECTORED_EXCEPTION_HANDLER VectoredHandler
    );

    向进程里注册一个异常捕获函数,参数FirstHandler 决定插入到链表的位置(非0为头部,0为底部),异常处理中最先执行

    • VCH(同上,最低端 的异常处理 )
    1
    2
    3
    4
    PVOID WINAPI AddVectoredContinueHandler(
      _In_  ULONG FirstHandler,
      _In_  PVECTORED_EXCEPTION_HANDLER VectoredHandler
    );

    向进程里注册一个异常捕获函数,参数FirstHandler 决定插入到链表的位置(非0为头部, 0为底部 ) ,异常处理中最后执行

    • SEH(结构化异常处理,基于线程栈的异常处理)

    SEH是基于线程的异常处理,因为SEH链指针是在TEB(线程信息块)的第一个结构体成员(NT_TIB)的头部:fs:[0]

    • UEF(TopLevelEH,顶级异常处理)
    1
    2
    3
    LPTOP_LEVEL_EXCEPTION_FILTER WINAPI SetUnhandledExceptionFilter(
      _In_ LPTOP_LEVEL_EXCEPTION_FILTER lpTopLevelExceptionFilter
    );
    TopLevelEH 为线程顶级异常处理器,通常可以处理到所有线程消息发生的异常。
     
    这里我们可以发现以上异常处理回调函数参数大都为 EXCEPTION_POINTERS 结构体,我们查询下它的结构:
    1
    2
    3
    4
    typedef struct _EXCEPTION_POINTERS {
        PEXCEPTION_RECORD ExceptionRecord;
        PCONTEXT ContextRecord;
    } EXCEPTION_POINTERS, *PEXCEPTION_POINTERS;
    EXCEPTION_RECORD:
    1
    2
    3
    4
    5
    6
    7
    8
    typedef struct _EXCEPTION_RECORD {
        DWORD    ExceptionCode;          //异常码,以STATUS_或EXCEPTION_开头,可自定义。(sehdef.inc)
        DWORD ExceptionFlags;            //异常标志。0可修复;1不可修复;2正在展开,不要试图修复
        struct _EXCEPTION_RECORD *ExceptionRecord; //指向嵌套的异常结构,通常是异常中又引发异常
        PVOID ExceptionAddress;          //异常发生的地址
        DWORD NumberParameters;      //下面ExceptionInformation所含有的dword数目
        ULONG_PTR ExceptionInformation[EXCEPTION_MAXIMUM_PARAMETERS]; //附加消息,如读或写冲突
    } EXCEPTION_RECORD;
    CONTEXT:
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    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;
    CONTEXT结构体大家应该都懂!
    下面我们简单的写一个Demo,试验一下他们的处理顺序:
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    // SEHTest.cpp : 定义控制台应用程序的入口点。
    //
     
    #include "stdafx.h"
    //
    #include <windows.h>
    #include <stdio.h>
    #include <stdlib.h>
     
    //
    LONG __stdcall VEHandler(
        EXCEPTION_POINTERS *ExceptionInfo
        )
    {
        printf("VEHandler ");
        return EXCEPTION_CONTINUE_SEARCH;
    }
     
    LONG __stdcall VCHandler(
        EXCEPTION_POINTERS *ExceptionInfo
        )
    {
        printf("VCHandler ");
        ExceptionInfo->ContextRecord->Eip++;
        return EXCEPTION_CONTINUE_EXECUTION;
    }
     
    //
    LONG NTAPI TopLevelExcepFilter(EXCEPTION_POINTERS *pExcepInfo)
    {
        printf("TopLevelEHandler ");
        return EXCEPTION_CONTINUE_EXECUTION;
    }
    //
    LONG NTAPI SEHander(EXCEPTION_POINTERS *ExceptionInfo){
        //异常处理
        printf("SEHandler ");
     
        return EXCEPTION_CONTINUE_SEARCH;
    }
    int _tmain(int argc, _TCHAR* argv[])
    {
        AddVectoredExceptionHandler(0,VEHandler);
        AddVectoredContinueHandler(0,VCHandler);
        SetUnhandledExceptionFilter(&TopLevelExcepFilter);
        __try
        {
            __asm int 3
        }
        __except (SEHander(GetExceptionInformation()))
        {
        }
        system("Pause");
        return 0;
    }
    我们分别注册了VEH、VCH、 TopLevalEH 、SEH,我们看下结果:
    他们处理异常的优先级为:
    1. 调试器
    2. VEH
    3. SEH
    4. UEF
    5. VCH
    为什么调试器在第一个呢?因为我们发现在VS里面调试直接接管了异常。(/手动滑稽)
     

    认识SEH链及处理机机制

    我们上一章发现SEH链表位于结构体 NT_TIB 的第一个结构体成员,而结构体 NT_TIB 也位于TEB的第一个结构体成员,一句话而言SEH链表
    指针位于寄存器 FS : [ 0 ] 的位置:
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    ntdll!_TEB
       +0x000 NtTib            : _NT_TIB                //SEH链表头指针
       +0x01c EnvironmentPointer : Ptr32 Void
       +0x020 ClientId         : _CLIENT_ID
       +0x028 ActiveRpcHandle  : Ptr32 Void
       +0x02c ThreadLocalStoragePointer : Ptr32 Void
       +0x030 ProcessEnvironmentBlock : Ptr32 _PEB
       +0x034 LastErrorValue   : Uint4B
       +0x038 CountOfOwnedCriticalSections : Uint4B
       +0x03c CsrClientThread  : Ptr32 Void
       +0x040 Win32ThreadInfo  : Ptr32 Void
       +0x044 User32Reserved   : [26] Uint4B
       +0x0ac UserReserved     : [5] Uint4B
       +0x0c0 WOW32Reserved    : Ptr32 Void
       +0x0c4 CurrentLocale    : Uint4B
       +0x0c8 FpSoftwareStatusRegister : Uint4B
       +0x0cc SystemReserved1  : [54] Ptr32 Void
       +0x1a4 ExceptionCode    : Int4B
       +0x1a8 ActivationContextStack : _ACTIVATION_CONTEXT_STACK
       +0x1bc SpareBytes1      : [24] UChar
       +0x1d4 GdiTebBatch      : _GDI_TEB_BATCH
       +0x6b4 RealClientId     : _CLIENT_ID
       +0x6bc GdiCachedProcessHandle : Ptr32 Void
       +0x6c0 GdiClientPID     : Uint4B
       +0x6c4 GdiClientTID     : Uint4B
       +0x6c8 GdiThreadLocalInfo : Ptr32 Void
       +0x6cc Win32ClientInfo  : [62] Uint4B
       +0x7c4 glDispatchTable  : [233] Ptr32 Void
       +0xb68 glReserved1      : [29] Uint4B
       +0xbdc glReserved2      : Ptr32 Void
       +0xbe0 glSectionInfo    : Ptr32 Void
       +0xbe4 glSection        : Ptr32 Void
       +0xbe8 glTable          : Ptr32 Void
       +0xbec glCurrentRC      : Ptr32 Void
       +0xbf0 glContext        : Ptr32 Void
       +0xbf4 LastStatusValue  : Uint4B
       +0xbf8 StaticUnicodeString : _UNICODE_STRING
       +0xc00 StaticUnicodeBuffer : [261] Uint2B
       +0xe0c DeallocationStack : Ptr32 Void
       +0xe10 TlsSlots         : [64] Ptr32 Void
       +0xf10 TlsLinks         : _LIST_ENTRY
       +0xf18 Vdm              : Ptr32 Void
       +0xf1c ReservedForNtRpc : Ptr32 Void
       +0xf20 DbgSsReserved    : [2] Ptr32 Void
       +0xf28 HardErrorsAreDisabled : Uint4B
       +0xf2c Instrumentation  : [16] Ptr32 Void
       +0xf6c WinSockData      : Ptr32 Void
       +0xf70 GdiBatchCount    : Uint4B
       +0xf74 InDbgPrint       : UChar
       +0xf75 FreeStackOnTermination : UChar
       +0xf76 HasFiberData     : UChar
       +0xf77 IdealProcessor   : UChar
       +0xf78 Spare3           : Uint4B
       +0xf7c ReservedForPerf  : Ptr32 Void
       +0xf80 ReservedForOle   : Ptr32 Void
       +0xf84 WaitingOnLoaderLock : Uint4B
       +0xf88 Wx86Thread       : _Wx86ThreadState
       +0xf94 TlsExpansionSlots : Ptr32 Ptr32 Void
       +0xf98 ImpersonationLocale : Uint4B
       +0xf9c IsImpersonating  : Uint4B
       +0xfa0 NlsCache         : Ptr32 Void
       +0xfa4 pShimData        : Ptr32 Void
       +0xfa8 HeapVirtualAffinity : Uint4B
       +0xfac CurrentTransactionHandle : Ptr32 Void
       +0xfb0 ActiveFrame      : Ptr32 _TEB_ACTIVE_FRAME
       +0xfb4 SafeThunkCall    : UChar
       +0xfb5 BooleanSpare     : [3] UChar
    我们直接访问 FS:[0] 即为TIB的结构体地址:
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    typedef struct _NT_TIB {
        struct _EXCEPTION_REGISTRATION_RECORD *ExceptionList;
        PVOID StackBase;
        PVOID StackLimit;
        PVOID SubSystemTib;
    #if defined(_MSC_EXTENSIONS)
        union {
            PVOID FiberData;
            DWORD Version;
        };
    #else
        PVOID FiberData;
    #endif
        PVOID ArbitraryUserPointer;
        struct _NT_TIB *Self;
    } NT_TIB;
    typedef NT_TIB *PNT_TIB;
    如上述代码所示 结构体成员 ExceptionList 即为SEH链的头部指针 
    So、 fs:[0]即为SEH链的指针,我们接着看对于SEH链的定义:
    1
    2
    3
    4
    typedef struct _EXCEPTION_REGISTRATION_RECORD {
        struct _EXCEPTION_REGISTRATION_RECORD *Next;
        PEXCEPTION_ROUTINE Handler;
    } EXCEPTION_REGISTRATION_RECORD;
    第一个成员 Next 为指向下一个链表的指针,直到遇到 0xFFFFFFFF 结束,而结构体成员 Handler 为SEH的异常处理函数指针,我们接着看它对于
    SEH异常处理函数 EXCEPTION_ROUTINE 的定义:
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    typedef
    _IRQL_requires_same_
    _Function_class_(EXCEPTION_ROUTINE)
    EXCEPTION_DISPOSITION
    NTAPI
    EXCEPTION_ROUTINE (
        _Inout_ struct _EXCEPTION_RECORD *ExceptionRecord,
        _In_ PVOID EstablisherFrame,
        _Inout_ struct _CONTEXT *ContextRecord,
        _In_ PVOID DispatcherContext
        );
    可以看到它对于SEH定义了以 EXCEPTION_DISPOSITION 为返回值的回调函数,我们接着查看它们的定义:
    1
    2
    3
    4
    5
    6
    typedef enum _EXCEPTION_DISPOSITION {
        ExceptionContinueExecution,        //继续执行异常代码
        ExceptionContinueSearch,            //运行下一个异常处理器
        ExceptionNestedException,           //在OS内部使用
        ExceptionCollidedUnwind             //在OS内部使用
    } EXCEPTION_DISPOSITION;
    接着我们整理下它的异常处理过程:

    从上图可以明白 SEH接收到异常然后处理,处理失败返回 ExceptionContinueSearch(1) 继续运行下一个Handler处理,直到返回
    ExceptionContinueSearch(0),若是一直处理不了直到遇到0xFFFFFFFF 把异常交给UEF处理。

     

    SEH的注册及SEH的删除

    通过上述的整理就可以知道,SEH的异常处理的定义为:
    1
    2
    3
    4
    5
    EXCEPTION_DISPOSITION NTAPI _except_handler(
        _Inout_ struct _EXCEPTION_RECORD *ExceptionRecord,    //指向包含异常信息的EXCEPTION_RECORD结构
        _In_ PVOID EstablisherFrame,        //指向该异常相关的EXCEPTION_REGISTRATION结构
        _Inout_ struct _CONTEXT *ContextRecord,    //指向线程环境CONTEXT结构的指针
        _In_ PVOID DispatcherContext)

    现在要来谈SEH的注册了,我们的操作为:

    1
    2
    3
    push @_except_handler    ;异常处理器
    push dwod ptr fs:[0]     ;取出 SEH链表头
    mov dwod ptr fs:[0],esp  ;添加链表
     
    卸载SEH:
    1
    2
    pop dword ptr fs:[0]    ;还原链表头
    add esp,4    ;删除 异常处理器
    这些操作很简单,很多前辈们帖子里都有,代码可能不一样,反正是一个意思就行。
     

     异常的种类和常见的异常代码 

    这里是MSDN中定义的异常代码:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    /*lint -save -e767 */  
    #define STATUS_WAIT_0                           ((DWORD   )0x00000000L) 
    #define STATUS_ABANDONED_WAIT_0          ((DWORD   )0x00000080L)    
    #define STATUS_USER_APC                  ((DWORD   )0x000000C0L)    
    #define STATUS_TIMEOUT                   ((DWORD   )0x00000102L)    
    #define STATUS_PENDING                   ((DWORD   )0x00000103L)    
    #define DBG_EXCEPTION_HANDLED            ((DWORD   )0x00010001L)    
    #define DBG_CONTINUE                     ((DWORD   )0x00010002L)    
    #define STATUS_SEGMENT_NOTIFICATION      ((DWORD   )0x40000005L)    
    #define STATUS_FATAL_APP_EXIT            ((DWORD   )0x40000015L)    
    #define DBG_TERMINATE_THREAD             ((DWORD   )0x40010003L)    
    #define DBG_TERMINATE_PROCESS            ((DWORD   )0x40010004L)    
    #define DBG_CONTROL_C                    ((DWORD   )0x40010005L)    
    #define DBG_PRINTEXCEPTION_C             ((DWORD   )0x40010006L)    
    #define DBG_RIPEXCEPTION                 ((DWORD   )0x40010007L)    
    #define DBG_CONTROL_BREAK                ((DWORD   )0x40010008L)    
    #define DBG_COMMAND_EXCEPTION            ((DWORD   )0x40010009L)    
    #define STATUS_GUARD_PAGE_VIOLATION      ((DWORD   )0x80000001L)    
    #define STATUS_DATATYPE_MISALIGNMENT     ((DWORD   )0x80000002L)    
    #define STATUS_BREAKPOINT                ((DWORD   )0x80000003L)    
    #define STATUS_SINGLE_STEP               ((DWORD   )0x80000004L)    
    #define STATUS_LONGJUMP                  ((DWORD   )0x80000026L)    
    #define STATUS_UNWIND_CONSOLIDATE        ((DWORD   )0x80000029L)    
    #define DBG_EXCEPTION_NOT_HANDLED        ((DWORD   )0x80010001L)    
    #define STATUS_ACCESS_VIOLATION          ((DWORD   )0xC0000005L)    
    #define STATUS_IN_PAGE_ERROR             ((DWORD   )0xC0000006L)    
    #define STATUS_INVALID_HANDLE            ((DWORD   )0xC0000008L)    
    #define STATUS_INVALID_PARAMETER         ((DWORD   )0xC000000DL)    
    #define STATUS_NO_MEMORY                 ((DWORD   )0xC0000017L)    
    #define STATUS_ILLEGAL_INSTRUCTION       ((DWORD   )0xC000001DL)    
    #define STATUS_NONCONTINUABLE_EXCEPTION  ((DWORD   )0xC0000025L)    
    #define STATUS_INVALID_DISPOSITION       ((DWORD   )0xC0000026L)    
    #define STATUS_ARRAY_BOUNDS_EXCEEDED     ((DWORD   )0xC000008CL)    
    #define STATUS_FLOAT_DENORMAL_OPERAND    ((DWORD   )0xC000008DL)    
    #define STATUS_FLOAT_DIVIDE_BY_ZERO      ((DWORD   )0xC000008EL)    
    #define STATUS_FLOAT_INEXACT_RESULT      ((DWORD   )0xC000008FL)    
    #define STATUS_FLOAT_INVALID_OPERATION   ((DWORD   )0xC0000090L)    
    #define STATUS_FLOAT_OVERFLOW            ((DWORD   )0xC0000091L)    
    #define STATUS_FLOAT_STACK_CHECK         ((DWORD   )0xC0000092L)    
    #define STATUS_FLOAT_UNDERFLOW           ((DWORD   )0xC0000093L)    
    #define STATUS_INTEGER_DIVIDE_BY_ZERO    ((DWORD   )0xC0000094L)    
    #define STATUS_INTEGER_OVERFLOW          ((DWORD   )0xC0000095L)    
    #define STATUS_PRIVILEGED_INSTRUCTION    ((DWORD   )0xC0000096L)    
    #define STATUS_STACK_OVERFLOW            ((DWORD   )0xC00000FDL)    
    #define STATUS_DLL_NOT_FOUND             ((DWORD   )0xC0000135L)    
    #define STATUS_ORDINAL_NOT_FOUND         ((DWORD   )0xC0000138L)    
    #define STATUS_ENTRYPOINT_NOT_FOUND      ((DWORD   )0xC0000139L)    
    #define STATUS_CONTROL_C_EXIT            ((DWORD   )0xC000013AL)    
    #define STATUS_DLL_INIT_FAILED           ((DWORD   )0xC0000142L)    
    #define STATUS_FLOAT_MULTIPLE_FAULTS     ((DWORD   )0xC00002B4L)    
    #define STATUS_FLOAT_MULTIPLE_TRAPS      ((DWORD   )0xC00002B5L)    
    #define STATUS_REG_NAT_CONSUMPTION       ((DWORD   )0xC00002C9L)    
    #define STATUS_HEAP_CORRUPTION           ((DWORD   )0xC0000374L)    
    #define STATUS_STACK_BUFFER_OVERRUN      ((DWORD   )0xC0000409L)    
    #define STATUS_INVALID_CRUNTIME_PARAMETER ((DWORD   )0xC0000417L)    
    #define STATUS_ASSERTION_FAILURE         ((DWORD   )0xC0000420L)    
    #if defined(STATUS_SUCCESS) || (_WIN32_WINNT > 0x0500) || (_WIN32_FUSION >= 0x0100) 
    #define STATUS_SXS_EARLY_DEACTIVATION    ((DWORD   )0xC015000FL)    
    #define STATUS_SXS_INVALID_DEACTIVATION  ((DWORD   )0xC0150010L)    
    #endif 
    /*lint -restore */ 
    下面我们举例几个常用到的异常代码:

    STATUS_ACCESS_VIOLATION(0xC0000005)

    非法访问异常,试图访问不存在、没有访问权限,或是试图向没有写入权限的地址或是向内核区域写入发生的异常。

    STATUS_BREAKPOINT(0x80000003)

    断点异常,这个不用提了吧,就是我们常说的INT 3(0xCC)断点

    STATUS_ILLEGAL_INSTRUCTION(0xC000001D)

    CPU遇到无法解析的指令时发生该异常

    STATUS_INTEGER_DIVIDE_BY_ZERO(0xC0000094)

    除法中,分母为0时发生的异常

    STATUS_SINGLE_STEP

    单步调试异常,在EFlag寄存器把TF标志位置1发生的单步调试异常。

    除此之外,也有很多平时可以遇到的,我只是举例了几个简单的。

     

    SEH的异常处理

    我这里就随便写个Demo了:
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    // SEHList.cpp : 定义控制台应用程序的入口点。
    //
     
    #include "stdafx.h"
    //
    #include <windows.h>
    #include <stdio.h>
    #include <stdlib.h>
    DWORD dwTest;
    EXCEPTION_DISPOSITION NTAPI ExceptHandler(
        _Inout_ struct _EXCEPTION_RECORD *ExceptionRecord,
        _In_ PVOID EstablisherFrame,
        _Inout_ struct _CONTEXT *ContextRecord,
        _In_ PVOID DispatcherContext){
        printf("进入异常处理 ");
        printf("异常地址:%X<异常代码:%X> ", ExceptionRecord->ExceptionAddress,
            ExceptionRecord->ExceptionCode);
        ContextRecord->Eax = (DWORD)(&dwTest);
        return ExceptionContinueExecution;
    }
     
    int _tmain(int argc, _TCHAR* argv[])
    {
        printf("注册SEH ");
        __asm{
            lea eax, ExceptHandler
                push eax
                push fs : [0]
                mov dword ptr fs : [0], ESP
        }
        __asm{
            xor eax,eax
                mov dword ptr[eax],1234h
        }
        printf("删除SEH ");
        __asm{
            pop dword ptr fs : [0]
                add esp, 4
        }
        printf("dwTest=%X ", dwTest);
        getchar();
        return 0;
    }
    运行结果:

     转自https://bbs.pediy.com/thread-223939.htm

  • 相关阅读:
    类的设计问题
    php数组存在重复的相反元素,去重复
    常用JS验证函数总结
    python常用模块
    re 模块
    logging 模块
    configparser模块
    python 文件处理
    第15章-输入/输出 --- 理解Java的IO流
    第10章-验证框架 --- 验证器类型
  • 原文地址:https://www.cnblogs.com/yilang/p/11850734.html
Copyright © 2011-2022 走看看