测试InlineHook

0x01主要是针对内部函数的hook

这里有需要注意的地方

内部含糊的地址

HOOK的位置

保存现场: pushfd  pushad

原本硬编码的恢复


extern "C" _declspec(naked)void HookProc()
{
	//保存现场
	_asm
	{
		pushad
		pushfd
	}
	//获取寄存器
	_asm
	{
			mov reg.Eax,eax
			mov reg.Ecx,ecx
			mov reg.Ebx,ebx
			mov reg.Edx,edx
			mov reg.Esp,esp
			mov reg.Ebp,ebp
			mov reg.Esi,esi
			mov reg.Edi,edi

			mov EAX,DWORD PTR SS:[esp+0x28]
			mov dwParaX,EAX
			mov EAX,DWORD PTR SS:[esp+0x2C]
			mov dwParaY,EAX
	}

	//当前寄存器的内容
	
	OutputDebugStringF("Eax:%d,Ebx:%d,Ecx,%d,Edx:%d",reg.Eax,reg.Ebx,reg.Ecx,reg.Edx);
	OutputDebugStringF("esp:%d,ebp:%d,esi,%d,edi:%d",reg.Esp,reg.Ebp,reg.Esi,reg.Edi);
	
	
	//参数内容
	OutputDebugStringF("X:%d.Y:%d",dwParaX,dwParaY);

	//恢复现场
	_asm
	{
		popfd
		popad
	}
	//执行覆盖代码
	_asm
	{
		push ebp
		mov ebp,esp
		sub esp,40h
	}

	//跳回去
	_asm
	{
		jmp g_dwRetAddr
	}

}


裸函数的运用


0x02 跳转地址的注意事项


	//备份硬编码
	g_pCodePatch = new BYTE[bytes];
	memcpy(g_pCodePatch,(void*)dwHookAddr,bytes);
	
	//填充90
	dwJumpCode = dwProcAddr - dwHookAddr - 5;
	memset((void*)dwHookAddr,0x90,bytes);

	// jmp 0x0000
	*(PBYTE)dwHookAddr = 0xE9;
	*(PDWORD)((PBYTE)dwHookAddr + 1) = dwJumpCode;
	


0x03 上面贴的是核心代码

详细代码如下


// 20180203_01.cpp : Defines the entry point for the application.
//

#include "stdafx.h"
#include "DebugTool.h"


DWORD g_dwHookAddr; //Hook开始的地方
DWORD g_dwRetAddr; //Hook结束的地方
DWORD g_dwLength; //Hook字节数
PBYTE g_pCodePatch; //存储Hook原来的硬编码
DWORD g_dwHookFlag; //HOOK状态, 1 Hook成功, 0 HOOK 失败

typedef struct _REGISTER
{
	DWORD Eax;
	DWORD Ecx;
	DWORD Edx;
	DWORD Ebx;
	DWORD Esp;
	DWORD Ebp;
	DWORD Esi;
	DWORD Edi;
}Register;

DWORD dwParaX;
DWORD dwParaY;

Register reg= {0};
TCHAR szBuffer[100] = {0};


extern "C" _declspec(naked)void HookProc()
{
	//保存现场
	_asm
	{
		pushad
		pushfd
	}
	//获取寄存器
	_asm
	{
			mov reg.Eax,eax
			mov reg.Ecx,ecx
			mov reg.Ebx,ebx
			mov reg.Edx,edx
			mov reg.Esp,esp
			mov reg.Ebp,ebp
			mov reg.Esi,esi
			mov reg.Edi,edi

			mov EAX,DWORD PTR SS:[esp+0x28]
			mov dwParaX,EAX
			mov EAX,DWORD PTR SS:[esp+0x2C]
			mov dwParaY,EAX
	}

	//当前寄存器的内容
	
	OutputDebugStringF("Eax:%d,Ebx:%d,Ecx,%d,Edx:%d",reg.Eax,reg.Ebx,reg.Ecx,reg.Edx);
	OutputDebugStringF("esp:%d,ebp:%d,esi,%d,edi:%d",reg.Esp,reg.Ebp,reg.Esi,reg.Edi);
	
	
	//参数内容
	OutputDebugStringF("X:%d.Y:%d",dwParaX,dwParaY);

	//恢复现场
	_asm
	{
		popfd
		popad
	}
	//执行覆盖代码
	_asm
	{
		push ebp
		mov ebp,esp
		sub esp,40h
	}

	//跳回去
	_asm
	{
		jmp g_dwRetAddr
	}

}

