本文作者:sodme
本文出處:http://blog.csdn.net/sodme
聲明:本文可以不經(jīng)作者同意任意轉(zhuǎn)載,但任何對本文的引用都須注明作者、出處及此聲明信息。謝謝!!
特別聲明:
本人非常欣賞暴雪及他們的游戲,之所以寫這個(gè)文章,是想讓大家了解一些網(wǎng)絡(luò)封包分析方面的常見方法以及學(xué)習(xí)暴雪游戲在網(wǎng)
絡(luò)處理方面的經(jīng)驗(yàn),偶認(rèn)為作為一個(gè)網(wǎng)絡(luò)編程者,熟練掌握封包分析的工具和方法應(yīng)該是其基本功之一。本文所列的所有封包分析內(nèi)容,全部是采用普通黑箱方式即
可得來的,并未涉及對魔獸世界可執(zhí)行程序的逆向工程。同時(shí),除此文涉及的內(nèi)容外,本人拒絕向任何人透露更詳細(xì)的關(guān)于魔獸世界封包方面的更多內(nèi)容,有興趣者
請自己進(jìn)行相關(guān)的試驗(yàn),本人在此文中也將盡量避免公開敏感的封包內(nèi)容及相關(guān)加解密算法。謹(jǐn)以此文獻(xiàn)給忠愛的暴雪!
一、登錄模塊流程及封包分析
我們先看登錄流程。從封包流程來看,魔獸的登錄流程是這樣的:
1.由
Client向登錄/賬號服務(wù)器(Login
Server)發(fā)送用戶名及密碼等信息。此數(shù)據(jù)包的最后部分是用戶名(明文表示,未加密),在用戶名的前一個(gè)字節(jié)表示的是用戶名的長度。登錄/賬號服務(wù)器
向Client返回登錄成功及后續(xù)連接到游戲服務(wù)器服務(wù)器所必備的信息等。這中間的兩個(gè)來往數(shù)據(jù)包,我還沒有看出具體有什么作用。在這個(gè)交互過程中,由登
錄/賬號服務(wù)器向Client發(fā)送所有的游戲服務(wù)器列表,服務(wù)器列表數(shù)據(jù)包的內(nèi)容包括:ip, port,
服務(wù)器上所擁有的角色個(gè)數(shù)等信息,因服務(wù)器列表內(nèi)容過多,被客戶端分為兩次接收完畢。
2.Client收到Login
Server的服務(wù)器列表后,根據(jù)最近訪問的服務(wù)器標(biāo)識(這個(gè)信息應(yīng)該是包含在那個(gè)服務(wù)器列表數(shù)據(jù)包中),連接到最近游戲的那個(gè)游戲服務(wù)器(Game
Server)。連接成功后,Game
Server首先向Client發(fā)送一個(gè)8字節(jié)的數(shù)據(jù)包,據(jù)以往的常識判斷,這個(gè)數(shù)據(jù)包的內(nèi)容很可能是以后客戶端與服務(wù)器通信的加密密鑰。
3.Client向Game Server再次發(fā)送自己的賬號信息。Game
Server與Client經(jīng)過兩個(gè)數(shù)據(jù)包的交互后,向Client發(fā)送角色數(shù)據(jù)包,此包中包括了玩家在該Game
Server所創(chuàng)建的所有角色信息,當(dāng)然這個(gè)信息只是部分的,并不是該角色的所有信息。
4.在此后的通信過程中,Client每隔30秒向Game Server發(fā)送一個(gè)保持連接的包,該包長度為10字節(jié),包的最后四字節(jié)是一個(gè)遞增數(shù)字,前面6字節(jié)暫時(shí)未看出規(guī)律。
5.只要Client沒有點(diǎn)擊某個(gè)角色進(jìn)入最終的Game Server,則Client要始終與Login
Server保持連接。當(dāng)Client點(diǎn)擊角色進(jìn)入Game Server時(shí),Client才與Login
Server斷開連接。在以后的游戲過程中,Client始終與且僅與該Game Server進(jìn)行數(shù)據(jù)通信。
通過對登錄流程中的數(shù)據(jù)包初步分析,可以得出以下幾個(gè)結(jié)論:
1.Client向Login
Server發(fā)的第一個(gè)數(shù)據(jù)包,用戶名部分是采用明文的,且該數(shù)據(jù)包的內(nèi)容,每次登錄都一樣,并沒有因時(shí)間的不同而發(fā)生改變。由此可以推算:針對于此數(shù)據(jù)
包中的密碼加密算法是固定不變的,換句話說,密碼的加密算法是比較容易通過逆向工程被找到的。偶認(rèn)為,針對于此處,服務(wù)器也應(yīng)該先向客戶端發(fā)送一個(gè)加密密
鑰,以后的通信可以用該密鑰作為安全驗(yàn)證的依據(jù)。但暴雪沒有這樣作,最大的可能是為了提高服務(wù)器的效率,在登錄服務(wù)器上,如果每個(gè)客戶端一旦連接成功,登
錄服務(wù)器都得向客戶端廣播一個(gè)數(shù)據(jù)包的話,可能這個(gè)量還是比較大的,這可能延長了玩家的登錄等待時(shí)間,所以他們沒有在這塊作。
2.Client在登錄Login Server的地址,每次Login
Server的登錄地址都可能是不一樣的。偶沒有在客戶端目錄里找到這些地址,只在客戶端目錄里找到了四個(gè)大區(qū)的四個(gè)域名,我猜想,魔獸世界是用的DNS
解析的簡單方法來實(shí)現(xiàn)Login Server的簡單動態(tài)均衡的。不知道這個(gè)猜想是否正確。
3.“根據(jù)玩家最近在玩的哪個(gè)游戲,由客戶端和服務(wù)器自動為玩家選擇進(jìn)入這個(gè)游戲服務(wù)器”,這一項(xiàng)設(shè)定充分體現(xiàn)了暴雪一貫的風(fēng)格:為玩家著想,最大限度地提高游戲的舒適度。再次對暴雪的態(tài)度予以肯定!
4.一旦玩家進(jìn)入了游戲世界,客戶端與服務(wù)器的通信端口會一直保持不變。即:魔獸世界的游戲世界服務(wù)器群設(shè)計(jì)結(jié)構(gòu)采用的是帶網(wǎng)關(guān)的服務(wù)器集群。
5.偶覺得在整個(gè)的登錄流程中,讓我產(chǎn)生最大疑問的就是Login Server與Client的連接保持邏輯。當(dāng)Client與Game
Server連接了之后,Client并未與Login
Server斷開,是一直保持連接的。后來,經(jīng)進(jìn)一步的抓包分析,Client之所以要與Login
Server保持這樣的連接,是為了當(dāng)Client重新選擇服務(wù)器時(shí),不至于重新連接Login
Server。當(dāng)Client點(diǎn)擊了"選擇服務(wù)器"按紐后,Login
Server會每隔5秒向Client發(fā)一個(gè)當(dāng)前所有的服務(wù)器列表數(shù)據(jù)包。要知道,這個(gè)服務(wù)器列表數(shù)據(jù)包的內(nèi)容可是非常大的,如果有玩家就打開了這個(gè)窗口
不關(guān)閉,Login
Server向這種情況的所有玩家每5秒鐘就發(fā)一個(gè)服務(wù)器列表數(shù)據(jù)包,這個(gè)廣播量可是很大的哦(2k左右,這可是一個(gè)用戶是2k哦)。偶認(rèn)為這里的邏輯設(shè)
計(jì)是相當(dāng)不合理的。Login
Server如果為了給客戶端提供一個(gè)最新的全局服務(wù)器列表,可以保持連接,但也沒必要每隔5秒就向客戶端發(fā)一個(gè)服務(wù)器列表,最多只在客戶端在某個(gè)服務(wù)器
上創(chuàng)建了不同的角色后再更新這個(gè)列表也是可以的,但只用更新這個(gè)列表中的變化內(nèi)容即可,不用發(fā)全部的完整包,這樣,在通信量上就小了很多。據(jù)說,魔獸剛開
始的時(shí)候,產(chǎn)生DOWN機(jī)的原因就是登錄模塊沒有處理好,偶不知道現(xiàn)在的這個(gè)情況是不是已經(jīng)經(jīng)過改良的了。但偶還是認(rèn)為每隔5秒就向客戶端發(fā)送一個(gè)2K的
包,這一點(diǎn)是不可以被接受的。
以上只是針對于魔獸世界登錄流程的簡單分析,沒有多少技術(shù)含量,拿出來跟大家相互討論討論,看看有沒有可以借鑒的地方,后面還會有其它部分的封包分析。歡迎繼續(xù)關(guān)注偶的Blog: http://blog.csdn.net/sodme。
偶在文章前面部分說過,作為一個(gè)網(wǎng)絡(luò)編程人員,熟練使用截包軟件和掌握基本的封包分析方法是其基本能力之一,發(fā)此文的目的一個(gè)原因也是希望向正在作網(wǎng)絡(luò)編程的兄弟介紹一下相關(guān)工具的使用和常見的分析方法。下面補(bǔ)充一下關(guān)于封包分析的基本方法和相關(guān)工具:
1.你需要一個(gè)截包工具,偶推薦:commview,小巧但功能強(qiáng)大,支持自定義的封包分析插件以DLL形式裝載,也就是說只要你愿意,你可以寫個(gè)DLL對某類特殊形式的包進(jìn)行顯示、記錄、解密等特別處理。
2.如何查看真正的封包數(shù)據(jù)。在commview里,會詳細(xì)列出自網(wǎng)卡級別以上的各層封包數(shù)據(jù),包括Ethernet層,IP層和TCP層。而我們作封
包分析時(shí),只需要關(guān)注TCP層。但TCP層里也有很多內(nèi)容,對于我們的分析需求來說,我們需要關(guān)注的是其Data字段(在協(xié)議目錄里可以看到"data
length標(biāo)識,點(diǎn)擊即可查看data段")的內(nèi)容。
3.TCP的幾個(gè)狀態(tài)對于我們分析所起的作用。在TCP層,有個(gè)FLAGS字
段,這個(gè)字段有以下幾個(gè)標(biāo)識:SYN, FIN, ACK, PSH, RST,
URG.其中,對于我們?nèi)粘5姆治鲇杏玫木褪乔懊娴奈鍌€(gè)字段。它們的含義是:SYN表示建立連接,F(xiàn)IN表示關(guān)閉連接,ACK表示響應(yīng),PSH表示有
DATA數(shù)據(jù)傳輸,RST表示連接重置。其中,ACK是可能與SYN,F(xiàn)IN等同時(shí)使用的,比如SYN和ACK可能同時(shí)為1,它表示的就是建立連接之后的
響應(yīng),如果只是單個(gè)的一個(gè)SYN,它表示的只是建立連接。TCP的幾次握手就是通過這樣的ACK表現(xiàn)出來的。但SYN與FIN是不會同時(shí)為1的,因?yàn)榍罢?
表示的是建立連接,而后者表示的是斷開連接。RST一般是在FIN之后才會出現(xiàn)為1的情況,表示的是連接重置。一般地,當(dāng)出現(xiàn)FIN包或RST包時(shí),我們
便認(rèn)為客戶端與服務(wù)器端斷開了連接;而當(dāng)出現(xiàn)SYN和SYN+ACK包時(shí),我們認(rèn)為客戶端與服務(wù)器建立了一個(gè)連接。PSH為1的情況,一般只出現(xiàn)在
DATA內(nèi)容不為0的包中,也就是說PSH為1表示的是有真正的TCP數(shù)據(jù)包內(nèi)容被傳遞。TCP的連接建立和連接關(guān)閉,都是通過請求-響應(yīng)的模式完成的。
封包分析的手段,說簡單也挺簡單的,那就是:比較!要不斷地從不同的思維角度對封包進(jìn)行對比分析,要充分發(fā)揮你的想象力不斷地截取自己需要的包進(jìn)行比較。不僅要作橫向(同類)的比較,還要作縱向(不同類)的比較。即時(shí)對于同一個(gè)包,也要不斷地反復(fù)研究。
初涉封包分析的新手,一般會不知道封包分析究竟該從何入手。基于經(jīng)驗(yàn),本文將告訴你一般會從哪些類型的包入手進(jìn)行分析以及應(yīng)該怎樣對封包進(jìn)行初
步的分析。需要指出的是:封包分析是一件非常有趣但同時(shí)也非常考驗(yàn)?zāi)托牡氖拢ǔ#胩斓姆獍治鱿聛恚瑫屇阊矍叭侵T如“B0 EF 58 02
10 72....”之類的網(wǎng)絡(luò)數(shù)據(jù),而且附帶有頭疼、頭暈癥狀,所以,沒有充分的心理準(zhǔn)備,還請不要輕易嘗試。呵呵。
從事封包分析的基本前提是:應(yīng)該了解和熟悉TCP協(xié)議,并知道數(shù)據(jù)包“粘合”是怎么一回事。當(dāng)然,我們平常截獲到的包,從數(shù)量上來看,只有一小
部分是屬于“粘合”的情況。但如果不了解它,將可能會對你的分析思路產(chǎn)生誤導(dǎo)和困惑。關(guān)于“粘包”的更詳細(xì)解釋,請參考我的另外一篇文章“拼包函數(shù)及網(wǎng)絡(luò)
封包的異常處理(含代碼) (http://blog.csdn.net/sodme/archive/2005/07/10/419233.aspx)”。
上一篇有關(guān)魔獸世界封包分析的文章(http://blog.csdn.net/sodme/archive/2005/06/18/397371.aspx)中,我根據(jù)客戶端與服務(wù)器端連接及斷開事件的處理流程以及登錄過程中的一些數(shù)據(jù)包分析了魔獸的架構(gòu)和登錄邏輯。這篇文章中,我將結(jié)合聊天數(shù)據(jù)包的分析,來闡述魔獸世界封包的大體結(jié)構(gòu)。
首先解釋一下我們的目標(biāo):封包的大體結(jié)構(gòu)。封包的大體結(jié)構(gòu)包含哪些內(nèi)容呢?一般情況下,封包的大體結(jié)構(gòu)至少包括兩方面的信息:
1、一個(gè)封包是如何表示它的長度的?封包長度是由哪個(gè)字段表示的?(或者說:如何表示封包的開始和結(jié)束的)
2、各種不同的封包類型是通過哪個(gè)字段表示的?
是不是所有游戲的封包都必然會有表示“長度”信息的“字段”呢?答案是否定的。有的游戲確實(shí)沒有采用這種方式,它們的作法設(shè)定特殊的包開始和包
結(jié)束標(biāo)志。但是,從應(yīng)用的角度來看,偶推薦使用“長度”這樣的方法,因?yàn)椴还茉诰W(wǎng)絡(luò)底層的處理效率以及上層應(yīng)用的處理便捷性來說,使用“長度”字段標(biāo)識一
個(gè)完整的邏輯包都是比較好的辦法。在確定了封包的大體結(jié)構(gòu)后,我們才方便分析具體類型包(比如聊天、行走等)的詳細(xì)結(jié)構(gòu)。
作數(shù)據(jù)包分析,在單純采用黑箱分析的階段,我們選取的數(shù)據(jù)包,須要是具有這種性質(zhì)的,即:在數(shù)據(jù)包發(fā)送前客戶端未進(jìn)行加密等處理時(shí),這個(gè)數(shù)據(jù)包
中的部分內(nèi)容,我們是已經(jīng)知道的。這樣的包,就可以作為封包分析的突破口。這樣看來,我們拿“聊天封包”作為第一個(gè)分析對象也就不難理解了,因?yàn)槲覀冋f的
話,打上去的字,我們自己是知道的,但是我們說的話經(jīng)過客戶端的處理后,發(fā)到網(wǎng)絡(luò)上的可能就是已經(jīng)加了密的或者加了校驗(yàn)碼的。站在黑箱分析的角度,我們能
作的,就是不斷截取各種“聊天包”進(jìn)行對比、判斷和總結(jié)。
OK,打開你的commview。讓我們從“聊天封包”開始。
分析“聊天包”的前提,是我們能夠正常判斷哪種類型的數(shù)據(jù)包是屬于聊天的,不要誤把行走或其它的數(shù)據(jù)包當(dāng)作了聊天數(shù)據(jù)包。為了減小分析難度,建
議新手到游戲中人少或周圍沒有玩家的地方進(jìn)行封包分析。這樣一來沒人打擾,二來你的網(wǎng)絡(luò)通信量會相對小得多,比較容易進(jìn)行一些封包判定。
第一步,我們需要確定客戶端與服務(wù)器通信所用的端口,然后在commview的rules->ports中設(shè)定服務(wù)器端口,截獲與該端口
通信的所有數(shù)據(jù)包。服務(wù)器端口的確定方法:不要使用其它網(wǎng)絡(luò)通信工具,打開commview,進(jìn)游戲,截包,觀察其通信端口。進(jìn)行封包分析時(shí),特別是初期
的封包分析時(shí),你的網(wǎng)絡(luò)通信應(yīng)該盡可能是單一的,即:除了游戲,其它的通信軟件盡可能不要開。但當(dāng)你確定了服務(wù)器的IP和端口后,就可以照常使用其它網(wǎng)絡(luò)
軟件了。
第二步,如前面述,在游戲中找個(gè)人少或沒人的地方,開始“自言自語”,呵呵。說話的內(nèi)容,建議以字母和數(shù)字為宜,不要說中文。因?yàn)橹形氖请p字節(jié)
的,而字母和數(shù)字是單字節(jié)的,對于單字節(jié)的信息內(nèi)容,截包軟件會以單字節(jié)的文本信息顯示,但對于雙字節(jié)的漢字而言,截包軟件在對其進(jìn)行顯示時(shí)由于換行等原
因會造成部分中文顯示有亂碼,不容易直接看出中文內(nèi)容。如果執(zhí)意要說中文,偶也不攔你,給你推薦一個(gè)工具:String Demander(下載地址:http://www.cnxhacker.com/Download/show/395.html),這個(gè)軟件,可以查詢中文所對應(yīng)的編碼。
第三步,設(shè)定好commview的rules并使之生效,開始截包。
觀察通過以上的過程所截的包,可以發(fā)現(xiàn),魔獸世界的聊天封包的說話內(nèi)容是明文的!這一點(diǎn),用不著大驚小怪,呵呵。聊天封包本身并不會對游戲的關(guān)
鍵邏輯造成損害,所以,即使讓其明文顯示也不足為奇。但是,我們還是不太相信自己的眼睛,于是再截若干個(gè)包,發(fā)現(xiàn)包中的說話內(nèi)容確實(shí)是明文的!但是,包的
其它字段卻是我們一時(shí)看不懂的“密文”。
看來,下面的事情就是對這些包里的“密文”進(jìn)行研究了。一般情況下,這種“密文”的加密方法,通過封包分析是分析不出來的,但,我們?nèi)匀豢梢酝ㄟ^封包分析來推論一些與“密文”生成算法有關(guān)的問題。我們可以作以下的對比分析:
1、連續(xù)三次輸入“a”,并分別觀察及保存封包數(shù)據(jù);
2、連續(xù)三次輸入“aa”,并分別觀察及保存封包數(shù)據(jù);
3、連續(xù)三次輸入“aaa”,并分別觀察及保存封包數(shù)據(jù)。
輸入的封包用例,我們選擇了字母"a",它的ASCII碼是61。輸入的規(guī)律是:每種情況連續(xù)輸入三次,然后逐次增加a字母的個(gè)數(shù)。于是,我們發(fā)現(xiàn)這樣一個(gè)有趣的現(xiàn)象:
1、包中有關(guān)說話的內(nèi)容是明文的;
2、即使針對于同樣的說話內(nèi)容,比如“a”,客戶端所發(fā)出去的包也是不一樣的;
3、當(dāng)一次說話的字母個(gè)數(shù)增加1時(shí),封包的總體長度也隨之增加1;
4、除每個(gè)封包的前面6個(gè)字節(jié)以及說話的字節(jié)外,其余的封包內(nèi)容每次都一樣;
5、每個(gè)聊天封包的結(jié)尾字節(jié)都是0。
于是,我們可以試著得出如下結(jié)論:
1、包是沒有壓縮的,它所使用的加密算法應(yīng)該是按字節(jié)進(jìn)行的,并沒有改變封包的長度使之看上去使用統(tǒng)一的長度;
2、包是以0結(jié)尾的(盡管我們不知道它是以什么表示開頭的,呵呵);
3、封包加密算法中所使用的密鑰是可變的,即針對于相同的數(shù)據(jù)包內(nèi)容由于加密的密鑰不同,所以產(chǎn)生的密文也不同。由于客戶端的數(shù)據(jù)傳到服務(wù)器端后,服務(wù)
器端還要對數(shù)據(jù)進(jìn)行解密。所以,客戶端的加密算法與服務(wù)器端的解密算法應(yīng)該共用了前6字節(jié)中的某些內(nèi)容,以此作為解密算法的密鑰。如果這6字節(jié)中沒有包含
有關(guān)封包加、解密所需要的同步數(shù)據(jù),那客戶端和服務(wù)器之間應(yīng)該會通過其它的方式同步這樣的數(shù)據(jù)。不過,偶傾向于前者,即:這6字節(jié)中應(yīng)該含有加、解密所需
要的密鑰信息。
回頭看我們上面觀察到的有趣現(xiàn)象,針對于第2點(diǎn),反過來想,這應(yīng)該也是最起碼的功能了。就是說,即使客戶端作出的是同樣的動作,在客戶端發(fā)出的包中,包的內(nèi)容也是不一樣的。這樣,外掛就不能靠單純的重復(fù)發(fā)相同的包而達(dá)到其目的了。
分析來分析去,我們還是沒能確定魔獸封包的大體結(jié)構(gòu)。其實(shí),到現(xiàn)在,我覺得我此文的目的已經(jīng)達(dá)到了,即向大家展示封包分析的思維角度和思維方
式。至于具體結(jié)果,偶覺得倒真的不重要的了。可以肯定地告訴大家的是,魔獸的封包結(jié)構(gòu)偶大致已經(jīng)掌握了。偶僅在此公布我的分析結(jié)果:
1、魔獸的封包長度字段是每個(gè)封包的前兩字節(jié),它的表示方式是:前兩字節(jié)的數(shù)值+2。之所以加這個(gè)2,是因?yàn)榉獍L度字段本身占用了兩個(gè)字節(jié)的長度。
2、魔獸的封包類型偶推斷是第三和第四字節(jié),其中普通聊天的類型標(biāo)識是“95 00”。
請不要來信向我詢問任何有關(guān)魔獸封包破解的內(nèi)容,偶能說的都已經(jīng)在文章里說了,偶之所以寫這個(gè)系列的文章不是想破解魔獸,而是想以這樣優(yōu)秀的一
款游戲作為案例來向大家展示它在封包設(shè)計(jì)方面值得我們學(xué)習(xí)和討論的地方,同時(shí)向更多的朋友普及有關(guān)封包分析的常識、工具以及思維方式,僅此而已。
ps:由于每次封包分析的內(nèi)容都很多,所以,一有了點(diǎn)結(jié)論后,要及時(shí)記錄和總結(jié),并與之前取得的總結(jié)進(jìn)行對比,及時(shí)更新相關(guān)的記錄文檔。
posted on 2009-09-23 23:48
暗夜教父 閱讀(842)
評論(0) 編輯 收藏 引用 所屬分類:
Game Development