从TEB到PEB再到SEH(二)
阅读原文时间:2023年07月09日阅读:4

什么是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&nbsp;<windows.h>

#include&nbsp;<stdio.h>

#include&nbsp;<stdlib.h>

/``/

LONG __stdcall&nbsp;VEHandler(

EXCEPTION_POINTERS *``ExceptionInfo

)

{

printf(``"VEHandler\n"``);

return EXCEPTION_CONTINUE_SEARCH;

}

LONG __stdcall&nbsp;VCHandler(

EXCEPTION_POINTERS *``ExceptionInfo

)

{

printf(``"VCHandler\n"``);

ExceptionInfo``-``>ContextRecord``-``>Eip``+``+``;

return EXCEPTION_CONTINUE_EXECUTION;

}

/``/

LONG NTAPI&nbsp;TopLevelExcepFilter(EXCEPTION_POINTERS *``pExcepInfo)

{

printf(``"TopLevelEHandler\n"``);

return EXCEPTION_CONTINUE_EXECUTION;

}

/``/

LONG NTAPI&nbsp;SEHander(EXCEPTION_POINTERS *``ExceptionInfo){

/``/``异常处理

printf(``"SEHandler\n"``);

return EXCEPTION_CONTINUE_SEARCH;

}

int _tmain(``int argc,&nbsp;_TCHAR``* argv[])

{

AddVectoredExceptionHandler(``0``,VEHandler);

AddVectoredContinueHandler(``0``,VCHandler);

SetUnhandledExceptionFilter(&TopLevelExcepFilter);

__try

{

__asm int 3

}

__except&nbsp;(SEHander(GetExceptionInformation()))

{

}

system(``"Pause"``);

return 0``;

}

我们分别注册了VEH、VCH、 TopLevalEH 、SEH,我们看下结果:

他们处理异常的优先级为:

为什么调试器在第一个呢?因为我们发现在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&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;:&nbsp;_NT_TIB /``/``SEH链表头指针

+``0x01c EnvironmentPointer&nbsp;:&nbsp;Ptr32&nbsp;Void

+``0x020 ClientId&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;:&nbsp;_CLIENT_ID

+``0x028 ActiveRpcHandle&nbsp;&nbsp;:&nbsp;Ptr32&nbsp;Void

+``0x02c ThreadLocalStoragePointer&nbsp;:&nbsp;Ptr32&nbsp;Void

+``0x030 ProcessEnvironmentBlock&nbsp;:&nbsp;Ptr32&nbsp;_PEB

+``0x034 LastErrorValue&nbsp;&nbsp;&nbsp;:&nbsp;Uint4B

+``0x038 CountOfOwnedCriticalSections&nbsp;:&nbsp;Uint4B

+``0x03c CsrClientThread&nbsp;&nbsp;:&nbsp;Ptr32&nbsp;Void

+``0x040 Win32ThreadInfo&nbsp;&nbsp;:&nbsp;Ptr32&nbsp;Void

+``0x044 User32Reserved&nbsp;&nbsp;&nbsp;:&nbsp;[``26``]&nbsp;Uint4B

+``0x0ac UserReserved&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;:&nbsp;[``5``]&nbsp;Uint4B

+``0x0c0 WOW32Reserved&nbsp;&nbsp;&nbsp;&nbsp;:&nbsp;Ptr32&nbsp;Void

+``0x0c4 CurrentLocale&nbsp;&nbsp;&nbsp;&nbsp;:&nbsp;Uint4B

+``0x0c8 FpSoftwareStatusRegister&nbsp;:&nbsp;Uint4B

+``0x0cc SystemReserved1&nbsp;&nbsp;:&nbsp;[``54``]&nbsp;Ptr32&nbsp;Void

+``0x1a4 ExceptionCode&nbsp;&nbsp;&nbsp;&nbsp;:&nbsp;Int4B

+``0x1a8 ActivationContextStack&nbsp;:&nbsp;_ACTIVATION_CONTEXT_STACK

+``0x1bc SpareBytes1&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;:&nbsp;[``24``]&nbsp;UChar

