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 工程下载
直接分享代码吧,
记住不同机器上 Plus的地址不一样, 自己先测试吧!!