我在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都会卸载掉(不是用远程线程去别的进程中卸载)。

解决方案 »

  1.   

    HHOOK g_ShellHook;要用共享节进行共享。
      

  2.   

    加到共享节也不行,执行UnAPIHook后,其他进程中还有DLL
      

  3.   

    第2个SetWindowsHookEx前加个判断,不要重复执行。
      

  4.   

    我加了一个
    if(!bHook)
    {
     if(lstrcmpi(szWindowName,"计算器")==0)
         g_ShellHook=SetWindowsHookEx(WH_SHELL,(HOOKPROC)ShellProc,hInst,GetWindowThreadProcessId(pCwp->hwnd,0));
    bHook=TRUE;
    }
    还是不行,在别的进程中的DLL还是卸载不掉。
      

  5.   

    chASSERT(g_ShellHook == NULL); // Illegal to install twice in a rowg_ShellHook = SetWindowsHookEx(xxx);
      

  6.   

    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文件。请问我代码的问题出在哪里?谢谢。
      

  7.   

    g_ShellHook=SetWindowsHookEx(WH_SHELL,(HOOKPROC)ShellProc,hInst,GetWindowThreadProcessId(pCwp->hwnd,0));
    把hInst改成NULL试试。
      

  8.   

    调用SetWindowsHookEx的进程退出后,其它被hook的进程中的dll会自动卸载掉。
      

  9.   

    点停止后TxPlatform.exe中还是有一个MyDll。
      

  10.   

    从代码上没有看出问题,你调试一下,看UnhookWindowsHookEx是否成功。另外在卸载之后,用“Attach to Process”来调试任意一个未卸载DLL的进程,在Hook函数上设置断点,看看是哪个Hook没有卸掉。