首页
社区
课程
招聘
[求助]HOOK运行不稳定
发表于: 2015-5-5 12:27 6633

[求助]HOOK运行不稳定

2015-5-5 12:27
6633
一段很简单的注入代码
    void __cdecl GetCMD(DWORD val1, DWORD val2, DWORD val3)
        {
        DWORD dwebx = 0;
        DWORD dwesp = 0;
        //原本地址存储于EDI中,发现进入后大部分寄存器数值均已消失
        _asm
        {
        mov dwebx, ebx;
        mov dwesp, esp;
        }
        //扫尾,处理参数传递
        DWORD dwback = stc_mapdata->baseaddr + 0x41A10;
        _asm
        {
        push val3;
        push val2;
        push val1;
        mov ecx, dwback;
        call ecx;
        add esp, 0xc;
        }
        }

然后在运行的时候采用HOOK注入目标游戏进程:
::SetWindowsHookEx(WH_CBT, (HOOKPROC)CrkProc, theApp.m_hInstance, dwthread);

这段注入代码做的事情很简单,就是查看一下寄存器里的值然后传递出去。

而目标进程的注入处是这样子的(打算注入02254c32处的CALL):

这个CALL的内部结构如下:



该段代码在大部分电脑上测试运行正常(大部分>100台以上的电脑)。
可发布出去后,部分64位WIN7、WIN8以及个别XP用户系统下就出现了问题,目标进程经常运行着就出现崩溃。

请问有人知道这是为什么吗?
我查找了很多关于HOOK的资料,可很少见到有资料解释稳定性的。

[培训]内核驱动高级班,冲击BAT一流互联网大厂工作,每周日13:00-18:00直播授课

收藏
免费 0
支持
分享
最新回复 (13)
雪    币: 8
活跃值: (21)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
2
我知道,我以前hook系统某些函数经常出现这样的情况,最后加了一行代码就都解决了
2015-5-5 14:01
0
雪    币: 53
活跃值: (528)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
3
撸主,注意调用约定。stdcall和cdecl是不一样的哦。
2015-5-5 14:08
0
雪    币: 22
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
4
请问是什么代码?
能指点下嘛


是啊,所以我自己处理的堆栈啊
难道目标函数不是cdecl?
2015-5-5 15:02
0
雪    币: 73
活跃值: (923)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
5
context,我记得有这么个结构,要hook,你得保存之前的上下文环境吧?
2015-5-5 19:25
0
雪    币: 22
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
6
请问你的意思是需要先PUSHAD之后再POPAD吗?
2015-5-5 19:40
0
雪    币: 8
活跃值: (21)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
7
他们说的都没到正点上,哈哈
2015-5-6 00:31
0
雪    币: 66
活跃值: (41)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
8
你得脑补HOOK 。你所用的HOOK是消息HOOK ,
你要实现的东西叫 patch
2015-5-6 00:54
0
雪    币: 298
活跃值: (43)
能力值: ( LV3,RANK:30 )
在线值:
发帖
回帖
粉丝
9
芳哥,你还在搞赖子呢
2015-5-6 10:56
0
雪    币: 298
活跃值: (43)
能力值: ( LV3,RANK:30 )
在线值:
发帖
回帖
粉丝
10
//原本地址存储于EDI中,发现进入后大部分寄存器数值均已消失

GetCMD用裸函数,不过函数里要自己处理堆栈平衡
2015-5-6 11:02
0
雪    币: 22
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
11
昨晚试了一下这样,先PUSHAD再POPAD:
void __cdecl GetCMD(DWORD val1, DWORD val2, DWORD val3)
{
	DWORD dwebx = 0;
	DWORD dwesp = 0;
	//原本牌地址存储于EDI中,发现进入后大部分寄存器数值均已消失
	_asm
	{
		mov dwebx, ebx;
		mov dwesp, esp;
		pushad;
	}

        //do something....

	//扫尾,处理参数传递
	DWORD dwback = stc_mapdata->baseaddr + 0x41A10;

	_asm
	{
		popad;
		mov edx, val3;
		push edx;
		mov eax, val2;
		push eax;
		mov ecx, val1;
		push ecx;
		mov ebx, dwback;
		call ebx;
		add esp, 0xc;
	}
}

放出去测试后,发现部分原先会出现问题的电脑好使了,可还有部分电脑错误依然如故,挠头……
2015-5-6 21:43
0
雪    币: 81
活跃值: (100)
能力值: ( LV3,RANK:20 )
在线值:
发帖
回帖
粉丝
12
你要是想自己pushad,popad来管理context,请用naked函数,这样是没法用局部变量的
你要是要系统帮你管理context,你就不要读寄存器里的值,因为进入函数以后一部分已经发生变化了,想办法在堆栈例找你要的数据

一个通用的解决方案是,先hook一个naked函数,把所有寄存器压栈,然后call一个stdcall的innerhook,innerhook里通过读栈(参数)获取所有寄存器,最后naked里出栈所有寄存器平衡
这样做可以hook任意点,获取到所有的寄存器和hook点堆栈,但是代码量比较大,比较麻烦
2015-5-7 14:49
0
雪    币: 22
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
13
谢谢指点……
不过老实说
很多地方还不懂
裸函数什么的都去研究了一番,但限定的时间太短,没得出什么结果来

最后我是采用这样的方法解决的:
void __cdecl GetCMD(DWORD val1, DWORD val2, DWORD val3)
{
	_asm
	{
		mov stc_dweax, eax;
		mov stc_dwecx, ecx;
		mov stc_dwedx, edx;
		mov stc_dwedi, edi;
		mov stc_dwesi, esi;
		mov stc_dwebx, ebx;
		mov stc_dwesp, esp;
	}

	if (stc_dwebx > 0 && stc_dwebx <= 0x14)
	{
            //do something...
	}

	stc_dwback = stc_mapdata->baseaddr + 0x41A10;

	_asm
	{
		mov eax, stc_dweax;
		mov ebx, stc_dwebx;
		mov ecx, stc_dwecx;
		mov edx, stc_dwedx;
		mov edi, stc_dwedi;
		mov esi, stc_dwesi;

		mov edx, val3;
		push edx;
		mov eax, val2;
		push eax;
		mov ecx, val1;
		push ecx;
		mov ebx, stc_dwback;
		call ebx;
		add esp, 0xc;
	}
}


其实就是把所有寄存器都先存起来……
这方法非常挫,但确实成功解决了我目前遇到的问题。
2015-5-8 17:37
0
雪    币: 81
活跃值: (100)
能力值: ( LV3,RANK:20 )
在线值:
发帖
回帖
粉丝
14
这样是有问题的,你拿到的并不是你想要的寄存器的值,但也不是总是这样,所以你目前的情况只是恰巧没遇上而已
2015-5-12 09:40
0
游客
登录 | 注册 方可回帖
返回
//