• HOOK技术键盘鼠标钩子实例


    1.首先创建一个DLL项目,用以生成自定义的DLL文件,在DLL文件中对外有两个接口,安装钩子的函数SetHook和卸载钩子函数UnSetHook函数,对于

       这些函数由于需要导出,所以在工程项目的.h文件中需要声明这些函数需要导出。

    //MouseKeyboardHook.h
    #ifdef MOUSEKEYBOARDHOOK_EXPORTS
    #define MOUSEKEYBOARDHOOK_API __declspec(dllexport)
    #else
    #define MOUSEKEYBOARDHOOK_API __declspec(dllimport)
    #endif
    
    extern "C" MOUSEKEYBOARDHOOK_API int SetHook( DWORD dwThreadId  );
    extern "C" MOUSEKEYBOARDHOOK_API int UnSetHook(void);

        这里只有安装钩子函数有参数,该参数是线程ID号,这里需要注意,如果在调用DLL时发现找不到函数地址,那就需要加extern “C” 说明了,当时我就是没有加郁闷了很久才找到这个问题。我思考了一下,应该是DLL中我采用的是C编程语言,而我的调用该DLL的应用程序默认是C++,但是由于C和C++的OBJ的函数名格式不同,所以才会出现找不到函数地址的问题。是对于DLL的头文件按照这个格式就可以导出函数了。

    //MouseKeyboardHook.cpp文件
    
    #include "stdafx.h"
    #include "MouseKeyboardHook.h"
    #include "stdio.h"
    
    
    //共享内存变量
    #pragma data_seg("MouseKeyboardHook")
    HHOOK g_hMouseHook = NULL;
    HHOOK g_hKeyboardHook = NULL;
    #pragma data_seg()
    // 这是导出变量的一个示例
    MOUSEKEYBOARDHOOK_API int nMouseKeyboardHook=0;
    
    // 这是导出函数的一个示例。
    int UnSetHook(void);
    int fnMouseKeyboardHook(void);
    int SetHook( DWORD dwThreadId  );
    //注意:钩子函数的格式必须是 LRESULT CALLBACK 函数名( int 钩子类型, WPARAM wParam, LPARAM lParam );
    LRESULT CALLBACK MouseHookProc( int nCode, WPARAM wParam, LPARAM lParam );//处理鼠标的钩子函数
    LRESULT CALLBACK KeyboardHookProc( int nCode, WPARAM wParam, LPARAM lParam );//处理键盘的钩子函数
    HMODULE WINAPI ModuleFromAddress(PVOID pv) ;//这个是获取DLL的内存地址,可以重复使用,当做模版
    
    
    MOUSEKEYBOARDHOOK_API int fnMouseKeyboardHook(void)//这个是项目自己生成的没多大用
    {
    	return 42;
    }
    
    LRESULT CALLBACK KeyboardHookProc( int nCode, WPARAM wParam, LPARAM lParam )
    {
    	if( wParam=='Q' && lParam>0 )//当只有按下Q键的时候才会退出钩子函数。其他其他的话都屏蔽
    	{
    		MessageBox( NULL, "卸载钩子中...", "卸载钩子", MB_OK );
    		UnSetHook();
    	}
    	else return TRUE;
    	return ::CallNextHookEx(g_hKeyboardHook, nCode, wParam, lParam);
    }
    
    LRESULT CALLBACK MouseHookProc( int nCode, WPARAM wParam, LPARAM lParam )//我这里屏蔽所有鼠标消息
    {
    	return ::CallNextHookEx(g_hMouseHook, nCode, wParam, lParam);
    }
    // 这是已导出类的构造函数。
    // 有关类定义的信息,请参阅 MouseKeyboardHook.h
    
    CMouseKeyboardHook::CMouseKeyboardHook()
    {
    	return;
    }
    
    MOUSEKEYBOARDHOOK_API int SetHook( DWORD dwThreadId  )//安装钩子函数
    {
    	g_hMouseHook = ::SetWindowsHookEx( WH_MOUSE, MouseHookProc, ModuleFromAddress(MouseHookProc), 0 );
    	g_hKeyboardHook = ::SetWindowsHookEx( WH_KEYBOARD, KeyboardHookProc, ModuleFromAddress(KeyboardHookProc), 0 );
    	return 0;
    }
    
    MOUSEKEYBOARDHOOK_API int UnSetHook(void)//卸载钩子函数,不过这个例子有问题,卸载不了,不知道为什么
    {
    
    	BOOL b1 = ::UnhookWindowsHookEx( g_hMouseHook );
    	BOOL b2 = ::UnhookWindowsHookEx( g_hKeyboardHook );
    	if( b1==FALSE || b2==FALSE )
    		MessageBox( NULL, "卸载钩子失败!", "", MB_OK );
    	return 0;
    }
    
    HMODULE WINAPI ModuleFromAddress(PVOID pv) 
    {
    	MEMORY_BASIC_INFORMATION mbi;
    	if(::VirtualQuery(pv, &mbi, sizeof(mbi)) != 0)
    	{
    		return (HMODULE)mbi.AllocationBase;
    	}
    	else
    	{
    		return NULL;
    	}
    }



    这里要注意的地方是钩子函数的格式,其他的话应该问题不大。同时,因为在头文件中已经声明了导出函数,所以这里不需要再次声明了,按照正常函数写即可。

    不过不知道为什么我的钩子卸载时失败了,真心不懂!


    2.创建加载该DLL的应用程序

        因为需要监视整个计算机,所以SetHook函数传参是0,代表监视整个计算机。

       在本实例中,对于DLL的加载方式是动态加载的。

       具体流程是:加载DLL文件-->获取导出函数地址-->调用钩子安装函数-->卸载钩子

       程序主要源码如下:

    BOOL bInstall = FALSE;//用来指示是否已经安装了钩子
    // 用于应用程序“关于”菜单项的 CAboutDlg 对话框
    //需要声明导出函数指针
    typedef int ( *pSetHook)(DWORD * );//声明函数类型
    typedef int ( *pUnsetHook)(void);
    
    void CKeyMouseHookAppDlg::OnBnClickedButton1()//程序是按下按钮动态加载DLL的
    {
    	
    	HMODULE hModule = ::LoadLibrary( "MouseKeyboardHook.dll" );//加载DLL库
    	if( hModule!=NULL )
    	{
    		if( bInstall==FALSE )
    		{
    			pSetHook mpSetHook;
    			mpSetHook = (pSetHook)::GetProcAddress( hModule, "SetHook" );//获取导出函数地址
    			if( mpSetHook!=NULL )
    			{
    				mpSetHook( 0 );//安装全局钩子
    				bInstall = TRUE;
    				GetDlgItem( IDC_BUTTON1 )->SetWindowText( "卸载DLL" );
    			}
    			else MessageBox( "获取函数地址失败!" );
    		}
    		else
    		{
    			pUnsetHook mpUnsetHook;
    			mpUnsetHook = (pUnsetHook)::GetProcAddress( hModule, "UnSetHook" );
    			if( mpUnsetHook!=NULL )
    			{
    				mpUnsetHook();//卸载钩子
    				bInstall = FALSE;
    				GetDlgItem( IDC_BUTTON1 )->SetWindowText( "加载DLL" );
    			}
    			else MessageBox( "获取函数地址失败!" );
    			::FreeLibrary( hModule );//释放加载的DLL库
    		}
    	}
    	else MessageBox( "加载DLL失败!" );
    }
    


  • 相关阅读:
    Java基础——clone()方法浅析
    Unity shader error: “Too many texture interpolators would be used for ForwardBase pass”
    ar 解压一个.a文件报错: xxx.a is a fat file (use libtool(1) or lipo(1) and ar(1) on it)
    How to set up "lldb_codesign" certificate!
    Unity-iPhone has Conflicting Provisioning Settings
    ETC1/DXT1 compressed textures are not supported when publishing to iPhone
    Xcode 提交APP时遇到 “has one iOS Distribution certificate but its private key is not installed”
    XCode iOS之应用程序标题本地化
    苹果电脑(Mac mini或Macbook或iMac)恢复出厂设置
    Unity 4.7 导出工程在XCode10.1上编译报错
  • 原文地址:https://www.cnblogs.com/arbboter/p/4225265.html
Copyright © 2020-2023  润新知