阻止SPY++类似的程序捕捉软件窗口

我以前用Spy++能轻易捕捉360软件界面,除了一些应用DHTML制作的窗体.昨天我再用Spy++捕捉的时候捕捉不到了,甚至连最外围的对话框都捕捉不到,显然是做了类似拦截API的处理.下面我也模拟一下这种效果,让自己的程序窗口不能被捕捉.
Spy++之类的程序一般通过API函数WindowFromPoint和ChildWindowFromPoint来获取指定位置的窗口句柄。拦截一下WindowFromPoint函数,如果捕捉到的是自己程序的窗口,而且实施捕捉的进程不是自己程序的进程,那就直接返回NULL(这样自己的程序捕捉自己的窗口就不会受影响).拦截API我直接用微软的Detour库,使用起来方便.
由于是拦截所有进程地址空间的WindowFromPoint函数,我借助于全局WH_SHELL钩子,因此拦截操作放在一单独的DLL项目中.先封装一下Detour操作CInterceptSpyFun类:
////////////////////h文件///////////////////////////

class CInterceptSpyFun

{

private:

    //是否已经拦截

    BOOL  m_bIntercepted;



public:

    //保存要屏蔽WindowFromPoint函数的进程ID

    static  DWORD  m_dwValidProcessID;  



public:

    CInterceptSpyFun( );

    ~CInterceptSpyFun( );



    BOOL  IsIntercepted() 

    {

        return this->m_bIntercepted;

    }



    /*

    * 拦截操作

    * dwValidProcessID: 待屏蔽WindowFromPoint函数的进程ID

    * 返回拦截成功与否

    */

    BOOL  Intercept( DWORD dwValidProcessID  );



    /*

    * 取消拦截,还原成原先的操作

    */

    void    UnIntercept();

};

///////////////////////////cpp////////////////////////////

DWORD  CInterceptSpyFun::m_dwValidProcessID   =  0;



//让Real_WindowFromPoint指针指向实际上的WindowFromPoint函数地址

DETOUR_TRAMPOLINE( HWND WINAPI Real_WindowFromPoint( POINT pt ), WindowFromPoint );



/*

* 自定义WindowFromPoint函数的处理

*/

HWND WINAPI Mine_WindowFromPoint( POINT pt )

{

    //调用实际上的WindowFromPoint函数,取得窗口句柄

    HWND  hWnd =  Real_WindowFromPoint( pt );



    //获取窗口所属的进程ID

    DWORD  dwProcessID(0);

    ::GetWindowThreadProcessId( hWnd, &dwProcessID );



    if( ( CInterceptSpyFun::m_dwValidProcessID == dwProcessID ) && ( ::GetCurrentProcessId() != CInterceptSpyFun::m_dwValidProcessID ) )

    {    //如果窗口属于指定的进程并且是被不是指定进程的其他进程调用WindowFromPoint访问时,返回NULL

        return NULL;

    }



    return hWnd;

}







CInterceptSpyFun::CInterceptSpyFun( )

{

    m_bIntercepted  =  FALSE;

}



CInterceptSpyFun::~CInterceptSpyFun( )

{

}



BOOL  CInterceptSpyFun::Intercept( DWORD dwValidProcessID )

{

    CInterceptSpyFun::m_dwValidProcessID   =  dwValidProcessID;

    //Detour库拦截处理

    m_bIntercepted  =  DetourFunctionWithTrampoline( (PBYTE)Real_WindowFromPoint,  (PBYTE)Mine_WindowFromPoint );

    return m_bIntercepted;

}



void    CInterceptSpyFun::UnIntercept()

{

    if( m_bIntercepted )

    {

        //取消拦截

        DetourRemove( (PBYTE)Real_WindowFromPoint,(PBYTE)Mine_WindowFromPoint );

        m_bIntercepted  =  FALSE;

    }

}

