遊戲外掛製作原理
遊戲外掛開發原理
外掛現在大體上來講分為三種,分別是模擬按鍵,WPE封包和記憶體掛。比如模擬鍵盤的,滑鼠的,這種就叫做按鍵模擬,也叫指令碼精靈;還有修改資料包的,這種就叫做WPE封包外掛,這種外掛相對而言比較穩定,但是對於技術要求難度也比較高,因為修改WPE封包,你需要知道和了解加密解密演算法等等一系列的知識;還有最後一種就是修改本地記憶體的,這種相對而言比較常見,市場上面比較常見的也是這種遊戲外掛,相對而言技術要求也不是太高,資料也比較齊全,比較大眾;但好像沒有修改伺服器記憶體的哦,呵呵。其實修改伺服器也是有辦法的,只是技術太高一般人沒有辦法入手而已。這裡就記一下本地修改記憶體的外掛製作原理。
其實,製作記憶體掛也不是很難,步驟就這麼幾步。 第一步 ,找遊戲資料記憶體地址,偏移地址; 第二步 ,修改記憶體地址的值,達到外掛的目的; 第三步,用程式語言寫出一個程式,使得外掛方便於攜帶傳輸,同時也方便於下次玩遊戲直接使用。其實第三步主要是方便使用,方便販賣等等,很多時候對於一個高手而言,根本不需要寫出來,記錄下記憶體地址,偏移地址以後,下次上游戲直接工具裡面修改就是了。但是如果經常玩某個遊戲,可以寫出來,用不著每次玩遊戲都去修改。
外掛開發第一步——找遊戲記憶體地址
說道找遊戲記憶體地址,偏移地址,這可能是整個遊戲外掛開發中最難的一步,因為一個大型的網路遊戲,可能一個技能或者血條的記憶體基址可能會偏移很多次,最後才得到一個記憶體地址也叫實體地址。那麼,這裡有個問題來了,我們為什麼要找技能或者血條的記憶體基址?不是直接修改實體地址就行了嗎?這樣是不行的,因為實體地址是會變動的;舉個例子,每次關閉遊戲重新啟動以後,遊戲程序是會變動的,同樣的,遊戲程式碼在記憶體中的存放位置,因為遊戲結束以後,釋放掉了記憶體地址,這個記憶體地址可能會被其他程式所佔用,所以是會變動的;當你關閉遊戲重新進入以後,遊戲的技能或者血條在記憶體中的實體地址就變了。但是,遊戲技能或者血條的記憶體基址是不會變動的,在記憶體中的實體地址不管怎麼變動,記憶體基址都不會變動。那麼記憶體基址和實體地址之間是一種什麼樣的關係呢?看下面這個公式:
實體地址 = 一級偏移地址 + 偏移地址 一級偏移地址 = 二級偏移地址 + 偏移地址 二級偏移地址 = 三級偏移地址 + 偏移地址 三級偏移地址 = 遊戲技能基址 + 偏移地址 |
如上公式,一個遊戲的實體地址是等於這個遊戲的基址加上偏移地址的,所以,想要每次重新進入遊戲都能夠找到準確的實體地址進行修改記憶體地址的值,達到外掛的目的的話,就必須找到這個實體地址當前對應的偏移地址和基址,只有這樣才能夠確保每次登陸游戲都能夠修改實體地址的值。下面,就通過《植物大戰殭屍》這款經典的單機遊戲來演示一下找這款遊戲的記憶體基址的過程。
首先,介紹一款找遊戲記憶體基址的工具Cheat Engine簡稱CE,Cheat Engine是一款記憶體修改編輯工具 ,它允許修改遊戲或軟體記憶體資料,以得到一些其他功能。它包括16進位制編輯,反彙編程式,記憶體查詢工具。與同類修改工具相比,它具有強大的反彙編功能,且自身附帶了外掛製作工具,可以用它直接生成外掛。好了,這個工具的具體介紹有興趣的去百度,這裡也就是百度了一下,簡單的說了一下這個工具的作用,下面,開啟植物大戰殭屍,開啟CE,在CE中找到植物大戰殭屍,附加到CE中去,如圖所示:
遊戲附加到OD以後,看自己想修改哪兒的內容,就去找對應的記憶體基址,怎麼找呢?比如修改無限陽光吧;首先,看一下最開始的陽光是多少?比如這裡,開局陽光是50,就在CE中 數值 一項輸入50, 掃描型別 選擇 精確數值 在 數值型別 選擇 4位元組 然後點選 首次搜尋 ,這裡不懂為什麼這樣選擇的,自己百度科普一下基礎知識。如圖所示:
如上圖所示,出來了這麼多的地址,究竟哪一個是我們想要的實體地址呢?接下來就需要在遊戲中改動一下陽光的值,然後點選 再次搜尋 ,結果就會出來了,如圖所示:

