Hooks
(钩子)
一、MSDN:索引Hooks
A hook is a point in the system message-handling mechanism where an application can install a subroutine to monitor the message traffic in the system and process certain types of messages before they reach the target window procedure.
翻译:一个钩子是一个指向消息句柄机制的指针,它可以确保一个消息到达窗体过程,监视消息队列系统安装子程序。(翻译有点拗口,意思呢就是说钩子程序是一个监视消息队列的程序,可以确保子程序在安装)
Windows消息机制:(图解)
Overviews
About Hooks
This topic discusses how hooks should be used.翻译:这个主题讨论钩子的使用
Hooks tend to slow down the system because they increase the amount of processing the system must perform for each message. You should install a hook only when necessary, and remove it as soon as possible.
翻译:因为钩子程序必须对处理系统的每个消息进行处理,增加了系统进程,因此将导致减慢系统。只有当你真正需要的时候才去安装钩子程序,并及时地移除它们。
Hook Chains 钩子链
[由于具体的内容相对较长请自行查阅]主要意思就是说,系统维护一条钩子链,所有的消息都要经过相关钩子过程的处理,比如说WH_MOUSE Hook,系统捕获鼠标消息,并进行相应处理。
Hook Procedures
To take advantage of a particular type of hook, the developer provides a hook procedure and uses the SetWindowsHookEx function to install it into the chain associated with the hook. A hook procedure must have the following syntax:
翻译:利用特殊的钩子类,开发者提供一个钩子过程并使用SetWindowsHookEx函数,来把钩子和钩子链关联起来(将它们加入钩子链),一个钩子过程必须有下面的语法。
LRESULT CALLBACK HookProc(
int nCode,
WPARAM wParam,
LPARAM lParam
);
SetWindowsHookEx Function
The SetWindowsHookEx function installs an application-defined hook procedure into a hook chain. You would install a hook procedure to monitor the system for certain types of events. These events are associated either with a specific thread or with all threads in the same desktop as the calling thread.
Syntax
翻译:SetWindowsHookEx函数将一个应用程序定义过程添加进钩子链。你添加的钩子链将监视系统中确定类型的事件。这些事件像调用进程一样,关联一个进程或者所有运行于当前桌面的进程。
HHOOK SetWindowsHookEx(
int idHook,
HOOKPROC lpfn,
HINSTANCE hMod,
DWORD dwThreadId
);
Return Value
(SetWindowsHookEx
)
If the function succeeds, the return value is the handle to the hook procedure.
If the function fails, the return value is NULL. To get extended error information, call GetLastError.
翻译:如果这个函数调用成功,将返回一个钩子句柄。如果调用失败,返回值是NULL。如果想获得失败信息,就调用GetLastError。
……更多信息请查看MSDN
二、实际操作
InnerHook
1
、新建MFC对话框程序
在BOOL CInnerHookDlg::OnInitDialog()中添加钩子过程
g_hWnd=m_hWnd;
g_hMouse=SetWindowsHookEx(WH_MOUSE,MouseProc,NULL,GetCurrentThreadId()); //
安装鼠标钩子
g_hKeyboard=SetWindowsHookEx(WH_KEYBOARD,KeyboardProc,NULL,GetCurrentThreadId()); //
安装键盘钩子
并定义:
// CInnerHookDlg
消息处理程序
HHOOK g_hKeyboard=NULL;
HHOOK g_hMouse;
HWND g_hWnd=NULL;
LRESULT CALLBACK MouseProc(
int nCode,
WPARAM wParam,
LPARAM lParam
)
{
return 1;
}
LRESULT CALLBACK KeyboardProc(
int code,
WPARAM wParam,
LPARAM lParam
)
{
//if(VK_SPACE==wParam || VK_RETURN==wParam) //
空格或者回车
/*if(VK_F4==wParam && (1==(lParam>>29 & 1))) //ALT+F4
return 1; //
表示已经处理过该消息了//屏蔽消息
else
return CallNextHookEx(g_hKeyboard,code,wParam,lParam); //
将消息传递给下一个Hooks函数
*/
if(VK_F2==wParam)
{
::SendMessage(g_hWnd,WM_CLOSE,0,0); //
发送消息将其窗口关闭
UnhookWindowsHookEx(g_hKeyboard); //
移除钩子过程
UnhookWindowsHookEx(g_hMouse); //
移除钩子过程
}
return 1;
}
1、 屏蔽所有当前正在运行的进程/线程的钩子程序
需要将钩子代码放置动态链接库才可生效
SetWindowsHookEx
获得动态链接库的句柄可以使用DllMain也可以用GetModuleHandle("HookDll")
HINSTANCE g_hInst;
BOOL WINAPI DllMain(
HINSTANCE hinstDLL, // handle to the DLL module
DWORD fdwReason, // reason for calling function
LPVOID lpvReserved // reserved
)
{
g_hInst=hinstDLL;
}
或
GetModuleHandle("HookDll") -> [
等价写法:]GetModuleHandle("HookDll.dll")
2、 如果要获得调用窗体的句柄,最巧妙的方法是直接让调用程序把自己的句柄传递进来。
区别:
void
SetHook() 与
void
SetHook(HWND hwnd)
3、 将窗口设置为最顶层窗口SetWindowPos(wndTopMost,……)
配合其他的参数,可以将窗口设置为顶层,并占据整个窗口,并将其他窗口挡住!
4、 动态链接库中定义的全局变量,由各个程序分别调用,但是并不是当前窗口(标题栏不是蓝色而是灰色),这时候,即使使用程序中设置的F2来关闭窗口,也是无法完成任务的。那么要让传入的hWnd能够变成大家共享的一个,也就是任何进程都可以调用的话。那么可以使用写入式拷贝
利用dumpbin –headers HookDll.dll可以查看“节”的信息,我们可以创建一个节来放置特殊的变量。比如定义一个可写入,读取,并共享的节,并将hWnd放置在里面
在HookDll.cpp文件中定义节
//
定义一个新节
#pragma
data_seg("MySec") //()
内的字符数量必须小于等于8个
HWND g_hWnd=NULL;
#pragma
data_seg()
//
设置节的属性
#pragma
comment(linker,"/section:MySec,RWS") //
设置节的属性RWS=ReadWriteShared的缩写!
另外一种设置节的属性的方法是在.def文件中
SEGMENTS
MySec READ WRITE SHARED
详细用法:MSDN:pragma directives (#pragma)
5、 注意事项:使用钩子要十分注意,比如刚才一定要给自己留个“退出”的方法,否则后果十分严重!
from 玩转C科技.NET