日期:2014-05-17  浏览次数:20784 次

Windows 反消息钩子(1)

       消息钩子在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版本中好像没了。好了,下面介绍其实现。