dwValidProcessID(要拦截WindowFromPoint函数的进程ID)需要在LoadLibrary之后,安装钩子之前传递,并且需要保存到共享节中以达到在所有的进程中数据共享的目的. 
#pragma  data_seg(".unspy")
HHOOK   hHook   =   NULL;  
DWORD  dwValidProcessID  =  0;
#pragma  data_seg()
#pragma comment(linker,"/section:.unspy,rws")

 

 

HOOK句柄和dwValidProcessID  都保存到共享节”.unspy”中。

设置dwValidProcessID  的导出函数:
extern"C" __declspec( dllexport ) void SetValidProcessID( DWORD  dwProcessID )
{
 dwValidProcessID   =  dwProcessID;
}

声明拦截类的全局变量:
CInterceptSpyFun  interceptSpy;  
HMODULE   hDllModule   =  NULL;  //保存DLL模块句柄

SHELL钩子处理:

LRESULT CALLBACK CustomShellProc (int nCode, WPARAM wParam, LPARAM lParam)

{    

    if( !interceptSpy.IsIntercepted() )

    {  //拦截API

        interceptSpy.Intercept( dwValidProcessID );

    }



    return ::CallNextHookEx( hHook, nCode, wParam, lParam );

}





extern"C" __declspec( dllexport ) void InstallHook( )

{

    hHook = ::SetWindowsHookEx( WH_SHELL , CustomShellProc ,(HINSTANCE)hDllModule, 0 );

}



extern"C" __declspec( dllexport ) void UninstallHook()

{    

    if( hHook != NULL )

    {

        ::UnhookWindowsHookEx( hHook );

    }

    hHook = NULL;

}

取消拦截操作应在卸载DLL的时候:

BOOL APIENTRY DllMain( HMODULE hModule,  DWORD  ul_reason_for_call,   LPVOID lpReserved  )

{

 hDllModule   =   hModule;

 switch (ul_reason_for_call)

 {

 case DLL_PROCESS_ATTACH: 

  break;

 case DLL_THREAD_ATTACH:

  break;

 case DLL_THREAD_DETACH:

  break;

 case DLL_PROCESS_DETACH:

  {

      interceptSpy.UnIntercept();

  }

  break;

 }



    return TRUE;

}

至此,DLL部分已经完成.在需要屏蔽WindowFromPoint函数的程序中需加载该DLL,调用DLL的SetValidProcessID,将当前的进程ID传入,随后安装钩子:

m_hInstance  = ::LoadLibrary(_T("AvoidSpyLib.dll"));

  if ( m_hInstance == NULL )

  {

   ::MessageBox(NULL,_T("LoadLibrary Failed"),_T(""),MB_OK);

  }



  if( m_hInstance == NULL )

   return 0;

 

  typedef void (*PSetValidProcessID)( DWORD  dwProcessID );

  PSetValidProcessID pSetFunc;

  pSetFunc = (PSetValidProcessID)::GetProcAddress( m_hInstance , "SetValidProcessID");

  if ( pSetFunc != NULL )

  {

   (*pSetFunc)( ::GetCurrentProcessId() );

  }



  typedef void (*PInstallHook)( );

  PInstallHook pInstallFunc;

  pInstallFunc = (PInstallHook)::GetProcAddress( m_hInstance , "InstallHook");

  if ( pInstallFunc != NULL )

  {

    (*pInstallFunc)();

}

//卸载钩子

if( m_hInstance != NULL )

{

   typedef void (*PUninstallHook)( );

   PUninstallHook pFunc;

   pFunc = (PUninstallHook)::GetProcAddress( m_hInstance , "UninstallHook");

   if ( pFunc != NULL )

   {

    (*pFunc)();

   }



   ::FreeLibrary( m_hInstance );

}

全部完工,运行了一下,呵呵,和360软件的效果一样,Spy++再也捕捉不到界面的任何东西了.

你可能感兴趣的:(软件)