+``0x1d4 GdiTebBatch&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;:&nbsp;_GDI_TEB_BATCH

+``0x6b4 RealClientId&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;:&nbsp;_CLIENT_ID

+``0x6bc GdiCachedProcessHandle&nbsp;:&nbsp;Ptr32&nbsp;Void

+``0x6c0 GdiClientPID&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;:&nbsp;Uint4B

+``0x6c4 GdiClientTID&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;:&nbsp;Uint4B

+``0x6c8 GdiThreadLocalInfo&nbsp;:&nbsp;Ptr32&nbsp;Void

+``0x6cc Win32ClientInfo&nbsp;&nbsp;:&nbsp;[``62``]&nbsp;Uint4B

+``0x7c4 glDispatchTable&nbsp;&nbsp;:&nbsp;[``233``]&nbsp;Ptr32&nbsp;Void

+``0xb68 glReserved1&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;:&nbsp;[``29``]&nbsp;Uint4B

+``0xbdc glReserved2&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;:&nbsp;Ptr32&nbsp;Void

+``0xbe0 glSectionInfo&nbsp;&nbsp;&nbsp;&nbsp;:&nbsp;Ptr32&nbsp;Void

+``0xbe4 glSection&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;:&nbsp;Ptr32&nbsp;Void

+``0xbe8 glTable&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;:&nbsp;Ptr32&nbsp;Void

+``0xbec glCurrentRC&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;:&nbsp;Ptr32&nbsp;Void

+``0xbf0 glContext&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;:&nbsp;Ptr32&nbsp;Void

+``0xbf4 LastStatusValue&nbsp;&nbsp;:&nbsp;Uint4B

+``0xbf8 StaticUnicodeString&nbsp;:&nbsp;_UNICODE_STRING

+``0xc00 StaticUnicodeBuffer&nbsp;:&nbsp;[``261``]&nbsp;Uint2B

+``0xe0c DeallocationStack&nbsp;:&nbsp;Ptr32&nbsp;Void

+``0xe10 TlsSlots&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;:&nbsp;[``64``]&nbsp;Ptr32&nbsp;Void

+``0xf10 TlsLinks&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;:&nbsp;_LIST_ENTRY

+``0xf18 Vdm&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;:&nbsp;Ptr32&nbsp;Void

+``0xf1c ReservedForNtRpc&nbsp;:&nbsp;Ptr32&nbsp;Void

+``0xf20 DbgSsReserved&nbsp;&nbsp;&nbsp;&nbsp;:&nbsp;[``2``]&nbsp;Ptr32&nbsp;Void

+``0xf28 HardErrorsAreDisabled&nbsp;:&nbsp;Uint4B

+``0xf2c Instrumentation&nbsp;&nbsp;:&nbsp;[``16``]&nbsp;Ptr32&nbsp;Void

+``0xf6c WinSockData&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;:&nbsp;Ptr32&nbsp;Void

+``0xf70 GdiBatchCount&nbsp;&nbsp;&nbsp;&nbsp;:&nbsp;Uint4B

+``0xf74 InDbgPrint&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;:&nbsp;UChar

+``0xf75 FreeStackOnTermination&nbsp;:&nbsp;UChar

+``0xf76 HasFiberData&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;:&nbsp;UChar

+``0xf77 IdealProcessor&nbsp;&nbsp;&nbsp;:&nbsp;UChar

+``0xf78 Spare3&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;:&nbsp;Uint4B

+``0xf7c ReservedForPerf&nbsp;&nbsp;:&nbsp;Ptr32&nbsp;Void

+``0xf80 ReservedForOle&nbsp;&nbsp;&nbsp;:&nbsp;Ptr32&nbsp;Void

+``0xf84 WaitingOnLoaderLock&nbsp;:&nbsp;Uint4B

+``0xf88 Wx86Thread&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;:&nbsp;_Wx86ThreadState

+``0xf94 TlsExpansionSlots&nbsp;:&nbsp;Ptr32&nbsp;Ptr32&nbsp;Void

