游戏外挂制作教材
前言:
? ? ? 做自己喜歡的!------ 明天你來自己做外掛?
? ? ? 隨著網絡游戲的日益火爆,很多玩家都投身到游戲中。目前很多玩家都依賴于一些游戲的外掛程序來進行游戲。那么做一個游戲的外掛程序是否是一件很困難的事呢?回答是"否",誠然編寫一些程序是需要一些基本知識的,所以我們想以最簡單的語言來給你講授編寫外掛程序的一些技巧,一些方法,并提供給你一些基本的輔助工具,即使你是一個菜鳥,看了我們的教程,并技巧地使用我們提供給你的工具,你完全能夠編寫出一個完全屬于你自己的外掛。在本教程內,我們提供了金庸群俠傳,以及網絡三國這兩個游戲的修改實際例子,因為這兩款游戲都是對封包進行過加密運算的,如果你對這兩個游戲的修改有了一定的了解后,相信你在其他游戲中也能非常好地做出屬于自己的外掛。我們提供了金庸打增援20個NPC和網絡三國在PK中自動吃藥,自動發鏢這兩個實際的例子,讓你上手更容易。我們也會本教程內附上這兩個軟件以提供給你使用和學習。我們會在教程內講授給你怎么去破解封包的加密算法,怎么利用我們提供給你工具來偽造和發送封包。本教程除了文字教程外,我們還會提供金庸群俠和三國的外掛程序,另外還提供6個外掛制作工具,以供你使用。希望在以后的游戲中,每一個玩家都能夠在游戲中成長起來,不但游戲玩的出色,修改游戲也同樣出色,做一個真正的游戲DIY。 要想在修改游戲中做到百戰百勝,是需要相當豐富的計算機知識的。有很多計算機高手就是從玩游戲,修改游戲中,逐步對計算機產生濃厚的興趣,逐步成長起來的。不要在羨慕別人能夠做到的,因為別人能夠做的你也能夠!我相信你們看了本教程后,會對游戲有一個全新的認識,呵呵,因為我是個好老師!(別拿雞蛋砸我呀,救命啊!#¥%……*)?
? ? ? 不過要想從修改游戲中學到知識,增加自己的計算機水平,可不能只是靠修改游戲呀!?
? ? ? 要知道,修改游戲只是一個驗證你對你所了解的某些計算機知識的理解程度的場所,只能給你一些發現問題、解決問題的機會,只能起到幫助你提高學習計算機的興趣的作用,而決不是學習計算機的捷徑。
一:什么叫外掛?
? ? ? 現在的網絡游戲多是基于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路由器收到此數據包后繼續轉發,直至發到目的地。路由器之間可以通過路由協議來進行路由信息的交換,從而更新路由表。但是您仔細看,您的名字在每個封包中并不是出現在相同的位置上- 在第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 89?
? ? ? SEND-> 0000 F4 44 0C E3 3B 13 05 00 29 1C 05 08?
? ? ? SEND-> 0000 F4 44 09 D2 7A 00 00 00 48?
? ? ? SEND-> 0000 F4 44 10 DA 01 DB 6C 79 F6 05 02 27 35 01 00 00
? ? ? 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 1A?
? ? ? SEND-> 0000 F4 44 0C E3 3B 13 05 00 29 1C 05 84?
? ? ? SEND-> 0000 F4 44 09 D2 56 00 00 00 48?
? ? ? SEND-> 0000 F4 44 10 DA 01 B8 6C 79 F6 05 02 27 35 01 00 00?
? ? ? 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 00 SEND-> 0010 EB 03 F8 05 02 27 36 01 00 00根據上面的分析,黃狗的代碼為"4B 7D F6 00040011),不過兩只黃狗服務器怎樣分辨呢?看看"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都構造這樣一個包,按順序連在一起發送給客戶端,客戶端也就被我們騙過了,很簡單吧。以后戰斗中其他的事我們就不
管了,盡情地開打吧,呵呵。
? ? ? ?上面講的需要一定的編程基礎,但是不難,即使你不會編程,相信你繼續看下去就會有收獲了。
五:怎么用計算機語言去寫一個單機代理?
? ? ? 在上一章,我們已經對于代理的原理進行了講解,大家對于代理已經有了一個初步的認識,現在我教大家如何用計算機語言編寫一個自己的代理,我們考慮到簡單明了,我們選用VB,因為用VB編寫代理只需要很少的代碼
。
? ? ? 代碼如下:
? ? ? Private Sub
? ? ? Form_Load()?
? ? ? DaiLi.LocalPort = "1234"?
? ? ? Server.RemotePort = "1234"
? ? ? Server.RemoteHost = "211.100.20.26"
? ? ? DaiLi.Listen
? ? ? End Sub
? ? ? Private Sub
? ? ? DaiLi_ConnectionRequest(ByVal requestID As Long)?
? ? ? Server.Connect
? ? ? Client.Accept
? ? ? requestID
? ? ? End Sub
? ? ? Private Sub?
? ? ? Client_DataArrival(ByVal bytesTotal As Long)?
? ? ? Dim ClientToServer() As Byte Client.GetData
? ? ? ClientToServer Server.SendData?
? ? ? ClientToServer
? ? ? End Sub
? ? ? Private Sub Server_DataArrival(ByVal bytesTotal As Long) Dim?
? ? ? ServerToClient() As Byte Server.GetData ServerToClient Client.SendData?
? ? ? ServerToClient
? ? ? End Sub
? ? ? Form_Load()這個過程表示在程序啟動的時候要做的一些初始化操作。 DaiLi.LocalPort = "1234" 設定監聽端口Server.RemotePort = "1234" 設定象游戲服務器連接的端口(和監聽端口是相同的)Server.RemoteHost = ? "211.100.20.26" 設定游戲服務器的IP地址 DaiLi.Listen 監聽本地的連接請求這時你只要將游戲的服務器列表的IP改成127.0.0.1,那么游戲的客戶端程序就會來連接我們的代理,我們的代理會調用如下的過程: Private Sub DaiLi_ConnectionRequest(ByVal requestID As Long) Server.Connect ?代理客戶端向服務器連接 Client.Accept requestID 接受客戶端的連接請求 End Sub當客戶端向服務器發送數據時,就會調用下邊的過程 Private Sub Client_DataArrival(ByVal bytesTotal As Long) Dim ClientToServer() As Byte 變量定義,請求了一個用于存放數據的空間 Client.GetData ClientToServer 客戶端的連接接收這些數據 在這里我們可以添加自己的代碼,對封包進行修改,然后再發向服務器。Server.SendData ClientToServer 服務器的連接把這些數據發向服務器 End Sub當服務器發送數據給客戶端時,會調用下邊的過程 Private Sub Server_DataArrival(ByVal bytesTotal As Long) Dim ServerToClient() As Byte 變量定義,請求了一個用于存放數據的空間 Server.GetData ServerToClient 服務器連接接收數據 在這里我們可以添加自己的代碼,對封包進行修改,然后再發給客戶端。Client.SendData ServerToClient End Sub用其他語言編寫基本的原理也是差不多的,不過可能稍微要麻煩一些,因為VB本身有一個MSWINSCK.OCX控件,這個控件封裝了WINDOWS的網絡操作,而且接口很簡單,推薦大家使用。
六:如果單機代理被封,我們怎么利用底層的技術來接管游戲的發包?
? ? ? 在WINDOWS系統中,網絡通訊的任務是由一個叫WSOCK32.DLL(在SYSTEM目錄下)來完成的,每當游戲被運行時,他都會自動的去調用這個動態連接庫,因為在WINDOWS系統中對于文件的搜索順序是程序目錄>系統目錄>路徑中設置的目錄,所以我們就有機會替換掉系統的WSOCK32.DLL使的游戲調用我們的WSOCK32.DLL,這樣我們就有了對于游戲封包絕對的控制權,有人問:"我們應該怎么做呢?",我們只要自己編寫一個WSOCK32.DLL放到游戲的目錄下,就OK了,當然讓我們完全自己去編寫一個WSOCK32.DLL是不太現實的,因為本身網絡通訊要處理很多更底層的東西,比如說從網卡讀取BIT流,所以我們選擇由我們的WSOCK32.DLL去調用系統的WSOCK32.DLL來完成這個功能。
? ? ? WSOCK32.DLL有很多的輸出函數,函數如下:
? ? ? __WSAFDIsSet accept AcceptEx Arecv Asend bind?
? ? ? closesocket closesockinfo connect dn_expand EnumProtocolsA EnumProtocolsW?
? ? ? GetAcceptExSockaddrs GetAddressByNameA GetAddressByNameW gethostbyaddr?
? ? ? gethostbyname gethostname GetNameByTypeA GetNameByTypeW getnetbyname?
? ? ? getpeername getprotobyname getprotobynumber getservbyname getservbyport?
? ? ? GetServiceA GetServiceW getsockname getsockopt GetTypeByNameA?
? ? ? GetTypeByNameW htonl htons inet_addr inet_network inet_ntoa ioctlsocket?
? ? ? listen MigrateWinsockConfiguration NPLoadNameSpaces NSPStartup ntohl ntohs?
? ? ? rcmd recv recvfrom rexec rresvport s_perror select send sendto sethostname?
? ? ? SetServiceA SetServiceW setsockopt shutdown socket TransmitFile WEP?
? ? ? WSAAsyncGetHostByAddr WSAAsyncGetHostByName WSAAsyncGetProtoByName?
? ? ? WSAAsyncGetProtoByNumber WSAAsyncGetServByName WSAAsyncGetServByPort?
? ? ? WSAAsyncSelect WSACancelAsyncRequest WSACancelBlockingCall WSACleanup?
? ? ? WSAGetLastError WSAIsBlocking WSApSetPostRoutine WSARecvEx?
? ? ? WSASetBlockingHook WSASetLastError WSAStartup WSAUnhookBlockingHook?
? ? ? WsControl WSHEnumProtocols
在這里,不是所有的函數都要修改,因為我們只關心發送和接收的封包,所以我們只要修改send 和recv兩個函數,前者是發送封包的后者是接收封包的,我們在這兩個函數的處理中加入我們自己的代碼,來完成封包的辨認,修改以
及轉發等功能。
七:怎么來分析客戶端的有關資料?
? ? ? 自己作外掛,大多時候要分析封包,不過因為有的功能是由客戶端來辨別的,所以分析客戶端的程序同樣也很重要,分析客戶端首先要求你能看懂匯編指令(只要"看懂",要求很低的),其次是要能夠熟練的運用一些工
具,然后能剩下的也就是運氣和游戲公司的漏洞了。(哈,不是每次都能成功的啊)下邊我分步教給大家。
? ? ? 第一章 8086匯編指令
? ? ? 注:AX,BX,CX...,EAX,EBX,ECX...這些都是CPU用來存儲數據的地方。
一、數據傳輸指令 作用:它們在存貯器和寄存器、寄存器和輸入輸出端口之間傳送數據.?
1. 通用數據傳送指令. MOV 傳送字或字節. MOVSX先符號擴展,再傳送. MOVZX 先零擴展,再傳送. PUSH 把字壓入堆棧. POP 把字彈出堆棧. PUSHA 把AX,CX,DX,BX,SP,BP,SI,DI依次壓入堆棧. POPA 把DI,SI,BP,SP,BX,DX,CX,AX依次彈出堆棧. PUSHAD 把EAX,ECX,EDX,EBX,ESP,EBP,ESI,EDI依次壓入堆棧. POP把EDI,ESI,EBP,ESP,EBX,EDX,ECX,EAX依次彈出堆棧. BSWAP 交換32位寄存器里字節的順序 XCHG 交換字或字節.(至少有一個操作數為寄存器,段寄存器不可作為操作數) CMPXCHG 比較并交換操作數.( 第二個操作數必須為累加器AL/AX/EAX ) XADD先交換再累加.( 結果在第一個操作數里 ) XLAT 字節查表轉換. BX 指向一張 256 字節的表的起點, AL 為表的索引值 (0-255,即0-FFH); 返回 AL 為查表結果. ( [BX+AL]->AL ) ? ?
2. 輸入輸出端口傳送指令. IN I/O端口輸入. ( 語法: IN 累加器, {端口號│DX} ) OUT I/O端口輸出. ( 語法: OUT 端口號│DX},累加器 ) 輸入輸出端口由立即方式指定時, 其范圍是 0-255; 由寄存器 DX 指定時,其范圍是?
0-65535.
3. 目的地址傳送指令. LEA 裝入有效地址. 例: LEA DX,string ;把偏移地址存到DX. LDS?
? ? ? 傳送目標指針,把指針內容裝入DS. 例: LDS SI,string ;把段地址:偏移地址存到DS:SI. LES?
? ? ? 傳送目標指針,把指針內容裝入ES. 例: LES DI,string ;把段地址:偏移地址存到ES:DI. LFS?
? ? ? 傳送目標指針,把指針內容裝入FS. 例: LFS DI,string ;把段地址:偏移地址存到FS:DI. LGS?
? ? ? 傳送目標指針,把指針內容裝入GS. 例: LGS DI,string ;把段地址:偏移地址存到GS:DI. LSS?
? ? ? 傳送目標指針,把指針內容裝入SS. 例: LSS DI,string ;把段地址:偏移地址存到SS:DI.
4. 標志傳送指令. LAHF 標志寄存器傳送,把標志裝入AH. SAHF 標志寄存器傳送,把AH內容裝入標志寄存器. PUSHF 標志入棧. POPF 標志出棧. PUSHD 32位標志入棧. POPD 32位標志出棧.
二、算術運算指令 ADD 加法. ADC 帶進位加法. INC 加 1. AAA 加法的ASCII碼調整. DAA 加法的十進制調整. SUB減法. SBB 帶借位減法. DEC 減 1. NEC 求反(以 0 減之). CMP 比較.(兩操作數作減法,僅修改標志位,不回送結果). AAS減法的ASCII碼調整. DAS 減法的十進制調整. MUL 無符號乘法. IMUL 整數乘法. 以上兩條,結果回送AH和AL(字節運算),或DX和AX(字運算), AAM 乘法的ASCII碼調整. DIV 無符號除法. IDIV 整數除法. ?以上兩條,結果回送: 商回送AL,余數回送AH, (字節運算); 或 商回送AX,余數回送DX, (字運算). AAD 除法的ASCII碼調整. CBW 字節轉換為字. (把AL中字節的符號擴展到AH中去) CWD 字轉換為雙字. (把AX中的字的符號擴展到DX中去)CWDE 字轉換為雙字. (把AX中的字符號擴展到EAX中去) CDQ 雙字擴展. (把EAX中的字的符號擴展到EDX中去)三、邏輯運算指令 AND 與運算. OR 或運算. XOR 異或運算. NOT 取反. TEST 測試.(兩操作數作與運算,僅修改標志位,不回送結果). SHL 邏輯左移. SAL 算術左移.(=SHL) SHR 邏輯右移. SAR 算術右移.(=SHR) ROL 循環左移. ROR 循環右移. RCL 通過進位的循環左移. RCR 通過進位的循環右移. 以上八種移位指令,其移位次數可達255次. 移位一次時, 可直接用操作碼. 如 SHL AX,1. 移位>1次時, 則由寄存器CL給出移位次數. 如 MOV CL,04 SHL?
AX,CL
四、串指令 DS:SI 源串段寄存器 :源串變址. ES:DI 目標串段寄存器:目標串變址. CX 重復次數計數器. AL/AX 掃描值. D標志 0表示重復操作中SI和DI應自動增量; 1表示應自動減量. Z標志 用來控制掃描或比較操作的結束. MOVS 串傳送. ( MOVSB 傳送字符. MOVSW 傳送字. MOVSD 傳送雙字. ) CMPS 串比較. ( CMPSB 比較字符. CMPSW 比較字. ) SCAS 串掃描. 把AL或AX的內容與目標串作比較,比較結果反映在標志位. LODS 裝入串. 把源串中的元素(字或字節)逐一裝入AL或AX中. ( LODSB 傳送字符. LODSW 傳送字. LODSD 傳送雙字. ) STOS 保存串. 是LODS的逆過程. REP 當CX/ECX<>0時重復. REPE/REPZ 當ZF=1或比較結果相等,且CX/ECX<>0時重復. REPNE/REPNZ 當ZF=0或比較結果不相等,且CX/ECX<>0時重復. REPC 當CF=1且CX/ECX<>0時重復. REPNC 當CF=0且CX/ECX<>0時重復.
五、程序轉移指令?
1>無條件轉移指令 (長轉移) JMP 無條件轉移指令 CALL 過程調用 RET/RETF過程返回.?
2>條件轉移指令 (短轉移,-128到+127的距離內) ( 當且僅當(SF XOR OF)=1時,OP1循環控制指令(短轉移) LOOP CX不為零時循環. LOOPE/LOOPZ CX不為零且標志Z=1時循環. LOOPNE/LOOPNZ CX不為零且標志Z=0時循環. JCXZ CX為
零時轉移. JECXZ ECX為零時轉移.?
4>中斷指令 INT 中斷指令 INTO 溢出中斷 IRET 中斷返回?
5>處理器控制指令 HLT 處理器暫停, 直到出現中斷或復位信號才繼續. WAIT 當芯片引線TEST為高電平時使CPU進入等待狀態. ESC 轉換到外處理器. LOCK 封鎖總線. NOP 空操作. STC 置進位標志位. CLC 清進位標志位. CMC?
進位標志取反. STD 置方向標志位. CLD 清方向標志位. STI 置中斷允許位. CLI 清中斷允許位.
六、偽指令 DW 定義字(2字節). PROC 定義過程. ENDP 過程結束. SEGMENT 定義段. ASSUME 建立段寄存器尋址. ENDS 段結束. END 程序結束. 當然不是所有的指令都能用的上的,我在這里全部寫出來是為了讓大家認識一下,
方便大家以后的學習,我歸納了一下常用的指令,這些指令大家一定要熟練掌握才可以啊。MOV 數據傳送指令 PUSH,POP 堆棧指令 CMP 比較指令 LEA 取地址指令 XOR 異或指令 JE,JZ,JMP...(所有的轉移指令)
一些工具的使用
? ? ? 用到的工具包括Fi2.9,Wasm8.9 ,UltraEdit
? ? ? 一、 Fi2.9?
? ? ? 因為現在軟件為了保護,另外也為了減少程序的大小,都采用了加殼技術。有人問了"殼是什么呢",在自然界中,我想大家對"殼"這東西應該都不會陌生了,植物用它來保護種子,動物用它來保護身體等等。同樣,在一些計算機軟件里也有一段專門負責保護軟件不被非法修改或反編譯的程序。它們一般都是先于程序運行,拿到控制權,然后完成它們保護軟件的任務。就像動植物的殼一般都是在身體外面一樣理所當然。由于這段程序和自然界的殼在功能上有很多相同的地方,基于命名的規則,大家就把這樣的程序稱為"殼"了。 現在我們已經知道"殼"是用來保護程序的,那我們要分析游戲程序,必須先把他的這層殼退掉,我們稱之為"脫殼",這個很容易的,因為現在網上有很多的脫殼軟件可以脫殼,不過在脫殼前我們必須先知道程序用什么加的"殼",Fi就是這樣一個軟件,操作很簡單,將要分析的軟件和Fi放在同一個目錄,然后直接運行Fi,在按回車就OK了。?
? ? ? 二、Wasm8.9 這是一個用來反匯編程序的軟件(反匯編,就是把機器代碼轉變為匯編代碼)。操作很簡單, 圖一(打開文件) 圖二(簡單介紹)首先打開文件,進行反匯編操作,然后選擇"串式參考"找到在程序中出現
的內容,定位到該地址,進行分析,分析完成,進行修改,加亮當前要修改的指令,然后看"當前指令在文件中的地址偏移",記下這個值。
? ? ? 三、UltraEdit 是一個功能強大的編輯軟件,能直接修改程序的16進制指令代碼。
? ? ? 實例解析
? ? ? 下邊以金庸的隨地逃為例進行解析。
? ? ? 首先將金庸的Loginp.exe文件和Fi放在同一個目錄,然后運行Fi,可以看到屏幕如圖 ?
? ? ? 可以看到程序用UPX加過殼了,所以首先進行脫殼(由于該文件用UPX加殼后進行了修改,用現成的工具無法脫殼,鑒于會員當前水平的考慮,這個文件的脫殼方法以后講給大家聽,我們直接提供一個脫過殼的文件給會員
用于會員的學習),脫過殼之后,運行Wasm進行反匯編,然后點"串式參考",找到"次處非逃離點"如圖
? ? ? 程序如下(請打開MagicWin)
? ? ? :00616376 6681B8EC470000AD65 cmp word ptr [eax+000047EC],?
? ? ? 65AD<---此處比較是否為逃離點 :0061637F 7577 jne 006163F8 <---不是就跳走
? ? ? * Referenced by a (U)nconditional or (C)onditional Jump at?
? ? ? Address:|:0061636D(C)|:00616381 8BC3 mov eax, ebx:00616383 E8D4D1FFFF call?
? ? ? 0061355<----一個隨機處理判斷是否逃跑成功:00616388 84C0 test al, al:0061638A 7440 je?
? ? ? 006163CC <----不成功就跳走:0061638C 66C743530600 mov [ebx+53], 0006:00616392?
? ? ? B81E000000 mov eax, 0000001E:00616397 E80CC9DEFF call 00402CA8:0061639C?
? ? ? 890424 mov dword ptr [esp], eax:0061639F DB0424 fild dword ptr?
? ? ? [esp]:006163A2 DB2DDC656100 fld tbyte ptr [006165DC]:006163A8 DEC9 fmulp?
? ? ? st(1), st(0):006163AA D80550666100 fadd dword ptr [00616650]:006163B0?
? ? ? DB2DDC656100 fld tbyte ptr [006165DC]:006163B6 DEC1 faddp st(1),?
? ? ? st(0):006163B8 DD9BF8D06500 fstp qword ptr [ebx+0065D0F8]:006163BE 9B?
? ? ? wait:006163BF C6435201 mov [ebx+52], 01:006163C3 8BC3 mov eax,?
? ? ? ebx:006163C5 E8924E0000 call 0061B25C:006163CA EB3F jmp 0061640B
? ? ? * Referenced by a (U)nconditional or (C)onditional Jump at?
? ? ? Address:|:0061638A(C)|:006163CC A11CA36700 mov eax, dword ptr?
? ? ? [0067A31C]:006163D1 8B00 mov eax, dword ptr [eax]:006163D3 33C9 xor ecx,?
? ? ? ecx
? ? ? * Possible StringData Ref from Data Obj ->"発瞞ア毖"|:006163D5 BA5C666100 mov?
? ? ? edx, 0061665C:006163DA E83D9BF7FF call 0058FF1C:006163DF 8A8368010000 mov?
? ? ? al, byte ptr [ebx+00000168]:006163E5 04F9 add al, F9:006163E7 2C02 sub al,?
? ? ? 02:006163E9 7320 jnb 0061640B:006163EB 33C9 xor ecx, ecx:006163ED 33D2 xor?
? ? ? edx, edx:006163EF B0DE mov al, DE:006163F1 E8C6AE0100 call?
? ? ? 006312BC:006163F6 EB13 jmp 0061640B
? ? ? * Referenced by a (U)nconditional or (C)onditional Jump at?
? ? ? Address:|:0061637F(C)|:006163F8 A11CA36700 mov eax, dword ptr?
? ? ? [0067A31C]:006163FD 8B00 mov eax, dword ptr [eax]:006163FF 33C9 xor ecx,?
? ? ? ecx
? ? ? * Possible StringData Ref from Data Obj ->"矪獶発瞞翴"|:00616401 BA70666100?
? ? ? mov edx, 00616670:00616406 E8119BF7FF call 0058FF1C
? ? ? * Referenced by a (U)nconditional or (C)onditional Jump at?
? ? ? Addresses:|:006163CA(U), :006163E9(C), :006163F6(U)|:0061640B B201 mov dl,?
? ? ? 01:0061640D 8BC3 mov eax, ebx:0061640F E8BCC10000 call 006225D0:00616414?
? ? ? C6836801000000 mov byte ptr [ebx+00000168], 00:0061641B E977010000 jmp?
? ? ? 00616597:00616420 888368010000 mov byte ptr [ebx+00000168], al:00616426?
? ? ? C68300D1650000 mov byte ptr [ebx+0065D100], 00:0061642D 33C9 xor ecx,?
? ? ? ecx:0061642F 33D2 xor edx, edx:00616431 B0DE mov al, DE:00616433?
? ? ? E884AE0100 call 006312BC:00616438 B201 mov dl, 01
? ? ? 所以我們只要讓上邊兩個注釋的地方都不要跳走,就可以實現隨時隨地逃的功能了,修改很簡單,我們把上邊的兩個跳轉語句全部注銷掉就OK了,匯編語言里注銷語句為NOP?
? ? ? 轉為機器指令也就是90,所以修改如下
? ? ? 原文:00616376 6681B8EC470000AD65 cmp word ptr [eax+000047EC],?
? ? ? 65AD<---此處比較是否為逃離點:0061637F 7577 jne 006163F8 <---不是就跳走
? ? ? * Referenced by a (U)nconditional or (C)onditional Jump at?
? ? ? Address:|:0061636D(C)|:00616381 8BC3 mov eax, ebx:00616383 E8D4D1FFFF call?
? ? ? 0061355<----一個隨機處理判斷是否逃跑成功:00616388 84C0 test al, al:0061638A 7440 je?
? ? ? 006163CC <----不成功就跳走
? ? ? 修改之后
? ? ? :00616376 6681B8EC470000AD65 cmp word ptr [eax+000047EC],?
? ? ? 65AD<---此處比較是否為逃離點:0061637F 90 nop:00616380 90 nop <---不是就跳走
? ? ? * Referenced by a (U)nconditional or (C)onditional Jump at?
? ? ? Address:|:0061636D(C)|:00616381 8BC3 mov eax, ebx:00616383 E8D4D1FFFF call?
? ? ? 0061355<----一個隨機處理判斷是否逃跑成功:00616388 84C0 test al, al:0061638A 90 nop?
? ? ? :0061638B 90 nop
? ? ? 當然我們要把修改落實到文件上的,用UltraEdit打開脫殼后的Loginp.exe 選擇Search->Goto?
? ? ? Line/Page來到地址0x21637f 可以看到這里的兩個字節內容為7577(jne?
? ? ? 006163f8)把兩個字節內容改為9090,來到地址0x21638a 可以看到這里的兩個字節內容為7440(je?
? ? ? 006163cc)把兩個字節內容改為9090,然后保存進入金庸游戲看看,是不是可以隨地逃了啊,:)
? ? ? 注:教程中提供的地址會隨著loginp.exe的版本的不同有所改變,教程中采用的文件為1月7號的版本,會員可以到下載去下載到,如果會員需要最新的脫殼版本我們可以提供。
? ? ?
? ? ? 做自己喜歡的!------ 明天你來自己做外掛?
? ? ? 隨著網絡游戲的日益火爆,很多玩家都投身到游戲中。目前很多玩家都依賴于一些游戲的外掛程序來進行游戲。那么做一個游戲的外掛程序是否是一件很困難的事呢?回答是"否",誠然編寫一些程序是需要一些基本知識的,所以我們想以最簡單的語言來給你講授編寫外掛程序的一些技巧,一些方法,并提供給你一些基本的輔助工具,即使你是一個菜鳥,看了我們的教程,并技巧地使用我們提供給你的工具,你完全能夠編寫出一個完全屬于你自己的外掛。在本教程內,我們提供了金庸群俠傳,以及網絡三國這兩個游戲的修改實際例子,因為這兩款游戲都是對封包進行過加密運算的,如果你對這兩個游戲的修改有了一定的了解后,相信你在其他游戲中也能非常好地做出屬于自己的外掛。我們提供了金庸打增援20個NPC和網絡三國在PK中自動吃藥,自動發鏢這兩個實際的例子,讓你上手更容易。我們也會本教程內附上這兩個軟件以提供給你使用和學習。我們會在教程內講授給你怎么去破解封包的加密算法,怎么利用我們提供給你工具來偽造和發送封包。本教程除了文字教程外,我們還會提供金庸群俠和三國的外掛程序,另外還提供6個外掛制作工具,以供你使用。希望在以后的游戲中,每一個玩家都能夠在游戲中成長起來,不但游戲玩的出色,修改游戲也同樣出色,做一個真正的游戲DIY。 要想在修改游戲中做到百戰百勝,是需要相當豐富的計算機知識的。有很多計算機高手就是從玩游戲,修改游戲中,逐步對計算機產生濃厚的興趣,逐步成長起來的。不要在羨慕別人能夠做到的,因為別人能夠做的你也能夠!我相信你們看了本教程后,會對游戲有一個全新的認識,呵呵,因為我是個好老師!(別拿雞蛋砸我呀,救命啊!#¥%……*)?
? ? ? 不過要想從修改游戲中學到知識,增加自己的計算機水平,可不能只是靠修改游戲呀!?
? ? ? 要知道,修改游戲只是一個驗證你對你所了解的某些計算機知識的理解程度的場所,只能給你一些發現問題、解決問題的機會,只能起到幫助你提高學習計算機的興趣的作用,而決不是學習計算機的捷徑。
一:什么叫外掛?
? ? ? 現在的網絡游戲多是基于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路由器收到此數據包后繼續轉發,直至發到目的地。路由器之間可以通過路由協議來進行路由信息的交換,從而更新路由表。但是您仔細看,您的名字在每個封包中并不是出現在相同的位置上- 在第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 89?
? ? ? SEND-> 0000 F4 44 0C E3 3B 13 05 00 29 1C 05 08?
? ? ? SEND-> 0000 F4 44 09 D2 7A 00 00 00 48?
? ? ? SEND-> 0000 F4 44 10 DA 01 DB 6C 79 F6 05 02 27 35 01 00 00
? ? ? 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 1A?
? ? ? SEND-> 0000 F4 44 0C E3 3B 13 05 00 29 1C 05 84?
? ? ? SEND-> 0000 F4 44 09 D2 56 00 00 00 48?
? ? ? SEND-> 0000 F4 44 10 DA 01 B8 6C 79 F6 05 02 27 35 01 00 00?
? ? ? 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 00 SEND-> 0010 EB 03 F8 05 02 27 36 01 00 00根據上面的分析,黃狗的代碼為"4B 7D F6 00040011),不過兩只黃狗服務器怎樣分辨呢?看看"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都構造這樣一個包,按順序連在一起發送給客戶端,客戶端也就被我們騙過了,很簡單吧。以后戰斗中其他的事我們就不
管了,盡情地開打吧,呵呵。
? ? ? ?上面講的需要一定的編程基礎,但是不難,即使你不會編程,相信你繼續看下去就會有收獲了。
五:怎么用計算機語言去寫一個單機代理?
? ? ? 在上一章,我們已經對于代理的原理進行了講解,大家對于代理已經有了一個初步的認識,現在我教大家如何用計算機語言編寫一個自己的代理,我們考慮到簡單明了,我們選用VB,因為用VB編寫代理只需要很少的代碼
。
? ? ? 代碼如下:
? ? ? Private Sub
? ? ? Form_Load()?
? ? ? DaiLi.LocalPort = "1234"?
? ? ? Server.RemotePort = "1234"
? ? ? Server.RemoteHost = "211.100.20.26"
? ? ? DaiLi.Listen
? ? ? End Sub
? ? ? Private Sub
? ? ? DaiLi_ConnectionRequest(ByVal requestID As Long)?
? ? ? Server.Connect
? ? ? Client.Accept
? ? ? requestID
? ? ? End Sub
? ? ? Private Sub?
? ? ? Client_DataArrival(ByVal bytesTotal As Long)?
? ? ? Dim ClientToServer() As Byte Client.GetData
? ? ? ClientToServer Server.SendData?
? ? ? ClientToServer
? ? ? End Sub
? ? ? Private Sub Server_DataArrival(ByVal bytesTotal As Long) Dim?
? ? ? ServerToClient() As Byte Server.GetData ServerToClient Client.SendData?
? ? ? ServerToClient
? ? ? End Sub
? ? ? Form_Load()這個過程表示在程序啟動的時候要做的一些初始化操作。 DaiLi.LocalPort = "1234" 設定監聽端口Server.RemotePort = "1234" 設定象游戲服務器連接的端口(和監聽端口是相同的)Server.RemoteHost = ? "211.100.20.26" 設定游戲服務器的IP地址 DaiLi.Listen 監聽本地的連接請求這時你只要將游戲的服務器列表的IP改成127.0.0.1,那么游戲的客戶端程序就會來連接我們的代理,我們的代理會調用如下的過程: Private Sub DaiLi_ConnectionRequest(ByVal requestID As Long) Server.Connect ?代理客戶端向服務器連接 Client.Accept requestID 接受客戶端的連接請求 End Sub當客戶端向服務器發送數據時,就會調用下邊的過程 Private Sub Client_DataArrival(ByVal bytesTotal As Long) Dim ClientToServer() As Byte 變量定義,請求了一個用于存放數據的空間 Client.GetData ClientToServer 客戶端的連接接收這些數據 在這里我們可以添加自己的代碼,對封包進行修改,然后再發向服務器。Server.SendData ClientToServer 服務器的連接把這些數據發向服務器 End Sub當服務器發送數據給客戶端時,會調用下邊的過程 Private Sub Server_DataArrival(ByVal bytesTotal As Long) Dim ServerToClient() As Byte 變量定義,請求了一個用于存放數據的空間 Server.GetData ServerToClient 服務器連接接收數據 在這里我們可以添加自己的代碼,對封包進行修改,然后再發給客戶端。Client.SendData ServerToClient End Sub用其他語言編寫基本的原理也是差不多的,不過可能稍微要麻煩一些,因為VB本身有一個MSWINSCK.OCX控件,這個控件封裝了WINDOWS的網絡操作,而且接口很簡單,推薦大家使用。
六:如果單機代理被封,我們怎么利用底層的技術來接管游戲的發包?
? ? ? 在WINDOWS系統中,網絡通訊的任務是由一個叫WSOCK32.DLL(在SYSTEM目錄下)來完成的,每當游戲被運行時,他都會自動的去調用這個動態連接庫,因為在WINDOWS系統中對于文件的搜索順序是程序目錄>系統目錄>路徑中設置的目錄,所以我們就有機會替換掉系統的WSOCK32.DLL使的游戲調用我們的WSOCK32.DLL,這樣我們就有了對于游戲封包絕對的控制權,有人問:"我們應該怎么做呢?",我們只要自己編寫一個WSOCK32.DLL放到游戲的目錄下,就OK了,當然讓我們完全自己去編寫一個WSOCK32.DLL是不太現實的,因為本身網絡通訊要處理很多更底層的東西,比如說從網卡讀取BIT流,所以我們選擇由我們的WSOCK32.DLL去調用系統的WSOCK32.DLL來完成這個功能。
? ? ? WSOCK32.DLL有很多的輸出函數,函數如下:
? ? ? __WSAFDIsSet accept AcceptEx Arecv Asend bind?
? ? ? closesocket closesockinfo connect dn_expand EnumProtocolsA EnumProtocolsW?
? ? ? GetAcceptExSockaddrs GetAddressByNameA GetAddressByNameW gethostbyaddr?
? ? ? gethostbyname gethostname GetNameByTypeA GetNameByTypeW getnetbyname?
? ? ? getpeername getprotobyname getprotobynumber getservbyname getservbyport?
? ? ? GetServiceA GetServiceW getsockname getsockopt GetTypeByNameA?
? ? ? GetTypeByNameW htonl htons inet_addr inet_network inet_ntoa ioctlsocket?
? ? ? listen MigrateWinsockConfiguration NPLoadNameSpaces NSPStartup ntohl ntohs?
? ? ? rcmd recv recvfrom rexec rresvport s_perror select send sendto sethostname?
? ? ? SetServiceA SetServiceW setsockopt shutdown socket TransmitFile WEP?
? ? ? WSAAsyncGetHostByAddr WSAAsyncGetHostByName WSAAsyncGetProtoByName?
? ? ? WSAAsyncGetProtoByNumber WSAAsyncGetServByName WSAAsyncGetServByPort?
? ? ? WSAAsyncSelect WSACancelAsyncRequest WSACancelBlockingCall WSACleanup?
? ? ? WSAGetLastError WSAIsBlocking WSApSetPostRoutine WSARecvEx?
? ? ? WSASetBlockingHook WSASetLastError WSAStartup WSAUnhookBlockingHook?
? ? ? WsControl WSHEnumProtocols
在這里,不是所有的函數都要修改,因為我們只關心發送和接收的封包,所以我們只要修改send 和recv兩個函數,前者是發送封包的后者是接收封包的,我們在這兩個函數的處理中加入我們自己的代碼,來完成封包的辨認,修改以
及轉發等功能。
七:怎么來分析客戶端的有關資料?
? ? ? 自己作外掛,大多時候要分析封包,不過因為有的功能是由客戶端來辨別的,所以分析客戶端的程序同樣也很重要,分析客戶端首先要求你能看懂匯編指令(只要"看懂",要求很低的),其次是要能夠熟練的運用一些工
具,然后能剩下的也就是運氣和游戲公司的漏洞了。(哈,不是每次都能成功的啊)下邊我分步教給大家。
? ? ? 第一章 8086匯編指令
? ? ? 注:AX,BX,CX...,EAX,EBX,ECX...這些都是CPU用來存儲數據的地方。
一、數據傳輸指令 作用:它們在存貯器和寄存器、寄存器和輸入輸出端口之間傳送數據.?
1. 通用數據傳送指令. MOV 傳送字或字節. MOVSX先符號擴展,再傳送. MOVZX 先零擴展,再傳送. PUSH 把字壓入堆棧. POP 把字彈出堆棧. PUSHA 把AX,CX,DX,BX,SP,BP,SI,DI依次壓入堆棧. POPA 把DI,SI,BP,SP,BX,DX,CX,AX依次彈出堆棧. PUSHAD 把EAX,ECX,EDX,EBX,ESP,EBP,ESI,EDI依次壓入堆棧. POP把EDI,ESI,EBP,ESP,EBX,EDX,ECX,EAX依次彈出堆棧. BSWAP 交換32位寄存器里字節的順序 XCHG 交換字或字節.(至少有一個操作數為寄存器,段寄存器不可作為操作數) CMPXCHG 比較并交換操作數.( 第二個操作數必須為累加器AL/AX/EAX ) XADD先交換再累加.( 結果在第一個操作數里 ) XLAT 字節查表轉換. BX 指向一張 256 字節的表的起點, AL 為表的索引值 (0-255,即0-FFH); 返回 AL 為查表結果. ( [BX+AL]->AL ) ? ?
2. 輸入輸出端口傳送指令. IN I/O端口輸入. ( 語法: IN 累加器, {端口號│DX} ) OUT I/O端口輸出. ( 語法: OUT 端口號│DX},累加器 ) 輸入輸出端口由立即方式指定時, 其范圍是 0-255; 由寄存器 DX 指定時,其范圍是?
0-65535.
3. 目的地址傳送指令. LEA 裝入有效地址. 例: LEA DX,string ;把偏移地址存到DX. LDS?
? ? ? 傳送目標指針,把指針內容裝入DS. 例: LDS SI,string ;把段地址:偏移地址存到DS:SI. LES?
? ? ? 傳送目標指針,把指針內容裝入ES. 例: LES DI,string ;把段地址:偏移地址存到ES:DI. LFS?
? ? ? 傳送目標指針,把指針內容裝入FS. 例: LFS DI,string ;把段地址:偏移地址存到FS:DI. LGS?
? ? ? 傳送目標指針,把指針內容裝入GS. 例: LGS DI,string ;把段地址:偏移地址存到GS:DI. LSS?
? ? ? 傳送目標指針,把指針內容裝入SS. 例: LSS DI,string ;把段地址:偏移地址存到SS:DI.
4. 標志傳送指令. LAHF 標志寄存器傳送,把標志裝入AH. SAHF 標志寄存器傳送,把AH內容裝入標志寄存器. PUSHF 標志入棧. POPF 標志出棧. PUSHD 32位標志入棧. POPD 32位標志出棧.
二、算術運算指令 ADD 加法. ADC 帶進位加法. INC 加 1. AAA 加法的ASCII碼調整. DAA 加法的十進制調整. SUB減法. SBB 帶借位減法. DEC 減 1. NEC 求反(以 0 減之). CMP 比較.(兩操作數作減法,僅修改標志位,不回送結果). AAS減法的ASCII碼調整. DAS 減法的十進制調整. MUL 無符號乘法. IMUL 整數乘法. 以上兩條,結果回送AH和AL(字節運算),或DX和AX(字運算), AAM 乘法的ASCII碼調整. DIV 無符號除法. IDIV 整數除法. ?以上兩條,結果回送: 商回送AL,余數回送AH, (字節運算); 或 商回送AX,余數回送DX, (字運算). AAD 除法的ASCII碼調整. CBW 字節轉換為字. (把AL中字節的符號擴展到AH中去) CWD 字轉換為雙字. (把AX中的字的符號擴展到DX中去)CWDE 字轉換為雙字. (把AX中的字符號擴展到EAX中去) CDQ 雙字擴展. (把EAX中的字的符號擴展到EDX中去)三、邏輯運算指令 AND 與運算. OR 或運算. XOR 異或運算. NOT 取反. TEST 測試.(兩操作數作與運算,僅修改標志位,不回送結果). SHL 邏輯左移. SAL 算術左移.(=SHL) SHR 邏輯右移. SAR 算術右移.(=SHR) ROL 循環左移. ROR 循環右移. RCL 通過進位的循環左移. RCR 通過進位的循環右移. 以上八種移位指令,其移位次數可達255次. 移位一次時, 可直接用操作碼. 如 SHL AX,1. 移位>1次時, 則由寄存器CL給出移位次數. 如 MOV CL,04 SHL?
AX,CL
四、串指令 DS:SI 源串段寄存器 :源串變址. ES:DI 目標串段寄存器:目標串變址. CX 重復次數計數器. AL/AX 掃描值. D標志 0表示重復操作中SI和DI應自動增量; 1表示應自動減量. Z標志 用來控制掃描或比較操作的結束. MOVS 串傳送. ( MOVSB 傳送字符. MOVSW 傳送字. MOVSD 傳送雙字. ) CMPS 串比較. ( CMPSB 比較字符. CMPSW 比較字. ) SCAS 串掃描. 把AL或AX的內容與目標串作比較,比較結果反映在標志位. LODS 裝入串. 把源串中的元素(字或字節)逐一裝入AL或AX中. ( LODSB 傳送字符. LODSW 傳送字. LODSD 傳送雙字. ) STOS 保存串. 是LODS的逆過程. REP 當CX/ECX<>0時重復. REPE/REPZ 當ZF=1或比較結果相等,且CX/ECX<>0時重復. REPNE/REPNZ 當ZF=0或比較結果不相等,且CX/ECX<>0時重復. REPC 當CF=1且CX/ECX<>0時重復. REPNC 當CF=0且CX/ECX<>0時重復.
五、程序轉移指令?
1>無條件轉移指令 (長轉移) JMP 無條件轉移指令 CALL 過程調用 RET/RETF過程返回.?
2>條件轉移指令 (短轉移,-128到+127的距離內) ( 當且僅當(SF XOR OF)=1時,OP1循環控制指令(短轉移) LOOP CX不為零時循環. LOOPE/LOOPZ CX不為零且標志Z=1時循環. LOOPNE/LOOPNZ CX不為零且標志Z=0時循環. JCXZ CX為
零時轉移. JECXZ ECX為零時轉移.?
4>中斷指令 INT 中斷指令 INTO 溢出中斷 IRET 中斷返回?
5>處理器控制指令 HLT 處理器暫停, 直到出現中斷或復位信號才繼續. WAIT 當芯片引線TEST為高電平時使CPU進入等待狀態. ESC 轉換到外處理器. LOCK 封鎖總線. NOP 空操作. STC 置進位標志位. CLC 清進位標志位. CMC?
進位標志取反. STD 置方向標志位. CLD 清方向標志位. STI 置中斷允許位. CLI 清中斷允許位.
六、偽指令 DW 定義字(2字節). PROC 定義過程. ENDP 過程結束. SEGMENT 定義段. ASSUME 建立段寄存器尋址. ENDS 段結束. END 程序結束. 當然不是所有的指令都能用的上的,我在這里全部寫出來是為了讓大家認識一下,
方便大家以后的學習,我歸納了一下常用的指令,這些指令大家一定要熟練掌握才可以啊。MOV 數據傳送指令 PUSH,POP 堆棧指令 CMP 比較指令 LEA 取地址指令 XOR 異或指令 JE,JZ,JMP...(所有的轉移指令)
一些工具的使用
? ? ? 用到的工具包括Fi2.9,Wasm8.9 ,UltraEdit
? ? ? 一、 Fi2.9?
? ? ? 因為現在軟件為了保護,另外也為了減少程序的大小,都采用了加殼技術。有人問了"殼是什么呢",在自然界中,我想大家對"殼"這東西應該都不會陌生了,植物用它來保護種子,動物用它來保護身體等等。同樣,在一些計算機軟件里也有一段專門負責保護軟件不被非法修改或反編譯的程序。它們一般都是先于程序運行,拿到控制權,然后完成它們保護軟件的任務。就像動植物的殼一般都是在身體外面一樣理所當然。由于這段程序和自然界的殼在功能上有很多相同的地方,基于命名的規則,大家就把這樣的程序稱為"殼"了。 現在我們已經知道"殼"是用來保護程序的,那我們要分析游戲程序,必須先把他的這層殼退掉,我們稱之為"脫殼",這個很容易的,因為現在網上有很多的脫殼軟件可以脫殼,不過在脫殼前我們必須先知道程序用什么加的"殼",Fi就是這樣一個軟件,操作很簡單,將要分析的軟件和Fi放在同一個目錄,然后直接運行Fi,在按回車就OK了。?
? ? ? 二、Wasm8.9 這是一個用來反匯編程序的軟件(反匯編,就是把機器代碼轉變為匯編代碼)。操作很簡單, 圖一(打開文件) 圖二(簡單介紹)首先打開文件,進行反匯編操作,然后選擇"串式參考"找到在程序中出現
的內容,定位到該地址,進行分析,分析完成,進行修改,加亮當前要修改的指令,然后看"當前指令在文件中的地址偏移",記下這個值。
? ? ? 三、UltraEdit 是一個功能強大的編輯軟件,能直接修改程序的16進制指令代碼。
? ? ? 實例解析
? ? ? 下邊以金庸的隨地逃為例進行解析。
? ? ? 首先將金庸的Loginp.exe文件和Fi放在同一個目錄,然后運行Fi,可以看到屏幕如圖 ?
? ? ? 可以看到程序用UPX加過殼了,所以首先進行脫殼(由于該文件用UPX加殼后進行了修改,用現成的工具無法脫殼,鑒于會員當前水平的考慮,這個文件的脫殼方法以后講給大家聽,我們直接提供一個脫過殼的文件給會員
用于會員的學習),脫過殼之后,運行Wasm進行反匯編,然后點"串式參考",找到"次處非逃離點"如圖
? ? ? 程序如下(請打開MagicWin)
? ? ? :00616376 6681B8EC470000AD65 cmp word ptr [eax+000047EC],?
? ? ? 65AD<---此處比較是否為逃離點 :0061637F 7577 jne 006163F8 <---不是就跳走
? ? ? * Referenced by a (U)nconditional or (C)onditional Jump at?
? ? ? Address:|:0061636D(C)|:00616381 8BC3 mov eax, ebx:00616383 E8D4D1FFFF call?
? ? ? 0061355<----一個隨機處理判斷是否逃跑成功:00616388 84C0 test al, al:0061638A 7440 je?
? ? ? 006163CC <----不成功就跳走:0061638C 66C743530600 mov [ebx+53], 0006:00616392?
? ? ? B81E000000 mov eax, 0000001E:00616397 E80CC9DEFF call 00402CA8:0061639C?
? ? ? 890424 mov dword ptr [esp], eax:0061639F DB0424 fild dword ptr?
? ? ? [esp]:006163A2 DB2DDC656100 fld tbyte ptr [006165DC]:006163A8 DEC9 fmulp?
? ? ? st(1), st(0):006163AA D80550666100 fadd dword ptr [00616650]:006163B0?
? ? ? DB2DDC656100 fld tbyte ptr [006165DC]:006163B6 DEC1 faddp st(1),?
? ? ? st(0):006163B8 DD9BF8D06500 fstp qword ptr [ebx+0065D0F8]:006163BE 9B?
? ? ? wait:006163BF C6435201 mov [ebx+52], 01:006163C3 8BC3 mov eax,?
? ? ? ebx:006163C5 E8924E0000 call 0061B25C:006163CA EB3F jmp 0061640B
? ? ? * Referenced by a (U)nconditional or (C)onditional Jump at?
? ? ? Address:|:0061638A(C)|:006163CC A11CA36700 mov eax, dword ptr?
? ? ? [0067A31C]:006163D1 8B00 mov eax, dword ptr [eax]:006163D3 33C9 xor ecx,?
? ? ? ecx
? ? ? * Possible StringData Ref from Data Obj ->"発瞞ア毖"|:006163D5 BA5C666100 mov?
? ? ? edx, 0061665C:006163DA E83D9BF7FF call 0058FF1C:006163DF 8A8368010000 mov?
? ? ? al, byte ptr [ebx+00000168]:006163E5 04F9 add al, F9:006163E7 2C02 sub al,?
? ? ? 02:006163E9 7320 jnb 0061640B:006163EB 33C9 xor ecx, ecx:006163ED 33D2 xor?
? ? ? edx, edx:006163EF B0DE mov al, DE:006163F1 E8C6AE0100 call?
? ? ? 006312BC:006163F6 EB13 jmp 0061640B
? ? ? * Referenced by a (U)nconditional or (C)onditional Jump at?
? ? ? Address:|:0061637F(C)|:006163F8 A11CA36700 mov eax, dword ptr?
? ? ? [0067A31C]:006163FD 8B00 mov eax, dword ptr [eax]:006163FF 33C9 xor ecx,?
? ? ? ecx
? ? ? * Possible StringData Ref from Data Obj ->"矪獶発瞞翴"|:00616401 BA70666100?
? ? ? mov edx, 00616670:00616406 E8119BF7FF call 0058FF1C
? ? ? * Referenced by a (U)nconditional or (C)onditional Jump at?
? ? ? Addresses:|:006163CA(U), :006163E9(C), :006163F6(U)|:0061640B B201 mov dl,?
? ? ? 01:0061640D 8BC3 mov eax, ebx:0061640F E8BCC10000 call 006225D0:00616414?
? ? ? C6836801000000 mov byte ptr [ebx+00000168], 00:0061641B E977010000 jmp?
? ? ? 00616597:00616420 888368010000 mov byte ptr [ebx+00000168], al:00616426?
? ? ? C68300D1650000 mov byte ptr [ebx+0065D100], 00:0061642D 33C9 xor ecx,?
? ? ? ecx:0061642F 33D2 xor edx, edx:00616431 B0DE mov al, DE:00616433?
? ? ? E884AE0100 call 006312BC:00616438 B201 mov dl, 01
? ? ? 所以我們只要讓上邊兩個注釋的地方都不要跳走,就可以實現隨時隨地逃的功能了,修改很簡單,我們把上邊的兩個跳轉語句全部注銷掉就OK了,匯編語言里注銷語句為NOP?
? ? ? 轉為機器指令也就是90,所以修改如下
? ? ? 原文:00616376 6681B8EC470000AD65 cmp word ptr [eax+000047EC],?
? ? ? 65AD<---此處比較是否為逃離點:0061637F 7577 jne 006163F8 <---不是就跳走
? ? ? * Referenced by a (U)nconditional or (C)onditional Jump at?
? ? ? Address:|:0061636D(C)|:00616381 8BC3 mov eax, ebx:00616383 E8D4D1FFFF call?
? ? ? 0061355<----一個隨機處理判斷是否逃跑成功:00616388 84C0 test al, al:0061638A 7440 je?
? ? ? 006163CC <----不成功就跳走
? ? ? 修改之后
? ? ? :00616376 6681B8EC470000AD65 cmp word ptr [eax+000047EC],?
? ? ? 65AD<---此處比較是否為逃離點:0061637F 90 nop:00616380 90 nop <---不是就跳走
? ? ? * Referenced by a (U)nconditional or (C)onditional Jump at?
? ? ? Address:|:0061636D(C)|:00616381 8BC3 mov eax, ebx:00616383 E8D4D1FFFF call?
? ? ? 0061355<----一個隨機處理判斷是否逃跑成功:00616388 84C0 test al, al:0061638A 90 nop?
? ? ? :0061638B 90 nop
? ? ? 當然我們要把修改落實到文件上的,用UltraEdit打開脫殼后的Loginp.exe 選擇Search->Goto?
? ? ? Line/Page來到地址0x21637f 可以看到這里的兩個字節內容為7577(jne?
? ? ? 006163f8)把兩個字節內容改為9090,來到地址0x21638a 可以看到這里的兩個字節內容為7440(je?
? ? ? 006163cc)把兩個字節內容改為9090,然后保存進入金庸游戲看看,是不是可以隨地逃了啊,:)
? ? ? 注:教程中提供的地址會隨著loginp.exe的版本的不同有所改變,教程中采用的文件為1月7號的版本,會員可以到下載去下載到,如果會員需要最新的脫殼版本我們可以提供。
? ? ?
總結