消息钩子的反拦截

消息钩子的反拦截首先声明一下,标题所指的钩子是消息钩子,而不是API钩子(一种对API地址的替换技术)。若标题使您误解,请不要继续阅读。      消息钩子在Windows编程中有着非常广泛的应用,它可以任意拦截Windows系统,这个以消息为驱动的系统中的绝大多数消息类型。一方面这给编程者带来了巨大的灵活性,另一方面也埋下了巨大隐患,大多数窃密软件都使用这种方法。此篇文章给您提供一种钩子的反拦截方

大家好,又见面了,我是你们的朋友全栈君。如果您正在找激活码,请点击查看最新教程,关注关注公众号 “全栈程序员社区” 获取激活教程,可能之前旧版本教程已经失效.最新Idea2022.1教程亲测有效,一键激活。

Jetbrains全系列IDE使用 1年只要46元 售后保障 童叟无欺

首先声明一下,标题所指的钩子是消息钩子,而不是API钩子(一种对API地址的替换技术)。若标题使您误解,请不要继续阅读。  
         
消息钩子在Windows编程中有着非常广泛的应用,它可以任意拦截Windows系统,这个以消息为驱动的系统中的绝大多数消息类型。一方面这给编程者带来了巨大的灵活性,另一方面也埋下了巨大隐患,大多数窃密软件都使用这种方法。此篇文章给您提供一种钩子的反拦截方法,希望对您有所帮助。文章中使用了API钩子,您之前必须对此技术有一定了解。
 
         
为求完整,文章分为两部分,第一部分为消息钩子的使用,熟悉此技术的读者可以直接跳过此节。第二部分为消息钩子的反拦截。
 
         
一、消息钩子的使用。
 
         
消息钩子分为本地(local)和远程(remote)两种(两个local   system-wide   hook例外,无关主题,不多说了)。local类型的钩子函数只能拦截本进程的消息。能够拦截本进程以外的消息的钩子,都是remote类型。remote类型的钩子必须放在DLL里面。下面以remote类型为例,通过安装键盘钩子介绍其使用。
 
          1
、首先建立DLL,在头文件中添加如下代码。
 
   
  #ifdef   KM_EXPORTS  
  #define   KM_API   __declspec(dllexport)  
  #else  
  #define   KM_API   __declspec(dllimport)  
  #endif  
   
  KM_API   BOOL   HookStart();//
安装钩子
 
  KM_API   BOOL   HookStop();//
卸载钩子
 
   
          2
、在.cpp文件中添加代码
 
   
  #pragma   data_seg(“Shared”)  
  HHOOK   g_hhookKey=NULL;  
  #pragma   data_seg()  
  #pragma   comment(linker,”/SECTION:Shared,RWS”)  
   
          g_hhookKey
为键盘钩子的句柄,为确保此数值在所有实例中均保持不变,将其存放于此模块所有实例的共享数据区,若在exe程序中按此格式添加一int   变量   appNum,在程序启动时appNum++,则可以通过访问此变量的数值,确定有多少个exe的实例,当然这种方法也可以替代同步对象用于只启动一个实例。
 
   
  HINSTANCE   g_hinstDll=NULL;         //
添加全局变量用于记录此DLL模块的句柄
 
  BOOL   APIENTRY   DllMain(   HANDLE   hModule,     DWORD     ul_reason_for_call,     LPVOID   lpReserved   )  
  {  
      switch   (ul_reason_for_call)  
      {  
          case   DLL_PROCESS_ATTACH:  
          g_hinstDll=(HINSTANCE)hModule;//
DLL加载时对全局变量赋值
 
          ………………  
      }  
  }  
   
  LRESULT   KeyHookProc(int   nCode,WPARAM   wParam,LPARAM   lParam)//
键盘钩子的过滤函数
 
  {  
      …………………  
      return::CallNextHookEx(g_hhookKey,nCode,wParam,lParam);//*****
请留意此行代码
*****  
  }  
   
  BOOL   HookStart()//
