Windows 全局钩子 Hook 详解

Windows 全局钩子 Hook 详解监控程序的实现 nbsp nbsp nbsp nbsp nbsp 我们发现一些木马或其他病毒程序常常会将我们的键盘或鼠标的操作消息记录下来然后再将它发到他们指定的地方以实现监听 这种功能其他是利用了全局钩子将鼠标或键盘消息进行了截取 从而获得了操作的消息 要得到鼠标和键盘的控制权 我们要用 SetWindowsHo 这个函数 nbsp HHOOKSetWind nbsp nbsp nbsp intidHook nbsp nbsp nbsp nbsp nbsp nbsp nbsp

WH_CALLWNDPROCRET

WH_CBTWH_DEBUG

WH_FOREGROUNDIDLE

WH_GETMESSAGE

WH_JOURNALPLAYBACK

WH_JOURNALRECORD

WH_KEYBOARD

WH_KEYBOARD_LL

WH_MOUSE

WH_MOUSE_LL

WH_MSGFILTER

WH_SHELL

  1. HMODULE WINAPI ModuleFromAddress(PVOID pv) //获得钩子函数的地址   
  2. {   
  3.       MEMORY_BASIC_INFORMATION mbi;   
  4.      if(::VirtualQuery(pv, &mbi, sizeof(mbi)) != 0)   
  5.      {   
  6.           return (HMODULE)mbi.AllocationBase;   
  7.      }   
  8.      else   
  9.     {   
  10.          return NULL;   
  11.     }   
  12. }   
  13. LRESULT CALLBACK KeyHookProc(int nCode, WPARAM wParam, LPARAM lParam)// 键盘钩子函数消息过程   
  14. {   
  15.      if(nCode < 0 || nCode == HC_NOREMOVE)   
  16.           return ::CallNextHookEx(g_hHook, nCode, wParam, lParam);  
  17.      if(lParam & 0x) // 消息重复就交给下一个hook链   
  18.     {   
  19.        return ::CallNextHookEx(g_hHook, nCode, wParam, lParam);   
  20.     }  
  21.     // 通知主窗口。wParam参数为虚拟键码, lParam参数包含了此键的信息   
  22.     ::PostMessage(g_hWndCaller, HM_KEY, wParam, lParam);   //发送自定义键盘消息   
  23.     return ::CallNextHookEx(g_hHook, nCode, wParam, lParam);   
  24. }   
  25. BOOL WINAPI SetKeyHook(BOOL bInstall, DWORD dwThreadId, HWND hWndCaller)// 安装、卸载钩子的函数   
  26. {   
  27.     BOOL bOk;   
  28.     g_hWndCaller = hWndCaller;  
  29.     if(bInstall)   
  30.    {   
  31.        g_hHook = ::SetWindowsHookEx(WH_KEYBOARD, KeyHookProc,   
  32.        ModuleFromAddress(KeyHookProc), dwThreadId);               //安装键盘钩子   
  33.       bOk = (g_hHook != NULL);   
  34.    }   
  35.    else   
  36.    {   
  37.    bOk = ::UnhookWindowsHookEx(g_hHook);   
  38.    g_hHook = NULL;   
  39.    }  
  40.    return bOk;   
  41. }   
  42. LRESULT CALLBACK MouseProc(int nCode, WPARAM wParam, LPARAM lParam)//鼠标钩子处理过程   
  43. {   
  44.    if(nCode < 0 || nCode == HC_NOREMOVE)   
  45.    return ::CallNextHookEx(g_hMouseHook, nCode, wParam, lParam);   
  46.    ::PostMessage(g_hWndCaller, HM_MOUSE, wParam, lParam);//发送自定义鼠标消息   
  47.    return ::CallNextHookEx(g_hMouseHook, nCode, wParam, lParam);   
  48. }   
  49. BOOL WINAPI SetMouseHook(BOOL bInstall, DWORD dwThreadId, HWND hWndCaller)   
  50. {   
  51.    BOOL bOk;   
  52.    g_hWndCaller = hWndCaller;   
  53.    if(bInstall)   
  54.    {   
  55.        g_hMouseHook = ::SetWindowsHookEx(WH_MOUSE, MouseProc,   
  56.        ModuleFromAddress(MouseProc),dwThreadId);   //安装鼠标钩子   
  57.        bOk = (g_hMouseHook != NULL);   
  58.    }   
  59.    else   
  60.   {   
  61.        bOk = ::UnhookWindowsHookEx(g_hMouseHook);   
  62.        g_hMouseHook = NULL;   
  63.   }   
  64.      return bOk;   
  65. }   
