none
API拦截在WindowXP功能正常, WIN7下没有效果 RRS feed

  • 问题

  • 自己实现的全局钩子,在DllMain中,修改每个进程的导入表,修改OpenProcess的地址指向我自定义的函数。xp下功能一切正常,任务管理器关闭不了。但是在win7这个程序就不行了,任务管理器可以关闭。

    实现细节:

    我只修改了exe模块的导入表,是不是win7下的任务管理器从通过别的模块里面函数间接调用OpenProcess呢?比较懒,只实现了exe模块的导入表的修改。

    求助几个工具: 可以查看exe文件的导入模块,和导入函数;
      可以查看已经运行的文件导入了什么模块,看看win7下的进程有没有链接我的lib。

    还有1个问题: 我在xp下在控制台中使用鼠标右键的debug, 调用VC2008实例,可以调试taskmgr.exe,我自己的dll的断点可以相应; 但在win7下,利用debug, 断点无法响应。(别人的机器,我自己的机器还没装win7)。求高手解释。

    2012年3月23日 2:44

答案

  • 真正的原因已经找到,在msdn线上版的SetWindowsHookEx的remark中有叙述:

    SetWindowsHookEx can be used to inject a DLL into another process. A 32-bit DLL cannot be injected into a 64-bit process, and a 64-bit DLL cannot be injected into a 32-bit process. If an application requires the use of hooks in other processes, it is required that a 32-bit application call SetWindowsHookEx to inject a 32-bit DLL into 32-bit processes, and a 64-bit application call SetWindowsHookEx to inject a 64-bit DLL into 64-bit processes. The 32-bit and 64-bit DLLs must have different names.

    主要是运行环境是windows 7 x64,  我的程序是x86, 重新编译成x64的程序,功能就正常了。

    2012年3月26日 13:12

