掀開高階遊戲黑客的面紗,教你打造遊戲修改器 (10千字)
掀開高階遊戲黑客的面紗,教你打造遊戲修改器
工具:SoftICE、金山遊俠2002、VC++7.0、PE檢視器、SPY++
測試平臺:Window2000
Professional SP2
大家好!我先給大家拜個晚年,時間過真快工,一年又過去了,我也和大家分開一年了,真是感慨萬分呀,不知道大還記得不記得YY了,不過我是不會忘記大家的.
這一年真是太忙了,根本就沒有時間再像從前那樣在深夜裡一邊聽著音樂一邊寫文章了,今天就著假期,再給大家充充電:D
今天YY給大家帶來些什麼呢?呵呵,看題目就知道了,看起來很酷吧,“高階遊戲黑客”,什麼?你說你就遊戲黑客?看好了,是“高階”的!什麼是高階的?等你看完這篇文章就知道了:D
首先我介紹一下將會用到的工具:
1、 SoftICE(不用多說了吧,我想你應該會用)
2、
金山遊俠2002(這個你也應該會用)
3、 VC++7.0(不要求你一定會用,但至少應該會一種程式設計工具)
4、 PE檢視器(你可以隨意找一個,沒有也沒關係,我會教你用SoftICE檢視)
5、
SPY++(VC裡的一個檢視程式資訊的工具,你可以和別的,比如Delphi和C++Builder的WinSight32)
然後就是你應該會的知識:
1、 彙編基礎
2、 一些程式設計基礎,至少應該看懂我介紹的幾個API函式
3、 PE檔案結構的基礎,不會也沒關係,我會解釋給你
以上幾點你都具備了的話我們就可以開始了。
我來介紹一下我要教給你的東西。想必大家都玩過PC遊吧,那麼也一定用過一些專用的遊戲修改器吧,比如暗黑,紅警,大富翁這些經典的遊戲都有它們專用的修改器,注意,我說的不是FPE之類的通用修改工具。
你試沒試過用金山遊俠修改紅警二的金錢?如果有的話你應該知道每玩一次就要改一次,因為這個遊戲是動態分配記憶體的,每次重新開始都會改變。所以你會選擇到網上去下載一個專用的修改器,那麼你有沒有想過自己做一上呢?想過?那你為什麼不做?什麼不會?那就好辦了,看了這篇教程你就會了:D費話少說,我來講一下原理。
有一些經常修改遊的朋友一定會知道,不論遊戲中“物品”的記憶體地址是否是動態的,物品與物品之間相隔的距離都是不變的,我拿“楚留香新傳”為例,我先用金山遊俠查詢內力值的記憶體地址,找到的結果是:79F695C,再查詢物品“金創藥”的地址是:328D1DC,現在我用79F695C減去328D1DC,得到:4769780,這個數就是內力值與金創藥的偏移值,沒看懂?接著看呀,我還沒說完呢,現在重新再執行遊戲,查詢內力值的地址,得到:798695C再查詢金創藥得到的地址是:321D1DC,兩個值的記憶體地址都改變了,但是用你內力值的地址減去金創藥的地址得到的結果是什麼?沒錯,還是4769780,也就是說,無論這兩個值的記憶體地址變成多少,它們之間的距離是永遠不變的,不光是這個遊戲,一般的遊戲都是,至少我沒見過不是的:D
上面講的東西總結出一個結論,那就是我們只要得到這兩個地址中的任何一個,就可以得到另外一個,只要你知道它們之間的偏移量是多少。
我們第一步要做的就是得到這個地址,但是記憶體中的地址是動態改變的,得到也沒有用,這裡我就教你把它變成靜態的,叫它永遠都不變!我繼續拿“楚留香新傳”為例,如果你有這個遊的話就跟我一起做,沒有的也沒關係,只要看懂這幾個步驟就行了。開工!
首先進入遊戲,查詢內值的地址,得到的是:798695C(不知道為什麼這上游並不是每次重起都改變記憶體地址),按Ctrl+D開啟SoftICE,下命令:BPM
798695C W(寫這個地址時則中斷),回到遊戲中,開啟人物屬性皮膚,遊戲中斷了,在SofitICE中你會看到這條指令:
0047EB17
MOV EAX [EDX+000003F4] 下命令:D EDX+3F4將看到內力值
0047EB1D PUSH
EAX
………………………………
………………………………
從上面可看出0047EB17處的指令是將內力值的指標送到EAX暫存器中,這是一個典型的定址方式,設想一下,我們是到了EDX中的基址,那麼無論什麼時候只要用EDX+3F4就可以輕鬆的得到內力值的地址,因為000003F4是一個常量,它是不會改變的,改變的只是EDX中的地址,所以只要有辦法得到EDX中的值就什麼都好辦了,你明白了沒有?如果還是不懂,那麼請再看一遍。現在要做的就是如何得到這個值,下面我教給你如何做:
我的辦法就是設計一段程式碼,把EDX中的值存放到一個地址中,然後執行這段程式碼,再返回遊戲的原有指令繼續執行,什麼?補丁技術?SMC?隨你怎麼說啦,只要執行正常就一切OK啦:D
實際操作:
首先在程式中找一段空白處來存放我們設計的程式碼,很簡單,只要懂得一些PE檔案結構的朋友都會知道,一般在EXE檔案的資料段(.data段)的結尾都會有一段緩衝區,我們可以在這段區域中寫任何東西,當然你也可以用“90大法”找一段空白區,但我還是推薦你用我教給你的方法。上同我提到,如果你沒有PE檔案檢視工具我可以教你用SoftICE檢視,而且很簡單,只要一個命令:MAP32
“模組名”,看一下我是怎麼做的你就知道了。
Ctrl+D呼收出SoftICE,然後下命令:MAP32 CrhChs,這時你應該看到EXE各個段的資訊,我們要注意的只是.data段,既然要找的是資料段的結尾,那麼我們就從下一個段開始向上找,如下:
.data 004FB000
.rsrc 00507000
.data的下一個段是.rsrc段,它是從00507000開始的,也就是說以00507000為基礎向上一個位元組就是資料段的結尾,我所擇從00506950處開始寫程式碼,說了這麼半天那麼我們的程式碼到底是什麼樣子呢?修改後的指令又是什麼樣的呢?別急,請看下面:
修改0047EB17後程式碼:
0047EB17 JMP 00506950 //跳到我們的程式碼中去執行
0047EB1C NOP //由於這條指令原來的長度是6位元組,而修改後的長度是5個位元組,所以用一個空指令補上
0047EB1D
PUSH EAX
//我們的程式碼:
00506950 MOV DWORD PTR
EAX,[EDX+00003F4] //恢復我們破壞的指令
00506956 MOV DWORD PTR [00506961],EDX
//把EDX儲存以00506961中去
0050695C JMP 0047EB1D //返回原來的指令去執行
把上面的程式碼用SoftICE的A命令寫入,OK!
現在我們試一下執行的效果,你現在用金山遊俠搜尋一下內力址的地址,什麼又變了?那就地啦,它要是不變我們還用費這麼大勁兒嗎?記下這個地址返回到遊戲中去,Ctrl+D撥出SoftICE,下命令
D *[00506961]+000003F4,在資料視窗看到什麼了?呵呵,沒錯,看到了你剛才記住的那個地址,裡面的數值正是內力的值,試著改一下,回到遊戲中,呵呵,內力值變了吧:D
講到這裡,我們的工作已經完成了%90,但別高興的太早,後面的%10要遠比前的%90花的時間長,因為我們要用程式設計實現這一切,因為你不能每次都像剛才那樣做一次吧!
現在我來說一下程式設計的步驟:
首先用FindWindow函式得到視窗控制程式碼,然後用GetWindowThreadID函式從視窗控制程式碼得到這個程式的ID,接著用OpenProcess得到程式的讀寫許可權,最後用WriteProcessMemory和ReadProcessMemory讀寫記憶體,然後。。。。呵呵,你的修改器就做成啦:D
下面是我抄寫以前寫的修改器源程式片斷,第一部分是動態寫入剛才的程式碼,第二部分是讀取並修改內力值,由於我沒有時間整理和測試,所以不能保證沒有錯誤,如果大家發現有遺漏的話,可以在QQ上給我留言或寫信給我,程式碼如下:
有幾點請大家注意:
1、 寫機器碼時要一個位元組一個位元組的寫
2、 注意要先寫入自己的程式碼,然後再修改遊中的指令(下面的程式碼沒有這樣做,因為不影響,但是你應該注意這個問題)
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
//動態寫入程式碼
//0047EB17
#define MY_CODE1 0xE9
#define MY_CODE2 0x34
#define MY_CODE3 0x7E
#define MY_CODE4 0x08
#define MY_CODE5
0x00
#define MY_CODE6 0x90
//00506950
#define MY2_CODE1 0x8B
#define MY2_CODE2 0x82
//這部分是要寫入的機器碼的常量定義
#define MY2_CODE3 0xF4
#define MY2_CODE4
0x03
#define MY2_CODE5 0x00
#define MY2_CODE6 0x00
#define MY3_CODE1 0x89
#define MY3_CODE2 0x15
#define
MY3_CODE3 0x61
#define MY3_CODE4 0x69
#define MY3_CODE5
0x50
#define MY3_CODE6 0x00
#define MY4_CODE1 0xE9
#define MY4_CODE2 0xBC
#define MY4_CODE3 0x81
#define
MY4_CODE4 0xF7
#define MY4_CODE5 0xFF
//-----------------------------------------------------------------------------//
DWORD A1 =MY_CODE1;
DWORD A2 =MY_CODE2;
DWORD A3 =MY_CODE3;
DWORD A4 =MY_CODE4;
DWORD A5 =MY_CODE5;
DWORD A6 =MY_CODE6;
DWORD B1 =MY2_CODE1;
DWORD
B2 =MY2_CODE2;
DWORD B3 =MY2_CODE3; //這部分是變數的定義
DWORD B4 =MY2_CODE4;
DWORD B5
=MY2_CODE5;
DWORD B6 =MY2_CODE6;
DWORD
C1 =MY3_CODE1;
DWORD C2 =MY3_CODE2;
DWORD
C3 =MY3_CODE3;
DWORD C4 =MY3_CODE4;
DWORD
C5 =MY3_CODE5;
DWORD C6 =MY3_CODE6;
DWORD
D1 =MY4_CODE1;
DWORD D2 =MY4_CODE2;
DWORD
D3 =MY4_CODE3;
DWORD D4 =MY4_CODE4;
DWORD
D5 =MY4_CODE5;
//--------------------------------------------------------------------------//
HWND hWnd =::FindWindow("CRHClass",NULL); //得到視窗控制程式碼
if(hWnd ==FALSE)
MessageBox("遊戲沒有執行!");
else
{
GetWindowThreadProcessId(hWnd,&hProcId); // 從視窗控制程式碼得到程式ID
HANDLE nOK =OpenProcess(PROCESS_ALL_ACCESS|PROCESS_TERMINATE|PROCESS_VM_OPERATION|PROCESS_VM_READ|
PROCESS_VM_WRITE,FALSE,hProcId);
//開啟程式並得到讀與許可權
if(nOK ==NULL)
MessageBox("開啟程式時出錯");
else
{
//0047EB17
WriteProcessMemory(nOK,(LPVOID)0x0047EB17,&A1,1,NULL);
WriteProcessMemory(nOK,(LPVOID)0x0047EB18,&A2,1,NULL);
WriteProcessMemory(nOK,(LPVOID)0x0047EB19,&A3,1,NULL);
WriteProcessMemory(nOK,(LPVOID)0x0047EB1A,&A4,1,NULL);
WriteProcessMemory(nOK,(LPVOID)0x0047EB1B,&A5,1,NULL);
WriteProcessMemory(nOK,(LPVOID)0x0047EB1C,&A6,1,NULL);
//00506950
WriteProcessMemory(nOK,(LPVOID)0x00506950,&B1,1,NULL);
WriteProcessMemory(nOK,(LPVOID)0x00506951,&B2,1,NULL);
WriteProcessMemory(nOK,(LPVOID)0x00506952,&B3,1,NULL);
WriteProcessMemory(nOK,(LPVOID)0x00506953,&B4,1,NULL);
WriteProcessMemory(nOK,(LPVOID)0x00506954,&B5,1,NULL);
WriteProcessMemory(nOK,(LPVOID)0x00506955,&B6,1,NULL);
//第二句
WriteProcessMemory(nOK,(LPVOID)0x00506956,&C1,1,NULL);
WriteProcessMemory(nOK,(LPVOID)0x00506957,&C2,1,NULL);
WriteProcessMemory(nOK,(LPVOID)0x00506958,&C3,1,NULL);
WriteProcessMemory(nOK,(LPVOID)0x00506959,&C4,1,NULL);
WriteProcessMemory(nOK,(LPVOID)0x0050695A,&C5,1,NULL);
WriteProcessMemory(nOK,(LPVOID)0x0050695B,&C6,1,NULL);
//最後一句
WriteProcessMemory(nOK,(LPVOID)0x0050695C,&D1,1,NULL);
WriteProcessMemory(nOK,(LPVOID)0x0050695D,&D2,1,NULL);
WriteProcessMemory(nOK,(LPVOID)0x0050695E,&D3,1,NULL);
WriteProcessMemory(nOK,(LPVOID)0x0050695F,&D4,1,NULL);
WriteProcessMemory(nOK,(LPVOID)0x00506960,&D5,1,NULL);
CloseHandle(nOK); //關閉程式控制程式碼
}
}
}
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
//讀取並修改內力值
DWORD hProcId;
HWND hWnd =::FindWindow("CRHClass",NULL);
if(hWnd ==FALSE)
MessageBox("No");
else
{
GetWindowThreadProcessId(hWnd,&hProcId);
HANDLE
nOK =OpenProcess(PROCESS_ALL_ACCESS|PROCESS_TERMINATE|PROCESS_VM_OPERATION|PROCESS_VM_READ|
PROCESS_VM_WRITE,FALSE,hProcId);
if(nOK ==NULL)
MessageBox("ProcNo!");
else
{
DWORD buf1;
DWORD write;
BOOL OK=ReadProcessMemory(nOK,(LPCVOID)0x00506961,(LPVOID)&buf1,4,NULL); //讀取我們儲存EDX中的基礎
if(OK ==TRUE)
{
write
=buf1+0x000003F4; //得到內力值的地址
DWORD Writeed =0x00; //要修改的數值
BOOL B =WriteProcessMemory(nOK,(LPVOID)write,&Writeed,1,NULL);
if(B==FALSE)
MessageBox("WriteNo");
}
}
CloseHandle(nOK);
}
啊,寫的我手都麻啦,今天就到這裡了,才疏學淺難免會有遺漏,請大家指教,如果我不會或不喜歡用VC的話,你可以在QQ上與我交流,我可以教你如何用Delphi、C++Builder、Win32Asm或VC實同上面的功能。
(如轉載本篇文章請不要改動內容及作者!)
作者:CrackYY
Email:CoolYY@msn.com
OICQ:20651482
相關文章
- 遊戲修改器 (轉)2007-12-14遊戲
- 揭開ThreadLocal的面紗2019-03-31thread
- 解開“QUIC”的神秘面紗2022-01-04UI
- 萬丈高樓平地起,撥開技術神祕的面紗2021-12-10
- 揭開“QUIC”的神祕面紗2022-01-07UI
- 【C#——揭開你的面紗】2016-01-05C#
- 揭開OKR (Objectives and Key Results) 的面紗2019-04-09OKRObject
- 揭開 Hyperledger Cacti 專案的面紗2022-12-16
- 高階遊戲開發工程師測試題2011-03-19遊戲開發工程師
- PEDIY 之 打造你自己的遊戲祕技(一) (3千字)2015-11-15遊戲
- 【微信刮刮卡抽獎遊戲】教你輕鬆做個抽獎遊戲頁面2021-09-27遊戲
- Android 3D遊戲開發(高階篇)——Opengl ES遊戲引擎實現2010-06-04Android3D遊戲開發遊戲引擎
- 揭開Java記憶體管理的面紗2019-02-26Java記憶體
- 揭開Kotlin協程的神秘面紗2018-08-08Kotlin
- 揭開計算機的神祕面紗2015-02-28計算機
- 『MySQL』揭開索引神祕面紗2019-02-26MySql索引
- HTML5移動遊戲開發高階程式設計 2:從玩具到遊戲2018-02-15HTML遊戲開發程式設計
- 什麼牌子的高階遊戲本比較好?2021-10-15遊戲
- 【騰訊遊戲-深圳】Golang高階工程師2018-01-22遊戲Golang工程師
- 掀起 OPEN API 的面紗2008-07-18API
- HTML5移動遊戲開發高階程式設計 10:自建Quintus引擎(2)2018-02-18HTML遊戲開發程式設計UI
- Steam遊戲《Northgard(北境之地)》修改器製作2021-06-07遊戲
- 揭開redux,react-redux的神祕面紗2019-03-03ReduxReact
- 揭開Future的神祕面紗——任務取消2018-09-04
- 揭開MSSQL---extents內部的神秘面紗2016-06-10SQL
- 文案唯美,畫面驚豔,現象級遊戲如何打造?2020-01-17遊戲
- 掠奪者Predator 8圖賞 再掀遊戲浪潮2016-02-20遊戲
- 再掀遊戲浪潮?掠奪者Predator 8評測2016-02-20遊戲
- 解鎖 2022 Google 遊戲開發者峰會 | 打造高質量的遊戲體驗2022-04-13Go遊戲開發
- 揭開java記憶體模型的神祕面紗2020-01-12Java記憶體模型
- 《吃透MQ系列》之扒開Kafka的神祕面紗2021-06-21MQKafka
- 揭開Future的神祕面紗——任務執行2018-11-03
- 揭開AI、機器學習和深度學習的神秘面紗2020-11-04AI機器學習深度學習
- 揭開單體應用程式的神祕面紗2022-06-08
- Java高階面試-面經2020-11-30Java面試
- 揭開神秘面紗——深入淺出ThreadLocal2021-09-09thread
- HTML5遊戲開發進階 8 :新增更多的遊戲元素2018-02-13HTML遊戲開發
- HTML5遊戲開發進階 2 :建立基本的遊戲世界2018-02-09HTML遊戲開發