安装钩子
 
  {    
      g_hhookKey=::SetWindowsHookEx(WH_KEYBOARD,(HOOKPROC)KeyHookProc,g_hinstDll,  
                                ::GetWindowThreadProcessId(::FindWindow(NULL,”
被监视的窗口的标题
“),NULL)   );  
      return   (g_hhookKey!=NULL);  
  }  
   
  BOOL   HookStop()//
卸载钩子
 
  {  
      BOOL   ret;  
      if(g_hhookKey!=NULL)  
      ret=::UnhookWindowsHookEx(g_hhookKey);  
      g_hhookKey=NULL;  
      return   ret;  
  }  
   
         
只要在exe程序中调用HookStart函数,就可以监视某一窗口的键盘消息,若此窗口为QQ的密码框,你的密码就泄漏了。
 
   
         
二、消息钩子的反拦截。
 
         
请留意前面带*号注释的代码,其中传入了钩子的句柄g_hhookKey,只要使用API钩子将CallNextHookEx函数替换,并在替换函数中将其卸载,消息钩子就完蛋了。同时,还要保证本进程安装的钩子不被卸载,其中既可能有local类型的还可能有remote类型的。不要以为自己没有在程序中安装钩子,程序中就一定没有安装钩子,在MFC4版本中,MFC会自己装一个local类型的钩子,MFC7版本中好像没了。好了,下面介绍其实现。
 
          1
、建立DLL,在头文件中添加如下代码。
 
   
  #ifdef   HOOKFORBID_EXPORTS  
  #define   HOOKFORBID_API   __declspec(dllexport)  
  #else  
  #define   HOOKFORBID_API   __declspec(dllimport)  
  #endif  
   
  HOOKFORBID_API   int   fnHookForbid(void);//
exe程序中调用此函数,使DLL加载
 
  HOOKFORBID_API   bool   AddHhook(HHOOK   Hhook);//
exe中安装remote类型消息钩子,将其句柄添加
 
  HOOKFORBID_API   bool   DelHhook(HHOOK   Hhook);//
exe中卸载remote类型消息钩子时,删除其句柄
 
   
          2
、在.cpp文件中添加代码。
 
   
  CArray<HHOOK,HHOOK>   array;//
用于记录本进程安装的钩子的句柄
 
  //  
  int   fnHookForbid(void)  
  {  
      return   1;  
  }  
   
  bool   AddHhook(HHOOK   Hhook)  
  {  
      array.Add(Hhook);  
      return   true;  
  }  
   
  bool   DelHhook(HHOOK   Hhook)  
  {  
      bool   ret=false;  
      for(int   i=0;i<array.GetSize();i++)  
      {  
          if(array.GetAt(i)==Hhook)  
          {  
              array.RemoveAt(i);  
              ret=true;  
              break;  
          }  
      }  
      return   ret;  
  }  
  //  
   
         
下面的代码用于API替换,其中用到了CAPIHook   类,《Windows   核心编程》(Jeffrey   Richter著)一书中有源代码。使用其它开发包也可以实现此功能。
 
   
  //  
  typedef   HHOOK   (WINAPI   *PFNSETWINDOWSHOOKEX)(  
          int   idHook,  
          HOOKPROC   lpfn,  
          HINSTANCE   hMod,  
          DWORD   dwThreadId  
  );  
   
  typedef   LRESULT     (WINAPI   *PFNCALLNEXTHOOKEX)(  
          HHOOK   hhk,  
          int   nCode,  
          WPARAM   wParam,  
          LPARAM   lParam  
  );  
  //  
   
  extern   CAPIHook   g_SetWindowsHookExA;  
  extern   CAPIHook   g_SetWindowsHookExW;  
  extern   CAPIHook   g_CallNextHookEx;  
   
  //  
   
  //
此函数用于替换SetWindowsHookEx函数的ASCII版本
SetWindowsHookExA  
  HHOOK   WINAPI   Hook_SetWindowsHookExA(   int   idHook,     HOOKPROC   lpfn,     HINSTANCE   hMod,     DWORD   dwThreadId   )    
  {  
      HHOOK   nResult   =0;  
   
      nResult   =   ((PFNSETWINDOWSHOOKEX)(PROC)   g_SetWindowsHookExA)(   idHook,   lpfn,     hMod,   dwThreadId     );  
   
      //
若在本进程中安装了local类型钩子,记录其句柄
 
      if(hMod==NULL)                    
          array.Add(nResult);  
   
      return(nResult);  
  }  
   
  //
