在下刚开始学习HOOK,看了这个帖子
《函数hook注意事项》之后尝试自己动手写一个,结果在实践中发现有很多问题……特地来请教各位达人。
在目标程序Target.exe中,我设置了一个静态变量并初始化DWORD stc_MemTarget = 2188934;然后每点击一下按钮就自增一次,然后打算通过HOOK截取该变量的最新值。
void CtestDlg::OnBnClickedButtonTestSubmit()
{
sprintf_s(m_Log, sizeof(m_Log), "the num is %ld", stc_MemTarget);
Msg(m_Log);
Plus();
}
Plus()函数被预定为目标函数,为了方便找到它我在前面特地加了个字符串……
int CtestDlg::Plus()
{
++ stc_MemTarget;
return 1;
}
启动目标程序,用OD加载,然后我打算HOOK的这个CALL在如图0x004018ec处,也就是目标函数Plus()所被CALL的位置:
从它的寄存器数值可以看到此时EAX上有着我需要的变量数值:
函数内部也确实做的是简单的自增操作:
然后我进行HOOK,从OD的监视中可以看到HOOK成功,CALL的指向成功变成了替换函数:
这是HOOK部分的代码:
LRESULT __stdcall myHookProc(int nCode, WPARAM wParam, LPARAM lParam)
{
if (false == stc_Hooked)
{
AFX_MANAGE_STATE(AfxGetStaticModuleState());
char szLog[1024] = {0};
HWND hWnd = ::FindWindow(NULL, "Target");
if (NULL == hWnd)
{
return::CallNextHookEx(stc_hHook, nCode, wParam ,lParam);
}
DWORD dwPid = 0;
GetWindowThreadProcessId(hWnd, &dwPid);
HANDLE hHandle = ::OpenProcess(PROCESS_ALL_ACCESS, FALSE, dwPid);
if (NULL == hHandle || INVALID_HANDLE_VALUE == hHandle)
{
return::CallNextHookEx(stc_hHook, nCode, wParam ,lParam);
}
DWORD Addr = DWORD(GetCMD);
Addr -= 0x004018ec;
Addr -= 4;
::WriteProcessMemory(hHandle, (DWORD*)0x004018ec, &Addr, 4, NULL);
stc_Hooked = true;
}
return ::CallNextHookEx(stc_hHook, nCode, wParam ,lParam);
}
结果我发现进入后,函数很莫名的在前面需要先向EAX存放数据,直接导致我无法获取到需要的变量了:
我回头看看自己写的替代函数,貌似很简单的操作,可为什么会导致这样的结果呢?
int GetCMD()
{
_asm
{
pushad;
mov stc_Result, eax;
}
char szBuffer[100] = {0};
sprintf_s(szBuffer, sizeof(szBuffer), "%ld", stc_Result);
::MessageBox(NULL, szBuffer, "Got", MB_OK);
_asm
{
mov ecx, 0x0041e05e;
call ecx;
popad;
}
return 0;
}
而且尽管我pushad和popad都做了,替代函数也做到了参数返回值和目标函数完全一致,可进出后仍然导致了寄存器数值被更改,使目标函数最终得到的数据出现了错误,仅仅是因为这是测试程序,没有拿目标函数的数据来做什么所以没有崩溃而已。
请问这样做为什么会错误,我该怎样写才正确呢?
附:
这里是程序源码
[培训]内核驱动高级班,冲击BAT一流互联网大厂工作,每周日13:00-18:00直播授课