C++钩子技术

涉及函数

HHOOK SetWindowsHookEx(      

    int idHook,
    HOOKPROC lpfn,
    HINSTANCE hMod,
    DWORD dwThreadId
);

参数说明:

    idHook: 钩子类型

WH_CALLWNDPROC: 回调钩子, 监视在系统发送消息到目标窗口之前获取消息 

WH_CALLWNDPROCRET: 监视 在系统发送消息到目标窗口之后获取消息 WH_CBT: WH_DEBUG: 调试钩子 WH_FOREGROUNDIDLE:处理前景色钩子 WH_GETMESSAGE: 监视发送消息到消息队列 WH_JOURNALPLAYBACK:查看被 WH_JOURNALRECORD 记录的消息 WH_JOURNALRECORD: 记录输入的消息,发送到消息队列,主要用在记录宏 WH_KEYBOARD:键盘消息钩子 WH_KEYBOARD_LL:键盘消息钩子,用在监视较低级别的键盘事件 WH_MOUSE: 鼠标钩子 WH_MOUSE_LL: 监视低级别的鼠标事件 钩子 WH_MSGFILTER: 监视对话框,消息框,菜单,滚动条的输入事件 WH_SHELL : 监视 shell 程序 

WH_SYSMSGFILTER: 监视与调用线程在同一桌面上的控件消息

lpfn:指向过程函数的指针

如果dwThreadId =0 或者被不同进程创建的线程,那么lpfn 必须指向是DLL的钩子

否则,lpfn指向当前进程中定义的钩子过程

hMod: 包含指向lpfn参数的钩子的DLL句柄, 如果dwThreadId指示的线程是当前进程创建并且关联到当前进程的钩子

那么hMod 设置为NULL

dwThreadId: 钩子过程关联的线程,如果为0, 为全局钩子,将监视当前调用线程同一桌面的所有的消息


SetWindowsHookEx : 把一个新的钩子 加入到钩子链中, 最后加入的钩子在链的最前面


返回值: 成功,钩子过程的句柄; 失败返回NULL

描述:

SetWindowsHookEx 可以进行DLL 注入到另外一个进程,但是32位 DLL不能注入到64位进程, 64位DLL的也不能注入到32位的进程中。

如果使用钩子进行注入DLL, 32位的DLL 和64位饿DLL 需要名称不相同

如果hMod = NULL,并且 (dwThreadId=0, 或者dwThreadId被另外一个进程创建),那么将抛出错误。

建议调用 CallNextHookEx 把事件往下一个钩子传递, 否则最终程序获取不到事件,也有可能导致系统错误。 除非你一定不想让消息往下传递。

在中断程序前, 一定要调用 UnhookWindowsHookEx 去是否钩子所占用的系统资源


HookScope
WH_CALLWNDPROCThread or global
WH_CALLWNDPROCRETThread or global
WH_CBTThread or global
WH_DEBUGThread or global
WH_FOREGROUNDIDLEThread or global
WH_GETMESSAGEThread or global
WH_JOURNALPLAYBACKGlobal only
WH_JOURNALRECORDGlobal only
WH_KEYBOARDThread or global
WH_KEYBOARD_LLGlobal only
WH_MOUSEThread or global
WH_MOUSE_LLGlobal only
WH_MSGFILTERThread or global
WH_SHELLThread or global
WH_SYSMSGFILTERGlobal only

如果既是线程钩子又是全局钩子, 那么先调用线程钩子,再调用全局钩子。


Minimum DLL Versionuser32.dll
HeaderDeclared in Winuser.h, include Windows.h
Import libraryUser32.lib
Minimum operating systemsWindows 95, Windows NT 3.1
UnicodeImplemented as ANSI and Unicode versions


测试: 

1.线程钩子

创建MFC 对话框应用程序, 在OnInitDialog 中加入 代码

SetWindowsHookEx(WH_MOUSE,(HOOKPROC)MouseProc,NULL,GetCurrentThreadId());

因为是当前主线程创建的钩子,所有 hMod =NULL , 获取当前线程Id 使用 GetCurrentThreadId(), 钩子类型是鼠标钩子

添加钩子过程函数:

LRESULT CALLBACK MouseProc(int nCode,
	WPARAM wParam,
	LPARAM lParam
	)
{


}



LRESULT CallNextHookEx(      

    HHOOK hhk,
    int nCode,
    WPARAM wParam,
    LPARAM lParam
);
此函数, 是把参数传递到当前钩子链中的下一个钩子


问题: VS2010生成 lib 文件

VS2010默认生成dll,但不生成Lib文件,方法是:在所建工程上单击鼠标右键,在弹出的右键菜单中选择“添加-->新建项....---->模块定义文件”,在该模块定义文件中写导出函数表,单击确定。然后在所建工程上单击鼠标右键,选择“属性”菜单,在弹出的属性对话框中“链接器-->输入-->模块定义文件”中填写刚才定义的def文件,然后再重新编译即可生成LIB文件。


