外挂心得 - 全局钩子

最初,我采用SendMessage WM_SETHOTKEY的方法,来实现在游戏中呼出外挂并激活。
这种做法确实简单(仅仅一个标准控件加几行代码),但存在非常大的弊端:
1 使用Hotkey呼出外挂将导致外挂窗口被强行带到前端,此时游戏窗口被最小化,非常麻烦而且游戏人物很危险。
注:WM_HOTKEY与WM_SETHOTKEY不是同一个事件,对于后者,MSDN说:
An application sends a WM_SETHOTKEY message to a window to associate a hot key with the window. When the user presses the hot key, the system activates the window.
可见这个问题基本上无解。
2 对于一个窗口来说,Hotkey只能有一个,而我们需要 挖矿开关,开启外挂功能,关闭外挂功能 三个热键。

=====================

怎么办?当然我一下就想到了大家耳熟能详的名词--钩子。
虽然钩子这个名词我非常熟悉,可是真正自己编写一个钩子程序,那还是第一次。没什么,承认自己的不足是进步的第一步,下次不就知道了么?
OK! 查资料,得到这样的描述:

Windows系统是建立在事件驱动的机制上的,说穿了就是整个系统都是通过消息的传递来实现的。而钩子是Windows系统中非常重要的系统接口,用它可以截获并处理送给其他应用程序的消息,来完成普通应用程序难以实现的功能。钩子的种类很多,每种钩子可以截获并处理相应的消息,如键盘钩子可以截获键盘消息,外壳钩子可以截取、启动和关闭应用程序的消息等。
钩子实际上是一个处理消息的程序段,通过系统调用,把它挂入系统。每当特定的消息发出,在没有到达目的窗口前,钩子程序就先捕获该消息,亦即钩子函数先得到控制权。这时钩子函数即可以加工处理(改变)该消息,也可以不作处理而继续传递该消息,还可以强制结束消息的传递。对每种类型的钩子由系统来维护一个钩子链,最近安装的钩子放在链的开始,而最先安装的钩子放在最后,也就是后加入的先获得控制权。要实现Win32的系统钩子,必须调用SDK中的API函数SetWindowsHookEx来安装这个钩子函数,这个函数的原型是
HHOOK SetWindowsHookEx(int idHook,HOOKPROC lpfn,HINSTANCE hMod,DWORD dwThreadId);
其中,第一个参数是钩子的类型;第二个参数是钩子函数的地址;第三个参数是包含钩子函数的模块句柄;第四个参数指定监视的线程。如果指定确定的线程,即为线程专用钩子;如果指定为空,即为全局钩子。其中,全局钩子函数必须包含在DLL(动态链接库)中,而线程专用钩子还可以包含在可执行文件中。得到控制权的钩子函数在完成对消息的处理后,如果想要该消息继续传递,那么它必须调用另外一个SDK中的API函数CallNextHookEx来传递它。钩子函数也可以通过直接返回TRUE来丢弃该消息,并阻止该消息的传递。

==========================

看起来线程钩子比较简单,于是我选择实现它。
在程序中添加
m_hHook = SetWindowsHookEx( WH_KEYBOARD, KeyboardProc, NULL, PID );
其中PID是这个网络游戏的进程号。
看上去很好,可是实际测试无法工作,一检查,原来这里m_hHook返回NULL,根本就没成功。。。
再翻MSDN:
The hMod parameter(就是参数三) must be set to NULL if the dwThreadId parameter specifies a thread created by the current process and if the hook procedure is within the code associated with the current process.
原来线程钩子必须是当前进程(也就是外挂本身)创建的,不能用线程钩子去钩其他进程!汗!

========================

没办法,必须做一个全局钩子
建一个DLL工程,导出DLL和LIB;
然后在外挂中引用它。
核心代码:
在DLL中:
BOOL CKeyboardHook::StartHook()
{
BOOL bResult=FALSE;
glhHook=SetWindowsHookEx(WH_KEYBOARD,KeyboardProc,glhInstance,0);
if(glhHook!=NULL)
bResult=TRUE;
return bResult;
}
在外挂中:
CKeyboardHook m_hook;
m_hook.StartHook();

================================

搞定了?没有!
欲知后事如何,请看:
外挂心得 - DLL共享数据

你可能感兴趣的:(心得)