Hook功能已经实现,现在有个问题,当我修改玩系统的loadlibraryexw的地址的为我要改的地址的时候,一打开ie就崩了,补充,我hook的原理就是修改loadlibraryexw的地址 然后替换,如果不需要的时候再改回来
调用IE的时候DebugView会打出
[3284] ERROR: Not all DirectUser Contexts were destroyed before EndProcess().
的错误
请问怎么解决情况啊

解决方案 »

  1.   

     我同时Hook的loadlibraryexw和createprocess 当分别运行的时候都没事 一起运行调用ie explore就崩了。。
      

  2.   

    BOOL HookStatus(BOOL Status){
    BOOL ret=FALSE;
    if (Status) {
    ret = WriteProcessMemory(hProcess, (void *)FunAddr, NewCode, 5, 0);
    if (ret) return TRUE;}
    else {
    ret = WriteProcessMemory(hProcess, (void *)FunAddr, OldCode, 5, 0);
    if (ret) return TRUE;}
    return FALSE;
    }BOOL loadHookStatus(BOOL Status){
    BOOL ret=FALSE;
    if (Status) {
    ret = WriteProcessMemory(loadhProcess, (void *)loadFunAddr, loadNewCode, 5, 0);
    if (ret) return TRUE;}
    else {
    ret = WriteProcessMemory(loadhProcess, (void *)loadFunAddr, loadOldCode, 5, 0);
    if (ret) return TRUE;}
    return FALSE;
    }//Char转WChar
    WCHAR* ToWChar(char * str) 

    //在GDI+中,有关字符的参数类型全部都是WCHAR类型的 
    //该函数是将传统字符串进行转换  static WCHAR buffer[1024]; 
    wcsset(buffer,0); 
    MultiByteToWideChar(CP_ACP,0,str,strlen(str),buffer,1024); 
    return buffer; 
    }//CreateProcess的替代函数
    BOOL WINAPI CreateProcessWCallBack(LPCWSTR lpApplicationName,
      LPWSTR lpCommandLine,
      LPSECURITY_ATTRIBUTES lpProcessAttributes,
      LPSECURITY_ATTRIBUTES lpThreadAttributes,
      BOOL bInheritHandles,
      DWORD dwCreationFlags,
      LPVOID lpEnvironment,
      LPCWSTR lpCurrentDirectory,
      LPSTARTUPINFOW lpStartupInfo,
      LPPROCESS_INFORMATION lpProcessInformation){
     
    return CreateProcessW(lpApplicationName,lpCommandLine,lpProcessAttributes,lpThreadAttributes,bInheritHandles,
    dwCreationFlags,lpEnvironment,lpCurrentDirectory,lpStartupInfo,lpProcessInformation);
    }VOID OutputDebugStringExW(const wchar_t* szFormat, ...)  
    {  
    WCHAR Buffer[2048] = {0};   va_list argList;  
    va_start(argList, szFormat);  
    vswprintf(Buffer, sizeof(Buffer), szFormat, argList);  
    va_end(argList);   OutputDebugStringW(Buffer);  
    }  HMODULE WINAPI LoadLibraryExWCallBack(LPCWSTR lpLibFileName,HANDLE hFile,DWORD dwFlags){
    OutputDebugStringW(ToWChar ("1"));
    loadHookStatus(FALSE);
    loadBool = FALSE;
    OutputDebugStringW(ToWChar ("2"));
    OutputDebugStringW(lpLibFileName);
    return LoadLibraryExW(lpLibFileName,hFile,dwFlags);
    }//修改原始CreateProcess为我们的替换函数
    BOOL HookCreateProcess(){
    ULONG JmpAddr=0;
    char msg[255]={0}; FunAddr = (ULONG)GetProcAddress(LoadLibrary("Kernel32.dll"), "CreateProcessW");//得到CreateProcessW函数的地址
    memcpy(OldCode, (void *)FunAddr, 5);//保存函数地址的5字节
    //修改CreateProcess地址
    NewCode[0] = 0xe9;
    JmpAddr = (ULONG)CreateProcessWCallBack - FunAddr - 5;
    memcpy(&NewCode[1], &JmpAddr, 4);
    //更改CreateProcess地址
    HookStatus(TRUE);
    return TRUE;
    }BOOL HookLoadLibraryExW(){
    ULONG JmpAddr=0;
    char msg[255]={0}; loadFunAddr = (ULONG)GetProcAddress(LoadLibrary("Kernel32.dll"), "LoadLibraryExW");//得到CreateProcessW函数的地址
    memcpy(loadOldCode, (void *)loadFunAddr, 5);//保存函数地址的5字节

    loadNewCode[0] = 0xe9;
    JmpAddr = (ULONG)LoadLibraryExWCallBack- loadFunAddr - 5;
    memcpy(&loadNewCode[1], &JmpAddr, 4);

    loadHookStatus(TRUE);
    return TRUE;
    }BOOL APIENTRY DllMain( HANDLE hModule, 
                           DWORD  ul_reason_for_call, 
                           LPVOID lpReserved)
    {
    hMod = (HINSTANCE)hModule;
    if (ul_reason_for_call==DLL_PROCESS_ATTACH){//dll被映射时
    //CreateProcess
    hProcess = OpenProcess(PROCESS_ALL_ACCESS, 0, GetCurrentProcessId());
    hExe = FindWindow(NULL, "Hook CreateProcessW");
    HookCreateProcess();
    CreateBool = FALSE;
    loadhMod = (HINSTANCE)hModule;
    //LoadLibraryExW
    loadhProcess = OpenProcess(PROCESS_ALL_ACCESS, 0, GetCurrentProcessId());
    loadhExe = FindWindow(NULL, "Hook LoadLibraryExW");
    HookLoadLibraryExW();
    loadBool = FALSE;
    }
    if (ul_reason_for_call==DLL_PROCESS_DETACH) //dll被解除映射时
    {
    HookStatus(FALSE);
    loadHookStatus(FALSE);
    }
        return TRUE;
    }
      

  3.   

     DWORD dwOldProtect;
     loadFunAddr = (ULONG)GetProcAddress(LoadLibrary("Kernel32.dll"), "LoadLibraryExW");//得到CreateProcessW函数的地址
    VirtualProtect(loadFunAddr,5, PAGE_EXECUTE_READWRITE, &dwOldProtect); //试下更改页面保护属性
        memcpy(loadOldCode, (void *)loadFunAddr, 5);//保存函数地址的5字节
      

  4.   

    就该一个么 Createprocess不改吗
      

  5.   

    首先,你这种HOOK方法不是很好.
    每次调用原函数都要重新恢复前面5个字节,
    很烦琐不说,多线程下也不安全.
    而且有些函数头前面5个字节并不一定是完全的汇编指令,
    恰好 LoadLibraryExW是这样,
    你不管三七二十一,直接就把前面5个字节改成JMP跳转指令,
    连后面的指令也破坏了.
    原始的LoadLibraryExW函数是这样的.kernel32!LoadLibraryExW:
    7c801af5 6a34            push    34h
    7c801af7 68f8e0807c      push    offset kernel32!DuplicateHandle+0x25a (7c80e0f8)
    7c801afc e8d5090000      call    kernel32!ReleaseMutex+0x1f (7c8024d6)
    7c801b01 33ff            xor     edi,edi
    7c801b03 897dd8          mov     dword ptr [ebp-28h],edi
    7c801b06 897dd4          mov     dword ptr [ebp-2Ch],edi
    7c801b09 897de0          mov     dword ptr [ebp-20h],edi
    7c801b0c 897de4          mov     dword ptr [ebp-1Ch],edi强行更改前面5字节后,就变这样的,
    原本第3条是CALL指令,现在变成add了.
    第3条指令也一起被破坏了.kernel32!LoadLibraryExW:
    7c801af5 e9e6f6c083      jmp     004111e0
    7c801afa 807ce8d509      cmp     byte ptr [eax+ebp*8-2Bh],9
    7c801aff 0000            add     byte ptr [eax],al
    7c801b01 33ff            xor     edi,edi
    7c801b03 897dd8          mov     dword ptr [ebp-28h],edi
    7c801b06 897dd4          mov     dword ptr [ebp-2Ch],edi
    7c801b09 897de0          mov     dword ptr [ebp-20h],edi
    7c801b0c 897de4          mov     dword ptr [ebp-1Ch],edi比较好的方法是这样LPVOID pfnLoadLibraryExW = 0;
    typedef HMODULE (WINAPI *LOADLIBRARYEX)(LPCWSTR lpLibFileName,HANDLE hFile,DWORD dwFlags);HMODULE WINAPI LoadLibraryExWCallBack(LPCWSTR lpLibFileName,HANDLE hFile,DWORD dwFlags)
    {
    if (_tcscmp(lpLibFileName, TEXT("123.dll")) == 0)
    {
    return 0;
    } return ((LOADLIBRARYEX)pfnLoadLibraryExW)(lpLibFileName,hFile,dwFlags);
    }
    BOOL HookLoadLibraryExW()
    {
    /*HOOK前面7个字节,不是5个字节,
    因为前面push    34h只有2个字节,不能容纳一条JMP指令,
    */
    CONST int CODELEN = 7; 
    BYTE OldCode[CODELEN];
    DWORD dwOldProtect; pfnLoadLibraryExW = GetProcAddress(GetModuleHandle(TEXT("Kernel32.dll")), "LoadLibraryExW");
    //更改页面保护属性
    VirtualProtect(pfnLoadLibraryExW, CODELEN, PAGE_EXECUTE_READWRITE, &dwOldProtect); 
    //保存函数地址的7字节
    memcpy(OldCode, pfnLoadLibraryExW, CODELEN); 
    //先用NOP指令填充
    memset(pfnLoadLibraryExW, 0x90, CODELEN); 
    //开始写入跳转指令
    *(LPBYTE)pfnLoadLibraryExW = 0xe9;
    *(LPINT)((int)pfnLoadLibraryExW+1) = (int)LoadLibraryExWCallBack - (int)pfnLoadLibraryExW - 5;
    //刷新进程缓冲,恢复原始页面保护属性
    FlushInstructionCache((HANDLE)-1, pfnLoadLibraryExW, CODELEN);
    VirtualProtect(pfnLoadLibraryExW, CODELEN, dwOldProtect, NULL);
    //申请一段大小为之前破坏掉的代码大小+JMP指令大小的内存
    pfnLoadLibraryExW = VirtualAlloc(NULL, CODELEN+5, MEM_COMMIT, PAGE_EXECUTE_READWRITE);
    //再把之前备份的指令复制到刚刚申请的内存中
    memcpy(pfnLoadLibraryExW, OldCode, sizeof(OldCode));
    //然后再构建一段跳转指令跳回到LoadLibraryExW函数.
    *(LPBYTE)((int)pfnLoadLibraryExW+CODELEN) = 0xe9;
    *(LPINT)((int)pfnLoadLibraryExW+CODELEN+1) = (int)LoadLibraryExW - (int)pfnLoadLibraryExW - 7;//((int)LoadLibraryExW+CODELEN) - ((int)pfnLoadLibraryExW+CODELEN) - 5; return TRUE;
    }再反汇编看下,第6-7个字节被2个NOP指令代替了.
    没有破坏第三条CALL指令.
    调用原函数也不用重新恢复前面5个字节.kernel32!LoadLibraryExW:
    7c801af5 e9e6f6c083      jmp     004111e0
    7c801afa 90              nop
    7c801afb 90              nop
    7c801afc e8d5090000      call    kernel32!ReleaseMutex+0x1f (7c8024d6)
    7c801b01 33ff            xor     edi,edi
    7c801b03 897dd8          mov     dword ptr [ebp-28h],edi
    7c801b06 897dd4          mov     dword ptr [ebp-2Ch],edi
    7c801b09 897de0          mov     dword ptr [ebp-20h],edi