键盘记录器编写笔记

键盘Hook

目的

  • 利用Windows钩子监控键盘事件,记录键盘字符,编译成dll在后台运行

实现

  • 工程位于E:\Project\Cpp\Keyboard\KeyboardRecorder\Crack

头文件

  • 包含windows.h

全局变量

  • 定义模块句柄HINSTANCE hin

DllMain函数

  • DLL的入口函数,按照固定格式必写

  • 在DLLMain中初始化hin=HModule

Install函数

  • extern "C" __declspec(dllexport)定义为导出函数
  • 调用SetWindowsHookEx钩子监控键盘事件,并注册回调函数KeyboardProc
  • Sleep,主要工作在回调函数中完成,不Sleep的话进程很快退出

Remove函数

  • UnhookWindowsHookEx卸载钩子

KeyboardProc函数

  • 键盘回调,参数分别保存消息代码,虚拟键代码和扫描代码
  • CreateFile创建文件,GetFileSize和SetFilePointer移动指针追加字符
	HANDLE pFile = CreateFile("C:\\key.txt", GENERIC_WRITE, FILE_SHARE_READ, NULL, OPEN_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
	DWORD dwHigh;
	DWORD dwPos = GetFileSize(pFile, &dwHigh);
	SetFilePointer(pFile, dwPos, 0, FILE_BEGIN);
  • 通过GetKeyboardState获取256字节的虚拟键代码
  • 通过GetKeyState判断shift键是否按下
  • 调用ToAscii函数,传入上述值,获取键盘Ascii码
  • 将键盘字符通过WriteFile写入文件
  • 返回CallNextHookEx

DLL调试

  • 转化为exe来逐步调试,但实际上我并没能够进入回调函数内的断点
  • 生成DLL,rundll运行并通过MessageBox来打印调试信息,并通过GetLastError来获取内部报错
char ch[10];
snprintf(ch, 10, "[INFO]%d", GetLastError());
MessageBox(NULL,ch,NULL,0);
  • rundll在后台运行,每次调试后可通过下列方式杀死进程
1.资源监视器
资源监视器->CPU->关联句柄,输入运行的文件夹,结束下面的进程
2.tasklist
tasklist | findstr rundll
taskkill /pid pid /F

遇到的问题

  • 由于dll是由rundll启动的,所以通过getModuleHandle获取不到主模块,传入SetWindowsHookEx错误,解决方法:在dllMain函数中获取模块值
  • 通过GetKeyNameTextA(lParam, szKey, 100)能够直接获取键盘字符,但是不能识别大小写和shift
  • (此部分实现在Crack_scan.cpp中)通过wParam判断键盘按下/弹上,通过vkCode取扫描码,将扫描码逐个转化为目标字符,该方法更细粒度,但实际调试发现取不到vkCode,故放弃
  • (此部分实现在Crack.cpp中)最后选用了ToAscii函数来转化字符,可处理大小写和shift
  • 尝试通过GetActiveWindow获取窗口标题,但结果不准确
  • 将文件写入C盘会有权限问题,解决办法:一是写入Windows/Temp目录,二是点击目标文件夹属性->安全->编辑->full control,增加写权限

Windows API例程

https://hub.おうか.tw/microsoft/Windows-classic-samples/tree/1d363ff4bd17d8e20415b92e2ee989d615cc0d91

posted @ 2022-10-05 08:47  z5onk0  阅读(159)  评论(0编辑  收藏  举报