WEB开发网
开发学院软件开发VC 用VC编程阻止全局钩子的加载 阅读

用VC编程阻止全局钩子的加载

 2007-03-15 21:52:19 来源:WEB开发网   
核心提示: 修改LoadLibraryExW函数的前5个字节,用一个jmp 指令跳到我们的newLoadLibraryExW函数起始处,用VC编程阻止全局钩子的加载(2),虽然这里只用了5个字节,但是我们先看一下LoadLibraryExW函数的前两条指令: //你机器上的版本具体的数字可能和我的不一

  • 修改LoadLibraryExW函数的前5个字节,用一个jmp 指令跳到我们的newLoadLibraryExW函数起始处。虽然这里只用了5个字节,但是我们先看一下LoadLibraryExW函数的前两条指令:
  • //你机器上的版本具体的数字可能和我的不一样
    push 34h?//6A 34
    push 7C80E288h?//68 88 E2 80 7C

    一共有7个字节,我们不能只修改前5个字节,然后从fakeLoadLibraryExW函数跳到第6个字节处开始执行,而要跳到第三条指令即第8个字节开始处,这就是上一步N为什么取7的原因。画个图示意一下,修改前:

    修改后:

    以下是封装的一个类,使用时定义一个该类的全局变量,调用一下PatchLoadLibrary函数即可。

    //***********************************************************************************//
    // FileName : GBlockHookDll.h          
    // Author :耿海增      
    // Date : 2006.10.07         
    //***********************************************************************************//
    #pragma once
    #include 
    #pragma comment(lib,"psapi.lib")
    class GBlockHookDll
    {
    public:
    GBlockHookDll()
    {
     MODULEINFO user32ModInfo = {0};
     
     //获取user32.dll的加载基址和映象大小 
     GetModuleInformation(GetCurrentProcess(),GetModuleHandle("user32.dll"),&user32ModInfo,sizeof(user32ModInfo));
     m_dwUser32Low = (DWORD)user32ModInfo.lpBaseOfDll;
     m_dwUser32Hi = (DWORD)user32ModInfo.lpBaseOfDll+user32ModInfo.SizeOfImage;
    }
    void PatchLoadLibrary()
    {
     //LoadLibraryExW
     //7C801AF1 6A 34        push    34h
     //7C801AF3 68 88 E2 80 7C    push    7C80E288h
     LPVOID* pfnRaw = (LPVOID*)&rawLoadLibraryExW;
     LPVOID fnNew = (LPVOID)newLoadLibraryExW;
     BYTE* fnRaw = (BYTE*)*pfnRaw;
     //1 save the first 7 bytes
     const int nFirstBytes = 7;
     BYTE* fnFake = (BYTE*)fakeLoadLibraryExW;
     memcpy(fnFake,*pfnRaw,nFirstBytes);
     fnFake[nFirstBytes] = 0xE9; //jmp to rawAddr+nFirstBytes
     *(UINT32*)(fnFake + nFirstBytes+1) = (UINT32)fnRaw+nFirstBytes - (UINT32)(fnFake + nFirstBytes + 5);
     //2 modify the raw to jmp to fnNew
     DWORD dwOldProtect = 0;
     VirtualProtect(fnRaw,nFirstBytes,PAGE_READWRITE,&dwOldProtect); //修改该代码段的属性为可写
     *fnRaw = 0xE9;
     *(UINT32*)(fnRaw+1) = (UINT32)fnNew - (UINT32)(fnRaw + 5);
     VirtualProtect(fnRaw,nFirstBytes,dwOldProtect,0);
     //3 change the rawPointer
     *pfnRaw = fnFake;
    }
    private: 
    static HMODULE WINAPI newLoadLibraryExW(LPCWSTR lpLibFileName,HANDLE hFile,DWORD dwFlags)
    {
     //get the return address
     DWORD dwCaller;
     __asm push dword ptr [ebp+4]
     __asm pop dword ptr [dwCaller]
     if(dwCaller > m_dwUser32Low && dwCaller < m_dwUser32Hi)
     {
    #ifdef _DEBUG
      UINT uLenWide = lstrlenW(lpLibFileName);
      char* pNewChar = new char[uLenWide + 1];
      memset(pNewChar,0,uLenWide+1);
      WideCharToMultiByte(CP_ACP,0,lpLibFileName,-1,pNewChar,uLenWide,NULL,NULL);
      TRACE2(".......................LoadLibrary:return addr 0x%x,%s ",dwCaller,pNewChar);
      TRACE("Blocked.......................
    ");
      delete []pNewChar;
    #endif
      return 0;
     }
     return rawLoadLibraryExW(lpLibFileName,hFile,dwFlags);
    }
    private:
    static DWORD m_dwUser32Low;  //user32.dll 的加载基址
    static DWORD m_dwUser32Hi;  //user32.dll 的加载基址+ImageSize
    static BYTE fakeLoadLibraryExW[12]; //save first bytes of the raw function,and jmp back to that function
    //保存LoadLibraryExW的指针,然后修改为fakeLoadLibraryExW
    static HMODULE (WINAPI *rawLoadLibraryExW)( LPCWSTR lpLibFileName, HANDLE hFile, DWORD dwFlags );
    };
    DWORD GBlockHookDll::m_dwUser32Low = 0;
    DWORD GBlockHookDll::m_dwUser32Hi = 0;
    BYTE GBlockHookDll::fakeLoadLibraryExW[12] = {0};
    HMODULE (WINAPI *GBlockHookDll::rawLoadLibraryExW)(LPCWSTR lpLibFileName,HANDLE hFile,DWORD dwFlags) = LoadLibraryExW;

    注1:怎么知道函数的返回地址呢?我们都知道,函数调用的时候,先要把参数入栈,然后把返回地址入栈,这样,在我们的函数里,esp指向的应该就是函数的返回地址了。但是为了返回函数时恢复原来的栈和在函数中方便引用传递的参数,编译器一般都会产生两条指令:

    push ebp

    mov ebp,esp

    先把ebp入栈,把原来的esp保存在ebp寄存器中,这样,我们的返回地址就是[ebp+4],第一个参数是[ebp+8],第二个是[ebp+0xC]

    注2:如果想写一个通用一点儿的API Hook,就不能简单的patch前5个或者前7字节了,需要根据不同的指令分析需要patch多少字节。可以参考微软的 Detours 的实现。

    上一页  1 2 

    Tags:VC 编程 阻止

    编辑录入:爽爽 [复制链接] [打 印]
    赞助商链接