HMODULE WINAPI ModuleFromAddress(PVOID pv) //获得钩子函数的地址 { MEMORY_BASIC_INFORMATION mbi; if(::VirtualQuery(pv, &mbi, sizeof(mbi)) != 0) { return (HMODULE)mbi.AllocationBase; } else { return NULL; } } LRESULT CALLBACK KeyHookProc(int nCode, WPARAM wParam, LPARAM lParam)// 键盘钩子函数消息过程 { if(nCode < 0 || nCode == HC_NOREMOVE) return ::CallNextHookEx(g_hHook, nCode, wParam, lParam); if(lParam & 0x) // 消息重复就交给下一个hook链 { return ::CallNextHookEx(g_hHook, nCode, wParam, lParam); } // 通知主窗口。wParam参数为虚拟键码, lParam参数包含了此键的信息 ::PostMessage(g_hWndCaller, HM_KEY, wParam, lParam); //发送自定义键盘消息 return ::CallNextHookEx(g_hHook, nCode, wParam, lParam); } BOOL WINAPI SetKeyHook(BOOL bInstall, DWORD dwThreadId, HWND hWndCaller)// 安装、卸载钩子的函数 { BOOL bOk; g_hWndCaller = hWndCaller; if(bInstall) { g_hHook = ::SetWindowsHookEx(WH_KEYBOARD, KeyHookProc, ModuleFromAddress(KeyHookProc), dwThreadId); //安装键盘钩子 bOk = (g_hHook != NULL); } else { bOk = ::UnhookWindowsHookEx(g_hHook); g_hHook = NULL; } return bOk; } LRESULT CALLBACK MouseProc(int nCode, WPARAM wParam, LPARAM lParam)//鼠标钩子处理过程 { if(nCode < 0 || nCode == HC_NOREMOVE) return ::CallNextHookEx(g_hMouseHook, nCode, wParam, lParam); ::PostMessage(g_hWndCaller, HM_MOUSE, wParam, lParam);//发送自定义鼠标消息 return ::CallNextHookEx(g_hMouseHook, nCode, wParam, lParam); } BOOL WINAPI SetMouseHook(BOOL bInstall, DWORD dwThreadId, HWND hWndCaller) { BOOL bOk; g_hWndCaller = hWndCaller; if(bInstall) { g_hMouseHook = ::SetWindowsHookEx(WH_MOUSE, MouseProc, ModuleFromAddress(MouseProc),dwThreadId); //安装鼠标钩子 bOk = (g_hMouseHook != NULL); } else { bOk = ::UnhookWindowsHookEx(g_hMouseHook); g_hMouseHook = NULL; } return bOk; } 

  1. long CHookAppDlg::OnHookKey(WPARAM wParam, LPARAM lParam)   
  2. {   
  3.           // 此时参数wParam为用户按键的虚拟键码,   
  4.           // lParam参数包含按键的重复次数、扫描码、前一个按键状态等信息   
  5.          char szKey[80];   
  6.         ::GetKeyNameText(lParam, szKey, 80);   //获得按键名   
  7.          CString strItem;   
  8.          strItem.Format("用户按键:%s", szKey);   
  9.           CListBox *pListCtrl=((CListBox *)this->GetDlgItem(IDC_LIST1));   
  10.          pListCtrl->InsertString(-1,strItem);   
  11.         CFile MyFile;   
  12.         char *content;   
  13.         if(!MyFile.Open(this->MyDocumentDir,   
  14.              CFile::modeRead | CFile::modeWrite))   
  15.        {   
  16.                  MyFile.Open(this->MyDocumentDir,   
  17.                             CFile::modeCreate);   
  18.                 return 0;   
  19.       }   
  20.       MyFile.SeekToEnd();                 //移动记录指针到末尾   
  21.       pListCtrl->GetText(pListCtrl->GetCount()-1,strItem);   
  22.       content=strItem.GetBuffer(MAX_PATH);   
  23.        MyFile.Write(content,strItem.GetLength());   
  24.        CTime today=CTime::GetCurrentTime();   
  25.        CString str=today.Format("/t/t%Y年%m月%d日 %H:%M:%S/r/n");   
  26.       MyFile.Write(str.GetBuffer(str.GetLength()),str.GetLength());   
  27.       MyFile.Close();   
  28.      return 0;   
  29. }   
  30. long CHookAppDlg::OnHookMouse(WPARAM wParam, LPARAM lParam)   
  31. {   
  32. LPMOUSEHOOKSTRUCT pMouseHook=(MOUSEHOOKSTRUCT FAR *)lParam;   
  33. CString strItem,strText;   
  34.      CListBox *pListCtrl=((CListBox *)this->GetDlgItem(IDC_LIST1));   
  35. CPoint point;   
  36. ::GetCursorPos(&point);   
  37. ClientToScreen(&point);   
  38. CWnd *pWnd=CWnd::GetForegroundWindow();   
  39. if(pWnd)   
  40. {   
  41.    char str[80];   
  42.    pWnd->GetWindowText(str,80);   
  43.    strText.Format("窗口:%s",str);   
  44. }   
  45. CString str;   
  46. /*CString tempstr;  
  47. //   ClientToScreen(&pMouseHook->pt);  
  48.    int x,y;  
  49.    x=pMouseHook->pt.x;  
  50.    y=pMouseHook->pt.y;  
  51.    tempstr.Format("X=%d,Y=%d",x,y);  
  52.    strText+=tempstr;*/   
  53.      if(wParam==WM_RBUTTONDOWN)   
  54.    {   
  55.             str.Format("   右键单击:位置 X=%d,Y=%d",point.x,point.y);   
  56.             strText+=str;   
  57.             pListCtrl->InsertString(-1,strText);   
  58.            this->SaveToFile(strText,pListCtrl);   
  59.   }   
  60. if(wParam==WM_LBUTTONDBLCLK)   
  61. {   
  62.      ScreenToClient(&point);   
  63.    str.Format("   左键双击:位置 X=%d,Y=%d",point.x,point.y);   
  64.    strText+=str;   
  65.    pListCtrl->InsertString(-1,strText);   
  66.    this->SaveToFile(strText,pListCtrl);   
  67. }   
  68. if(wParam==WM_LBUTTONDOWN)   
  69. {   
  70.    str.Format("   左键单击:位置 X=%d,Y=%d",point.x,point.y);   
  71.    //MessageBox(strText);   
  72.    strText+=str;   
  73.    pListCtrl->InsertString(-1,strText);   
  74.    this->SaveToFile(strText,pListCtrl);   
  75. }   
  76. return 0;   
  77. }   
  78. void CHookAppDlg::SaveToFile(CString strText,CListBox *pListCtrl)   
  79. {   
  80. char *content;   
  81.      CFile MyFile;   
  82. if(!MyFile.Open(this->MyDocumentDir,   
  83.    CFile::modeRead | CFile::modeWrite))   
  84. {   
  85.    MyFile.Open(this->MyDocumentDir,   
  86.    CFile::modeCreate);   
  87.    pListCtrl->InsertString(-1,"失败");   
  88.    return;   
  89. }   
  90. MyFile.SeekToEnd();   
  91. content=strText.GetBuffer(strText.GetLength());   
  92. MyFile.Write(content,strText.GetLength());   
  93. CTime today=CTime::GetCurrentTime();   
  94. CString strTime=today.Format("/t/t%Y年%m月%d日 %H:%M:%S/r/n");   
  95. MyFile.Write(strTime.GetBuffer(strTime.GetLength()),strTime.GetLength());   
  96. MyFile.Close();   
  97. }   