此函数用于替换SetWindowsHookEx函数的UNICODE版本
SetWindowsHookExW  
  HHOOK   WINAPI   Hook_SetWindowsHookExW(   int   idHook,   HOOKPROC   lpfn,     HINSTANCE   hMod,   DWORD   dwThreadId     )    
  {  
      HHOOK   nResult   =0;  
   
      nResult   =   ((PFNSETWINDOWSHOOKEX)(PROC)   g_SetWindowsHookExW)(   idHook,   lpfn,     hMod,     dwThreadId     );  
   
      //
若在本进程中安装了local类型钩子,记录其句柄
 
      if(hMod==NULL)                    
          array.Add(nResult);  
   
      return(nResult);  
  }  
   
  //
此函数用于替换CallNextHookEx函数,此函数只有一个版本
 
  LRESULT     WINAPI   Hook_CallNextHookEx(   HHOOK   hhk,   int   nCode,     WPARAM   wParam,   LPARAM   lParam)    
  {  
      LRESULT     nResult   =0;  
   
      nResult   =   ((PFNCALLNEXTHOOKEX)(PROC)   g_CallNextHookEx)(   hhk,   nCode,   wParam,     lParam   );  
   
      //
在数组中查找句柄,若找不到,将其卸载
 
      bool   bfind=false;                      
      for(int   i=0;i<array.GetSize();i++)  
      {  
          if(array.GetAt(i)==hhk)  
          {  
              bfind=true;  
              break;  
          }  
      }  
      if(!bfind)  
      {  
          UnhookWindowsHookEx(     hhk     );  
      }  
      return   (nResult);  
  }  
   
  //  
   
  //
使用CAPIHook   类对函数进行替换
 
  CAPIHook   g_SetWindowsHookExA(“User32.dll”,   “SetWindowsHookExA”,    
        (PROC)   Hook_SetWindowsHookExA,   true);  
   
  CAPIHook   g_SetWindowsHookExW(“User32.dll”,   “SetWindowsHookExW”,    
        (PROC)   Hook_SetWindowsHookExW,   true);  
   
  CAPIHook   g_CallNextHookEx(“User32.dll”,   “CallNextHookEx”,    
        (PROC)   Hook_CallNextHookEx,   true);  
   
         
到了这里,所有工作都完成了,只要在exe程序中调用fnHookForbid函数,并在安装remote类型钩子时调用AddHhook函数记录其句柄,卸载时调用DelHhook函数删除句柄就万事ok了。
 
         
一点不足:这种方法可以有效屏蔽消息钩子对信息安全的威胁。可以使Spy++失效。然而,由于是在CallNextHookEx函数中卸载钩子,因此,钩子函数总是会被调用一次。还有一件非常费解的事,金山词霸总能够正常取词,不知道词霸是怎么做到的。
 
         
本人并非专业程序员,   若此方法存在任何错误或隐患,敬请批评指出,请不要在帖子上损我。  

 

 

呵呵!假如我的钩子是这么用的:  
   
  FUN_SETWINDOWSHOOKA   *pFn   =   (FUN_SETWINDOWSHOOKA   *)  
  ::GetProcAddress(::GetModuleHandle(“kernel32.dll”),   “SetWindowsHookA”);  
   
  pFn(…);  
   
 
你的方法还是屏蔽不了哦!不信试验一下!记得给分哦!(该法为:反反API钩子大法
”)  
   
 
当然!同理也可以绕过API钩子!有同样兴趣的人记得发消息给我哦!
 
   
 
首先声明一下:我拦截的是消息钩子,如果安装钩子时考虑到了反卸载则不在讨论之内。
 
 
其次:上述方法不可靠,对CAPIHook类进行更改,可以实时对地址进行替换,就象消息钩子被调用次序的不确定性一样,到时候没法确定那个替换函数被调用了。

