本文作者為易盾實驗室工程師。
隨著移動網際網路的高速發展,移動遊戲市場也得到了快速發展,與之對應的移動遊戲外掛和破解市場也是風生水起,外掛和破解的發展對遊戲的玩家體驗,以及廠商收益產生了極大的消極影響。為維護遊戲運營安全,保障玩家公平的遊戲環境,對遊戲的保護必不可少。
移動遊戲最重要的是部分是資源和邏輯,而遊戲引擎則是處理資源和邏輯的關鍵所在。惡意玩家可以透過遊戲引擎獲取解密後的遊戲指令碼或遊戲資源,然後修改指令碼或資源到達破解的目的;也能透過修改引擎的邏輯達到破解的目的;還可以透過引擎插入自己的指令碼或資源實現外掛功能。
因此遊戲引擎的保護是迫切的,在Android 遊戲中游戲引擎是SO檔案,如何保護SO檔案成了遊戲需要面臨的問題。遊戲,再怎麼考慮安全,也必須要考慮到遊戲體驗,順暢的遊戲體驗對玩家至關重要,一切安全解決方案必須在不影響遊戲效能和玩家體驗的基礎上進行。
目前SO檔案保護方案大概可以分為有源保護和無源保護,有源保護分為自解密、混淆、原始碼VMP等,無源保護分為加殼、VMP保護。
有源保護中的自解密保護的原理是:先加密需要加密的函式或者段,然後再載入SO檔案,解密先前加密的函式和段。由於執行後需要解密相關的邏輯,因此破解者只需要在SO檔案執行後,DUMP記憶體,即可獲取解密後的邏輯,破解門檻低,因此自解密的保護方式存在安全強度低、維護成本高的缺點。
市面上常用SO原始碼保護是基於LLVM的混淆,透過指令替換、控制流扁平化和虛假控制流等角度去混淆原始碼。如下原始碼為測試原始碼,試試一個簡單的校驗函式,測試程式是ARMV7A架構下的編譯。
下面是混淆前的控制流程圖展示:
對上面的原始碼進行一些混淆,在增加了虛假控制流、指令替換和控制流平坦化的處理後,控制流的複雜度增加。如下圖所示,增加了控制流程圖複雜度,加大了逆向分析的難度。基於LLVM的原始碼混淆比較靈活,可以根據不同的安全需求配置不同的安全策略,混淆程度越高,則效能影響越大,檔案膨脹越多。在對遊戲影響很小的前提下,混淆能做的比較有限,導致安全強度不夠,混淆存在安全強度和效能不可兼得的問題,不好找到平衡點。
由於原始碼混淆的方案在安全強度方面不夠,因而出現原始碼VMP的解決方案。
相對基於LLVM的混淆,VMP安全強度更高,並且對SO檔案的體積影響也較小,加固後的SO主要分為虛擬資料VMData和直譯器handler,如下圖所示為例子的VMData資料。
直譯器handler的控制流
採用VMP保護對原函式執行的效能有比較大的影響,對所有方法VMP是無法滿足遊戲方對效能的要求。VMP的在不瞭解VMData和handler的對應關係的情況下,安全強度非常高,若相關的對應關係被破解者掌握,則也可以被還原,不過handler的複雜性一般比較高,並且對應關係可以做到隨機處理,因此安全強度是完全滿足遊戲方的要求。
上面說的基於原始碼的保護都存在一個相同的問題是接入成本高,需要處理原始碼就需要有本地工具,特別有些遊戲引擎非開源,那基於原始碼的保護則無法接入。
無原始碼保護的加殼,市面上對應的加殼的方式有很多,安全強度差異也較大,不過核心是自定義linker。在殼SO檔案被執行後需要先解密、還原被保護的SO檔案,然後使用自定義linker載入被保護的SO,最後將執行權還給被保護的SO。加固的靜態保護強度很高,原SO的蛛絲馬跡完全抹去,但是動態執行後會還原部分內容,開發者也可以配合反除錯、反Dump等技術使用,彌補SO加固在記憶體安全強度上的弱點。雖然加固存在著比較明顯的弱點,然而加固也存在極大的優勢,加固是對遊戲效能影響最小,在遊戲執行中不會增加任何開支,並且接入成本低,不需要有任何接入的成本。
無原始碼VMP與基於原始碼的VMP原理上是相通的,加固處理後最關鍵的部分依然是虛擬資料VMData和指令解釋執行器handler。VMP處理時需要將原指令處理成VMData虛擬資料,並且插入直譯器handler,如下圖所示為無源VMP的handler。
VMP處理的安全強度高,逆向分析成本高,當然同樣存在效能的問題。
根據上面對目前SO檔案保護方案的說明,可以發現SO加殼是效能影響最小,VMP是安全強度最高,無原始碼方案是接入成本最低的方案。採用SO加固+無原始碼VMP結合的方式即可滿足遊戲對效能影響最小化的需求,最大程度的減少安全措施對遊戲效能的影響,同時滿足對遊戲引擎的保護需求,在遊戲引擎關鍵地方採用VMP防止破解者逆向分析,保障了遊戲的安全。