全部回复

  • BOOL WINAPI DllMain( HANDLE hDllHandle, DWORD dwReason, LPVOID lpreserved )
    {
        switch(dwReason)
        {
        case DLL_PROCESS_ATTACH:
           
            ReplaceIATInOneMode("Kernel32.dll", OpenProcess, MyOpenProcess, GetModuleHandle(NULL));
            break;
        case DLL_PROCESS_DETACH:
            ReplaceIATInOneMode("Kernel32.dll", MyOpenProcess, g_pOldFn, GetModuleHandle(NULL));
           
            
            break;
        }
        return TRUE;
    }
    void WINAPI ReplaceIATInOneMode(char* sTargetModName, void* pTargetFn, void* pMyFn, HMODULE hTargetMod)
    {
        ULONG ul;
        IMAGE_IMPORT_DESCRIPTOR* pImprotDes = (IMAGE_IMPORT_DESCRIPTOR*)::ImageDirectoryEntryToData(hTargetMod, TRUE, IMAGE_DIRECTORY_ENTRY_IMPORT, &ul);
        if(NULL == pImprotDes)
            return;
        const char* sModName = NULL;
        for( ; pImprotDes->Name; ++pImprotDes)
        {
            sModName = (const char*) hTargetMod + pImprotDes->Name;
            if( 0 ==::lstrcmpiA(sModName, sTargetModName) )
            {
                break;
            }
        }
        if(0 == pImprotDes->Name)
            return;
        IMAGE_THUNK_DATA* pThunkData = (IMAGE_THUNK_DATA*) ( (char*) hTargetMod + pImprotDes->FirstThunk );
        DWORD* pFn = NULL;
        for( ; pThunkData->u1.Function; ++pThunkData)
        {
            pFn = (DWORD*)&pThunkData->u1.Function;
            if(*pFn == (DWORD)pTargetFn)
            {
                //*ppDwOldFnAddress = pFn;
                extern POPPROCE g_pOldFn;
                g_pOldFn = (POPPROCE)pTargetFn;
            /*extern PFN g_pFn;
            g_pFn = (PFN)pTargetFn;*/
                
                WriteNewProc( pFn, (DWORD)pMyFn);
                break;
            }
        }
    }
    void WINAPI WriteNewProc(void* oldProc, DWORD newProcAddress)
    {
        BOOL bResult = FALSE;
        DWORD dwOldVal;
        DWORD dwTmp;
        bResult = ::VirtualProtect(oldProc, 4, PAGE_WRITECOPY, &dwOldVal);
        bResult = ::WriteProcessMemory( ::GetCurrentProcess(), oldProc, &newProcAddress, 4, NULL);
        bResult = ::VirtualProtect(oldProc, 4, dwOldVal, &dwTmp);
    }
    #pragma data_seg("SharedID")
    DWORD g_dwProcessID = 9998; //启动后修改为收保护的进程的PID
    #pragma data_seg()
    HANDLE WINAPI MyOpenProcess(DWORD dwDesiredAcess, BOOL bInIerientHandle, DWORD dwProcessID)
    {
        if(dwProcessID != g_dwProcessID)
        {
            HANDLE hHandle = NULL; 
            hHandle = ::OpenProcess(dwDesiredAcess, bInIerientHandle, dwProcessID);
            return hHandle;
        }
     
        return NULL;
    }

    2012年3月23日 2:46
  • BOOL WINAPI SetApiHook(BOOL bInstall, DWORD dwThreadID)
    {
     
        if(bInstall)
        {
            if( NULL != g_hHook)
                return FALSE;
            g_hHook = ::SetWindowsHookEx( WH_GETMESSAGE, GetMsgProc, ModuleFromAddress(&SetApiHook), dwThreadID);
            if( NULL == g_hHook)
                return FALSE;
            else
                return TRUE;
        }
        else
        {
            if( NULL == g_hHook)
                return FALSE;
            else
            {
                BOOL bResult = ::UnhookWindowsHookEx(g_hHook);
                
                if(TRUE == bResult)
                {
                    g_hHook = NULL;
                    return TRUE;
                }
                else
                    return FALSE;
            }
        }
    }

    2012年3月23日 2:46
  • #pragma data_seg("SharedID")
    DWORD g_dwProcessID = 9998;
    #pragma data_seg()
    HHOOK g_hHook = NULL;
    HANDLE g_hProcess = NULL;
    //PFN g_pFn = NULL;
    POPPROCE g_pOldFn = NULL;
    void WINAPI SetSharedValue(DWORD dwProcessID)
    {
        g_dwProcessID = dwProcessID;
    }
    HANDLE WINAPI MyOpenProcess(DWORD dwDesiredAcess, BOOL bInIerientHandle, DWORD dwProcessID)
    {
        if(dwProcessID != g_dwProcessID)
        {
            HANDLE hHandle = NULL; 
            hHandle = ::OpenProcess(dwDesiredAcess, bInIerientHandle, dwProcessID);
            return hHandle;
        }
        /*char namebuffer[100] = "";
        ::GetModuleFileName(NULL, namebuffer, 100);
        ::MessageBox(NULL, "试图获得被保护进程的HANDLE", namebuffer, MB_OK);*/
        return NULL;
    }

    2012年3月23日 2:48
  • 基本上主要的代码就这些了。在xp下运行是正常的,但是win7没有效果。 是不是win7下全局钩子SetWindowsHookEx( 。。。, , 0);  不会强迫某些进程加载我的d

    ll,  如果是的话,应该怎么解决这个问题呢。

    2012年3月23日 2:49
  • xp下功能是正常的,利用vc2008的attach to process 调用Taskermgr。exe 我打的断点可以相应。 win7下没效果,调式断点也没反应。
    2012年3月23日 2:58
  • .

                低权限的程序在win7下设置全局hook是默认不允许的, 所以SetWindowsHookEx不会成功.

                解决方法:

                [1] 有SetWindowsHookEx动作的exe需要右击使用"管理员权限运行"

                [2] 要调试此类程序也需要使用管理员权限启动visual studio, 否则没法调试.

                祝你好运.

    • 已建议为答案 Helen Zhao 2012年3月26日 6:56
    • 取消建议作为答案 lygf666 2012年3月26日 13:12
    2012年3月23日 7:04
  • 真正的原因已经找到,在msdn线上版的SetWindowsHookEx的remark中有叙述:

    SetWindowsHookEx can be used to inject a DLL into another process. A 32-bit DLL cannot be injected into a 64-bit process, and a 64-bit DLL cannot be injected into a 32-bit process. If an application requires the use of hooks in other processes, it is required that a 32-bit application call SetWindowsHookEx to inject a 32-bit DLL into 32-bit processes, and a 64-bit application call SetWindowsHookEx to inject a 64-bit DLL into 64-bit processes. The 32-bit and 64-bit DLLs must have different names.

    主要是运行环境是windows 7 x64,  我的程序是x86, 重新编译成x64的程序,功能就正常了。

    2012年3月26日 13:12