本文共 2968 字,大约阅读时间需要 9 分钟。
我们只需要用到 AddVectoredExceptionHandler 设置VEH异常捕获
PVOID WINAPI AddVectoredExceptionHandler( _In_ ULONG FirstHandler, _In_ PVECTORED_EXCEPTION_HANDLER VectoredHandler);ULONG WINAPI RemoveVectoredExceptionHandler( _In_ PVOID Handler);PVOID WINAPI AddVectoredContinueHandler( _In_ ULONG FirstHandler, _In_ PVECTORED_EXCEPTION_HANDLER VectoredHandler);ULONG WINAPI RemoveVectoredContinueHandler( _In_ PVOID Handler);
设置异常捕获后,我们的callback就能处理异常
_EXCEPTION_POINTERS 可以获得ExceptionRecord ExceptionRecord中还有异常代码(ExceptionCode)和异常地址(ExceptionAddress)
1.将需要HOOK的函数入口内容改为0xcc中断,如果你不了解中断向量表和int软中断你可以理解为设置了个断点,这样运行时就会产生异常
2.由我们的异常处理函数捕获后,修改寄存器的值(原参数)和EIP 3.返回EXCEPTION_CONTINUE_EXECUTION,让程序重新跑起来,就能达到HOOK的效果了
下面是个DLL,你需要自己手动在DLL_PROCESS_ATTACH时运行VEH_HOOK_MessageBoxA();
编译后随便写个EXE载入DLL调用MessageBoxA试试吧
// Dll.cpp : 定义 DLL 应用程序的导出函数。//#include "stdafx.h"#include "Dll.h"#include#define BREAKPOINTLEN 1PVOID MessageBoxA_Addr;BYTE MessageBoxA_New_INT;BYTE MessageBoxA_Ole_INT;DWORD dwNewProtect = PAGE_EXECUTE_READWRITE;DWORD dwOldProtect;//修改参数char lpText[] = "Test Text! ";LONG NTAPI CALL_MessageBoxA(struct _EXCEPTION_POINTERS *ExceptionInfo){ if (ExceptionInfo->ExceptionRecord->ExceptionCode == EXCEPTION_BREAKPOINT)//判断异常类型是否是断点 { PVOID addr = ExceptionInfo->ExceptionRecord->ExceptionAddress;//获得异常地址 if (addr != nullptr/*(PVOID)0*/) { //+0x8正常情况下是汇编中的第一个参数,+0x4为返回EIP //但是这里+0x8是汇编中的第二个参数,因为函数开头push ebp的代码被我们改成了0xcc,没有对esp进行压栈 //又由于所有参数从右到左依次入栈,所以顺序其实是反过来的 //+0xc 在MessageBox代码中是第二个lpText //+0x8 在MessageBox代码中是第三个lpCaption *(int*)((ExceptionInfo->ContextRecord->Esp) + 0x8) = (int)lpText; *(int*)((ExceptionInfo->ContextRecord->Esp) + 0xc) = (int)lpText; //修改状态 ExceptionInfo->ContextRecord->ContextFlags = CONTEXT_CONTROL; //查询控制寄存器组 ExceptionInfo->ContextRecord->Eip = /*(DWORD)&MessageBoxA;*/(DWORD)addr; /*修改TF标志位*/ ExceptionInfo->ContextRecord->EFlags |= 0x100; //恢复代码 VirtualProtect((void*)addr, BREAKPOINTLEN, dwNewProtect, &dwOldProtect); *(BYTE*)(addr) = MessageBoxA_Ole_INT;//把首个字节地址改回去 VirtualProtect((void*)addr, BREAKPOINTLEN, dwOldProtect, &dwNewProtect); //OutputDebugStringA("My::单步运行,取消断点"); printf_s("单步运行,取消断点\n"); //AddVectoredExceptionHandler(NULL,(PVECTORED_EXCEPTION_HANDLER)ExceptionInfo); return EXCEPTION_CONTINUE_EXECUTION; } return EXCEPTION_EXECUTE_HANDLER; } return EXCEPTION_EXECUTE_HANDLER;}void VEH_HOOK_MessageBoxA(){ AddVectoredExceptionHandler(0, CALL_MessageBoxA);//设置VEH异常捕获 MessageBoxA_Addr = (PVOID)&MessageBoxA;//MessageBoxA地址 MessageBoxA_Ole_INT = *(BYTE*)MessageBoxA_Addr; //MessageBoxA 首个字节 VirtualProtect((void*)MessageBoxA_Addr, BREAKPOINTLEN, dwNewProtect, &dwOldProtect); *(BYTE*)(MessageBoxA_Addr) = 0xcc;//首个字节内容改成0xcc(int 3)断点中断 VirtualProtect((void*)MessageBoxA_Addr, BREAKPOINTLEN, dwOldProtect, &dwNewProtect);}
看下面的图,程序状态字(标志寄存器),TF在8,但是开头是从0开始的,所以应该在从右向左第9个bit。
转载地址:http://ttlsi.baihongyu.com/