+``0xf98 ImpersonationLocale&nbsp;:&nbsp;Uint4B

+``0xf9c IsImpersonating&nbsp;&nbsp;:&nbsp;Uint4B

+``0xfa0 NlsCache&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;:&nbsp;Ptr32&nbsp;Void

+``0xfa4 pShimData&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;:&nbsp;Ptr32&nbsp;Void

+``0xfa8 HeapVirtualAffinity&nbsp;:&nbsp;Uint4B

+``0xfac CurrentTransactionHandle&nbsp;:&nbsp;Ptr32&nbsp;Void

+``0xfb0 ActiveFrame&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;:&nbsp;Ptr32&nbsp;_TEB_ACTIVE_FRAME

+``0xfb4 SafeThunkCall&nbsp;&nbsp;&nbsp;&nbsp;:&nbsp;UChar

+``0xfb5 BooleanSpare&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;:&nbsp;[``3``]&nbsp;UChar

我们直接访问 FS:[0] 即为TIB的结构体地址:

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

typedef&nbsp;struct&nbsp;_NT_TIB&nbsp;{

struct&nbsp;_EXCEPTION_REGISTRATION_RECORD *``ExceptionList;

PVOID&nbsp;StackBase;

PVOID&nbsp;StackLimit;

PVOID&nbsp;SubSystemTib;

#if&nbsp;defined(_MSC_EXTENSIONS)

union&nbsp;{

PVOID&nbsp;FiberData;

DWORD&nbsp;Version;

};

#else

PVOID&nbsp;FiberData;

#endif

PVOID&nbsp;ArbitraryUserPointer;

struct&nbsp;_NT_TIB *``Self;

}&nbsp;NT_TIB;

typedef&nbsp;NT_TIB *``PNT_TIB;

如上述代码所示 结构体成员 ExceptionList 即为SEH链的头部指针 

So、 fs:[0]即为SEH链的指针,我们接着看对于SEH链的定义:

1

2

3

4

typedef&nbsp;struct&nbsp;_EXCEPTION_REGISTRATION_RECORD&nbsp;{

struct&nbsp;_EXCEPTION_REGISTRATION_RECORD *``Next``;

PEXCEPTION_ROUTINE&nbsp;Handler;

}&nbsp;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&nbsp;(

_Inout_&nbsp;struct&nbsp;_EXCEPTION_RECORD *``ExceptionRecord,

_In_&nbsp;PVOID&nbsp;EstablisherFrame,

_Inout_&nbsp;struct&nbsp;_CONTEXT *``ContextRecord,

_In_&nbsp;PVOID&nbsp;DispatcherContext

);

可以看到它对于SEH定义了以 EXCEPTION_DISPOSITION 为返回值的回调函数,我们接着查看它们的定义:

1

2

3

4

5

6

typedef&nbsp;enum&nbsp;_EXCEPTION_DISPOSITION&nbsp;{

ExceptionContinueExecution, /``/``继续执行异常代码

ExceptionContinueSearch, /``/``运行下一个异常处理器

ExceptionNestedException, /``/``在OS内部使用

ExceptionCollidedUnwind /``/``在OS内部使用

}&nbsp;EXCEPTION_DISPOSITION;

接着我们整理下它的异常处理过程:

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

SEH的注册及SEH的删除

通过上述的整理就可以知道,SEH的异常处理的定义为:

1

2

3

4

5

EXCEPTION_DISPOSITION&nbsp;NTAPI&nbsp;_except_handler(

_Inout_&nbsp;struct&nbsp;_EXCEPTION_RECORD *``ExceptionRecord, /``/``指向包含异常信息的EXCEPTION_RECORD结构

_In_&nbsp;PVOID&nbsp;EstablisherFrame, /``/``指向该异常相关的EXCEPTION_REGISTRATION结构

_Inout_&nbsp;struct&nbsp;_CONTEXT *``ContextRecord, /``/``指向线程环境CONTEXT结构的指针

_In_&nbsp;PVOID&nbsp;DispatcherContext)

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

1

2

3