防止全局钩子的侵入  
   
                                                  Author:   pjf(jfpan20000@sina.com)  
          Windows
消息钩子一般都很熟悉了。它的用处很多,耳熟能详的就有——利用键盘钩子获取目标进程的键盘输入,从而获得各类密码以达到不可告人的目的。朋友想让他的软件不被别人的全局钩子监视,有没有办法实现呢?答案是肯定的,不过缺陷也是有的。
 
         
首先简单看看全局钩子如何注入别的进程。
 
         
消息钩子是由Win32子系统提供,其核心部分通过NtUserSetWindowsHookEx为用户提供了设置消息钩子的系统服务,用户通过它注册全局钩子。当系统获取某些事件,比如用户按键,键盘driver将扫描码等传入win32kKeyEvent处理函数,处理函数判断有无相应hook,有则callhook。此时,系统取得Hook对象信息,若目标进程没有装载对应的Dll,则装载之(利用KeUserModeCallback“调用用户例程,它与Apc调用不同,它是仿制中断返回环境,其调用是立即性质的)。
 
         
进入用户态的KiUserCallbackDispatcher后,KiUserCallbackDispatcher根据传递的数据获取所需调用的函数、参数等,随后调用。针对上面的例子,为装载hook   dll,得到调用的是LoadLibraryExW,随后进入LdrLoadDll,装载完毕后返回,后面的步骤就不叙述了。
 
         
从上面的讨论我们可以得出一个最简单的防侵入方案:在加载hook   dll之前hook相应api使得加载失败,不过有一个缺陷:系统并不会因为一次的失败而放弃,每次有消息产生欲call   hook时系统都会试图在你的进程加载dll,这对于性能有些微影响,不过应该感觉不到。剩下一个问题就是不是所有的LoadLibraryExW都应拦截,这个容易解决,比如判断返回地址。下面给出一个例子片断,可以添加一些判断使得某些允许加载的hook   dll被加载。
 
         
这里hook   api使用了微软的detours库,可自行修改。
 
   
 
以下内容为程序代码
:  
   
  typedef   HMODULE   (__stdcall   *LOADLIB)(  
          LPCWSTR   lpwLibFileName,  
          HANDLE   hFile,  
          DWORD   dwFlags);  
   
  extern   “C”   {  
                  DETOUR_TRAMPOLINE(HMODULE   __stdcall   Real_LoadLibraryExW(  
                                                                                                                    LPCWSTR   lpwLibFileName,  
                                                                                                                    HANDLE   hFile,  
                                                                                                                    DWORD   dwFlags),  
                                                                                                                  LoadLibraryExW);  
  }  
   
  ULONG   user32   =   0;  
   
  HMODULE   __stdcall   Mine_LoadLibraryExW(  
                                                      LPCWSTR   lpwLibFileName,  
                                                      HANDLE   hFile,  
                                                      DWORD   dwFlags)  
  {  
                  ULONG   addr;  
   
                  _asm   mov   eax,   [ebp+4]  
                  _asm   mov   addr,   eax  
   
                  if   ((user32   &   0xFFFF0000)   ==   (addr   &   0xFFFF0000))  
                  {  
                                  return   0;  
                  }  
   
                  HMODULE   res   =   (LOADLIB(Real_LoadLibraryExW))   (  
                                                                                                  lpwLibFileName,  
                                                                                                  hFile,  
                                                                                                  dwFlags);  
   
                  return   res;  
  }  
   
  BOOL   ProcessAttach()  
  {  
                  DetourFunctionWithTrampoline((PBYTE)Real_LoadLibraryExW,  
                                                                    (PBYTE)Mine_LoadLibraryExW);  
                  return   TRUE;  
  }  
   
  BOOL   ProcessDetach()  
  {  
                  DetourRemove((PBYTE)Real_LoadLibraryExW,  
                                                                      (PBYTE)Mine_LoadLibraryExW);  
                  return   TRUE;  
  }  
   
  CAnti_HookApp::CAnti_HookApp()     //
