#define FLATJMPCODE_LENGTH 5            //x86 平坦内存模式下,绝对跳转指令长度
#define FLATJMPCMD_LENGTH  1            //机械码0xe9长度
#define FLATJMPCMD         0xe9

// 记录被打桩函数的内容,以便恢复
BYTE g_apiBackup[FLATJMPCODE_LENGTH+FLATJMPCMD_LENGTH];

BOOL HookApi(LPVOID ApiFun,LPVOID HookFun)
{
    BOOL    IsSuccess = FALSE;
    DWORD   TempProtectVar;              //临时保护属性变量
    MEMORY_BASIC_INFORMATION MemInfo;    //内存分页属性信息
    
    VirtualQuery(ApiFun,&MemInfo,sizeof(MEMORY_BASIC_INFORMATION));
    
    if(VirtualProtect(MemInfo.BaseAddress,MemInfo.RegionSize,
        PAGE_READWRITE,&MemInfo.Protect))                            //修改页面为可写
    {
        memcpy((void*)g_apiBackup,(const void*)ApiFun, sizeof(g_apiBackup));

        *(BYTE*)ApiFun = FLATJMPCMD;                                    
        *(DWORD*)((BYTE*)ApiFun + FLATJMPCMD_LENGTH) = (DWORD)HookFun -
            (DWORD)ApiFun - FLATJMPCODE_LENGTH;
        
        VirtualProtect(MemInfo.BaseAddress,MemInfo.RegionSize,
            MemInfo.Protect,&TempProtectVar);                        //改回原属性
        
        IsSuccess = TRUE;
    }
    
    return IsSuccess;
}

BOOL UnHookApi(LPVOID ApiFun)
{
    BOOL    IsSuccess = FALSE;
    DWORD   TempProtectVar;              //临时保护属性变量
    MEMORY_BASIC_INFORMATION MemInfo;    //内存分页属性信息
    
    VirtualQuery(ApiFun,&MemInfo,sizeof(MEMORY_BASIC_INFORMATION));
    
    if(VirtualProtect(MemInfo.BaseAddress,MemInfo.RegionSize,
        PAGE_READWRITE,&MemInfo.Protect))                            //修改页面为可写
    {
        memcpy((void*)ApiFun, (const void*)g_apiBackup, sizeof(g_apiBackup));
        
        VirtualProtect(MemInfo.BaseAddress,MemInfo.RegionSize,
            MemInfo.Protect,&TempProtectVar);                        //改回原属性
        
        IsSuccess = TRUE;
    }
    
    return IsSuccess;
}