push&nbsp;@_except_handler&nbsp;&nbsp;&nbsp;&nbsp;;异常处理器

push&nbsp;dwod&nbsp;ptr&nbsp;fs:[``0``]&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;;取出&nbsp;SEH链表头

mov&nbsp;dwod&nbsp;ptr&nbsp;fs:[``0``],esp&nbsp;&nbsp;;添加链表

卸载SEH:

1

2

pop&nbsp;dword&nbsp;ptr&nbsp;fs:[``0``]&nbsp;&nbsp;&nbsp;&nbsp;;还原链表头

add&nbsp;esp,``4    ;删除&nbsp;异常处理器

这些操作很简单,很多前辈们帖子里都有,代码可能不一样,反正是一个意思就行。

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

这里是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&nbsp;STATUS_WAIT_0&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;((DWORD&nbsp;&nbsp;&nbsp;)0x00000000L)

#define&nbsp;STATUS_ABANDONED_WAIT_0&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;((DWORD&nbsp;&nbsp;&nbsp;)0x00000080L)

#define&nbsp;STATUS_USER_APC&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;((DWORD&nbsp;&nbsp;&nbsp;)0x000000C0L)

#define&nbsp;STATUS_TIMEOUT&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;((DWORD&nbsp;&nbsp;&nbsp;)0x00000102L)

#define&nbsp;STATUS_PENDING&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;((DWORD&nbsp;&nbsp;&nbsp;)0x00000103L)

#define&nbsp;DBG_EXCEPTION_HANDLED&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;((DWORD&nbsp;&nbsp;&nbsp;)0x00010001L)

#define&nbsp;DBG_CONTINUE&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;((DWORD&nbsp;&nbsp;&nbsp;)0x00010002L)

#define&nbsp;STATUS_SEGMENT_NOTIFICATION&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;((DWORD&nbsp;&nbsp;&nbsp;)0x40000005L)

#define&nbsp;STATUS_FATAL_APP_EXIT&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;((DWORD&nbsp;&nbsp;&nbsp;)0x40000015L)

#define&nbsp;DBG_TERMINATE_THREAD&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;((DWORD&nbsp;&nbsp;&nbsp;)0x40010003L)

#define&nbsp;DBG_TERMINATE_PROCESS&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;((DWORD&nbsp;&nbsp;&nbsp;)0x40010004L)

#define&nbsp;DBG_CONTROL_C&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;((DWORD&nbsp;&nbsp;&nbsp;)0x40010005L)

#define&nbsp;DBG_PRINTEXCEPTION_C&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;((DWORD&nbsp;&nbsp;&nbsp;)0x40010006L)

#define&nbsp;DBG_RIPEXCEPTION&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;((DWORD&nbsp;&nbsp;&nbsp;)0x40010007L)

#define&nbsp;DBG_CONTROL_BREAK&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;((DWORD&nbsp;&nbsp;&nbsp;)0x40010008L)

#define&nbsp;DBG_COMMAND_EXCEPTION&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;((DWORD&nbsp;&nbsp;&nbsp;)0x40010009L)

#define&nbsp;STATUS_GUARD_PAGE_VIOLATION&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;((DWORD&nbsp;&nbsp;&nbsp;)0x80000001L)

#define&nbsp;STATUS_DATATYPE_MISALIGNMENT&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;((DWORD&nbsp;&nbsp;&nbsp;)0x80000002L)

#define&nbsp;STATUS_BREAKPOINT&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;((DWORD&nbsp;&nbsp;&nbsp;)0x80000003L)

#define&nbsp;STATUS_SINGLE_STEP&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;((DWORD&nbsp;&nbsp;&nbsp;)0x80000004L)

#define&nbsp;STATUS_LONGJUMP&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;((DWORD&nbsp;&nbsp;&nbsp;)0x80000026L)

#define&nbsp;STATUS_UNWIND_CONSOLIDATE&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;((DWORD&nbsp;&nbsp;&nbsp;)0x80000029L)

#define&nbsp;DBG_EXCEPTION_NOT_HANDLED&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;((DWORD&nbsp;&nbsp;&nbsp;)0x80010001L)

