VEH HOOK

相关函数

我们只需要用到 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)

VEH HOOK原理

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 <stdio.h>
#define  BREAKPOINTLEN 1
PVOID 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);
}

关于Eflags|=0x100

看下面的图,程序状态字(标志寄存器),TF在8,但是开头是从0开始的,所以应该在从右向左第9个bit。
标志寄存器

  • 1
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 2
    评论
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

没事干写博客玩

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值