close
環境: Windows XP SP2   ,Borland C++ Builder 平台下編譯通過
對像目標: 
網絡遊戲  武林外傳 

上一節只說到從顏色方面入做掛,這一節開始講從分析遊戲內存做掛。
武林外傳遊戲進程 
elementclient.exe  沒有加殼,這對我們分析有很大好處。可以CE分析遊戲內存,也可以用OD 調試遊戲。
CE 全名 
Cheat Engine  ,是一款強大的分析遊戲內存的<SPAN class="t_tag" onclick=tagshow(event) 
href="tag.php?name=%A4u%A8%E3">工具,當然也有其他工具,不過我只熟悉這個,呵呵。
OD 全名 
Ollydbg  ,一款調試工具。我們用它可以分析遊戲的Call 
和一些偏移等。

CE的用法,大可以到廣海遊戲上看詳細教程,這裡就不貼上了,地址是
http://www.ghoffice.com/bbs/thre ... 
sc-DESC-page-1.html

其實廣海上面有很<SPAN class="t_tag" 
onclick=tagshow(event) href="tag.php?name=%B0%AA%A4%E2">高手的帖子和一些<SPAN 
class=t_tag onclick=tagshow(event) 
href="tag.php?name=%B8g%C5%E7">經驗方法帖,還有很多教程帖,<SPAN class="t_tag" 
onclick=tagshow(event) 
href="tag.php?name=%B7s%A4%E2">新手們可以從那裡起步學習基礎分析與製作,告訴大家哈,我也是從那裡開始的,呵呵。
為我們這裡只是講外掛製作,分析的地方很少,所以大部分的分析,我只是簡單的帶過,如需要詳細的<SPAN 
class=t_tag onclick=tagshow(event) 
href="tag.php?name=%B8%EA%AE%C6">資料,可以到廣海上搜索一下,很多的。

如何設計一個外掛,對很多新手想必是一個頭疼的問題,除了一開始要大量的分析外,程序製作部分也是一個難關。那麼多編譯工具,該選擇哪一款呢,這裡,我推薦初學者選擇VB 
,有一定基礎的可以直接選擇C++ ,其Borland C++ Builder 就是一個不錯的編譯工具。使用方法和VB一樣簡單。而VC++ 
則是需要熟悉界面的製作才推薦選擇。VB 版的武林助手源碼以前發過,這裡就不再發了,我們直接用C++ 
開始製作新版的掛,也就是武林小秘。

假設前提我們已經得到了足夠的信息和資料,例如基址,偏移等。
那麼我們開始來試著讀取一個偏移地址,例如<SPAN 
class=t_tag onclick=tagshow(event) 
href="tag.php?name=%A4H%AA%AB">人物的血值。
讀取武林172版人物血值,首先打開BCB,開啟後都會<SPAN 
class=t_tag onclick=tagshow(event) 
href="tag.php?name=%A6%DB%B0%CA">自動建立一個新的工程,我們就不新建了,在控件欄出選擇按鈕,在口裡畫出一個合適大小的按鈕來,再選擇Lable控件,照樣畫在窗口上,雙擊按鈕,進入按鈕<SPAN 
class=t_tag onclick=tagshow(event) 
href="tag.php?name=%A5N%BDX">代碼部分。
想要讀取其他進程的信息,我們首先要獲得這個進程的ID,然後打開進程,獲取信息,最後關閉打開的進程句柄。
這裡假設遊戲的基址是 
0x930014  ,這個是BCB裡十六進制的寫法,以後都會這樣寫。
一級偏移是 0x24 ,人物當前血值的偏移是 0x25C 
,下面開始寫代碼
在按鈕的代碼部分寫如下代碼:

DWORD eax,ecx,HP;
HANDLE mProcID;
DWORD 
hProcId;
HWND GameFormHwnd;
GameFormHwnd=FindWindow("QElementClient 
Window", "Element Client");

    
GetWindowThreadProcessId(GameFormHwnd,hProcId);
    
  
  mProcID = OpenProcess(PROCESS_ALL_ACCESS, false, hProcId);
  
  ReadProcessMemory(mProcID, LPVOID(0x930014), eax, 4, 0);
    
ReadProcessMemory(mProcID, LPVOID(eax + 0x1C), ecx, 4, 0);
    
ReadProcessMemory(mProcID, LPVOID(ecx + 0x24), eax, 4, 0);
    
ReadProcessMemory(mProcID, LPVOID(eax + 0x25C), HP, 4, 0);
    
Label1->Caption= IntToStr(HP);

    
CloseHandle(mProcID);

到這裡,啟動程序,就可以讀取人物當前的血值了。
下面對上面的代碼進行解釋:

DWORD 
eax,ecx,HP;  定義DWORD類型的變量,就是無符號整形變量。

HANDLE 
mProcID;  定義HANDLE 類型的句柄變量

HWND GameFormHwnd;   定義 
HWND 類型窗口句柄變量

GameFormHwnd=FindWindow("QElementClient Window", "Element 
Client"); 
利用API函數  FindWindow 我們可以得到遊戲窗口的句柄,QElementClient Window 
是類名,Element Client 是窗口標題 


GetWindowThreadProcessId(GameFormHwnd,hProcId);  進一步獲得進程Pid 
。這個很重要,我們是對進程操作,所以必須要得到進程Pid 。

mProcID = OpenProcess(PROCESS_ALL_ACCESS, 
false, 
hProcId);
這裡是打開進程,我們操作其他進程或者和其他進程通信,都必須先打開這個進程,這是Windows的死規定。

ReadProcessMemory(mProcID, 
LPVOID(0x930014), eax, 4, 0);
    ReadProcessMemory(mProcID, 
LPVOID(eax + 0x1C), ecx, 4, 0);
    ReadProcessMemory(mProcID, 
LPVOID(ecx + 0x24), eax, 4, 0);
    ReadProcessMemory(mProcID, 
LPVOID(eax + 0x25C), HP, 4, 0);
這裡就是開始讀取內存的地方了,利用ReadProcessMemory  
API函數讀取遊戲進程的內容。從上至下就是指針的順序  
基址>一級偏移>級偏移>人物血值偏移

Label1->Caption= 
IntToStr(HP);   把獲得的值 HP 
轉換成字符類型,並賦值給Lable1的Caption屬

CloseHandle(mProcID);  
關閉打開的進程,有打開必有關閉,不然會造成資源浪費,後果很嚴重。

上面紅色部分,就是我們需要獲取信息的部分,在下面還可以獲取更多的信息,例如:
ReadProcessMemory(mProcID, 
LPVOID(eax + 0x250), ManLv, 4, 0);    //0x24C 人物<SPAN class="t_tag" 
onclick=tagshow(event) href="tag.php?name=%B5%A5%AF%C5">等級
  
  ReadProcessMemory(mProcID, LPVOID(eax + 0x398), mex, 4, 0);  
//<SPAN class="t_tag" onclick=tagshow(event) 
href="tag.php?name=%A9%C7%AA%AB">怪物名字偏移
    
ReadProcessMemory(mProcID, LPVOID(mex), mname, 64, 0);    
//存放字符的地址,讀取後就是怪物的名字,(注意mex 變量需要先定義)
    ReadProcessMemory(mProcID, 
LPVOID(eax + 0x25C), HP, 4, 0);        //596 
當前體力  紅
    ReadProcessMemory(mProcID, LPVOID(eax + 
0x260), MP, 4, 0);        //600 
當前內力  藍
    ReadProcessMemory(mProcID, LPVOID(eax + 
0x274), MaxHP, 4, 0);     //620 最大血值
    
ReadProcessMemory(mProcID, LPVOID(eax + 0x278), MaxMP, 4, 0);  
   //624 最大內力值
    ReadProcessMemory(mProcID, 
LPVOID(eax + 0x2DC), Money, 4, 0);     //724 當前錢值
  
  ReadProcessMemory(mProcID, LPVOID(eax + 0x7D4), GWID, 4, 0);    
//120版 偏移加 8 或地址 0x0354AF44 當前目標怪物ID ,為負就是怪,為正就是NPC或<SPAN class="t_tag" 
onclick=tagshow(event) 
href="tag.php?name=%AA%B1%AEa">玩家,為0則怪物死亡,或沒有選擇怪物.
    
ReadProcessMemory(mProcID, LPVOID(eax + 0x264), Exp, 4, 0);  
   //0x25C 當前經驗值,十進制
    ReadProcessMemory(mProcID, 
LPVOID(eax + 0x2D8), GJDis, 4, 0);
    //升級經驗值是一個地址 加 
人物等級*4
    ReadProcessMemory( mProcID, LPVOID(MaxExpAdr + ManLv * 
0x4), MaxExp, 4, 0);      //0x930 人物升級經驗值,十進制(MaxExpAdr 
需要另外分析尋找)
    //ReadProcessMemory( mProcID, LPVOID(0x6020630), 
MaxExp, 4, 0);
    ReadProcessMemory( mProcID, LPVOID(eax + 0x3C), 
Mx, 4, 0);      //人物坐標 x  float 4字節
  
  ReadProcessMemory( mProcID, LPVOID(eax + 0x44), My, 4, 0);  
    //人物坐標 y  float 
4字節
這裡是一些基本的人物信息,在BCB裡面讀取遊戲內存,一般就是這個模式: 
找到需要處理的窗口的句柄,獲取該句柄指向的進程Pid,打開進程,讀取信息,關閉打開的進程。

這裡要說下,LPVOID(eax + 
0x44)  這個地方必須進程強制類型轉換,不然可能會出錯而無法編譯。LPVOID 的意思就是強制轉換為無類型指針 
類型。

一個Lable 標籤可以對應一個<SPAN class="t_tag" onclick=tagshow(event) 
href="tag.php?name=%BC%C6%BE%DA">數據顯示,當然也可以都顯示在一個標籤裡,不過不推薦,有多少個數據需要顯示,就應該每行畫出一個Lable標籤,格式上看起來都要舒服很多。

凡是都要知道,變量需要先定義後使用,如果你把上面這些代碼直接複製到程序裡,是行不通的,呵呵。


這一節到此結束,下一節我們進行界面設計和其他信息處理。
 
 
arrow
arrow
    全站熱搜
    創作者介紹
    創作者 UM程式研究日誌 的頭像
    UM程式研究日誌

    UM程式研究日誌

    UM程式研究日誌 發表在 痞客邦 留言(0) 人氣()