遊戲修改器製作流程

原文地址:http://www.cnblogs.com/gxlxzys/archive/2009/12/06/1618025.html

以休閒遊戲“植物大戰殭屍”爲例,製作無限陽光修改器。

製作遊戲修改器,應該有很多人對這類內容感興趣吧。

發現這個遊戲純屬巧合,一日我在百度搜索“植物”這個詞時,搜索框下方就列出一大堆“植物大戰殭屍”的相關內容,於時就下載來玩了一下,挺有意思的,玩到最後就有了修改的念頭,本人對於遊戲的態度是:能改則改,現實生活中我是窮人,在遊戲中至少也要變富人吧。費話不說了,準備開始,先看一下游戲截圖,好讓大家有一些總體認識,

此修改器的目的是要實現修改陽光值(如上圖中的數值:1950),因此要找出遊戲中存放“陽光”的內存地址,然後使用API函數WriteProcessMemory進行內存修改,但是每次運行遊戲時這個內存地址都會不一樣,所以要找出基址,我使用的工具是Cheat Engine 5.4簡體中文版(以下簡稱CE),步驟如下:

1、打開遊戲並運行在窗口模式,再打開CE,點擊左上角電腦圖標->選中進程->確定,如下圖:

2、在數值框中輸入當前陽光數50,點擊首次掃描;
切換到遊戲中種一棵向日葵,使陽光數變成0;
再切換回CE,在數值框中輸入0,點擊再次掃描;
將會搜索到一個結果,如下圖所示:

3、雙擊此地址添加到下方的地址列表中,在列表中雙擊“數值”下面對應的內容可以修改此內存值;
我們將值改成1000試試看,如下圖:

再看看遊戲中的值,修改成功了,如下圖:

如上圖所示,內存地址“0CD29FB8”就是存放陽光的地址,我們可以隨意的修改此內存中的數值,比金山遊俠還要好用。
但是此地址是動態的,下次運行遊戲時它存放的肯定就不是陽光了,我們要繼續查找不會變的靜態地址,看下一步。

4、在此地址上點右鍵->查找寫入該地址的代碼,會看到一個對話框“下列代碼更改選擇的地址”,裏面是空白的;
切換回遊戲,隨便種一棵植物(目的是讓陽光變少,好找出哪些代碼修改了此內存);再回到CE,會看到剛纔的空白對話框中已經有內容了,雙擊或點“更多信息”出現下圖內容:

注意看紅色彙編代碼 :mov 是傳送指令,把esi的值傳送到EDI+5560,ESI的值是16進制的320,等於10進制的800,恰好就是陽光值,而EDI指向的地址0CD24A58偏移加5560剛好等於0CD9FB8,此地址保存着當前陽光值,很顯然這就是改變內存的賦值代碼了,紅色代碼上面那行,很顯然就是減法運算。
記住EDI的值“0CD24A58“,下一步

5、將上面的搜索框前的16進制勾選上—>將EDI的值填進去—>首次掃描,如下圖所示:

搜索出一堆地址,剛開始時我也是毫無頭緒,搜索了幾次都發現有這個值“010D84E0”,以爲這個就是基址了,其實不是的,但這個值是怎麼來的呢?我們繼續下一步。

6、將上一步搜索出的值添加到地址列表—>右鍵—>查找所有訪問此地址的代碼,稍等一下就出一大堆代碼出來了,如下圖:

雙擊第一個mov 指令查看更多信息,如下圖:

原來ESI的值是EDI+768得來的,EDI的值是010D7D78,我們繼續搜索010D7D78,如下圖:

大功告成,查找到了綠色內存地址,綠色內存地址表明該地址在遊戲中是靜態的,它就是我們要找的基址了。

7、下面我們試着把這些內存地址連接起來,內存地址006a9ec0(值爲010D7D78)+偏移 768 = 010D84E0,地址010D84E0(值爲0CD24A58)+偏移5560=0CD9FB8(此地址就是我們第二步搜索出來的陽光地址)。
好了,我們用CE測試一下是否正確,如下圖,手動填加地址進行測試:

結果完全正確,最終地址指向的內存值爲800,繼續下一步。

8、有了內存基址,現在我們就可以寫程序了,相對於找基址,寫代碼就簡單得多。
核心代碼如下:

複製代碼
主要代碼
HWND hWnd = ::FindWindow(NULL,"植物大戰殭屍中文版"); //查找窗口句柄 if(hWnd == 0) return; HANDLE hProc; DWORD proID; GetWindowThreadProcessId(hWnd,&proID); //取得進程ID hProc=OpenProcess(PROCESS_ALL_ACCESS, false,proID); //打開進程 if(hProc==NULL) { //m_sunny = (int)hWnd; //UpdateData(false); //MessageBox("cannot open process!"); return; } DWORD ads_ps=0x006a9ec0; //讀取內存地址 DWORD value; ReadProcessMemory(hProc,(void *)ads_ps,&value,4,NULL); ads_ps = value + 0x768; ReadProcessMemory(hProc,(void *)ads_ps,&value,4,NULL); ads_ps = value + 0x5560; UpdateData(); value = m_sunny; //陽光值 WriteProcessMemory(hProc,(void *)ads_ps,&value,4,NULL); //寫內存 CloseHandle(hProc);
複製代碼

 

 

的VC和彙編都是剛學的,以上讀取指針的代碼我自己看了都覺得怪怪的,呵呵。將就用着先吧。
最終做出來的程序運行界面如下圖所示:

後記:
剛開始我只做了修改及鎖定,但後面覺得這樣太麻煩,乾脆就做了“安放植物不減陽光,反而獲得陽光的功能”,個人感覺這個功能更有意思,這個功能實現起來更簡單,還記得第4步的sub 減法指令嗎?只要將 sub 改成 add就行了,呵呵。
當然寫到我們的程序中是要用16進制的,這個16進制的獲得也在CE中獲得,如下圖:


仔細看了,sub esi,ebx 對應的16進制代碼爲 2b f3 ,我改成add esi,ebx 後代碼爲01 de,大家可以自己改改看了。
不過在我們的程序要修改其它程序的代碼是要有權限才行的,直接拿上面的代碼來用是行不通的,我在上面代碼基礎上加了個函數vrtualProtectEx,代碼如下:

複製代碼
代碼
DWORD ads_ps=0x0041ba74; //程序內存地址 WORD value; value = 0xde01; VirtualProtectEx(hProc,(void *)ads_ps,2,PAGE_READWRITE,&oldFlag); WriteProcessMemory(hProc,(void *)ads_ps,&value,2,NULL); VirtualProtectEx(hProc,(void *)ads_ps,2,oldFlag,&oldFlag); CloseHandle(hProc);
複製代碼

好了,一個簡單的遊戲修改器製作完成,我用同樣的方法也做了紅色警戒2的修改器(點擊查看),期間碰到一個問題,就是無法用SPY獲取遊戲的窗口句柄,因爲紅警是全屏運行了,後來我瞎猜了一個 “Red Alert 2”,競然成功了,呵呵。還請哪位高手指點一二,如何獲取全屏程序的句柄,或者進程ID。

源碼及程序下載:
源碼  (VC6代碼,哪位朋友有空轉成C#後,和我打個招呼,我好做個鏈接)
exe程序

發佈了8 篇原創文章 · 獲贊 26 · 訪問量 10萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章