反调试——VEH

VEH:向量化异常(vectored exception handle)

VEH和SEH的区别

SEH是基于线程的,而VEH是基于进程的。

因为很清楚的可以看到SEH的数据结构是保存在栈空间的,直接在函数体内用push来处理,而VEH是以双链表的形式保存在堆里面。

异常触发后的顺序:

优先顺序:调试器 > VEH > SEH

添加VEH异常

VEH有提供的API可以直接拿来添加VEH

AddVectoredExceptionHandler(ULONG First,//1表示添加到链表头部 0表示添加到链表尾部
PVECTORED_EXCEPTION_HANDLER Handler//异常处理器的地址
  );

定义异常处理程序


LONG PvectoredExceptionHandler(
_EXCEPTION_POINTERS *ExceptionInfo
)
{...}

使用该函数定义,可以得到基于VEH的异常处理程序的函数原型

异常处理程序的参数

typedef struct _EXCEPTION_POINTERS {
  PEXCEPTION_RECORD ExceptionRecord;//记录着异常的信息
  PCONTEXT ContextRecord; //PCONSTEXT表示寄存器的内容
} EXCEPTION_POINTERS, *PEXCEPTION_POINTERS;

返回值

To return control to the point at which the exception occurred, return EXCEPTION_CONTINUE_EXECUTION (0xffffffff). To continue the handler search, return EXCEPTION_CONTINUE_SEARCH (0x0).

有两种情况,一种是返回EXCEPTION_CONTINUE_EXECUTION ,另一种是返回EXCEPTION_CONTINUE_SEARCH。

EXCEPTION_CONTINUE_EXECUTION :表示继续执行

EXCEPTION_CONTINUE_SEARCH:表示查找下一个VEH来处理

代码编写VEH和SEH

#include<Windows.h>
#include<iostream>
EXCEPTION_DISPOSITION myExceptHandler(
struct _EXCEPTION_RECORD* ExceptionRecord,
PVOID EstablisherFrame,
PCONTEXT pcontext,
PVOID DispatcherContext
)
{
MessageBoxA(0, "SEH处理了异常", "异常报错", MB_OK);
pcontext->Eip = pcontext->Eip+ 4;
return ExceptionContinueExecution;
}

LONG WINAPI PvectoredExceptionHandler(
_EXCEPTION_POINTERS* ExceptionInfo
)
{
MessageBoxA(0, "VEH处理了异常", "异常处理", MB_OK);
ExceptionInfo->ContextRecord->Eip += 4;
return EXCEPTION_CONTINUE_EXECUTION;
}
int main()
{
AddVectoredExceptionHandler(1, PvectoredExceptionHandler);
DWORD execptionFuncAddr = (DWORD)myExceptHandler;//异常处理的函数地址
__asm
{
push execptionFuncAddr;
mov eax, fs: [0] ;
push eax;
mov fs : [0] , esp;
//添加异常,并且把异常放到异常链里面,并且把异常的头指针指向新的头结点
}
char* str = NULL;
str[0] = 'a';
printf("Sna1lGo\n");
system("pause");
return 0;
}#include<Windows.h>
#include<iostream>
EXCEPTION_DISPOSITION myExceptHandler(
struct _EXCEPTION_RECORD* ExceptionRecord,
PVOID EstablisherFrame,
PCONTEXT pcontext,
PVOID DispatcherContext
)
{
MessageBoxA(0, "SEH处理了异常", "异常报错", MB_OK);
pcontext->Eip = pcontext->Eip+ 4;
return ExceptionContinueExecution;
}

LONG WINAPI PvectoredExceptionHandler(
_EXCEPTION_POINTERS* ExceptionInfo
)
{
MessageBoxA(0, "VEH处理了异常", "异常处理", MB_OK);
ExceptionInfo->ContextRecord->Eip += 4;
return EXCEPTION_CONTINUE_EXECUTION;
}
int main()
{
AddVectoredExceptionHandler(1, PvectoredExceptionHandler);
DWORD execptionFuncAddr = (DWORD)myExceptHandler;//异常处理的函数地址
__asm
{
push execptionFuncAddr;
mov eax, fs: [0] ;
push eax;
mov fs : [0] , esp;
//添加异常,并且把异常放到异常链里面,并且把异常的头指针指向新的头结点
}
char* str = NULL;
str[0] = 'a';
printf("Sna1lGo\n");
system("pause");
return 0;
}

总结:

VEH是进程的异常处理,SEH是线程的异常处理,SEH可以直接用__try 和except语句使用,也可以直接创建SEH的处理函数和调用SHE来实现内部逻辑结构,VEH有提供的API,只需要创建一个VEH然后再创建一个VEH的异常处理函数就好了