在使用用户界面服务前调用
ProcessAttach  
  {  
                  user32   =   (ULONG)GetModuleHandle(“User32.dll”
;  
                  ProcessAttach();  
  }  
     
 WINDOWS
核心编程里的用IATAPIHOOK是不全面的。
 
  ::GetProcAddress(::GetModuleHandle(“kernel32.dll”),   “SetWindowsHookA”);  
 
就可以绕过。
 
  APIHOOK
最好的方法还是直接修改API入口点的代码。

同时HOOK   GetProcAddress   不就行了,但是要是对方使用搜索PE函数导出表的话就没用

防止IAT型的钩子我要是对PE文件的IAT加密,调用时解密调用,就可以了吧(极其复杂)  
 
防止jmp型的钩子我没想到好办法
 
 
防止调试我可以判断api入口处是否有int3中断代码就可以了吧(简单)

 

消息钩子的反拦截其实核心是利用API拦截,来取消钩子拦截.  
 
如果API拦截被激活成功教程也就是说消息钩子反拦截没有成功.

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。

发布者:全栈程序员-用户IM,转载请注明出处:https://javaforall.cn/159493.html原文链接:https://javaforall.cn

【正版授权,激活自己账号】: Jetbrains全家桶Ide使用,1年售后保障,每天仅需1毛

【官方授权 正版激活】: 官方授权 正版激活 支持Jetbrains家族下所有IDE 使用个人JB账号...

(0)


相关推荐

  • jedis操作redis_redis java使用

    jedis操作redis_redis java使用1、Jedis客户端https://redis.io/clients2、Jedis源码包与使用介绍https://github.com/xetorthio/jedis3、项目中使用通过maven引入Jedis的依赖包<!–https://mvnrepository.com/artifact/redis.clients/jedis–><depen…

    2022年10月10日
  • Git配置账号信息

    Git配置账号信息在前面我们已经简单的说了一下Git是什么,用来干嘛什么,他与SVN的区别,以及它的安装。今天我们接着讲,当第一次下载后我们如何配置自己Git账号信息(这里可以是Github也可以是国内的码云账号等等),下面我们开始主题:这里大概有两种方式一种是通过全局配置信息让所有的项目都使用这个账号,另一种是在指定项目下配置单独的信息默认在我们第一次下载后Git后我们最好是配置到自己…

  • composer windows安装,使用新手入门

    composer windows安装,使用新手入门

    2021年10月20日
  • 解决 无法解析名称 NaiveBayes.fit。/i get Undefined variable “NaiveBayes“ or class “NaiveBayes.fit“.

    解决 无法解析名称 NaiveBayes.fit。/i get Undefined variable “NaiveBayes“ or class “NaiveBayes.fit“.应用朴素贝叶斯分类器时候,发现报错无法解析名称NaiveBayes.fit这是因为你想用NaiveBayes。适用于MATLABR2018b。根据NaiveBayes的R2014b发布说明,fit被fitNaiveBayes取代:同时根据R2018a发布说明fitNaiveBayes被fitcnb取代。因此,使用fitcnb即可。将NaiveBayes.fit改为fitcnb就好啦!!!参考链接:链接:点击这里.打个小广告啊啊啊打个小广告,欢迎关注我的公众号“麦香E站”,分

  • stm32编程入门书籍_STM32开发板

    stm32编程入门书籍_STM32开发板1.STM32需要了解的基础知识STM32系列专为要求高性能、低成本、低功耗的嵌入式应用设计的ARMCortex®-M0,M0+,M3,M4和M7内核,按内核架构分为不同产品:主流产品(STM32F0、STM32F1、STM32F3)、超低功耗产品(STM32L0、STM32L1、STM32L4、STM32L4+)、高性能产品(STM32F2、STM32F4、STM32F7、STM32H7)。内核是ARM公司统一设计的于ARMv7架构的Cortex系列由ARM公司在2006年推出,Co

  • linux解压zip文件,

    linux解压zip文件,一,linux解压zip文件,命令:unzip如果没有该命令,可先安装,命令为:yum-yinstallunzip

发表回复

您的电子邮箱地址不会被公开。

关注全栈程序员社区公众号