我在DLL中下了一个WH_CALLWNDPROC全局钩子来监视某个程序的启动,在exe中调用SetAPIHook
HHOOK g_ShellHook;
HHOOK g_HTarget;void SetAPIHook()
{
g_HTarget=SetWindowsHookEx(WH_CALLWNDPROC,(HOOKPROC)CallProc,hInst,0);
}
//在回调函数中判断窗口标题是否是监视的程序,如果是的话下另一个钩子。
LRESULT CALLBACK CallProc(
int nCode, // hook code
WPARAM wParam, // current-process flag
LPARAM lParam // message data
)
{
CWPSTRUCT *pCwp = NULL;
TCHAR szWindowName[MAX_PATH];
pCwp = (CWPSTRUCT *)lParam;
GetWindowText(pCwp->hwnd,szWindowName,MAX_PATH); //如果窗口标题等于监视的窗口下一个进程内局部钩子
if(lstrcmpi(szWindowName,"计算器")==0)
g_ShellHook=SetWindowsHookEx(WH_SHELL,(HOOKPROC)ShellProc,hInst,GetWindowThreadProcessId(pCwp->hwnd,0));
}
//程序退出的时候调用UnAPIHook
void UnAPIHook()
{
if(::UnhookWindowsHookEx(g_HTarget))
{
g_HTarget=NULL;
}
if(::UnhookWindowsHookEx(g_ShellHook))
{
g_ShellHook=NULL;
}}我想问的是当我调用SetAPIHook下全局钩子的时候这个Dll会映射到其它进程中,这个用冰刃查看过,里面确实有这个dll。但我调用UnAPIHook的时候,我的理解是每个进程应该都把这个Dll卸载掉,但是我用冰刃查看的时候发现里面还有这个DLL,而我把下g_ShellHook钩子代码去掉,DLL就能卸载掉,请问是什么原因。是我的写法有问题吗?我应该怎样写才能在我程序退出的时候,所有进程中的DLL都会卸载掉(不是用远程线程去别的进程中卸载)。
HHOOK g_ShellHook;
HHOOK g_HTarget;void SetAPIHook()
{
g_HTarget=SetWindowsHookEx(WH_CALLWNDPROC,(HOOKPROC)CallProc,hInst,0);
}
//在回调函数中判断窗口标题是否是监视的程序,如果是的话下另一个钩子。
LRESULT CALLBACK CallProc(
int nCode, // hook code
WPARAM wParam, // current-process flag
LPARAM lParam // message data
)
{
CWPSTRUCT *pCwp = NULL;
TCHAR szWindowName[MAX_PATH];
pCwp = (CWPSTRUCT *)lParam;
GetWindowText(pCwp->hwnd,szWindowName,MAX_PATH); //如果窗口标题等于监视的窗口下一个进程内局部钩子
if(lstrcmpi(szWindowName,"计算器")==0)
g_ShellHook=SetWindowsHookEx(WH_SHELL,(HOOKPROC)ShellProc,hInst,GetWindowThreadProcessId(pCwp->hwnd,0));
}
//程序退出的时候调用UnAPIHook
void UnAPIHook()
{
if(::UnhookWindowsHookEx(g_HTarget))
{
g_HTarget=NULL;
}
if(::UnhookWindowsHookEx(g_ShellHook))
{
g_ShellHook=NULL;
}}我想问的是当我调用SetAPIHook下全局钩子的时候这个Dll会映射到其它进程中,这个用冰刃查看过,里面确实有这个dll。但我调用UnAPIHook的时候,我的理解是每个进程应该都把这个Dll卸载掉,但是我用冰刃查看的时候发现里面还有这个DLL,而我把下g_ShellHook钩子代码去掉,DLL就能卸载掉,请问是什么原因。是我的写法有问题吗?我应该怎样写才能在我程序退出的时候,所有进程中的DLL都会卸载掉(不是用远程线程去别的进程中卸载)。
if(!bHook)
{
if(lstrcmpi(szWindowName,"计算器")==0)
g_ShellHook=SetWindowsHookEx(WH_SHELL,(HOOKPROC)ShellProc,hInst,GetWindowThreadProcessId(pCwp->hwnd,0));
bHook=TRUE;
}
还是不行,在别的进程中的DLL还是卸载不掉。
#include <windows.h>#include "detours.h"
#include "Hook.h"#pragma data_seg("MySec")
HWND g_hMain=NULL;
HHOOK g_ShellHook=NULL;
HHOOK g_HTarget=NULL;
#pragma data_seg()
#pragma comment(linker,"/section:MySec,RWS")#pragma comment(lib,"detours.lib")
BOOL isHook=FALSE;
HINSTANCE hInst=NULL;
HWND g_hWnd=NULL;
DETOUR_TRAMPOLINE(BOOL WINAPI Real_ExtTextOut(
HDC hdc, // handle to DC
int X, // x-coordinate of reference point
int Y, // y-coordinate of reference point
UINT fuOptions, // text-output options
CONST RECT* lprc, // optional dimensions
LPCTSTR lpString, // string
UINT cbCount, // number of characters in string
CONST INT* lpDx // array of spacing values
),ExtTextOut);
LRESULT CALLBACK ShellProc(
int nCode, // hook code
WPARAM wParam, // current-process flag
LPARAM lParam // message data
)
{
HWND hWnd=HWND(wParam);
TCHAR szWindowText[MAX_PATH]={0};
GetWindowText(hWnd,szWindowText,MAX_PATH); //新建一个窗口时
if(nCode==HSHELL_WINDOWCREATED)
{ }
//销毁一个窗口时
if(nCode==HSHELL_WINDOWDESTROYED)
{ } return CallNextHookEx(g_ShellHook,nCode,wParam,lParam);
}
LRESULT CALLBACK CallProc(
int nCode, // hook code
WPARAM wParam, // current-process flag
LPARAM lParam // message data
)
{ CWPSTRUCT *pCwp = NULL;
TCHAR szClassName[MAX_PATH];
TCHAR szWindowName[MAX_PATH];
pCwp = (CWPSTRUCT *)lParam;
if (WM_SHOWWINDOW == pCwp->message)
{
GetClassName(pCwp->hwnd,szClassName,MAX_PATH);
GetWindowText(pCwp->hwnd,szWindowName,MAX_PATH);
if(lstrcmpi(szWindowName,"计算器")==0) //或者其它程序
{
if(!isHook)
{
g_ShellHook=SetWindowsHookEx(WH_SHELL,(HOOKPROC)ShellProc,hInst,GetWindowThreadProcessId(pCwp->hwnd,0));
isHook=TRUE;
}
}
} return CallNextHookEx(g_HTarget,nCode,wParam,lParam);
}BOOL SetAPIHook(HWND hWindow)
{
g_hMain=hWindow;
if(g_HTarget == NULL)
{
g_HTarget=SetWindowsHookEx(WH_CALLWNDPROC,(HOOKPROC)CallProc,hInst,0);
}
if(g_HTarget!=NULL)
{
return true;
}
else
{
return false;
}
}void UnAPIHook()
{ if(::UnhookWindowsHookEx(g_ShellHook))
{
g_ShellHook=NULL;
}
if(::UnhookWindowsHookEx(g_HTarget))
{
g_HTarget=NULL;
}
}
BOOL WINAPI DllMain(
HINSTANCE hinstDLL, // handle to the DLL module
DWORD fdwReason, // reason for calling function
LPVOID lpvReserved // reserved
)
{
hInst=hinstDLL;
switch(fdwReason)
{
case DLL_PROCESS_ATTACH:
Intercept();
break;
case DLL_THREAD_ATTACH:
break;
case DLL_THREAD_DETACH:
break;
case DLL_PROCESS_DETACH:
UnIntercept();
break;
}
return true;
}
BOOL WINAPI Replace_ExtTextOut(
HDC hdc, // handle to DC
int X, // x-coordinate of reference point
int Y, // y-coordinate of reference point
UINT fuOptions, // text-output options
CONST RECT* lprc, // optional dimensions
LPCTSTR lpString, // string
UINT cbCount, // number of characters in string
CONST INT* lpDx // array of spacing values
)
{
return Real_ExtTextOut(hdc,X,Y,fuOptions,lprc,lpString,cbCount,lpDx);
}void Intercept()
{
DetourFunctionWithTrampoline((PBYTE)Real_ExtTextOut, (PBYTE)Replace_ExtTextOut);
}void UnIntercept()
{
DetourRemove( (PBYTE)Real_ExtTextOut,(PBYTE)Replace_ExtTextOut);
}EXE的代码//开始按钮
void CMainDlg::OnButton1()
{
//InjectDLL();
// TODO: Add your control notification handler code here
m_Library=LoadLibrary("MyDll.dll");
if(m_Library==NULL)
MessageBox("加载失败");
if(m_Library!=NULL)
{
typedef BOOL (*pProc)(HWND);
pProc SetAPIHook=(pProc)GetProcAddress(m_Library,"SetAPIHook");
if(SetAPIHook!=NULL)
{
if(!SetAPIHook(m_hWnd))
{
MessageBox("安装钩子失败");
return;
}
}
else
{
MessageBox("执行SetAPIHook失败");
return;
}
}
}
//停止按钮
void CMainDlg::OnButton2()
{ if(m_Library!=NULL)
{
typedef void (*pProc)();
pProc UnAPIHook=(pProc)GetProcAddress(m_Library,"UnAPIHook");
if(UnAPIHook!=NULL)
{
UnAPIHook();
}
else
{
MessageBox("执行UnAPIHook失败");
return;
}
FreeLibrary(m_Library);
}}以上就是全部代码
我的本意是想HOOK 计算器(其它程序的也可以)中的ExtTextOut函数
点开始按钮的时候下g_ShellHook钩子监视计算器启动,然后下g_HTarget钩子HOOK ExtTextOut。因为g_ShellHook是全局钩子,所以会把MyDll映射到其他进程中,我觉得点停止的时候会把其他进程中的MyDll都卸载掉,但实际上不是这样,总会有几个进程中还存在MyDll,比如记事本中就经常会存在MyDll。所以也不能删除MyDll文件。请问我代码的问题出在哪里?谢谢。
把hInst改成NULL试试。