WH_GETMESSAGE是从消息队列中取消息, 而WH_CALLWNDPROC 是获取发送中前的消息

WH_GETMESSAGE Hook只拦截由GetMessage or PostMessage的消息,不能拦截由SendMessage引起的消息。
the WH_GETMESSAGE hook enables an application to monitor messages about to be returned by the GetMessage or PeekMessage function. You can use the WH_GETMESSAGE hook to monitor mouse and keyboard input and other messages posted to the message queue.


要Hook SendMessage必须Hook WH_CALLWNDPROC and WH_CALLWNDPROCRET Hooks
The WH_CALLWNDPROC and WH_CALLWNDPROCRET hooks enable you to monitor messages sent to window procedures by the SendMessage function. Windows calls a WH_CALLWNDPROC hook procedure before passing the message to the receiving window procedure, and calls the WH_CALLWNDPROCRET hook procedure after the window procedure has processed the message. 
The WH_CALLWNDPROCRET hook passes the address of a CWPRETSTRUCT structure to the hook procedure. The structure contains the return value from the window procedure that processed the message, as well as the message parameters associated with the message. Subclassing the window does not work for messages set between processes.


事列源码 : 线程钩子



目前最好的EasyHook的完整Demo程序,包括了Hook.dll动态库和Inject.exe注入程序。 Hook.dll动态库封装了一套稳定的下钩子的机制,以后对函数下钩子,只需要填下数组表格就能实现了,极大的方便了今后的使用。 Inject.exe是用MFC写的界面程序,只需要在界面上输入进程ID就能正确的HOOK上相应的进程,操作起来非常的简便。 这个Demo的代码风格也非常的好,用VS2010成功稳定编译通过,非常值得下载使用。 部分代码片段摘录如下: //【Inject.exe注入程序的代码片段】 void CInjectHelperDlg::OnBnClickedButtonInjectDllProcessId() { ////////////////////////////////////////////////////////////////////////// //【得到进程ID值】 UINT nProcessID = 0; if (!GetProcessID(nProcessID)) { TRACE(_T("%s GetProcessID 失败"), __FUNCTION__); return; } ////////////////////////////////////////////////////////////////////////// //【得到DLL完整路径】 CString strPathDLL; if (!GetDllFilePath(strPathDLL)) { TRACE(_T("%s GetDllFilePath 失败"), __FUNCTION__); return; } ////////////////////////////////////////////////////////////////////////// //【注入DLL】 NTSTATUS ntStatus = RhInjectLibrary(nProcessID, 0, EASYHOOK_INJECT_DEFAULT, strPathDLL.GetBuffer(0), NULL, NULL, 0); if (!ShowStatusInfo(ntStatus)) { TRACE(_T("%s ShowStatusInfo 失败"), __FUNCTION__); return; } } //【Hook.dll动态库的代码片段】 extern "C" __declspec(dllexport) void __stdcall NativeInjectionEntryPoint(REMOTE_ENTRY_INFO* InRemoteInfo) { if (!DylibMain()) { TRACE(_T("%s DylibMain 失败"), __FUNCTION__); return; } } FUNCTIONOLDNEW_FRMOSYMBOL array_stFUNCTIONOLDNEW_FRMOSYMBOL[]= { {_T("kernel32"), "CreateFileW", (void*)CreateFileW_new}, {_T("kernel32"), "CreateFileA", (void*)CreateFileA_new}, {_T("kernel32"), "ReadFile", (void*)ReadFile_new} }; BOOL HookFunctionArrayBySymbol() { /////////////////////////////////////////////////////////////// int nPos = 0; do { /////////////////////////////// FUNCTIONOLDNEW_FRMOSYMBOL* stFunctionOldNew = &g_stFUNCTIONOLDNEW_FRMOSYMBOL[nPos]; if (NULL == stFunctionOldNew->strModuleName) { break; } /////////////////////////////// if (!HookFunctionBySymbol(stFunctionOldNew->strModuleName, stFunctionOldNew->strNameFunction, stFunctionOldNew->pFunction_New)) { TRACE(_T("%s HookFunctionBySymbol 失败"), __FUNCTION__); return FALSE; } } while(++nPos); /////////////////////////////////////////////////////////////// return TRUE; } HANDLE WINAPI CreateFileW_new( PWCHAR lpFileName, DWORD dwDesiredAccess, DWORD dwShareMode, LPSECURITY_ATTRIBUTES lpSecurityAttributes, DWORD dwCreationDisposition, DWORD dwFlagsAndAttributes, HANDLE hTemplateFile ) { TRACE(_T("CreateFileW_new. lpFileName = %s"), lpFileName); return CreateFileW( lpFileName, dwDesiredAccess, dwShareMode, lpSecurityAttributes, dwCreationDisposition, dwFlagsAndAttributes, hTemplateFile); }
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值