線上訂房服務-台灣趴趴狗聯合訂房中心
發文 回覆 瀏覽次數:13631
推到 Plurk!
推到 Facebook!

遊戲外掛指南

 
conundrum
尊榮會員


發表:893
回覆:1272
積分:643
註冊:2004-01-06

發送簡訊給我
#1 引用回覆 回覆 發表時間:2005-02-09 02:45:09 IP:218.175.xxx.xxx 未訂閱
) 遊戲外掛指南
http://www.donews.net/eb/archive/2004/07/09/39944.aspx    要想在修改遊戲中做到百戰百勝,是需要相當豐富的電腦知識的。
有很多電腦高手就是從玩遊戲,修改遊戲中,逐步對電腦產生濃厚的興趣,逐步成長起來的。
不要在羡慕別人能夠做到的,因為別人能夠做的你也能夠!我相信你們看了本教
程後,會對遊戲有一個全新的認識,呵呵,因為我是個好老師!
(別拿雞蛋砸我呀,救命啊!#¥%……*) 不過要想從修改遊戲中學到知識,
增加自己的電腦水準,可不能只是靠修改遊戲呀!要知道,修改遊戲只是一個驗
證你對你所瞭解的某些電腦知識的理解程度的場所,只能給你一些發現問題、
解決問題的機會,只能起到幫助你提高學習電腦的興趣的作用,而決不是學習電腦的捷徑。     一:什麼叫外掛? 
  現在的網路遊戲多是基於Internet上客戶/伺服器模式,服務端程式運行在
遊戲伺服器上,遊戲的設計者在其中創造一個龐大的遊戲空間,各地的玩家可以
通過運行用戶端程式同時登錄到遊戲中。
簡單地說,網路遊戲實際上就是由遊戲開發商提供一個遊戲環境,而玩家們就是在這個環境中相對自由和開放地進行遊戲操作。
那麼既然在網路遊戲中有了伺服器這個概念,我們以前傳統的修改遊戲方法就顯
得無能為力了。記得我們在單機版的遊戲中,隨心所欲地通過記憶體搜索來修改
角色的各種屬性,這在網路遊戲中就沒有任何用處了。
因為我們在網路遊戲中所扮演角色的各種屬性及各種重要資料都存放在伺服器
上,在我們自己機器上(用戶端)只是顯示角色的狀態,所以通過修改用戶端記
憶體裏有關角色的各種屬性是不切實際的。
那麼是否我們就沒有辦法在網路遊戲中達到我們修改的目的?回答是"否"。
  我們知道Internet客戶/伺服器模式的通訊一般採用TCP/IP通信協定,
資料交換是通過IP資料包的傳輸來實現的,一般來說我們用戶端向伺服器發出
某些請求,比如移動、戰鬥等指令都是通過封包的形式和伺服器交換資料。
那麼我們把本地發出消息稱為SEND,意思就是發送資料,伺服器收到我們SEND
的消息後,會按照既定的程式把有關的資訊回饋給用戶端,比如,移動的座標,
戰鬥的類型。那麼我們把用戶端收到伺服器發來的有關消息稱為RECV。
知道了這個道理,接下來我們要做的工作就是分析用戶端和伺服器之間往來的資
料(也就是封包),這樣我們就可以提取到對我們有用的資料進行修改,然後類
比伺服器發給用戶端,或者模擬用戶端發送給伺服器,這樣就可以實現我們修改
遊戲的目的了。
  目前除了修改遊戲封包來實現修改遊戲的目的,我們也可以修改用戶端的有
關程式來達到我們的要求。我們知道目前各個伺服器的運算能力是有限的,
特別在遊戲中,遊戲伺服器要計算遊戲中所有玩家的狀況幾乎是不可能的,
所以有一些運算還是要依靠我們用戶端來完成,這樣又給了我們修改遊戲提供了
一些便利。比如我們可以通過將用戶端程式脫殼來發現一些程式的判斷分支,
通過跟蹤調試我們可以把一些對我們不利的判斷去掉,以此來滿足我們修改遊戲
的需求。 在下幾個章節中,我們將給大家講述封包的概念,和修改跟蹤用戶端
的有關知識。大家準備好了嗎?  
  
  遊戲資料格式和存儲: 
  在進行我們的工作之前,我們需要掌握一些關於電腦中儲存資料方式的知識
和遊戲中儲存資料的特點。本章節是提供給菜鳥級的玩家看的,如果你是高手就
可以跳過了,如果,你想成為無堅不摧的劍客,那麼,這些東西就會花掉你一些
時間;如果,你只想作個江湖的遊客的話,那麼這些東西,瞭解與否無關緊要。
是作劍客,還是作遊客,你選擇吧! 
  現在我們開始!首先,你要知道遊戲中儲存資料的幾種格式,
這幾種格式是:位元組(BYTE)、字(WORD)和雙字(DOUBLE WORD),
或者說是8位、16位元和32位元儲存方式。位元組也就是8位元方式能儲存0~255的數位;
字或說是16位元儲存方式能儲存0~65535的數;雙字即32位元方式能儲存0~4294967295的數。 
  為何要瞭解這些知識呢?在遊戲中各種參數的最大值是不同的,有些可能
100左右就夠了,比如,金庸群俠傳中的角色的等級、隨機遇敵個數等等。
而有些卻需要大於255甚至大於65535,象金庸群俠傳中角色的金錢值可達到數百萬。
所以,在遊戲中各種不同的資料的類型是不一樣的。在我們修改遊戲時需要尋找
準備修改的資料的封包,在這種時候,正確判斷資料的類型是迅速找到正確位址的重要條件。 
  在電腦中資料以位元組為基本的儲存單位,每個位元組被賦予一個編號,
以確定各自的位置。
這個編號我們就稱為位址。 在需要用到字或雙字時,電腦用連續的兩個位元組
來組成一個字,連續的兩個字組成一個雙字。
而一個字或雙字的位址就是它們的低位元位元組的位址。 
現在我們常用的Windows 9x作業系統中,位址是用一個32位的二進位數字表示的。
而在平時我們用到記憶體位址時,總是用一個8位的16進制數來表示它。 
  
  二進位和十六進位又是怎樣一回事呢? 
  簡單說來,二進位數字就是一種只有0和1兩個數碼,每滿2則進一位的計數進位法。
同樣,16進制就是每滿十六就進一位的計數進位法。
16進制有0--F十六個數位,它為表示十到十五的數位採用了A、B、C、D、E、F六個數位,
它們和十進位的對應關係是:A對應於10,B對應於11,C對應於12,D對應
於13,E對應於14,F對應於15。而且,16進制數和二進位數字間有一個簡單
的對應關係,那就是;四位二進位數字相當於一位16進制數。比如,一個四位
的二進位數字1111就相當於16進制的F,1010就相當於A。 
  瞭解這些基礎知識對修改遊戲有著很大的幫助,下面我就要談到這個問題。
由於在電腦中資料是以二進位的方式儲存的,同時16進制數和二進位間的轉換
關係十分簡單,所以大部分的修改工具在顯示電腦中的資料時會顯示16進制的
代碼,而且在你修改時也需要輸入16進制的數位。你清楚了吧?       在遊戲中看到的資料可都是十進位的,在要尋找並修改參數的值時,
可以使用Windows提供的計算器來進行十進位和16進制的換算,
我們可以在開始功能表裏的程式組中的附件中找到它。 
現在要瞭解的知識也差不多了!不過,有個問題在遊戲修改中是需要注意的。
在電腦中資料的儲存方式一般是低位元數儲存在低位元位元組,高位數儲存在高
位位元組。比如,十進位數字41715轉換為16進制的數為A2F3,但在電腦中這個數被存為F3A2。 
  看了以上內容大家對資料的存貯和資料的對應關係都瞭解了嗎? 
好了,接下來我們要告訴大家在遊戲中,封包到底是怎麼一回事了,來!大家把袖口卷起來,讓我們來幹活吧!       二:什麼是封包? 
  怎麼截獲一個遊戲的封包?怎麼去檢查遊戲伺服器的ip地址和埠號? 
Internet用戶使用的各種資訊服務,其通訊的資訊最終均可以歸結
為以IP包為單位的資訊傳送,IP包除了包括要傳送的資料資訊外,
還包含有資訊要發送到的目的IP位址、資訊發送的源IP位址、以及一些相關的控制資訊。
當一台路由器收到一個IP資料包時,它將根據資料包中的目的IP位址項查找路由表,根據查找的結果將此IP資料包送往對應埠。
下一台IP路由器收到此資料包後繼續轉發,直至發到目的地。
路由器之間可以通過路由協定來進行路由資訊的交換,從而更新路由表。
 那麼我們所關心的內容只是IP包中的資料資訊,我們可以使用許多監聽網路的
工具來截獲用戶端與伺服器之間的交換資料,下面就向你介紹其中的一種工具:
WPE。     WPE使用方法:執行WPE會有下列幾項功能可選擇: 
SELECT GAME選擇目前在記憶體中您想攔截的程式,
您只需雙擊該程式名稱即可。 
TRACE追蹤功能。用來追蹤擷取程式送收的封包。
WPE必須先完成點選欲追蹤的程式名稱,才可以使用此項目。 
按下Play鍵開始擷取程式收送的封包。您可以隨時按下 | | 暫停追蹤,想繼續時
請再按下 | | 。按下正方形可以停止擷取封包並且顯示所有已擷取封包內容。
若您沒按下正方形停止鍵,追蹤的動作將依照OPTION裏的設定值自動停止。
如果您沒有擷取到資料,試試將OPTION裏調整為Winsock Version 2。
WPE 及 Trainers 是設定在顯示至少16 bits 顏色下才可執行。 
FILTER過濾功能。用來分析所擷取到的封包,並且予以修改。 
SEND PACKET送出封包功能。能夠讓您送出假造的封包。 
TRAINER MAKER製作修改器。 
OPTIONS設定功能。讓您調整WPE的一些設定值。 
FILTER的詳細教學 - 當FILTER在啟動狀態時 ,ON的按鈕會呈現紅色。- 
當您啟動FILTER時,您隨時可以關閉這個視窗。
FILTER將會保留在原來的狀態,直到您再按一次 on / off 鈕。
- 只有FILTER啟用鈕在OFF的狀態下,才可以勾選Filter前的方框來編輯修改。
- 當您想編輯某個Filter,只要雙擊該Filter的名字即可。 
NORMAL MODE: 
範例: 
當您在 Street Fighter Online 
﹝快打旋風線上版﹞遊戲中,您使用了兩次火球而且擊中了對方,
這時您會擷取到以下的封包:
SEND-> 0000 08 14 21 06 01 04 
SEND-> 0000 02 09 87 00 67 FF A4 AA 11 22 00 00 00 00 
SEND-> 0000 03 84 11 09 11 09 
SEND-> 0000 0A 09 C1 10 00 00 FF 52 44 
SEND-> 0000 0A 09 C1 10 00 00 66 52 44 
  您的第一個火球讓對方減了16滴﹝16 = 10h﹞的生命值,
而您觀察到第4跟第5個封包的位置4有10h的值出現,應該就是這裏了。 
  您觀察10h前的0A 09 C1在兩個封包中都沒改變,
可見得這3個數值是發出火球的關鍵。 
  因此您將0A 09 C1 10填在搜尋列﹝SEARCH﹞,然後在修改列﹝MODIFY﹞的位置4填上FF。
如此一來,當您再度發出火球時,FF會取代之前的10,也就是攻擊力為255的火球了! 
ADVANCED MODE: 
範例: 
  當您在一個遊戲中,您不想要用真實姓名,您想用修改過的假名傳送給對方。
在您使用TRACE後,您會發現有些封包裏面有您的名字出現。
假設您的名字是Shadow,換算成16進位則是﹝53 68 61 64 6F 77﹞;
而您打算用moon﹝6D 6F 6F 6E 20 20﹞來取代他。
SEND-> 0000 08 14 21 06 01 04 
SEND-> 0000 01 06 99 53 68 61 64 6F 77 00 01 05   
SEND-> 0000 03 84 11 09 11 09 
SEND-> 0000 0A 09 C1 10 00 53 68 61 64 6F 77 00 11  
SEND-> 0000 0A 09 C1 10 00 00 66 52 44 
  但是您仔細看,您的名字在每個封包中並不是出現在相同的位置上 – 
在第2個封包裏,名字是出現在第4個位置上- 在第4個封包裏,
名字是出現在第6個位置上 在這種情況下,
您就需要使用ADVANCED MODE- 您在搜尋列﹝SEARCH﹞填上:53 68 61 64 6F 77 
﹝請務必從位置1開始填﹞- 
您想要從原來名字Shadow的第一個字母開始置換新名字,
因此您要選擇從數值被發現的位置開始替代連續數值
﹝from the position of the chain found﹞。- 
現在,在修改列﹝MODIFY﹞000的位置填上:6D 6F 6F 6E 20 20 
﹝此為相對應位置,也就是從原來搜尋欄的 001位置開始遞換﹞- 
如果您想從封包的第一個位置就修改數值,
請選擇﹝from the beginning of the packet﹞       瞭解一點TCP/IP協議常識的人都知道,互聯網是將資訊資料打包之後再傳送出去的。
每個資料包分為頭部資訊和資料資訊兩部分。
頭部資訊包括資料包的發送位址和到達位址等。
資料資訊包括我們在遊戲中相關操作的各項資訊。
那麼在做截獲封包的過程之前我們先要知道遊戲伺服器的IP位址
和埠號等各種資訊,實際上最簡單的是看看我們遊戲目錄下,
是否有一個SERVER.INI的配置檔,這個檔裏你可以查看到個遊戲伺服器
的IP位址,比如金庸群俠傳就是如此,
那麼除了這個我們還可以在DOS下使用NETSTAT這個命令, 
  NETSTAT命令的功能是顯示網路連接、路由表和網路介面資訊,
可以讓用戶得知目前都有哪些網路連接正在運作。
或者你可以使用木馬客星等工具來查看網路連接。工具是很多的,
看你喜歡用哪一種了。 
  NETSTAT命令的一般格式為:NETSTAT [選項] 
  命令中各選項的含義如下:-a 顯示所有socket,包括正在監聽的。
-c 每隔1秒就重新顯示一遍,直到用戶中斷它。-i 顯示所有網路介面的資訊。
-n 以網路IP位址代替名稱,顯示出網路連接情形。
-r 顯示核心路由表,格式同"route -e"。-t 
顯示TCP協定的連接情況。-u 顯示UDP協定的連接情況。
-v 顯示正在進行的工作。       三:怎麼來分析我們截獲的封包? 
  首先我們將WPE截獲的封包保存為文字檔案,然後打開它,
這時會看到如下的資料
(這裏我們以金庸群俠傳裏PK店小二用戶端發送的資料為例來講解):     第一個文件:SEND-> 0000 E6 56 0D 22 7E 6B E4 17 13 13 12 13 12 13 67 1B
SEND-> 0010 17 12 DD 34 12 12 12 12 17 12 0E 12 12 12 9B
SEND-> 0000 E6 56 1E F1 29 06 17 12 3B 0E 17 1A
SEND-> 0000 E6 56 1B C0 68 12 12 12 5A
SEND-> 0000 E6 56 02 C8 13 C9 7E 6B E4 17 10 35 27 13 12 12
SEND-> 0000 E6 56 17 C9 12 
第二個檔:
SEND-> 0000 83 33 68 47 1B 0E 81 72 76 76 77 76 77 76 02 7E
SEND-> 0010 72 77 07 1C 77 77 77 77 72 77 72 77 77 77 6D
SEND-> 0000 83 33 7B 94 4C 63 72 77 5E 6B 72 F3
SEND-> 0000 83 33 7E A5 21 77 77 77 3F
SEND-> 0000 83 33 67 AD 76 CF 1B 0E 81 72 75 50 42 76 77 77
SEND-> 0000 83 33 72 AC 77       我們發現兩次PK店小二的資料格式一樣,但是內容卻不相同,
我們是PK的同一個NPC,為什麼會不同呢? 
原來金庸群俠傳的封包是經過了加密運算才在網路上傳輸的,
那麼我們面臨的問題就是如何將密文解密成明文再分析了。 
  因為一般的資料包加密都是異或運算,所以這裏先講一下什麼是異或。 
簡單的說,異或就是"相同為0,不同為1"(這是針對二進位按位元來講的),
舉個例子,0001和0010異或,我們按位對比,得到異或結果是0011,
計算的方法是:0001的第4位為0,0010的第4位為0,它們相同,
則異或結果的第4位按照"相同為0,不同為1"的原則得到
0,0001的第3位為0,0010的第3位為0,
則異或結果的第3位得到0,0001的第2位為0,0010的第2位為1,
則異或結果的第2位得到1,0001的第1位為1,0010的第1位為0,
則異或結果的第1位元得到1,組合起來就是0011。
異或運算今後會遇到很多,大家可以先熟悉熟悉,熟練了對分析很有幫助的。 
下面我們繼續看看上面的兩個檔,按照常理,資料包的資料不會全部都有值的,
遊戲開發時會預留一些位元組空間來便於日後的擴充,也就是說資料包裏會存在
一些"00"的位元組,觀察上面的檔,我們會發現檔一裏很多"12",檔二裏很多
"77",那麼這是不是代表我們說的"00"呢?推理到這裏,我們就開始行動吧! 
  我們把檔一與"12"異或,檔二與"77"異或,當然用手算很費事,我們使用
"M2M 1.0 加密封包分析工具"來計算就方便多了。得到下面的結果: 
  第一個文件:
SEND-> 0000 F4 44 1F 30 6C 79 F6 05 01 01 00 01 00 01 75 09
SEND-> 0010 05 00 CF 26 00 00 00 00 05 00 1C 00 00 00 892 SEND-> 0000 F4 44 0C E3 3B 13 05 00 29 1C 05 083 
SEND-> 0000 F4 44 09 D2 7A 00 00 00 484 
SEND-> 0000 F4 44 10 DA 01 DB 6C 79 F6 05 02 27 35 01 00 005 SEND-> 0000 F4 44 05 DB 00       第二個檔:
SEND-> 0000 F4 44 1F 30 6C 79 F6 05 01 01 00 01 00 01 75 09
SEND-> 0010 05 00 70 6B 00 00 00 00 05 00 05 00 00 00 1A2 SEND-> 0000 F4 44 0C E3 3B 13 05 00 29 1C 05 843 
SEND-> 0000 F4 44 09 D2 56 00 00 00 484 
SEND-> 0000 F4 44 10 DA 01 B8 6C 79 F6 05 02 27 35 01 00 005 SEND-> 0000 F4 44 05 DB 00 
  哈,這一下兩個檔大部分都一樣啦,說明我們的推理是正確的,
上面就是我們需要的明文! 
  接下來就是搞清楚一些關鍵的位元組所代表的含義,這就需要截獲大量的資料來分析。 
  首先我們會發現每個資料包都是"F4 44"開頭,第3個位元組是變化的,
但是變化很有規律。
我們來看看各個包的長度,發現什麼沒有?對了,第3個位元組就是包的長度! 
  通過截獲大量的資料包,我們判斷第4個位元組代表指令,
也就是說用戶端告訴伺服器進行的是什麼操作。例如向伺服器請求戰鬥指令為
"30",戰鬥中移動指令為"D4"等。 
接下來,我們就需要分析一下上面第一個包
"F4 44 1F 30 6C 79 F6 05 01 01 00 01 00 01 75 09 05 00 CF 26 00 00 00 00 05 00 1C 00 00 00 89",
在這個包裏包含什麼資訊呢?應該有通知伺服器你PK的哪個NPC吧,
我們就先來找找這個店小二的代碼在什麼地方。 
我們再PK一個小嘍羅(就是大理客棧外的那個咯)
:SEND-> 0000 F4 44 1F 30 D4 75 F6 05 01 01 00 01 00 01 75 09 
SEND-> 0010 05 00 8A 19 00 00 00 00 11 00 02 00 00 00 C0 
我們根據常理分析,遊戲裏的NPC種類雖然不會超過65535(FFFF)
,但開發時不會把自己限制在字的範圍,那樣不利於遊戲的擴充,
所以我們在雙字裏看看。通過"店小二"和"小嘍羅"兩個包的對比,我們把目標放
在"6C 79 F6 05"和"CF 26 00 00"上。
(對比一下很容易的,但你不能太遲鈍咯,呵呵)
我們再看看後面的包,在後面的包裏應該還會出現NPC的代碼,
比如移動的包,遊戲允許觀戰,伺服器必然需要知道NPC的移動座標,
再廣播給觀戰的其他玩家。在後面第4個包
"SEND-> 0000 F4 44 10 DA 01 DB 6C 79 F6 05 02 27 35 01 00 00"
裏我們又看到了"6C 79 F6 05",初步斷定店小二的代碼就是它了!
(這分析裏邊包含了很多工作的,大家可以用WPE截下資料來自己分析分析)   
 第一個包的分析暫時就到這裏(裏面還有的資訊我們暫時不需要完全清楚了) 
  我們看看第4個包
"SEND-> 0000 F4 44 10 DA 01 DB 6C 79 F6 05 02 27 35 01 00 00",
再截獲PK黃狗的包,(狗會出來2只哦)看看包的格式:
SEND-> 0000 F4 44 1A DA 02 0B 4B 7D F6 05 02 27 35 01 00 00SEND-> 0010 EB 03 F8 05 02 27 36 01 00 00 
  根據上面的分析,黃狗的代碼為
"4B 7D F6 05"(100040011),不過兩隻黃狗伺服器怎樣分辨呢?
看看"EB 03 F8 05"(100140011),
是上一個代碼加上100000,呵呵,這樣伺服器就可以認出兩隻黃狗了。
我們再通過野外遇敵截獲的資料包來證實,果然如此。 
  那麼,這個包的格式應該比較清楚了:
第3個位元組為包的長度,"DA"為指令,第5個位元組為NPC個數,
從第7個位元組開始的10個位元組代表一個NPC的資訊,
多一個NPC就多10個位元組來表示。 
  大家如果玩過網金,必然知道隨機遇敵有時會出現增援,
我們就利用遊戲這個增援來讓每次戰鬥都會出現增援的NPC吧。 
  通過在戰鬥中出現增援截獲的資料包,
我們會發現伺服器端發送了這樣一個包
:F4 44 12 E9 EB 03 F8 05 02 00 00 03 00 00 00 00 00 00 
第5-第8個位元組為增援NPC的代碼(這裏我們就簡單的以黃狗的代碼來舉例)。 
那麼,我們就利用單機代理技術來同時欺騙用戶端和伺服器吧! 
  好了,呼叫NPC的工作到這裏算是完成了一小半,接下來的事情,
怎樣修改封包和發送封包,我們下節繼續講解吧。       四:怎麼冒充"用戶端"向"伺服器"發我們需要的封包? 
  這裏我們需要使用一個工具,它位於用戶端和伺服器端之間,
它的工作就是進行資料包的接收和轉發,這個工具我們稱為代理。
如果代理的工作單純就是接收和轉發的話,這就毫無意義了,但是請注意:
所有的資料包都要通過它來傳輸,這裏的意義就重大了。
我們可以分析接收到的資料包,或者直接轉發,或者修改後轉發,
或者壓住不轉發,甚至偽造我們需要的封包來發送。 
  下面我們繼續講怎樣來同時欺騙伺服器和用戶端,
也就是修改封包和偽造封包。 
通過我們上節的分析,我們已經知道了打多個NPC的封包格式,
那麼我們就動手吧! 
  首先我們要查找用戶端發送的包,找到戰鬥的特徵,
就是請求戰鬥的第1個包,我們找"F4 44 1F 30"這個特徵,
這是不會改變的,當然是要解密後來查找哦。 找到後,
表示用戶端在向伺服器請求戰鬥,我們不動這個包,轉發。
 繼續向下查找,這時需要查找的特徵碼不太好辦,我們先查找"DA",
這是用戶端發送NPC資訊的資料包的指令,那麼可能其他包也有"DA"
,沒關係,我們看前3個位元組有沒有"F4 44"就行了。找到後,我們的工作就開始了! 
  我們確定要打的NPC數量。這個數量不能很大,原因在於網金的封包長度
用一個位元組表示,那麼一個包可以有255個位元組,我們上面分析過,增加一
個NPC要增加10個位元組,所以大家算算就知道,打20個NPC比較合適。 
  然後我們要把用戶端原來的NPC代碼分析計算出來,因為增加的NPC代碼
要加上100000哦。再把我們增加的NPC代碼計算出來,並且組合成新的封包,注意代表包長度的位元組要修改啊,然後轉發到伺服器,這一步在編寫程式的時
候要注意演算法,不要造成較大延遲。 
  上面我們欺騙伺服器端完成了,欺騙用戶端就簡單了。
  發送了上面的封包後,我們根據新增NPC代碼構造封包馬上發給用戶端,
格式就是"F4 44 12 E9 NPC代碼 02 00 00 03 00 00 00 00 00 00",把每個新增的
NPC都構造這樣一個包,按順序連在一起發送給用戶端,用戶端也就被我們騙
過了,很簡單吧。 
  以後戰鬥中其他的事我們就不管了,盡情地開打吧。         遊戲外掛基本原理及實現      遊戲外掛已經深深地影響著眾多網路遊戲玩家,今天在網上看到了一些關於
遊戲外掛編寫的技術,於是轉載上供大家參考       1、遊戲外掛的原理       外掛現在分為好多種,比如類比鍵盤的,滑鼠的,修改資料包的,
還有修改本地記憶體的,但好像沒有修改伺服器記憶體的哦,呵呵。
其實修改伺服器也是有辦法的,只是技術太高一般人沒有辦法入手而已。
(比如請GM去夜總會、送禮、收黑錢等等辦法都可以修改伺服器資料,哈哈)       修改遊戲無非是修改一下本地記憶體的資料,或者截獲API函數等等。
這裏我把所能想到的方法都作一個介紹,希望大家能做出很好的外掛來使遊戲廠
商更好的完善自己的技術。我見到一篇文章是講魔力寶貝的理論分析,
寫得不錯,大概是那個樣子。下來我就講解一下技術方面的東西,以作引玉之用。       2 技術分析部分       2.1 類比鍵盤或滑鼠的回應       我們一般使用:       UINT SendInput( 
    UINT nInputs,   // count of input events 
    LPINPUT pInputs, // array of input events 
    int cbSize    // size of structure 
  );       API函數。第一個參數是說明第二個參數的矩陣的維數的,
第二個參數包含了回應事件,這個自己填充就可以,最後是這個結構的大小,
非常簡單,這是最簡單的方法類比鍵盤滑鼠了,呵呵。
注意,這個函數還有個替代函數:       VOID keybd_event( 
    BYTE bVk,       // 虛擬鍵碼 
    BYTE bScan,      // 掃描碼 
    DWORD dwFlags, 
    ULONG_PTR dwExtraInfo // 附加鍵狀態 
  );       與       VOID mouse_event( 
    DWORD dwFlags,      // motion and click options 
    DWORD dx,         // horizontal position or change 
    DWORD dy,        // vertical position or change 
    DWORD dwData,      // wheel movement 
    ULONG_PTR dwExtraInfo  // application-defined information 
  );       這兩個函數非常簡單了,我想那些按鍵精靈就是用的這個吧。
上面的是類比鍵盤,下面的是類比滑鼠的。這個僅僅是類比部分,
要和遊戲聯繫起來我們還需要找到遊戲的視窗才行,或者包含快捷鍵,
就象按鍵精靈的那個啟動鍵一樣,我們可以用GetWindow函數來枚舉視窗,
也可以用Findwindow函數來查找制定的視窗(注意,還有一個FindWindowEx),FindwindowEx可以找到視窗的子視窗,比如按鈕,等什麼東西。
當遊戲切換場景的時候我們可以用FindWindowEx來確定一些當前視窗的特徵,
從而判斷是否還在這個場景,方法很多了,比如可以GetWindowInfo來確定一些
東西,比如當查找不到某個按鈕的時候就說明遊戲場景已經切換了,等等辦法。
有的遊戲沒有控制項在裏面,這是對圖像做座標變換的話,
這種方法就要受到限制了。這就需要我們用別的辦法來輔助分析了。       至於快捷鍵我們要用動態連接庫實現了,裏面要用到hook技術了,這個也非常簡單。
大家可能都會了,其實就是一個全局的hook物件然後SetWindowHook就可以了,
回調函數都是現成的,而且現在網上的例子多如牛毛。
這個實現在外掛中已經很普遍了。如果還有誰不明白,那就去看看MSDN查找SetWindowHook就可以了。       不要低估了這個動態連接庫的作用,它可以切入所有的進程空間,
也就是可以載入到所有的遊戲裏面哦,只要用對,你會發現很有用途的。
這個需要你復習一下Win32編程的基礎知識了。呵呵,趕快去看書吧。       2.2 截獲消息       有些遊戲的回應機制比較簡單,是基於消息的,或者用什麼計時器的東西。
這個時候你就可以用攔截消息來實現一些有趣的功能了。       我們攔截消息使用的也是hook技術,裏面包括了鍵盤消息,滑鼠消息,
系統消息,日誌等,別的對我們沒有什麼大的用處,
我們只用攔截消息的回調函數就可以了,這個不會讓我寫例子吧。
其實這個和上面的一樣,都是用SetWindowHook來寫的,看看就明白了很簡單的。       至於攔截了以後做什麼就是你的事情了,比如在每個計時器消息裏面處理一
些我們的資料判斷,或者在計時器裏面在模擬一次計時器,那麼有些資料就會處
理兩次,呵呵。後果嘛,不一定是好事情哦,呵呵,不過如果資料計算放在用戶
端的遊戲就可以真的改變資料了,呵呵,試試看吧。
用途還有很多,自己想也可以想出來的,呵呵。       2.3 攔截Socket包       這個技術難度要比原來的高很多。       首先我們要替換WinSock.DLL或者WinSock32.DLL,
我們寫的替換函數要和原來的函數一致才行,就是說它的函數輸出什麼樣的,
我們也要輸出什麼樣子的函數,而且參數,參數順序都要一樣才行,
然後在我們的函數裏面調用真正的WinSock32.DLL裏面的函數就可以了。       首先:我們可以替換動態庫到系統路徑。       其次:我們應用程式啟動的時候可以載入原有的動態庫,
用這個函數LoadLibary然後定位函數入口用GetProcAddress函數獲得每個真正Socket函數的入口位址。       當遊戲進行的時候它會調用我們的動態庫,然後從我們的動態庫中處理完畢
後才跳轉到真正動態庫的函數位址,這樣我們就可以在裏面處理自己的資料了,
應該是一切資料。呵呵,興奮吧,攔截了資料包我們還要分析之後才能進行正確
的應答,不要以為這樣工作就完成了,還早呢。等分析完畢以後我們還要仿真應
答機制來和伺服器通信,一個不小心就會被封號。       分析資料才是工作量的來源呢,遊戲每次升級有可能加密方式會有所改變,
因此我們寫外掛的人都是亡命之徒啊,被人愚弄了還不知道。       2.4 截獲API       上面的技術如果可以靈活運用的話我們就不用截獲API函數了,
其實這種技術是一種補充技術。比如我們需要截獲Socket以外的函數作為我們
的用途,我們就要用這個技術了,其實我們也可以用它直接攔截在Socket中的
函數,這樣更直接。       現在攔截API的教程到處都是,我就不列舉了,我用的比較習慣的方法是
根據輸入節進行攔截的,這個方法可以用到任何一種作業系統上,比如Windows     98/2000等,有些方法不是跨平臺的,我不建議使用。這個技術大家可以參考
《Windows核心編程》裏面的545頁開始的內容來學習,如果是Win98系統可
以用“Windows系統奧秘”那個最後一章來學習。         網路遊戲外掛核心封包揭密      網路遊戲的封包技術是大多數編程愛好者都比較關注的關注的問題之一,
在這裏就讓我們一起研究一下這一個問題吧。      別看這是封包這一問題,但是涉及的技術範圍很廣範,實現的方式也很多
(比如說APIHOOK,VXD,Winsock2都可以實現),在這裏我們不可能每種技術
和方法都涉及,所以我在這裏以Winsock2技術作詳細講解,就算作抛磚引玉。      由於大多數讀者對封包類編程不是很瞭解,我在這裏就簡單介紹一下相關知識:      APIHooK:      由於Windows的把內核提供的功能都封裝到API裏面,所以大家要實現功
能就必須通過API,換句話說就是我們要想捕獲資料封包,就必須先要得知道並
且捕獲這個API,從API裏面得到封包資訊。      VXD:      直接通過控制VXD驅動程式來實現封包資訊的捕獲,
不過VXD只能用於win9X。      winsock2:      winsock是Windows網路編程介面,winsock工作在應用層,
它提供與底層傳輸協定無關的高層資料傳輸編程介面,winsock2是winsock2.0
提供的服務提供者介面,但只能在win2000下用。      好了,我們開始進入winsock2封包式編程吧。      在封包編程裏面我準備分兩個步驟對大家進行講解:1、封包的捕獲,2、封包的發送。      首先我們要實現的是封包的捕獲:      Delphi的封裝的winsock是1.0版的,很自然winsock2就用不成。
如果要使用winsock2我們要對winsock2在Delphi裏面做一個介面,
才可以使用winsock2。      1、如何做winsock2的介面?    1)        我們要先定義winsock2.0所用得到的類型,
2)        在這裏我們以WSA_DATA類型做示範,大家可以舉一仿三的來實現
winsock2其他類型的封裝。      我們要知道WSA_DATA類型會被用於
WSAStartup(wVersionRequired: word; var WSData: 
TWSAData): Integer;,大家會發現WSData是引用參數,在傳入參數時傳的是變
數的位址,所以我們對WSA_DATA做以下封裝:    const 
WSADESCRIPTION_LEN = 256; 
WSASYS_STATUS_LEN = 128; 
type 
PWSA_DATA = ^TWSA_DATA; 
WSA_DATA = record 
wVersion: Word; 
wHighVersion: Word; 
szDescription: array[0..WSADESCRIPTION_LEN] of Char; 
szSystemStatus: array[0..WSASYS_STATUS_LEN] of Char; 
iMaxSockets: Word; 
iMaxUdpDg: Word; 
lpVendorInfo: PChar; 
end; 
TWSA_DATA = WSA_DATA;       2)我們要從WS2_32.DLL引入winsock2的函數,在此我們也是以WSAStartup為例做函數引入:    function WSAStartup(wVersionRequired: word; var WSData: TWSAData): 
Integer; stdcall; 
implementation     const WinSocket2 = 'WS2_32.DLL'; 
function WSAStartup; external winsocket name 'WSAStartup';       通過以上方法,我們便可以對winsock2做介面,下面我們就可以用winsock2做封包捕獲了,不過首先要有一塊網卡。
因為涉及到正在運作的網路遊戲安全問題,
所以我們在這裏以IP資料包為例做封包捕獲,
如果下面的某些資料類型您不是很清楚,請您查閱MSDN:      1)我們要起動WSA,這時個要用到的WSAStartup函數,用法如下:    INTEGER WSAStartup(
 wVersionRequired: word,
 WSData: TWSA_DATA
);       2)使用socket函數得到socket控制碼,m_hSocket:=Socket(AF_INET, SOCK_RAW, 
IPPROTO_IP); 用法如下:    INTEGER socket(af: Integer, 
Struct: Integer, 
protocol: Integer
);     m_hSocket:=Socket(AF_INET, SOCK_RAW, IPPROTO_IP);      在程式裏m_hSocket為socket控制碼,AF_INET,SOCK_RAW,IPPROTO_IP均為常量。      3)定義SOCK_ADDR類型,跟據我們的網卡IP給Sock_ADDR類型附值,然後我們使用bind函數來綁定我們的網卡,Bind函數用法如下:    Type 
IN_ADDR = record 
S_addr : PChar;
End;    Type 
TSOCK_ADDR = record 
sin_family: Word;
sin_port: Word;
sin_addr : IN_ADDR
sin_zero: array[0..7] of Char; 
End;    var
LocalAddr:TSOCK_ADDR;    LocalAddr.sin_family: = AF_INET;
LocalAddr.sin_port: = 0;
LocalAddr.sin_addr.S_addr: = inet_addr('192.168.1.1'); 
//這裏你自己的網卡的IP位址,而inet_addr這個函數是winsock2的函數。    bind(m_hSocket, LocalAddr, sizeof(LocalAddr));      4)用WSAIoctl來註冊WSA的輸入輸出元件,其用法如下:    INTEGER WSAIoctl(s:INTEGER, 
dwIoControlCode : INTEGER, 
lpvInBuffer :INTEGER,
cbInBuffer : INTEGER, 
lpvOutBuffer : INTEGER,
cbOutBuffer: INTEGER, 
lpcbBytesReturned : INTEGER, 
lpOverlapped : INTEGER, 
lpCompletionRoutine : INTEGER
);      5)下面做閉環,在閉環塊裏,來實現資料的接收。但是徇環中間要用Sleep()做延時,不然程式會出錯。      6)在迴圈塊裏,用recv函數來接收資料,recv函數用法如下:    INTEGER recv (s : INTEGER, 
buffer:Array[0..4095] of byte, 
length : INTEGER,
flags : INTEGER,
);      7)在buffer裏就是我們接收回來的資料了,如果我們想要知道資料是什麼地方發來的,那麼,
我們要定義一定IP包結構,用CopyMemory()把IP資訊從buffer裏面讀出來就可以了,
不過讀出來的是十六進位的資料需要轉換一下。      看了封包捕獲的全過程式,對你是不是有點起發,然而在這裏要告訴大家的
是封包的獲得是很容易的,但是許多遊戲的封包都是加密的,如果你想搞清楚所
得到的是什麼內容還需要自己進行封包解密。        四種網路遊戲外掛的設計方法      在幾年前我看到別人玩網路遊戲用上了外掛,做為程式師的我心裏實在是不
爽,想搞清楚這到底是怎麼回事。就拿了一些來研究,小有心得,拿出來與大家
共用,外掛無非就是分幾種罷了(依製作難度):      1、動作式,所謂動作式,就是指用API發命令給視窗或API控制滑鼠、
鍵盤等,使遊戲裏的人物進行流動或者攻擊,最早以前的“石器”外掛就是這種方式。
(這種外掛完全是垃圾,TMD,只要會一點點API的人都知道該怎麼做,不過
這種外掛也是入門級的好東東,雖然不能提高你的戰鬥力,但是可以提高你的士
氣)      2、本地修改式,這種外掛跟傳統上的一些遊戲修改器沒有兩樣,
做這種外掛在編程只需要對記憶體位址有一點認識並且掌握API就可以實現,
“精靈”的外掛這是這種方式寫成的,它的難點在於找到那些位址碼,
找位址一般地要借助於別人的工具,有的遊戲還有雙碼校驗,正正找起來會比較
困難。(這種外掛,比上一種有一點點難度,但是這種外掛做起來能夠用,
也是有一定難度的啦~~,這種外掛可以很快提升你對記憶體位址的理解及應用,
是你編程技術提高的好東東)      3、木馬式,這種外掛的目的是幫外掛製作者偷到用戶的密碼
(TMD,“爛”就一個字,不過要知已知彼所以還是要談一下啦~~),
做這種外掛有一定的難度,需要HOOK或鍵盤監視技術做底子,才可以完成,
它的原理是先首截了用戶的帳號或密碼,然後發到指定郵箱。
(我以前寫過這樣的東東,但是從來沒有用過,我知道這種東東很不道德,
所以以後千萬別用呀!)      4、加速式,這種外掛可以加快遊戲的速度……
(對不起大家,這種東東我沒有實際做過,所以不能妄自評,慚愧)      這幾種外掛之中,前三種可以用VB,Delphi等語言比較好實現,
後兩種則要用VC等底層支援比較好的編程工具才好實現。       動作式外掛      首先,先來談一下動作式的外掛,這也是我第一次寫外掛時做的最簡單的一種。      記得還在“石器”時代的時候,我看到別人掛著一種軟體(外掛)
人物就可以四外遊走(當時我還不知道外掛怎麼回事),
於是找了這種軟體過來研究(拿來後才聽別人說這叫外掛),
發現這種東東其實實現起來並不難,仔佃看其實人物的行走無非就是滑鼠在不同的地方點來點去而已,
看後就有實現這功能的衝動,隨後跑到MSDN上看了一些資料,發現這種實現
這幾個功能,只需要幾個簡單的API函數就可以搞定:    1、        首先我們要知道現在滑鼠的位置(為了好還原現在滑鼠的位置)
所以我們就要用到API函數GetCursorPos,它的使用方法如下:    BOOL GetCursorPos( 
LPPOINT lpPoint // address of structure for cursor position 
);    2、        我們把滑鼠的位置移到要到人物走到的地方,
我們就要用到SetCursorPos函數來移動滑鼠位置,它的使用方法如下:    BOOL SetCursorPos(    int X, // horizontal position 
int Y // vertical position
);      3、類比滑鼠發出按下和放開的動作,我們要用到mouse_event函數來實現,具休使用方法用下:    VOID mouse_event(    DWORD dwFlags, // flags specifying various motion/click variants
DWORD dx, // horizontal mouse position or position change
DWORD dy, // vertical mouse position or position change
DWORD dwData, // amount of wheel movement
DWORD dwExtraInfo // 32 bits of application-defined information
);      在它的dwFlags處,可用的事件很多如移動MOUSEEVENTF_MOVE,
左鍵按下MOUSEEVENTF_LEFTDOWN,左鍵放開MOUSEEVENTF_LEFTUP,
具體的東東還是查一下MSDN吧~~~~~       好了,有了前面的知識,我們就可以來看看人物移走是怎麼實現的了:    getcursorpos(point);
setcursorpos(ranpoint(80,windowX),ranpoint(80,windowY));
//ranpoint是個自製的隨機座標函數
mouse_event(MOUSEEVENTF_LEFTDOWN,0,0,0,0);
mouse_event(MOUSEEVENTF_LEFTUP,0,0,0,0);
setcursorpos(point.x,point.y);      看了以上的代碼,是不是覺得人物的遊走很簡單啦~~,舉一仿三,
還有好多好東東可以用這個技巧實現
(我早就說過,TMD,這是垃圾外掛的做法,相信了吧~~~),
接下來,再看看遊戲裏面自動攻擊的做法吧(必需遊戲中攻擊支持快捷鍵的),
道理還是一樣的,只是用的API不同罷了~~~,
這回我們要用到的是keybd_event函數,其用法如下:    VOID keybd_event(    BYTE bVk, // virtual-key code
BYTE bScan, // hardware scan code
DWORD dwFlags, // flags specifying various function options
DWORD dwExtraInfo // additional data associated with keystroke
);    我們還要知道掃描碼不可以直接使用,要用函數MapVirtualKey把鍵值轉成掃描碼,
MapVirtualKey的具體使用方法如下:    UINT MapVirtualKey(    UINT uCode, // virtual-key code or scan code
UINT uMapType // translation to perform
);      好了,比說此快接鍵是CTRL A,接下來讓我們看看實際代碼是怎麼寫的:    keybd_event(VK_CONTROL,mapvirtualkey(VK_CONTROL,0),0,0);
keybd_event(65,mapvirtualkey(65,0),0,0);
keybd_event(65,mapvirtualkey(65,0),keyeventf_keyup,0);
keybd_event(VK_CONTROL,mapvirtualkey(VK_CONTROL,0),keyeventf_keyup,0);      首先模擬按下了CTRL鍵,再模擬按下A鍵,再模擬放開A鍵,
最後放開CTRL鍵,這就是一個模擬按快捷鍵的週期。      (看到這裏,差不多對簡易外掛有了一定的瞭解了吧~~~~做一個試試?
如果你舉一仿三還能有更好的東東出來,這就要看你的領悟能力了~~,
不過不要高興太早這只是才開始,以後還有更複雜的東東等著你呢~~)      本地修改式外掛      現在我們來看看,比動作式外掛更進一步的外掛——本地修改式外掛的整個
製作過程進行一個詳細的分解。      具我所知,本地修改式外掛最典型的應用就是在“精靈”遊戲上面,
因為我在近一年前(“精靈”還在測試階段),我所在的公司裏有很多同事玩
“精靈”,於是我看了一下遊戲的資料處理方式,
發現它所發送到伺服器上的資訊是存在於記憶體當中
(我看後第一個感受是:修改這種遊戲和修改單機版的遊戲沒有多大分別,
換句話說就是在他向伺服器提交資訊之前修改了記憶體位址就可以了),
當時我找到了位址於是修改了記憶體位址,果然,按我的想法修改了位址,
讓系統自動提交後,果然成功了~~~~~,後來“精靈”又改成了雙位址校檢,
記憶體校檢等等,在這裏我就不廢話了~~~~,OK,
我們就來看看這類外掛是如何製作的:      在做外掛之前我們要對Windows的記憶體有個具體的認識,
而在這裏我們所指的記憶體是指系統的記憶體偏移量,也就是相對記憶體,
而我們所要對其進行修改,那麼我們要對幾個Windows 
API進行瞭解,OK,跟著例子讓我們看清楚這種外掛的製作和API的應用
(為了保證網路遊戲的正常運行,我就不把找記憶體位址的方法詳細解說了):    1、        首先我們要用FindWindow,知道遊戲視窗的控制碼,
因為我們要通過它來得知遊戲的運行後所在進程的ID,
下面就是FindWindow的用法:    HWND FindWindow(    LPCTSTR lpClassName, // pointer to class name
LPCTSTR lpWindowName // pointer to win
        
系統時間:2024-11-22 8:35:39
聯絡我們 | Delphi K.Top討論版
本站聲明
1. 本論壇為無營利行為之開放平台,所有文章都是由網友自行張貼,如牽涉到法律糾紛一切與本站無關。
2. 假如網友發表之內容涉及侵權,而損及您的利益,請立即通知版主刪除。
3. 請勿批評中華民國元首及政府或批評各政黨,是藍是綠本站無權干涉,但這裡不是政治性論壇!