DWORD Plus(DWORD x,DWORD y)
{
	return x+y;
}


BOOL SetInlineHook(DWORD dwHookAddr,DWORD dwProcAddr,int bytes)
{
	BOOL bRet = FALSE;
	DWORD dwOldProtect = 0;
	DWORD dwJumpCode = 0;

	if(dwHookAddr == NULL || dwProcAddr==NULL)
	{
		OutputDebugStringF("Function Address Error!");
		return bRet;
	}

	if(bytes<5)
	{
		OutputDebugStringF("字节长度不够,操作失败!");
		return bRet;
	}

	bRet = VirtualProtectEx(::GetCurrentProcess(),(LPVOID)dwHookAddr,(DWORD)bytes,PAGE_EXECUTE_READWRITE,&dwOldProtect);
	
	if(!bRet)
	{
		OutputDebugStringF("内存空间申请权限失败");
		return bRet;
	}
	
	//备份硬编码
	g_pCodePatch = new BYTE[bytes];
	memcpy(g_pCodePatch,(void*)dwHookAddr,bytes);
	
	//填充90
	dwJumpCode = dwProcAddr - dwHookAddr - 5;
	memset((void*)dwHookAddr,0x90,bytes);

	// jmp 0x0000
	*(PBYTE)dwHookAddr = 0xE9;
	*(PDWORD)((PBYTE)dwHookAddr + 1) = dwJumpCode;
	
	//修改HOOK状态
	g_dwHookFlag = 1;
	g_dwHookAddr = dwHookAddr;
	g_dwLength = (DWORD)bytes;
	g_dwRetAddr = dwHookAddr + g_dwLength;

	return TRUE;

}

BOOL UnInlineHook()
{
	BOOL bRet = FALSE;
	DWORD dwOldProtect;
	if(!g_dwHookFlag)
	{
		OutputDebugStringF("no hook inline");
		return bRet;
	}
	bRet = VirtualProtectEx(::GetCurrentProcess(),(LPVOID)g_dwHookAddr,(DWORD)g_dwLength,PAGE_EXECUTE_READWRITE,&dwOldProtect);
	
	if(!bRet)
	{
		OutputDebugStringF("内存空间申请权限失败");
		return bRet;
	}
	
	//恢复硬编码
	memcpy((PDWORD)g_dwHookAddr,g_pCodePatch,g_dwLength);

	//修改HOOK状态
	delete[] g_pCodePatch;
	g_dwHookFlag = 0;
	g_dwHookAddr = 0;
	g_dwLength = 0;
	g_dwRetAddr = 0;
	g_pCodePatch= NULL;

	return TRUE;
}


VOID TestInlineHook(DWORD dwHookAddr,DWORD dwProcAddr,int bytes)
{

	SetInlineHook(dwHookAddr,dwProcAddr,bytes);
	Plus(11,55);
	//卸载HOOK
	UnInlineHook();
}



int APIENTRY WinMain(HINSTANCE hInstance,
                     HINSTANCE hPrevInstance,
                     LPSTR     lpCmdLine,
                     int       nCmdShow)
{
	DWORD TestFuncAddr = 0x004012A0;
	Plus(1,2);
	OutputDebugStringF("HookProc: %08X",HookProc);
	OutputDebugStringF("TestFuncAddr: %08X",TestFuncAddr);
	//安装HOOK
	TestInlineHook(TestFuncAddr,(DWORD)HookProc,6);
	
	return 0;
}


0x04 工程下载
inlineHook.rar
直接分享代码吧,
记住不同机器上 Plus的地址不一样, 自己先测试吧!!




原文链接: 测试InlineHook 版权所有,转载时请注明出处,违者必究。
注明出处格式:流沙团 ( https://gyarmy.com/post-394.html )

发表评论

0则评论给“测试InlineHook”