#define&nbsp;STATUS_ACCESS_VIOLATION&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;((DWORD&nbsp;&nbsp;&nbsp;)0xC0000005L)

#define&nbsp;STATUS_IN_PAGE_ERROR&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;((DWORD&nbsp;&nbsp;&nbsp;)0xC0000006L)

#define&nbsp;STATUS_INVALID_HANDLE&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;((DWORD&nbsp;&nbsp;&nbsp;)0xC0000008L)

#define&nbsp;STATUS_INVALID_PARAMETER&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;((DWORD&nbsp;&nbsp;&nbsp;)0xC000000DL)

#define&nbsp;STATUS_NO_MEMORY&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;((DWORD&nbsp;&nbsp;&nbsp;)0xC0000017L)

#define&nbsp;STATUS_ILLEGAL_INSTRUCTION&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;((DWORD&nbsp;&nbsp;&nbsp;)0xC000001DL)

#define&nbsp;STATUS_NONCONTINUABLE_EXCEPTION&nbsp;&nbsp;((DWORD&nbsp;&nbsp;&nbsp;)0xC0000025L)

#define&nbsp;STATUS_INVALID_DISPOSITION&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;((DWORD&nbsp;&nbsp;&nbsp;)0xC0000026L)

#define&nbsp;STATUS_ARRAY_BOUNDS_EXCEEDED&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;((DWORD&nbsp;&nbsp;&nbsp;)0xC000008CL)

#define&nbsp;STATUS_FLOAT_DENORMAL_OPERAND&nbsp;&nbsp;&nbsp;&nbsp;((DWORD&nbsp;&nbsp;&nbsp;)0xC000008DL)

#define&nbsp;STATUS_FLOAT_DIVIDE_BY_ZERO&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;((DWORD&nbsp;&nbsp;&nbsp;)0xC000008EL)

#define&nbsp;STATUS_FLOAT_INEXACT_RESULT&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;((DWORD&nbsp;&nbsp;&nbsp;)0xC000008FL)

#define&nbsp;STATUS_FLOAT_INVALID_OPERATION&nbsp;&nbsp;&nbsp;((DWORD&nbsp;&nbsp;&nbsp;)0xC0000090L)

#define&nbsp;STATUS_FLOAT_OVERFLOW&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;((DWORD&nbsp;&nbsp;&nbsp;)0xC0000091L)

#define&nbsp;STATUS_FLOAT_STACK_CHECK&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;((DWORD&nbsp;&nbsp;&nbsp;)0xC0000092L)

#define&nbsp;STATUS_FLOAT_UNDERFLOW&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;((DWORD&nbsp;&nbsp;&nbsp;)0xC0000093L)

#define&nbsp;STATUS_INTEGER_DIVIDE_BY_ZERO&nbsp;&nbsp;&nbsp;&nbsp;((DWORD&nbsp;&nbsp;&nbsp;)0xC0000094L)

#define&nbsp;STATUS_INTEGER_OVERFLOW&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;((DWORD&nbsp;&nbsp;&nbsp;)0xC0000095L)

#define&nbsp;STATUS_PRIVILEGED_INSTRUCTION&nbsp;&nbsp;&nbsp;&nbsp;((DWORD&nbsp;&nbsp;&nbsp;)0xC0000096L)

#define&nbsp;STATUS_STACK_OVERFLOW&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;((DWORD&nbsp;&nbsp;&nbsp;)0xC00000FDL)

#define&nbsp;STATUS_DLL_NOT_FOUND&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;((DWORD&nbsp;&nbsp;&nbsp;)0xC0000135L)

#define&nbsp;STATUS_ORDINAL_NOT_FOUND&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;((DWORD&nbsp;&nbsp;&nbsp;)0xC0000138L)

#define&nbsp;STATUS_ENTRYPOINT_NOT_FOUND&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;((DWORD&nbsp;&nbsp;&nbsp;)0xC0000139L)

