首页
社区
课程
招聘
[求助]请问如何才能正确的HOOK
发表于: 2012-12-4 13:15 5552

[求助]请问如何才能正确的HOOK

2012-12-4 13:15
5552
在下刚开始学习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直播授课

收藏
免费 0
支持
分享
最新回复 (7)
雪    币: 164
活跃值: (39)
能力值: ( LV3,RANK:20 )
在线值:
发帖
回帖
粉丝
2
我还在学汇编,坐等大神来,顶起~
2012-12-4 14:03
0
雪    币: 434
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
3
_declspec(naked) int GetCMD()

static char szBuffer[100] = {0};

popad位置不对

用指令ret返回 或者 改成没返回值函数

可能还有其它错误 你调试时再改改
2012-12-4 14:05
0
雪    币: 22
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
4
[QUOTE=cwind;1122988]_declspec(naked) int GetCMD()
static char szBuffer[100] = {0};
popad位置不对
用指令ret返回 或者 改成没返回值函数
可能还有其它错误 你调试时再改改[/QUOTE]

非常感谢,现在可以正确的获取到数据了。
我将代替函数改成了现在这个样子:
void _declspec(naked) GetCMD()
{
	_asm
	{
		pushad;
		mov stc_Result, eax;
	}

	static char szBuffer[100] = {0};
	sprintf_s(szBuffer, sizeof(szBuffer), "%ld", stc_Result);
	::MessageBox(NULL, szBuffer, "Got", MB_OK);

	_asm
	{
		popad;
		mov ecx, 0x0041e05e;
		call ecx;
	}
}

为了简单方便目标函数也改成没有返回值的了……

void CtestDlg::Plus()
{
++ stc_MemTarget;
}



不过在获取完毕后程序仍然会崩溃,我跟了下大概是因为使用了ECX保存地址的原因?然后我试着用了EDX、EBX也不行……我仔细看了看寄存器,在POPAD之后确实都恢复到了原本的状态,可最后CALL的时候一定得使用一个寄存器保存地址呀,那岂不是又弄乱了?请问该如何处理才能平安的返回原函数呢?
2012-12-4 16:02
0
雪    币: 2792
活跃值: (2588)
能力值: ( LV6,RANK:80 )
在线值:
发帖
回帖
粉丝
5

CALL ecx
需要平衡堆栈
加上ADD ESP,0x10

原因是:C调用方式,需要主函数平衡堆栈

上传的附件:
2012-12-4 17:38
0
雪    币: 22
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
6
[QUOTE=HOWMP;1123068]
CALL ecx
需要平衡堆栈
加上ADD ESP,0x10
原因是:C调用方式,需要主函数平衡堆栈
[/QUOTE]

非常感谢
请问是这样写吗?
void _declspec(naked) GetCMD()
{
	_asm
	{
		pushad;
		mov stc_Result, eax;
	}

	static char szBuffer[100] = {0};
	sprintf_s(szBuffer, sizeof(szBuffer), "%ld", stc_Result);
	::MessageBox(NULL, szBuffer, "Got", MB_OK);

	_asm
	{
		popad;
		mov ecx, 0x0041e05e;
		call ecx;
		add esp, 0x10;
	}
}


可我这样修改之后,仍然崩溃啊……不解……
我试着跟踪堆栈看了下,平时目标程序运行到位置,准备进入函数时:

它的堆栈是这样的:

可我在HOOK时,进行POPAD之后,准备call ecx原函数地址时:

堆栈是这样的:

然后程序就跳转到CALL的地址去了,然后就直接违例……
2012-12-5 08:59
0
雪    币: 434
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
7
mov ecx, 0x0041e05e
call ecx

--> push 0x0041e05e
    ret
2012-12-5 09:38
0
雪    币: 22
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
8
太神奇了,非常感谢
原来最后调用原函数还有这种方法,这样做看起来似乎好像可能没有占用任何寄存器……吧?所以先前是因为这个原因才导致无论如何都会崩溃吗?

另外顺便请教一下,我在看雪和广海等地方找来找去,类似系统性介绍HOOK和这方面知识的资料似乎很少,偶尔一点知识都是别人随口提那么一句才知道“原来还能这样”诸如此类……不知道哪本书或者资料能系统的学习到这方面内容呢?
2012-12-5 09:58
0
游客
登录 | 注册 方可回帖
返回
//