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

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

<!--<br /><br />Code highlighting produced by Actipro CodeHighlighter (freeware)<br />http://www.CodeHighlighter.com/<br /><br />--> class CInterceptSpyFun
{
private :
// 是否已经拦截
BOOLm_bIntercepted;

public :
// 保存要屏蔽WindowFromPoint函数的进程ID
static DWORDm_dwValidProcessID;

public :
CInterceptSpyFun();
~ CInterceptSpyFun();

BOOLIsIntercepted()
{
return this -> m_bIntercepted;
}

/*
*拦截操作
*dwValidProcessID:待屏蔽WindowFromPoint函数的进程ID
*返回拦截成功与否
*/
BOOLIntercept(DWORDdwValidProcessID);

/*
*取消拦截,还原成原先的操作
*/
void UnIntercept();
};

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

<!--<br /><br />Code highlighting produced by Actipro CodeHighlighter (freeware)<br />http://www.CodeHighlighter.com/<br /><br />--> DWORDCInterceptSpyFun::m_dwValidProcessID = 0 ;

// 让Real_WindowFromPoint指针指向实际上的WindowFromPoint函数地址
DETOUR_TRAMPOLINE(HWNDWINAPIReal_WindowFromPoint(POINTpt),WindowFromPoint);

/*
*自定义WindowFromPoint函数的处理
*/
HWNDWINAPIMine_WindowFromPoint(POINTpt)
{
// 调用实际上的WindowFromPoint函数,取得窗口句柄
HWNDhWnd = Real_WindowFromPoint(pt);

// 获取窗口所属的进程ID
DWORDdwProcessID( 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()
{
}

BOOLCInterceptSpyFun::Intercept(DWORDdwValidProcessID)
{
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钩子处理:

<!--<br /><br />Code highlighting produced by Actipro CodeHighlighter (freeware)<br />http://www.CodeHighlighter.com/<br /><br />--> LRESULTCALLBACKCustomShellProc( int nCode,WPARAMwParam,LPARAMlParam)
{
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++再也捕捉不到界面的任何东西了.

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