全局钩子的卸载问题

mcawxd 2010-05-31 09:30:08
我在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都会卸载掉(不是用远程线程去别的进程中卸载)。
...全文
953 17 打赏 收藏 转发到动态 举报
写回复
用AI写文章
17 条回复
切换为时间正序
请发表友善的回复…
发表回复
mcawxd 2010-06-07
  • 打赏
  • 举报
回复
谢谢大家的热心帮助
cnzdgs 2010-06-04
  • 打赏
  • 举报
回复
从代码上没有看出问题,你调试一下,看UnhookWindowsHookEx是否成功。另外在卸载之后,用“Attach to Process”来调试任意一个未卸载DLL的进程,在Hook函数上设置断点,看看是哪个Hook没有卸掉。
mngzilin 2010-06-03
  • 打赏
  • 举报
回复
mark
mcawxd 2010-06-03
  • 打赏
  • 举报
回复
[Quote=引用 12 楼 justin_shi 的回复:]
调用SetWindowsHookEx的进程退出后,其它被hook的进程中的dll会自动卸载掉。
[/Quote]
可实际是它没有自动被卸掉啊。难道不能在回调函数中再下钩子?
mcawxd 2010-06-03
  • 打赏
  • 举报
回复
[Quote=引用 11 楼 cnzdgs 的回复:]
g_ShellHook=SetWindowsHookEx(WH_SHELL,(HOOKPROC)ShellProc,hInst,GetWindowThreadProcessId(pCwp->hwnd,0));
把hInst改成NULL试试。
[/Quote]
点停止后TxPlatform.exe中还是有一个MyDll。
justin_shi 2010-06-03
  • 打赏
  • 举报
回复
调用SetWindowsHookEx的进程退出后,其它被hook的进程中的dll会自动卸载掉。
cnzdgs 2010-06-03
  • 打赏
  • 举报
回复
g_ShellHook=SetWindowsHookEx(WH_SHELL,(HOOKPROC)ShellProc,hInst,GetWindowThreadProcessId(pCwp->hwnd,0));
把hInst改成NULL试试。
普通网民 2010-06-02
  • 打赏
  • 举报
回复
mcawxd 2010-06-02
  • 打赏
  • 举报
回复
MyDll的代码如下:


#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文件。请问我代码的问题出在哪里?谢谢。
cnzdgs 2010-06-02
  • 打赏
  • 举报
回复
定义共享变量时要初始化才有效。
如果还有问题,把完整代码贴出来。
mcawxd 2010-06-01
  • 打赏
  • 举报
回复
[Quote=引用 6 楼 soswaidao 的回复:]
远程卸载
[/Quote]
远程卸载会被瑞星提示有害操作,然后就被阻止了。
soswaidao 2010-06-01
  • 打赏
  • 举报
回复
远程卸载
fishion 2010-06-01
  • 打赏
  • 举报
回复
chASSERT(g_ShellHook == NULL); // Illegal to install twice in a row

g_ShellHook = SetWindowsHookEx(xxx);
mcawxd 2010-06-01
  • 打赏
  • 举报
回复
[Quote=引用 3 楼 cnzdgs 的回复:]
第2个SetWindowsHookEx前加个判断,不要重复执行。
[/Quote]
我加了一个
if(!bHook)
{
if(lstrcmpi(szWindowName,"计算器")==0)
g_ShellHook=SetWindowsHookEx(WH_SHELL,(HOOKPROC)ShellProc,hInst,GetWindowThreadProcessId(pCwp->hwnd,0));
bHook=TRUE;
}
还是不行,在别的进程中的DLL还是卸载不掉。

cnzdgs 2010-06-01
  • 打赏
  • 举报
回复
第2个SetWindowsHookEx前加个判断,不要重复执行。
mcawxd 2010-05-31
  • 打赏
  • 举报
回复
[Quote=引用 1 楼 wangk 的回复:]
HHOOK g_ShellHook;

要用共享节进行共享。
[/Quote]
加到共享节也不行,执行UnAPIHook后,其他进程中还有DLL
wangk 2010-05-31
  • 打赏
  • 举报
回复
HHOOK g_ShellHook;

要用共享节进行共享。

15,471

社区成员

发帖
与我相关
我的任务
社区描述
VC/MFC 进程/线程/DLL
社区管理员
  • 进程/线程/DLL社区
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