VEH&VCH
本文99.9%的代码及内容作者:mengwuji
来自:http://www.mengwuji.net/forum.php?mod=viewthread&tid=1371
VEH:向量化异常处理,是对整个进程来说是全局的(SEH是针对线程的)异常捕获技术,只要通过简单的设置,只要当前进程发送了异常,都能被我们设置好的VEH捕获到。
#include<windows.h> LONG __stdcall FirstVEHandler( EXCEPTION_POINTERS *ExceptionInfo ) { printf("FirstVEHandler\n"); return EXCEPTION_CONTINUE_SEARCH; } LONG __stdcall LastVEHandler( EXCEPTION_POINTERS *ExceptionInfo ) { printf("LastVEHandler\n"); ExceptionInfo->ContextRecord->Eip++; return EXCEPTION_CONTINUE_EXECUTION; } void seHandler() { printf("seHandler\n"); } void main() { char* p=NULL; char c='a'; AddVectoredExceptionHandler(0,FirstVEHandler); AddVectoredContinueHandler(0,LastVEHandler); __try{ //__asm{ int 3 } *p=c; }__except(EXCEPTION_EXECUTE_HANDLER){ seHandler(); } getchar(); }
windows提供了两个API用来添加VEH和VCH的,分别是:
PVOID WINAPI AddVectoredExceptionHandler(
_In_ ULONG FirstHandler,
_In_ PVECTORED_EXCEPTION_HANDLER VectoredHandler
);
PVOID WINAPI AddVectoredContinueHandler(
_In_ ULONG FirstHandler,
_In_ PVECTORED_EXCEPTION_HANDLER VectoredHandler
);
FirstHandler-----这个参数,是当我们进程中添加了多个VEH或者VCH时才有效,比如调用了两次AddVectoredExceptionHandler,那么进程中存在两个向量化处理异常回调A和B,这时候此参数就决定了A先执行还是A后执行,如果FirstHandler等于零,那么A就代表最后执行,非零值就代表第一个执行。当然这种说法也不全对,要看B的FirstHandler参数具体是什么值。
VectoredHandler------是一个回调函数,这个回调函数是我们提供的,当有异常发生时,windows就会把异常信息交给我们的这个回调函数去执行。
AddVectoredExceptionHandler是添加VEH,AddVectoredContinueHandler是添加VCH,区别在于AddVectoredExceptionHandler是执行在所有SEH的前面,AddVectoredContinueHandler是执行在所有SEH后面。
LastVEHandler函数是没有被执行到,原因是__except(EXCEPTION_EXECUTE_HANDLER)这样的写法会让异常在seHandler处理了,处理完成后就没有异常了,所以LastVEHandler没有被执行。
为了xiang办法让LastVEHandler也执行,我们把代码改成这样的:__except(EXCEPTION_CONTINUE_EXECUTION);
如果你把 *p=c;改成int 3,结果是这样的:
这里又不会执行seHandler了,原因是EXCEPTION_CONTINUE_EXECUTION是忽略了此异常所以就进不了seHandler,但是记住我们必须在LastVEHandler里让eip加1,这里就等于LastVEHandler把异常给处理掉了。
从上面两幅图,虽然不能直观的看出几个函数的执行顺序,但是总结一下,他们的顺序也就是我说的FirstVEHandler-----seHandler-----LastVEHandler.
为了弄明白AddVectoredExceptionHandler和AddVectoredContinueHandler到底做了什么,我们可以看它们的反汇编代码。