接上一篇:手游防破解防外掛技術方案(一)客戶端篇 由于客戶端理論上總是能被人破解,所以所有客戶端都是不可信的,只有一個服務端是可信的,客戶端的邏輯不可信,客戶端發給服務端的資料也不可信,服務端作為唯一可信的中心,需要去驗證客戶端端發來的資料是否真實可信,然后根據業務需求做一些處理,此外,客戶端和服務端的通信信道可能被人截獲,所以通信協議上要做加密處理,本文分以下幾小節: - 通信協議加密 - 賬號偽裝 - 重放攻擊 - 例外資料判定 - 一個案例
通信協議加密
在網路上傳輸重要的資料都不應使用明文,有很多工具可以很容易地截取協議包,抓取和更改其中的資料,比如WireShark,對于長連接,使用TCP或UDP協議,資料會以明文方式存在于協議包中,對于短連接,http如今已很少使用,蘋果明確規定開發者須使用https,而非http,對于使用http協議的app會拒審,即使使用https,資料被網路協議層做了加密,但仍不安全,最典型的一種攻擊是中間人攻擊,做法是攻擊者位于客戶端和服務端的中間,截獲任何一方發送的資料,處理后發給另一方,對于客戶端來說,中間人偽裝成了服務端,對于服務端來說,中間人偽裝成了客戶端,中間人截獲到任何一方的資料,都用公鑰做一層解密,然后用自己的私鑰加密資料發送給另一方,這種情況下,我們設計的所有通信資料會被明文暴露給攻擊者,所以,不論使用什么形式的連接以及哪種網路協議,都需要自己做一層通信資料加密, 典型的方式是用對稱加密,客戶端和服務端協商好一個密鑰,可以通過一個公用的邏輯生成,也可以由服務端生成后傳輸給客戶端,根據共用的密鑰,一方對資料做加密后發送,另一方獲取到資料后做解密,經過這樣處理后,攻擊者抓包后無法簡單地獲取到解密資料,但是,由于客戶端總是能被人破解,通過分析二進制代碼或dll中間代碼,動態除錯等方法,就能逆向出加密解密的演算法和密鑰,所以,我們能做的就是增加破解的難度,通常有以下方法: 1 用加固加殼反除錯等各種方式增加逆向客戶端代碼的難度, 2 密鑰不存明文,而是通過一個函式動態計算回傳,函式名和實作都寫得盡量難懂一些,更進一步,可以一定程度犧牲代碼的可維護性,不把通用的加密解密演算法封裝成函式,而是把邏輯分散到網路相關的邏輯中,加大逆向難度, 3 密鑰經常更換,比如每一次連接用一個密鑰,或者一次客戶端啟動用一個密鑰,或者每一個客戶端版本用一個密鑰,根據業務需求設計不同強度的密鑰邏輯, 4 原始資料最好不用文本格式,而用二進制,比如Protocol buffer, 通信協議加密是防破解中重要的一環,一旦協議被人破解,攻擊者就能獲取原始資料制造進一步的危害,脫機掛就是其中一種,完全舍棄了游戲邏輯,只要實作所有通信協議介面就能偽裝成客戶端和服務端通信,賬號偽裝
客戶端是完全不可信的,所以服務端應校驗客戶端的真實性,一般游戲,服務端會對每個客戶端分配一個唯一識別符號ID,以方便管理,攻擊者可能會改變自己的ID,從而把自己偽裝成其他玩家,然后修改或破壞其他玩家的資料,很多攻擊者利用這種方式來幫助其他玩家修改資料,從而牟利,所以,我們得從機制上防止賬號偽裝,一個解決方案是用token(或cookie)機制,大致流程為: 1 客戶端登錄時,服務端回給客戶端一個token,該token是服務端根據用戶ID等重要資訊加密后得到,注意加密演算法和密鑰僅保存于服務端,客戶端不知道,所以破解者無法破解, 2 客戶端保存該token,以后發送任何請求,都帶上該token, 3 服務端回應客戶端后續請求時,先根據token和密鑰解密得到用戶資訊,與客戶端請求中的其他資訊比如用戶ID做對比,若不匹配,則校驗失敗,判定客戶端不可信, Token機制實作上的考慮: 1 token算好后是存入快取,后續收到請求時直接從快取取,還是丟棄掉,每次請求時再算一遍, 2 token是否設定過期時間,重放攻擊
重放攻擊是一種常見的攻擊方式,攻擊者截取網路包,簡單地復制多份,重復發送給接收端,使得接收端誤以為事件發生了多次,客戶端和服務端都可能遭受這種攻擊,攻擊者可以用這種方式實作各種效果,比如有限時間內多次攻擊怪物,多次下單購買商品,多次獲取同一商品,解決方案一般有幾種: 1 自增ID,協議包包含一個自增ID欄位,每發送一次自增一次,接收端收到包后,判定ID是否和之前重復,或者增長量得太大,如果是則有重放攻擊的風險,這個方案實作簡單,但一旦網路協議被破解,很容易繞過去, 2 亂數,協議包包含一個亂數欄位,發送端和接收端都用亂數生成器生成一連串亂數,用一個buffer保存之前一段時間接收到過的亂數,接收端收到包后,判定亂數是否在buffer內,更進一步,可以判定收到的亂數是否在未來N個亂數范圍內,以判定網路協議是否可能遭到了破解, 3 時間戳,協議包包含一個時間戳欄位,接收端判定收到的時間是否是過去時間且和現在時間有較大差值,一般會結合時間戳和亂數,在秒級別的時間戳上拼接一個亂數,如果有重復則有被重放攻擊的風險,例外資料判定
所謂道高一尺,魔高一丈,我們做的很多防破解作業都是在提高破解門檻,增加破解難度,根本上很難防住所有漏洞,但是,在服務端我們有一種從根本上解決問題的方式,任何一個被破解的資料,在資料上都會體現出一些規律,所以我們可以玩家的行為資料上尋找線索和模式,以判定該資料是否為作弊玩家, 比如,玩家的攻擊力,攻擊頻率,游戲貨幣的生成和消耗,各種道具的生成和消耗,都會符合我們游戲設計的一些規律,比如事件的產生不會超過一定頻率,某些數值的變化量每次不會超過一個閾值,某些數值的總量不會超過一個閾值,一些資料之間可能存在某種約束關系,我們可以記錄下這些關鍵資料和事件的消耗,上傳給服務端,由服務端的一個特定服務來批量處理這些資料,然后判定玩家是否存在作弊行為, 這些判定不一定非常準確,在判定的嚴格程度上,我們寧可漏掉一些作弊玩家,也不能把正常玩家誤判為作弊玩家,可以根據資料處理結果,把玩家標記為幾個檔次:正常,嫌疑,作弊,確定為作弊的玩家可以自動做警告,封號或清空資料等處理,對于嫌疑玩家,我們不確定他是否一定作弊了,就用人工再篩查一遍,并采取相對溫和的處理方式,為了滿足這些需求,我們需要建立相對完善的后臺工具,一個案例
淘寶上有很多賣游戲破解的服務,比如有個比較流行的弱聯網游戲《夢幻家園》的破解服務,可以得到上億金幣和獎杯,賣家提供的破解有兩種方式: 1 偽造客戶端 我們只需要給破解者提供我們設備的IDFA,破解者就可以偽造該玩家的客戶端,上傳一個無限金幣的存檔,若玩家在系統設定里設定了限制廣告識別符號,則IDFA獲取為0,這個方式就行不通, 2 偽造服務端 按照如下步驟: (1)從破解者指定網站下載證書,將其添加到系統信任,設定wifi代理,填寫為破解者提供的網址, (2)進入游戲,此時客戶端的網路請求會發給破解者的后臺程式,破解者解包得到玩家的存檔資訊,然后修改為無限金幣,回傳給客戶端, (3)客戶端拿到了該存檔后,就已經是無限金幣,洗掉證書和代理,再進游戲,連到官方服務器,金幣仍為無限, 這兩種破解都需要完全破解通信協議,而這又是通過逆向分析完全能做到的,該游戲的開發商Playrix也做了一定防護,當金幣改成無限后玩一段時間,就會彈出警告框,提示檢測到您的資料出現例外,被限制參加各種聯網活動,這正是我們前面提到的例外資料判定方案,轉載請註明出處,本文鏈接:https://www.uj5u.com/qita/21358.html
標籤:其他
