阻止Spy++之类的工具捕捉软件窗口
文章转自王牌软件
站长推荐:NSetup一键部署软件
一键式完成美化安装包制作,自动增量升级,数据统计,数字签名。应对各种复杂场景,脚本模块化拆分,常规复杂的脚本代码,图形化设置。无需专业的研发经验,轻松完成项目部署。(www.nsetup.cn)
只回答业务咨询
站长推荐:NSetup一键部署软件
一键式完成美化安装包制作,自动增量升级,数据统计,数字签名。应对各种复杂场景,脚本模块化拆分,常规复杂的脚本代码,图形化设置。无需专业的研发经验,轻松完成项目部署。(www.nsetup.cn)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 |
我以前用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++再也捕捉不到界面的任何东西了. |
学习日记,兼职软件设计,软件修改,毕业设计。
本文出自 学习日记,转载时请注明出处及相应链接。
本文永久链接: https://www.softwareace.cn/?p=401