一、制作背景和原理:
在平時玩游戲的過程中,大家肯定會接觸過形形色色的修改,特別是看到一些高手出的某某全能修,x項修改器,煞是羨慕,其實制作這樣寫一個這樣的修改器一點也不神秘, 好了,請各位看官一同隨我去揭開修改器之謎......“修改器”程序的就是修改我們想要數(shù)據(jù)的地址里面的數(shù)值,這句話比較拗口,但是這是“修改器”程序的關(guān)鍵。下面就以時興的Normal tanks(坦克大戰(zhàn))為例,和大家討論怎樣去DIY一個游戲修改器請大家移步且隨我步驟慢慢來。
二、找到我們想要的內(nèi)存地址:
這是很關(guān)鍵的一步, 給大家介紹一款優(yōu)秀的內(nèi)存編輯工具)。
在游戲中按熱Ctrl+Tab返回桌面,在Quick Memory Editor中點擊Add Task 。
搜索炮彈的數(shù)量,當(dāng)前游戲中是50,在Search value中填入50,然后點擊Search,搜索速度很快,這會出來很結(jié)果,然后回到游戲里,隨便放幾炮,當(dāng)前炮彈數(shù)量變?yōu)榱?7,然后返回桌面,在Quick
Memory Editor中的Search value中填入47,點擊Search, 這時候出來了幾個結(jié)果,結(jié)果還是不是很精確。返回游戲,再隨便放幾炮,當(dāng)前炮彈數(shù)量變成了43,再在Quick Memory
Editor搜索43,這時候出來了僅一個結(jié)果,這就是我們需要的內(nèi)存地址了,記下來004C9C84,等會兒我們要用到。
三、介紹兩個關(guān)鍵 API函數(shù)ReadProcessMemory()和 WriteProcessMemory():
詳細(xì)的注釋我表明在函數(shù)里
①BOOL ReadProcessMemory(
HANDLE hProcess, // 目標(biāo)進(jìn)程句柄
LPCVOID lpBaseAddress, // 讀取數(shù)據(jù)的起始地址
LPVOID lpBuffer, // 存放數(shù)據(jù)的緩存區(qū)地址
DWORD nSize, // 要讀取的字節(jié)數(shù)
LPDWORD lpNumberOfBytesRead ); // 實際讀取的數(shù)據(jù)大小地址
ReadProcessMemory()用于讀取游戲進(jìn)程中制定的內(nèi)存數(shù)據(jù); 在實際操作中,我們用它來讀取存放炮彈數(shù)量地址中的數(shù)據(jù)。
②BOOL WriteProcessMemory(
HANDLE hProcess, // 目標(biāo)進(jìn)程句柄
LPVOID lpBaseAddress, // 進(jìn)程的起始地址
LPVOID lpBuffer, // 數(shù)據(jù)內(nèi)容
DWORD nSize, // 需要寫入的字節(jié)數(shù)
LPDWORD lpNumberOfBytesWritten); // 實際寫入的數(shù)據(jù)大小的地址
WriteProcessMemory()和上面的ReadProcessMemory()用法一樣,在實際操作中,我們用它來修改存放炮彈數(shù)量地址中的數(shù)據(jù)。
四、編程實現(xiàn)游戲修改(完整代碼):
#include
HINSTANCE g_hInst;
HWND g_hWnd;
char szAppName[]="TankFix"; //The name of the exe
char szTitle[]="坦克大戰(zhàn)修改";
DWORD addr=0x004C9C84; //存放炮彈數(shù)量的內(nèi)存地址
DWORD pid; //坦克大戰(zhàn)的PID
int val=1000; //炮彈要修改的數(shù)量
//-------------------------------------------------------------------------------------------------
// WndProc- 窗口函數(shù)
//-------------------------------------------------------------------------------------------------
LRESULT CALLBACK WndProc(HWND hWnd,UINT message, WPARAM wParam, LPARAM lParam)
{
// int wmId,wmEvent;
switch (message)
{
case WM_DESTROY:
PostQuitMessage(0);
break;
case WM_TIMER:
{
HWND hw=FindWindow(NULL,"Normal-tanks"); //FindWindow()得到坦克大戰(zhàn)程序的句柄
HANDLE hProcess; //定義坦克大戰(zhàn)的進(jìn)程句柄
if (hw!=0)
{
SetForegroundWindow(hw); //使我們的坦克大戰(zhàn)設(shè)置為當(dāng)前窗口
GetWindowThreadProcessId(hw,&pid); //得到游戲的PID號
hProcess=OpenProcess(PROCESS_ALL_ACCESS,FALSE,pid); //打開進(jìn)程PROCESS_ALL_ACCESS參數(shù),制定進(jìn)程可讀可寫
WriteProcessMemory(hProcess,(LPVOID)addr,&val,4,0); //向坦克大戰(zhàn)進(jìn)程內(nèi)存中寫入數(shù)據(jù)
}
else
MessageBox(g_hWnd,"游戲還沒有運行吧!","提示信息",MB_OK|MB_ICONINFORMATION);
}
default:
return (DefWindowProc(hWnd,message,wParam,lParam));
}
return 0;
}