sbsummer(原作)
各位朋友大家好,嗷嗷,我第一次在這裡發文章,好高興
本人技術有限,不要笑話,如有錯誤請您告訴我一聲[em09]。
剛才我玩了幾把瘋狂坦克,輸了好幾盤,覺得無聊就搞搞這個,下面開始說說如何得到遊戲中的動態資料(
地址改變),以得到瘋狂坦克中坦克X座標為例
------------------------------------------------------------------------------
工具:
SoftICE動態除錯程式,遊戲修改工具(金山遊俠),反彙編(W32Dasm),Hex Workshop
------------------------------------------------------------------------------
一、找到記憶體中坦克X座標
1、用金山遊俠搜尋,方法如下(金山遊俠的使用我就不說了)
把坦克往左移動一些,就搜尋“減少”;坦克往右移動,就搜尋“增大”
反覆搜尋將會找到一個地址(當然其他遊戲可能不止一個),這裡是08BFAACC
注:動態的記憶體分配就是下次你如果再次搜尋,地址將不再是08BFAACC
2、找到那條程式碼修改了這個資料(X座標)
載入 SoftIce
在遊戲狀態 Ctrl+D 調出SoftIce,輸入 BPM 08BFAACC W,這裡的W表示如果這個地址被寫將中斷
回到遊戲,移動坦克,左移一下,程式中斷,SoftIce指向的上面一句是
004640B3
MOV DWORD PTR [ESI+000001A4],EAX
這句就是修改坦克座標的程式碼,當然右移也能找到一句,這裡就不重複了
3、修改程式使動態的資料變成靜態
這裡說點題外話,修改程式包括兩種,一種是直接修改程式,一種是修改記憶體中的程式(記憶體補丁)
,這裡由於我懶,所以用了第一種
修改程式:
瘋狂坦克程式存在Fortress2.dat當中,如果你把這個檔案改名為EXE檔案一樣可以執行,這裡我
們就把他修改成Fortress2.exe
開啟W32Dasm反彙編,SHIFT+F12跳到004046B3,你看到這幾行
004046B3 8986A4010000 MOV DWORD PTR
[ESI+000001A4],EAX
004046B9 8B8644020000
MOV EAX,DWORD PTR [ESI+00000244]
004046BF C744241001000000
MOV [ESP+10],00000001
剛才我們說了004046B3是修改X座標的那條語句,現在我們要讓他每次修改完程式就能夠把X座標
儲存到一個固定的地址
現在要讓它執行到這裡就JMP到一個我們自己的程式碼的地方,於是在程式的尾部我們找到一段空
白的區域00465A52,於是我修改004046BF為程式碼 JMP 00465A52,機器碼為E98E130600,因為這句的長度不夠以前的那句長,所以要加入幾個NOP,機器碼為90,所以我們開啟HEX
Workshop修改程式,CTRL+G跳到位移為000046BF的地方,看到了C744241001000000,我們把它修改為E98E130600909090,現在程式將一執行到這裡就跳到00465A52執行我們的程式碼。
4、實現我們自己的程式碼,然後跳回
我們的程式碼要做的是把動態變成靜態,
PUSH EAX
MOV EAX,[ESI+000001A4]
MOV [00470000],EAX
POP EAX
JMP 004046C7
這樣這個數值無論執行多少次,只要你移動(當然右移也要修改)就能在00470000中找到X座標
,這段機器碼為50 8B86A4010000
A300004700 58 E95BECF9FF
忘了說剛才我們把004046BF替換掉的那句MOV
[ESP+10],00000001也必須加上,所以開啟HEX
Workshop,CTRL+G跳到00465A52,修改加入
C744241001000000 50 8B86A4010000 A300004700 58 E95BECF9FF
這樣動態資料就變成了靜態
------------------------------------------------------------------------------
現在回顧一下
.首先搜尋座標地址
.找到改變這個地址的程式碼
.修改程式碼讓他跳到自己的程式碼中執行
.在程式的空白段加入自己的程式碼,當然要補上被替換了的那句,還有修改了暫存器,必須先
PUSH,再POP
下面的工作就是寫一個程式讀取這個地址了,我用VC寫了一個,順便貼一下關鍵程式碼
------------------------------------------------------------------------------
CProcess m_process;
bool m_ret
= m_process.FindProcess("FortressII");
if (m_ret)
{
BYTE
tank1xL = m_process.ReadByte(0x00470000);
BYTE tank1xR = m_process.ReadByte(0x00470001);
WORD tank1x = tank1xL+tank1xR*256;
temp = tank1x;
str.Format("%d",temp);
m_tank1x=str;
UpdateData(FALSE);
return TRUE;
}
else return FALSE;
-----------------------------------------------------------------------------
CProcess是一個我編寫的修改類,這裡用到的函式程式碼如下
HANDLE CProcess::OpenProcess(char *p_ClassName,
char *p_WindowTitle)
{
HWND hWindow;
DWORD pid;
hWindow
= FindWindow(p_ClassName, p_WindowTitle);
if (hWindow) {
GetWindowThreadProcessId(hWindow,
&pid);
return ::OpenProcess(PROCESS_ALL_ACCESS, false,
pid);
}
return NULL;
}
bool CProcess::FindProcess(char
*p_WindowTitle)
{
if (m_hProcess == NULL) {
m_hProcess
= this->OpenProcess(NULL, p_WindowTitle);
if (m_hProcess)
m_bGameRunning
= true;
return m_bGameRunning;
}
else
return
false;
}
BYTE CProcess::ReadByte(DWORD p_Address)
{
DWORD
bytes;
BYTE tmpValue;
if (m_bGameRunning) {
if
(ReadProcessMemory(m_hProcess, (void*)p_Address,
(void *)&tmpValue, 1, &bytes) == 0)
return
0;
else
return
tmpValue;
}
return 0;
}