玩转C科技.NET

从学会做人开始认识这个世界!http://volnet.github.io

导航

Hooks(钩子)_用于监听消息的方法

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消息机制:(图解)

应用程序

窗口过程

消息队列

操作系统

Windows消息机制:(图解)

 

1

2

4

3

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 ValueSetWindowsHookEx

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

详细用法:MSDNpragma directives (#pragma)

5、  注意事项:使用钩子要十分注意,比如刚才一定要给自己留个“退出”的方法,否则后果十分严重!

posted on 2008-07-18 20:01  volnet(可以叫我大V)  阅读(3252)  评论(0编辑  收藏  举报

使用Live Messenger联系我
关闭