#define&nbsp;STATUS_CONTROL_C_EXIT&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;((DWORD&nbsp;&nbsp;&nbsp;)0xC000013AL)

#define&nbsp;STATUS_DLL_INIT_FAILED&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;((DWORD&nbsp;&nbsp;&nbsp;)0xC0000142L)

#define&nbsp;STATUS_FLOAT_MULTIPLE_FAULTS&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;((DWORD&nbsp;&nbsp;&nbsp;)0xC00002B4L)

#define&nbsp;STATUS_FLOAT_MULTIPLE_TRAPS&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;((DWORD&nbsp;&nbsp;&nbsp;)0xC00002B5L)

#define&nbsp;STATUS_REG_NAT_CONSUMPTION&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;((DWORD&nbsp;&nbsp;&nbsp;)0xC00002C9L)

#define&nbsp;STATUS_HEAP_CORRUPTION&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;((DWORD&nbsp;&nbsp;&nbsp;)0xC0000374L)

#define&nbsp;STATUS_STACK_BUFFER_OVERRUN&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;((DWORD&nbsp;&nbsp;&nbsp;)0xC0000409L)

#define&nbsp;STATUS_INVALID_CRUNTIME_PARAMETER&nbsp;((DWORD&nbsp;&nbsp;&nbsp;)0xC0000417L)

#define&nbsp;STATUS_ASSERTION_FAILURE&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;((DWORD&nbsp;&nbsp;&nbsp;)0xC0000420L)

#if&nbsp;defined(STATUS_SUCCESS)&nbsp;||&nbsp;(_WIN32_WINNT&nbsp;>&nbsp;0x0500)&nbsp;||&nbsp;(_WIN32_FUSION&nbsp;>=&nbsp;0x0100)

#define&nbsp;STATUS_SXS_EARLY_DEACTIVATION&nbsp;&nbsp;&nbsp;&nbsp;((DWORD&nbsp;&nbsp;&nbsp;)0xC015000FL)

#define&nbsp;STATUS_SXS_INVALID_DEACTIVATION&nbsp;&nbsp;((DWORD&nbsp;&nbsp;&nbsp;)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&nbsp;:&nbsp;定义控制台应用程序的入口点。

/``/

#include&nbsp;"stdafx.h"

/``/

#include&nbsp;<windows.h>

#include&nbsp;<stdio.h>

#include&nbsp;<stdlib.h>

DWORD&nbsp;dwTest;

EXCEPTION_DISPOSITION&nbsp;NTAPI&nbsp;ExceptHandler(

_Inout_&nbsp;struct&nbsp;_EXCEPTION_RECORD *``ExceptionRecord,

_In_&nbsp;PVOID&nbsp;EstablisherFrame,

_Inout_&nbsp;struct&nbsp;_CONTEXT *``ContextRecord,

_In_&nbsp;PVOID&nbsp;DispatcherContext){

printf(``"进入异常处理\n"``);

printf(``"异常地址:%X<异常代码:%X>\n"``,&nbsp;ExceptionRecord``-``>ExceptionAddress,

ExceptionRecord``-``>ExceptionCode);

ContextRecord``-``>Eax = (DWORD)(&dwTest);

return ExceptionContinueExecution;

}

int _tmain(``int argc,&nbsp;_TCHAR``* argv[])

{

printf(``"注册SEH\n"``);

__asm{

lea&nbsp;eax,&nbsp;ExceptHandler

push&nbsp;eax

push&nbsp;fs&nbsp;:&nbsp;[``0``]

mov&nbsp;dword&nbsp;ptr&nbsp;fs&nbsp;:&nbsp;[``0``],&nbsp;ESP

}

__asm{

xor&nbsp;eax,eax

mov&nbsp;dword&nbsp;ptr[eax],``1234h

}

printf(``"删除SEH\n"``);

__asm{

pop&nbsp;dword&nbsp;ptr&nbsp;fs&nbsp;:&nbsp;[``0``]

add&nbsp;esp, 4

}

printf(``"dwTest=%X\n"``,&nbsp;dwTest);

getchar();

return 0``;

}

运行结果:

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