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標籤,格式上看起來都要舒服很多。 凡是都要知道,變量需要先定義後使用,如果你把上面這些代碼直接複製到程序裡,是行不通的,呵呵。 這一節到此結束,下一節我們進行界面設計和其他信息處理。 |
全站熱搜
留言列表