SEH(Structured Exception Handling,结构化异常处理)是window操作系统默认的异常处理机制,逆向分析中,SEH除了基本的异常处理功能外,还大量用于反调试程序。
1、SEH的相关数据结构
1、TIB结构
TIB(Thread Information Block,线程信息块)是保存线程基本信息的数据结构。在用户模式下,它位于TEB(Thread Environment Block,线程环境块)的头部,而TEB是操作系统为了保存每个线程的私有数据创建的,每个线程都有自己的TEB。TIB定义:
1 | typedef struct _NT_TIB{ |
2、_EXCEPTION_REGISTRATION_RECORD结构
TEB偏移量为0的_EXCEPTION_REGISTRATION_RECORD主要用于描述线程异常处理过程的地址,多个该结构体的链表描述了多个线程异常处理过程的嵌套层次关系,定义如下:
1 | struct EXCEPTION_REGISTRATION_RECORD |
3、EXCEPTION_DISPOSITION结构
由系统调用,是一个回调函数,第一个参数是一个指向EXCEPTION_RECORD结构体的指针
1 | EXCEPTION_DISPOSITION __cdecl _except_handler ( |
4、EXCEPTION_RECORD结构
异常处理函数的第三个参数是指向CONTEXT结构体的指针,CONTEXT结构体用来备份CPU的值。
1 | typedef struct _EXCEPTION_RECORD { |
异常发生的时候,执行异常代码的线程就会发生中断,转而运行SEH,此时操作系统会把线程CONTEXT结构体的指针传递给异常处理函数的相应参数。里面有个eip成员,在异常处理函数中将参数传递过来的CONTEXT.eip设置为其他地址,然后返回处理函数。这样之前暂停的线程会执行新的EIP地址处的代码。
2、VEH
向量化异常处理的基本概念和SEH相同,也是注册一个回调函数,当发生异常时会被系统的异常处理过程调用。
1 | WINBASEAPI PVOID WINAPI AddVectoreExceptionHandler ( |
VEH回调函数也形成一个链表。若参数FirstHandler的值为0,则回调函数位于VEH链表的尾部;若参数FirstHandler为非零值,则置于VEH链表的头部。
VEH回调函数所在的模块被卸载之后,系统不能自动将回调函数从VEH链表上移除,需要程序在退出前自己完成卸载工作。
1 | ULONG RemoveVectoreExceptionHandler ( |
VectoreHandlerHandle为AddVectoreExceptionHandler的返回值。
1 | #include "stdafx.h" |