long CHookAppDlg::OnHookKey(WPARAM wParam, LPARAM lParam) { // 此时参数wParam为用户按键的虚拟键码, // lParam参数包含按键的重复次数、扫描码、前一个按键状态等信息 char szKey[80]; ::GetKeyNameText(lParam, szKey, 80); //获得按键名 CString strItem; strItem.Format("用户按键:%s", szKey); CListBox *pListCtrl=((CListBox *)this->GetDlgItem(IDC_LIST1)); pListCtrl->InsertString(-1,strItem); CFile MyFile; char *content; if(!MyFile.Open(this->MyDocumentDir, CFile::modeRead | CFile::modeWrite)) { MyFile.Open(this->MyDocumentDir, CFile::modeCreate); return 0; } MyFile.SeekToEnd(); //移动记录指针到末尾 pListCtrl->GetText(pListCtrl->GetCount()-1,strItem); content=strItem.GetBuffer(MAX_PATH); MyFile.Write(content,strItem.GetLength()); CTime today=CTime::GetCurrentTime(); CString str=today.Format("/t/t%Y年%m月%d日 %H:%M:%S/r/n"); MyFile.Write(str.GetBuffer(str.GetLength()),str.GetLength()); MyFile.Close(); return 0; } long CHookAppDlg::OnHookMouse(WPARAM wParam, LPARAM lParam) { LPMOUSEHOOKSTRUCT pMouseHook=(MOUSEHOOKSTRUCT FAR *)lParam; CString strItem,strText; CListBox *pListCtrl=((CListBox *)this->GetDlgItem(IDC_LIST1)); CPoint point; ::GetCursorPos(&point); ClientToScreen(&point); CWnd *pWnd=CWnd::GetForegroundWindow(); if(pWnd) { char str[80]; pWnd->GetWindowText(str,80); strText.Format("窗口:%s",str); } CString str; /*CString tempstr; // ClientToScreen(&pMouseHook->pt); int x,y; x=pMouseHook->pt.x; y=pMouseHook->pt.y; tempstr.Format("X=%d,Y=%d",x,y); strText+=tempstr;*/ if(wParam==WM_RBUTTONDOWN) { str.Format(" 右键单击:位置 X=%d,Y=%d",point.x,point.y); strText+=str; pListCtrl->InsertString(-1,strText); this->SaveToFile(strText,pListCtrl); } if(wParam==WM_LBUTTONDBLCLK) { ScreenToClient(&point); str.Format(" 左键双击:位置 X=%d,Y=%d",point.x,point.y); strText+=str; pListCtrl->InsertString(-1,strText); this->SaveToFile(strText,pListCtrl); } if(wParam==WM_LBUTTONDOWN) { str.Format(" 左键单击:位置 X=%d,Y=%d",point.x,point.y); //MessageBox(strText); strText+=str; pListCtrl->InsertString(-1,strText); this->SaveToFile(strText,pListCtrl); } return 0; } void CHookAppDlg::SaveToFile(CString strText,CListBox *pListCtrl) { char *content; CFile MyFile; if(!MyFile.Open(this->MyDocumentDir, CFile::modeRead | CFile::modeWrite)) { MyFile.Open(this->MyDocumentDir, CFile::modeCreate); pListCtrl->InsertString(-1,"失败"); return; } MyFile.SeekToEnd(); content=strText.GetBuffer(strText.GetLength()); MyFile.Write(content,strText.GetLength()); CTime today=CTime::GetCurrentTime(); CString strTime=today.Format("/t/t%Y年%m月%d日 %H:%M:%S/r/n"); MyFile.Write(strTime.GetBuffer(strTime.GetLength()),strTime.GetLength()); MyFile.Close(); } 

上面的代码就是实现将鼠标消息和键盘消息的操作消息添加到一个列表框中和记录到一个文件上的代码.其中this->MyDocumentDir是你要将操作消息记录到的文件路径.

         这是鼠标和键盘消息的监听代码,你也可以为应用程序安装其他类型的钩子.









版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请联系我们举报,一经查实,本站将立刻删除。

发布者:全栈程序员-站长,转载请注明出处:https://javaforall.net/177799.html原文链接:https://javaforall.net

(0)
上一篇 2026年3月26日 下午6:43
下一篇 2026年3月26日 下午6:43


相关推荐

  • 使用jsPDF生成PDF文件

    使用jsPDF生成PDF文件使用两个开源项目 这是他们的地址 jsPDF https github com MrRio jsPDFjsPDF AutoTable https github com simonbengtss jsPDF AutoTable 项目引入 我使用的版本是 jsPDF 1 5 3 jsPDF AutoTable 3 2 4

    2026年3月16日
    3
  • 三阶魔方公式记录

    三阶魔方公式记录第一步 详见魔方小站视频教程 https imofang taobao com p jiaocheng31 htm spm a1z10 4 c s w5003 14960603961 1 6d4723276NiL amp scene taobao shop 第二步 完成底面白色作为底层 视频教程 https imofang taobao com p jiaocheng

    2026年3月19日
    2
  • 基尼系数简单算法_python简单计算器代码

    基尼系数简单算法_python简单计算器代码用Python实现基尼系数的计算

    2022年10月12日
    4
  • mysql如何使用乐观锁_mysql 乐观锁实现

    mysql如何使用乐观锁_mysql 乐观锁实现一 为什么需要锁 并发控制 在多用户环境中 在同一时间可能会有多个用户更新相同的记录 这会产生冲突 这就是著名的并发性问题 典型的冲突有 1 丢失更新 一个事务的更新覆盖了其它事务的更新结果 就是所谓的更新丢失 例如 用户 A 把值从 6 改为 2 用户 B 把值从 2 改为 6 则用户 A 丢失了他的更新 2 脏读 当一个事务读取其它完成一半事务的记录时 就会发生脏读取 例如 用户 A B 看到的值都是 6 用户 B 把值改为

    2026年3月26日
    1
  • Idea 2021年激活码刚出(最新序列号破解)

    Idea 2021年激活码刚出(最新序列号破解),https://javaforall.net/100143.html。详细ieda激活码不妨到全栈程序员必看教程网一起来了解一下吧!

    2022年3月18日
    103
  • JavaScript转义字符

    JavaScript转义字符本篇文章由泉州 SEOwww 234yp com 整理发布 js 教程 www 234yp com Article 188271 html 谢谢合作 js 教程转义字符是字符的一种间接表示方式 在特殊语境中 无法直接使用字符自身 例如 在字符串中包含说话内容 子曰 学而不思则罔 思而不学则殆 由于 JavaScript 已经赋予了双引号为字符串直接量的标识符 如果在字符串中包含双引号 就必须使用转义字符表示 子曰 学而不思则罔 思而不学则殆 JavaScript 定义反

    2026年3月20日
    5

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注

关注全栈程序员社区公众号