如上第二幅圖所示,我們想要的實體地址就出來了,把這個地址新增到地址列表中去,然後修改一下陽光的值,確認一下是不是想要的地址,不過這裡要注意,在修改的時候,我們需要點選列表地址中我們拉下來的這一行的 數值 這一欄,其他是修改地址和位元組型別用的,不要亂動,如圖所示:
如上圖所示,這就是我們想要的實體地址,這裡我們可以鎖定這個記憶體地址的值,一直是100或者200或者更多。只需要點選前面 啟用 這一欄選中就行了,從而達到鎖定陽光值的效果。但是當關閉遊戲,重新進入,這個地址就沒用了,又需要重新找。所以,這裡就需要找到真正的陽光值的基址和偏移地址,那麼,怎麼找呢?我們找到這個實體地址以後,就 右鍵 ,選擇 找出是什麼改寫了這個地址 也就是快捷鍵 F6 這個名字每個版本的漢化效果都不一樣的,這裡就會彈出一個視窗,是空白,然後我們再到遊戲中改變陽光的值,看看這個空白視窗中出現的程式碼,如圖所示:


如上圖三所示,分析這兩條程式碼,看見最終都指向了一個指標數值 17C88118 ,然後我們分析一下這兩條程式碼什麼意思,相信稍微懂一點組合語言的人都能夠看懂。首先分析一下 mov [edi+00005560],esi 這條指令,我們在 詳細資訊 中看見,暫存器 esi 中的程式碼是 000026DE 這個值換算成十進位制剛好是9950,那麼這個9950是怎麼來的呢?其實就是剛剛我在做上一步的時候,說了要變動遊戲中的陽光值,所以我先直接把陽光值修改成了10000,然後種了一個石頭,剛好是50,所以陽光值發生了變化,這條指令 mov [edi+00005560],esi 就是把暫存器 esi 的9950的陽光值放入 edi+00005560 這個地址中去,這個地址是誰呢?其實這個地址就是剛剛找出來的實體地址,剛好滿足前面的公式: 實體地址 = 陽光基址地址 + 偏移地址 不信的朋友可以自己加一下算一算,用暫存器 edi 裡面的指標數值 17C88118 加上偏移地址 00005560 看看是不是等於陽光實體地址 17C8D678 。接下看看 add [eax+00005560],ecx 這條指令, add 指令是相加的意思,前面的 mov 是賦值或者移動的意思,這條程式碼的意思就是,把 ecx 暫存器中的值加入 [eax+00005560] 這個地址中的值當中去,再看看暫存器 eax 的地址是多少?剛好又是 17C88118 這個指標數值,那麼,我們就可以確定一個事情,那就是 17C88118 這個指標數值,肯定是上一級的地址的指標數值,那麼上一級要麼是基址,要麼還是一個不偏移地址,這個需要進一步來確認。怎麼確認呢?這裡不是出來了 17C88118 這個指標數值嘛,再次放到CE中搜索一波,看看這個值對應的地址是多少,看看出來的是一個動態地址還是靜態地址,這裡需要普及一個知識點,在CE中,黑色的地址表示動態地址,綠色的表示靜態地址,那好,丟到CE中搜索,這裡這個值是十六進位制的,所以在搜尋的時候,需要勾選搜尋框前面的hex,也就是十六進位制搜尋的意思,這裡填好以後點選 新的掃描 , 首次掃描 如圖所示:
這裡可以看見結果為56個地址,這麼多,我們怎麼來確認究竟是哪個呢?可以看見還有很多紅色的地址。其實,這裡的紅色的地址,是一直在改變的地址,我們不用管它,直接點選 再次掃描 ,把這些紅色的過濾掉,然後看看還剩下的地址有哪些,如圖所示:
多次點選 再次掃描 以後發現不管怎麼點選都剩下來了52個結果,然後看了一下這些結果中並沒有綠色的靜態地址,並且其他地址開頭幾位都比較像,唯獨如圖所示兩個地址比較特殊,這兩個可能就是我們需要的地址了,後來我也去百度了一波,結果所說的是這種開頭比較像的是 陣列 ,也就是說,遇到這種,基本都不是我們需要的地址,直接放棄,把這兩個特殊的拉進下邊的地址列表,開始分析,雙擊 地址 這一欄,在出來的 更改地址 視窗中複製下這個地址,然後再勾選 指標 選項,在出來的內容框中填寫入剛剛複製的地址,在上面的內容框中寫入剛剛找到的 00005560 這個偏移地址,得到的結果剛好是陽光的實體地址,最後的陽光值也正好和當前的陽光值一樣,並且,這兩個地址都是一樣的,而且都是動態地址,如圖所示:
如上圖所示,這兩個地址加上偏移地址都可以得到陽光實體地址,那麼哪個才是我們所需要的真正的一級偏移地址呢?這裡就需要我們對這兩個地址進行詳細的分析了,同樣的 右鍵 – 找出是什麼訪問了這個地址 ,也就是快捷鍵的 F5 ,這裡一定不要搞混淆了,前面是 找出是什麼改寫了這個地址 ,不一樣的!我們進去以後也是和前面一樣出來一個視窗,但是這兩個窗口裡面的內容就不一樣了,第一個地址 0264A400 在 F5 找出是什麼訪問了這個地址以後的視窗中會出現內容,但是第二個地址 0956BD3C 在出現的窗口裡面是一片空白,所以,這兩個地址中, 0264A400 才是我們要找的真正的一級偏移地址,如圖所示:

如上第二幅圖所示,找到了真正的一級偏移地址 0264A400 後,訪問這個地址的視窗中看這些程式碼指令,通過對比,發現這些程式碼都指向同一個指標數值 02649C98 且都有偏移地址 00000768 ,如圖所示:
如上圖所示,既然所有的程式碼都指向了同一個指標數值 02649C98 那麼就繼續按照前面找一級偏移地址的辦法,丟到CE中,繼續新的十六進位制搜尋,搜尋指標數值 02649C98 以後得到如下圖所示的結果:
如上圖所示,一共搜尋到923個地址,而且還有幾個綠色的靜態地址,這裡我們就可以嘗試一下了,看看這幾個綠色的靜態地址究竟是不是我們想要的陽光基址,同樣的原理,我們把幾個綠色的靜態地址拉到地址列表中,在 地址 這一欄雙擊,在出來的 更改地址 視窗中複製下這個地址,然後再勾選 指標 選項,在出來的內容框中填寫入剛剛複製的地址,在上面的內容框中寫入剛剛找到的 00000768 這個偏移地址,然後再點選 新增偏移 在出來的內容框中輸入剛剛第一次找到的 00005560 這個偏移地址,得到的結果剛好是陽光實體地址和陽光當前的值,並且這幾個靜態地址的結果都是一樣的。這裡需要說明一下,為什麼這裡要填寫兩個偏移地址,因為剛剛第一次找到的是一級偏移地址,這次是二級偏移地址了,所以,這裡
陽光實體地址 = 一級偏移地址 + 偏移地址
一級偏移地址 = 陽光基址 + 偏移地址
陽光實體地址 = 陽光基址 + 第一次的偏移地址 + 第二次的偏移地址
如圖所示:



如上四幅圖所示,四個靜態地址最終結果都是一樣的,都可以用作陽光基址,那麼就隨便取一個就行。這樣,陽關的基址和偏移地址就找到了,陽光的基址和偏移地址如下:
陽光基址:006A9EC0 一級偏移:00000768 二級偏移:00005560 |
這裡可能有人會問,一級偏移地址不是我們第一次找出來的地址嗎?你這裡的一級偏移不應該是00005560嗎?對,也不對,我這裡所說的一級偏移不是一級偏移地址的偏移,而是基於陽光基址的一級偏移,可以理解為從陽關基址開始,第一次偏移是00000768第二次偏移才是00005560,這樣做主要是為了方便後面寫程式碼。好了,這就是找遊戲基址的思路,同樣的道理,還可以找植物冷卻時間,不過找冷卻時間思路不太一樣,因為冷卻時間我們不知道具體的值,可以通過找 未知的初始化值 的方式來找,也可以通過 位元組 的方式來找,具體詳見百度,我這裡只是把找遊戲記憶體基址的思路和過程中怎麼分析的給寫了出來,免得後人掉坑,比如我在找植物冷卻時間的時候,就掉了一個坑,我是通過 位元組 的方式來找來找的,通過植物冷卻的時候為0,冷卻好了為1找到了實體地址以後,在找一級偏移地址的時候,忘記把搜尋方式 位元組 換為 4位元組 型了,找了半天沒找到!其他思路是一樣的!
外掛開發第二步——修改遊戲記憶體地址的值
其實,這一步就比較簡單了,比如陽光的值,找到了以後,我們每次上游戲,直接在CE的地址列表框中手動新增地址,把像上面我們驗證這幾個基址的時候一樣,把基址,偏移地址填寫好,然後在 數值 這一欄雙擊,修改數值成為我們想要的陽光值就可以了,冷卻就把數值改為1即可,這一步就不用過多的提及了!
外掛開發第三步——編寫遊戲外掛
其實編寫外掛只有會寫程式的人都知道該怎麼弄了,只要找出來想要的功能的記憶體基址,偏移等,直接在程式中寫上讀取和寫入記憶體地址就行了, 比較簡單,我大概說一下就好了, 就是在外掛軟體啟動以後,我就讀取植物大戰殭屍的遊戲程序ID,然後讀取陽光的實體地址,加以輸出顯示,然後在啟動視窗建立完畢的時候還加一個定時器,達到實時監控陽光值的目的,然後設定了幾個按鈕,分別是增加陽光、鎖定陽光、鎖定冷卻時間和減少陽光、取消鎖定陽光、取消鎖定冷卻時間。下面分別來說一下幾個按鈕怎麼實現功能的。
增加陽光
增加陽光就定義了一個全域性變數,變數中獲取輸入框中的值,然後讓陽光實體地址裡面的值加上輸入的值,就達到了增加陽光的目的!
WriteMemory函式實現
減少陽光
減少陽光和增加陽關的寫法一模一樣,只不過把陽光實體地址裡面的值設定為了減去輸入的值而已,這樣就達到了減少陽關的目的!
WriteMemory函式實現
鎖定陽光
鎖定陽光我定義了一個定時器,設定週期為999毫秒,然後設定了陽光固定值1000。當按鈕鎖定陽光被單擊以後,就執行這個定時器的週期,也就是每隔999毫秒執行一次定時器下面的程式碼,也就是執行在陽光實體地址中改陽光的值為1000,這樣就達到了鎖定陽光的目的!
SetTimer WriteMemory函式實現
取消鎖定陽光
取消鎖定陽光其實就是把鎖定陽光這個定時器的週期設定為0,當取消鎖定陽光的按鈕被單擊以後,就執行這個定時器週期事件,定時器下面的程式碼也就不執行了,達到了取消陽光鎖定的目的!
後面的鎖定冷卻時間和取消鎖定冷卻時間的原理和上面鎖定陽光和取消鎖定陽光的原理一樣,就不再做詳細的解釋了,因為我這裡針對每個欄位的植物做了單獨的冷卻鎖定和取消鎖定,所以程式碼比較長,其實在找植物冷卻時間的時候,可以配合OD,直接找到冷卻時間前面的迴圈幹掉,這樣所有的植物欄的冷卻時間都沒了!
KillTimer函式實現
總結
其實不管是單機遊戲也好,還是網路遊戲也罷,原理都一樣,只不過,可能遊戲型別不同,所需要的東西也不一樣,比如射擊類遊戲,就需要D3D技術來做人物透視的定位等等,這個具體的方法,可以百度參考。但是萬變不離其中,都是找記憶體基址,找偏移地址。