/*
变速齿轮原理是,游戏在刷新画面时会用到时钟来控制刷新速度,有过游戏开发的人都知道,一般游戏锁定1秒30帧,这样会很流畅,人眼有视觉停顿,当速度达到1秒16帧的时候,就是在跑动画了,游戏用到的计时器有大部分是两个windows提供的api函数,一个是::GetTickCount,一个是::timeGetTime,这两个api的原型请查msdn,我们利用hook api 去修改它的值,从而改变游戏速度,下面是示例源代码。
工程是一个dll
*/
/************myhook.cpp******************/
#include "stdafx.h"
#include <stdio.h>
#define KEYHOOKLIB_EXPORTS
#include "myhook.h"
#include <mmsystem.h>
#include <process.h>
#pragma comment(lib,"winmm.lib")
HWND g_hWndCaller = NULL; // 保存主窗口句柄
SetParam_Ptr mySetParam[12];
/***************************HOOKAPI部分通过修改API头8字节******************/
BOOL WINAPI HookApi(LPCSTR modname,char funname[],PROC hook,SetParam_Ptr myParam){
//初始化内存
memset((myParam->m_newjmp),0,sizeof(BYTE)*8);
memset((myParam->m_oldjmp),0,sizeof(BYTE)*8);
//生成跳转语句
BYTE newjmp[8]={0xB8,0x00,0x00,0x40,0x00,0xFF,0xE0,0x00};
//拷贝内存
BYTE *temp=myParam->m_newjmp;
memcpy(temp,newjmp,sizeof(BYTE)*8);
//保存我们自己的api地址
*(DWORD*)(myParam->m_newjmp+1)=(DWORD)hook;
//加载指定模块
myParam->m_hmodule=::LoadLibrary((char*)modname);
if(myParam->m_hmodule==NULL){
myParam->m_apiaddress=NULL;
return false;
}
//获得API地址
myParam->m_apiaddress=::GetProcAddress(myParam->m_hmodule,funname);
//修改原API地址的前8字节,让它转向我们自己的代理API函数
if(myParam->m_apiaddress!=NULL){
DWORD oldprotect;
MEMORY_BASIC_INFORMATION mbi;
::VirtualQuery(myParam->m_apiaddress,&mbi,sizeof(mbi));
::VirtualProtect(myParam->m_apiaddress,8,PAGE_READWRITE,&oldprotect);
//保存原来的8字节
BYTE *temp2=myParam->m_oldjmp;
memcpy(temp2,myParam->m_apiaddress,sizeof(BYTE)*8);
//写入原来的执行代码
::WriteProcessMemory(::GetCurrentProcess(),(void*)myParam->m_apiaddress,myParam->m_newjmp,sizeof(DWORD)*2,NULL);
::VirtualProtect(myParam->m_apiaddress,8,mbi.Protect,0);
}
return true;
}
//取消挂钩API
BOOL WINAPI UnHookApi(SetParam_Ptr myParam){
if(myParam->m_apiaddress!=NULL){
DWORD oldprotect;
MEMORY_BASIC_INFORMATION mbi;
::VirtualQuery(myParam->m_apiaddress,&mbi,sizeof(mbi));
::VirtualProtect(myParam->m_apiaddress,8,PAGE_READWRITE,&oldprotect);
//写入真正的API地址
::WriteProcessMemory(::GetCurrentProcess(),(void*)myParam->m_apiaddress,myParam->m_oldjmp,sizeof(DWORD)*2,NULL);
::VirtualProtect(myParam->m_apiaddress,8,mbi.Protect,0);
return true;
}
return false;
}
//重新挂钩API
BOOL WINAPI ReHookApi(SetParam_Ptr myParam){
if(myParam->m_apiaddress!=NULL){
DWORD oldprotect;
MEMORY_BASIC_INFORMATION mbi;
::VirtualQuery(myParam->m_apiaddress,&mbi,sizeof(mbi));
::VirtualProtect(myParam->m_apiaddress,8,PAGE_READWRITE,&oldprotect);
//写入我们自己的代理API地址
::WriteProcessMemory(::GetCurrentProcess(),(void*)myParam->m_apiaddress,myParam->m_newjmp,sizeof(DWORD)*2,NULL);
::VirtualProtect(myParam->m_apiaddress,8,mbi.Protect,0);
return true;
}
return false;
}
/**************************************************************************/
BOOL WINAPI HookApi2(LPCSTR modname,char funname[],PROC hook,SetParam_Ptr myParam){
//初始化内存
memset((myParam->m_newjmp),0,sizeof(BYTE)*12);
memset((myParam->m_oldjmp),0,sizeof(BYTE)*12);
//生成跳转语句
BYTE newjmp[12]={0x00,0x00,0x00,0x00,0xB8,0x00,0x00,0x40,0x00,0xFF,0xE0,0x00};
//拷贝内存
BYTE *temp=myParam->m_newjmp;
memcpy(temp,newjmp,sizeof(BYTE)*12);
//保存我们自己的api地址
*(DWORD*)(myParam->m_newjmp+5)=(DWORD)hook;
//加载指定模块
myParam->m_hmodule=::LoadLibrary((char*)modname);
if(myParam->m_hmodule==NULL){
myParam->m_apiaddress=NULL;
return false;
}
//获得API地址
myParam->m_apiaddress=::GetProcAddress(myParam->m_hmodule,funname);
//修改原API地址的前8字节,让它转向我们自己的代理API函数
if(myParam->m_apiaddress!=NULL){
DWORD oldprotect;
MEMORY_BASIC_INFORMATION mbi;
::VirtualQuery(myParam->m_apiaddress,&mbi,sizeof(mbi));
::VirtualProtect(myParam->m_apiaddress,12,PAGE_READWRITE,&oldprotect);
//保存原来的8字节
BYTE *temp2=myParam->m_oldjmp;
memcpy(temp2,myParam->m_apiaddress,sizeof(BYTE)*12);
//写入原来的执行代码
::WriteProcessMemory(::GetCurrentProcess(),(void*)myParam->m_apiaddress,myParam->m_newjmp,sizeof(DWORD)*3,NULL);
::VirtualProtect(myParam->m_apiaddress,12,mbi.Protect,0);
}
return true;
}
//取消挂钩API
BOOL WINAPI UnHookApi2(SetParam_Ptr myParam){
if(myParam->m_apiaddress!=NULL){
DWORD oldprotect;
MEMORY_BASIC_INFORMATION mbi;
::VirtualQuery(myParam->m_apiaddress,&mbi,sizeof(mbi));
::VirtualProtect(myParam->m_apiaddress,12,PAGE_READWRITE,&oldprotect);
//写入真正的API地址
::WriteProcessMemory(::GetCurrentProcess(),(void*)myParam->m_apiaddress,myParam->m_oldjmp,sizeof(BYTE)*12,NULL);
::VirtualProtect(myParam->m_apiaddress,12,mbi.Protect,0);
return true;
}
return false;
}
//重新挂钩API
BOOL WINAPI ReHookApi2(SetParam_Ptr myParam){
if(myParam->m_apiaddress!=NULL){
DWORD oldprotect;
MEMORY_BASIC_INFORMATION mbi;
::VirtualQuery(myParam->m_apiaddress,&mbi,sizeof(mbi));
::VirtualProtect(myParam->m_apiaddress,12,PAGE_READWRITE,&oldprotect);
//写入我们自己的代理API地址
::WriteProcessMemory(::GetCurrentProcess(),(void*)myParam->m_apiaddress,myParam->m_newjmp,sizeof(BYTE)*12,NULL);
::VirtualProtect(myParam->m_apiaddress,12,mbi.Protect,0);
return true;
}
return false;
}
/***********************我们自己的代理API函数*********************************/
//代理
/*
DWORD __flag__=0;
DWORD WINAPI MyGetTickCount(){
UnHookApi(mySetParam[0]);
if(__flag__>=120){
__flag__=23;
}
DWORD __count__=0;
__flag__+=69;
__count__=::GetTickCount()+__flag__;
ReHookApi(mySetParam[0]);
return __count__;
}
*/
DWORD __flag__=0;
DWORD __flag1__=0;
DWORD WINAPI MyGetTickCount(){
UnHookApi(mySetParam[0]);
// if(__flag__>=120){
// __flag__=23;
// }
__flag1__++;
DWORD __count__=::GetTickCount();
__count__+=128*__flag1__;
// ::MessageBoxA(NULL,buff,"tick",MB_OK);
ReHookApi(mySetParam[0]);
return __count__;
}
DWORD WINAPI MytimeGetTime(){
UnHookApi(mySetParam[1]);
DWORD i=::timeGetTime();
__flag__++;
i+=128*__flag__;
// ::MessageBoxA(NULL,buff,"time",MB_OK);
ReHookApi(mySetParam[1]);
return i;
}
//HOOK初始化
int HookInit(){
//申请内存空间
for(int i=0;i<2;i++)
mySetParam[i]=new SetParam;
HookApi("winmm.dll","timeGetTime",(PROC)MytimeGetTime,mySetParam[1]);
HookApi("Kernel32.dll","GetTickCount",(PROC)MyGetTickCount,mySetParam[0]);
return 0;
}
//释放空间
int ReAllHook(){
for(int i=0;i<2;i++)
UnHookApi(mySetParam[i]);
fclose(fr);
return 1;
}
/**************************************************************************/
/*********************myhook.h****************************/
// 定义函数修饰宏,方便引用本DLL工程的导出函数
#ifdef KEYHOOKLIB_EXPORTS
#define KEYHOOKLIB_API __declspec(dllexport)
#else
#define KEYHOOKLIB_API __declspec(dllimport)
#endif
typedef struct SetParams{
PROC m_apiaddress; //目标函数地址
BYTE m_newjmp[8];//用来保存跳转地址
BYTE m_oldjmp[8];//用来保存原始跳转地址
HMODULE m_hmodule;//模块
}SetParam,*SetParam_Ptr;
// 声明要导出的函数
//初始化挂钩api
int HookInit();
//取消挂钩API
int ReAllHook();
BOOL KEYHOOKLIB_API WINAPI HookApi(LPCWSTR modname,char funname[],PROC hook,SetParam_Ptr myParam);
//重新挂钩API
BOOL KEYHOOKLIB_API WINAPI ReHookApi(SetParam_Ptr myParam);
//取消挂钩API
BOOL KEYHOOKLIB_API WINAPI UnHookApi(SetParam_Ptr myParam);
/***************************dllmain.cpp**************************/
// dllmain.cpp : 定义 DLL 应用程序的入口点。
#include "stdafx.h"
#include "myhook.h"
BOOL APIENTRY DllMain( HMODULE hModule,
DWORD ul_reason_for_call,
LPVOID lpReserved
)
{
switch (ul_reason_for_call)
{
case DLL_PROCESS_ATTACH:
HookInit();
// ::MessageBox(NULL,"Hello World!","",MB_OK);
break;
case DLL_THREAD_ATTACH:
break;
case DLL_THREAD_DETACH:
break;
case DLL_PROCESS_DETACH:
ReAllHook();
break;
}
return TRUE;
}
/****************************myhook.def***********************/
EXPORTS
HookApi
ReHookApi
UnHookApi
HookInit