一步解決 Unity 遊戲新安全風險

遊資網發表於2019-05-21
會議主題:技術專場 2
會議時間:2019 年 5 月 12 日
會議地點:上海國際會議中心

5 月 10 日晚,Unite Shanghai 2019 Keynote 主題演講於上海國際會議中心盛大舉行。從最前沿的技術到令人驚豔的 Made with Unity 案例,整場 Keynote 無不體現了 Unity 技術的每一個進步,都是服務於每一位創作者,以技術致敬每一位創作者 -Unity for all!

我們選擇了一些演講實錄在這裡分享給大家。這一次是是騰訊遊戲安全的陳小虎老師和 Unity 高川老師為我們帶來的《一步解決 Unity 遊戲新安全風險》。

演講內容

主持人:最後一場分享由騰訊遊戲安全的陳小虎老師和 Unity 的高川老師為我們帶來《一步解決 Unity 遊戲新安全風險》,大家歡迎!

陳小虎:大家下午好!很高興今天以講師的身份參加 Unite Shanghai 2019 的技術分享。今天的分享由我和 Unity 的一位同事一起,我負責技術環節的分享,高川負責後面 demo show 環節。

先做個自我介紹,我叫陳小虎,目前就職於騰訊遊戲安全團隊。我們團隊主要負責騰訊遊戲反外掛相關的工作。近年來,我們也向外部的遊戲廠商輸出了我們的安全服務和能力。我從事遊戲安全行業已經十多年了,現在主要負責騰訊遊戲客戶端保護工作,包括程式碼加密、遊戲加固、反盜版、反外掛的內容。

今天我們分享的主題是:一步解決 Unity 遊戲新安全風險,那麼什麼是新安全風險呢?

今天在座的各位大多是從事遊戲開發相關工作的。以前,我們經常使用 C/C++ 進行遊戲開發,這類遊戲會被直接編譯為彙編程式碼,外掛作者在製作這類遊戲外掛的時候需要具備一定的逆向經驗,不同外掛作者的經驗和技術差距非常之大。這是為什麼呢?因為外掛作者在編寫這類遊戲外掛時,需要熟悉彙編程式碼、各種偵錯程式以及分析工具,這使得學習成本成倍增加。

相比於使用 C/C++開發遊戲,使用 Unity 引擎開發遊戲,易上手,效率高,成本低。Unity 引擎帶來便捷和高效的同時,也引入了一些新的安全風險。遊戲逆向分析的門檻也被大幅降低,分析人員的差距被拉平,即使沒有太多逆向經驗的人,也可以開始嘗試製作外掛了。

Unity 支援 Mono 和 IL2CPP 兩種編譯模式。使用 Mono 編譯的遊戲,它將 C#指令碼程式碼編譯為 IL 中間語言打包到遊戲客戶端,在遊戲執行時候編譯為彙編程式碼。這類中間語言存在容易被反編譯為 C#原始碼的風險。後來基於安全性和執行效率方面的考慮,Unity 支援了 IL2CPP 編譯,大大提升了遊戲安全性,但還是存在被攻擊的風險。

那麼 Unity 遊戲新的安全風險有哪些特點呢?

相比 C/C++ 遊戲,Unity 遊戲的安全風險存在分析工具多、破解門檻低、攻擊方法通用化等幾個特點。

我們先來看看分析工具有多厲害。C# 反編譯相關的工具有很多,比如傳統的 ILDASM、PEBroswerDbg、GrayWolf、XenoCode 等。還有功能更加強大、操作更加簡單的 ILSpy、DnSpy、Reflector 等。以及記憶體 Hacking 工具 CheateEngine。這些工具簡便易用,很多人 5 分鐘就可以學會。我現在就來示範一下,如何使用這些工具完成一個遊戲破解任務。

我們前面說到,使用 Mono 模式編譯的遊戲,會將 C# 指令碼程式碼編譯為 IL 中間碼,釋出到遊戲客戶端。這種中間碼安全性較低,可以被一鍵反編譯,一鍵修改。

我們使用 Unity 官方的遊戲 demo 作為演示。遊戲玩法是消滅一隻怪可以獲得 100 積分,如何提高積分獲取效率呢,比如消滅一隻怪可以想要獲得 9999 積分。如何實現這個目標呢,下面我就開始正式的破解工作。首先使用工具 dnSpy 開啟這個遊戲的 Assembly-CSharp.dll 檔案,就可以看到遊戲的 C# 程式碼了。

一步解決 Unity 遊戲新安全風險

你可能會說,這不就是我們開發的程式碼麼?難道是原始碼洩露了?沒錯,就是原始碼洩露了。這裡不只能看,還可以改。只要我們修改圖中所示位置,就能實現修改積分的外掛功能。看一下我們的修改效果,左邊是修改前打一次加 100 積分,修改後打一次就可以獲得 9999 積分。幾乎是零學習成本,就是這麼簡單。

我們前面提到 IL2CPP,那麼 IL2CPP 編譯又有哪些風險呢?

使用 IL2CPP 模式編譯,遊戲的指令碼程式碼沒有了,指令碼程式碼被編譯成了 Native 程式碼釋出。前面提到的工具都失效了,安全性得到了一定的提升。但是 IL2CPP 編譯後會生成一個 global-metadata.dat 檔案,這個檔案裡面包含了大量的符號資訊。

如圖所示,我們使用現成的工具解析 global-metadata.dat 檔案,可以看到大量的原始碼資訊,例如類名、方法名、變數名以及函式程式碼位置等。

一步解決 Unity 遊戲新安全風險

雖然無法看到遊戲具體實現的程式碼,但有了這些資訊,依然可以大幅降低逆向成本。例如前面演示的修改積分功能,這次我們來修改遊戲初始積分。通過這些符號資訊,可以很快找到積分處理的相關函式:Score::Awake 函式。我們只要修改積分賦初值的地方就可以實現修改初始積分的效果。

這裡的重點不是修改積分帶來的危害,而是遊戲的邏輯被暴露以後,非常容易滋生外掛等各類傳統遊戲會遇到的安全問題。傳統遊戲中存在的安全風險,比如 FPS 遊戲的穿牆、飛天遁地、透視,自動開槍。MMORPG 中的無敵,秒怪,刷金幣,離線外掛等安全問題。當遊戲邏輯暴露之後,就更容易被外掛利用,外掛製作變得更簡單。還可能存在遊戲盜版、替換支付、廣告植入、病毒插入等安全問題。

為了解決上述安全問題,我們和 Unity 聯合開發了一個 Unity 保護方案:UPS。方案主要做了兩個方面的保護:Mono 保護,IL2CPP 保護。Mono 保護的物件是遊戲的主邏輯 dll:Assembly-CSharp.dll 和 Assembly-CSharp-firstpass.dll。IL2CPP 保護的物件是 metadata 檔案:global-metadata.dat

首先要做的是檔案級加密,以達到保護檔案的效果。加密前的指令碼檔案,我們可以看到 Assemply-CSharp.dll 可以被 PE 工具正確的識別。前面演示過,通過這個檔案可以直接反編譯得到原始碼。加密後的指令碼檔案,PE 工具無法識別出,其他反編譯工具也無法反編譯。

一步解決 Unity 遊戲新安全風險

經過檔案加密後的遊戲安全性的確是提升了,但是攻擊者還是可以從記憶體中得到明文檔案,然後進行反編譯。為了防止攻擊者從記憶體中獲取明文檔案,然後進行反編譯這樣的攻擊方式,我們還做了方法加密。

經過方法加密後,就算攻擊者得到了記憶體中的明文指令碼檔案,也無法反編譯。工具直接報錯,完全看不到原始的程式碼資訊。如圖中所示,綠色部分都是反編譯失敗的錯誤提示。

一步解決 Unity 遊戲新安全風險

方法加密之後,還存在很多的字串資訊,比如方法名和類名。於是我們要做進一步加密,把字串資訊也處理掉。加密結果可以看到,程式碼和類名方法名完全不可讀。

一步解決 Unity 遊戲新安全風險

除了方法加密,我們在指令方面也進行了保護。經過加密後的 opcode 對應的不再是 Mono 中標準的 IL 指令。比如標準中 0x01 opcode 對應的是 A(ldarg.0)指令,但經過指令加密後,0x01 對應的可能就是 B(call)指令了。亂序後的指令必須通過我們的解密過程,才能被正確的解釋和執行。通過以上這些方式,已經把位元組碼的安全性提高到了一個比較高的 level。

前述內容是關於 Mono 編譯的遊戲的保護,那 IL2CPP 保護又是什麼效果呢?

前面提到 global-metadata.dat 檔案中包含了大量的符號資訊,我們對此檔案進行了多級別加密,使得通用工具解析失敗,無法拿到遊戲的敏感資訊。實現的效果見下圖,這裡可以看到工具直接報錯無法解析。

一步解決 Unity 遊戲新安全風險

前面介紹的都是我們核心的安全特性。此外,通過和 Unity 合作, UPS 方案在穩定性和相容性都得到了進一步的提升。

穩定性方面,UPS 方案是 Unity 原生支援的,不會修改遊戲和引擎二進位制。

相容性方面,UPS 方案不會在遊戲工程中引入第三方元件。

跨平臺方面,我們支援 Win/Mac 版的 Unity-Editor,支援對 Windows/Android 雙平臺遊戲的保護。

保護強度方面,我們提供檔案級、方法級、指令級等多級加密,並且每次加密的結果都不一樣。

那麼這麼棒的功能使用起來一定很複雜吧,其實很簡單,現在只需要一步就能實現這樣的保護效果。和傳統的加密方案相比,我們的方案整合到 UnityEditor,只需勾選 Security Setting 頁面的 Enable Security Build 核取方塊就可以了,真正做到零成本接入。

一步解決 Unity 遊戲新安全風險

接下來有請 Unity 大中華區企業支援經理高川來為大家演示如何使用這麼棒的保護功能。

高川:我們這個方案是基於 2018.2.12f1 版本做的一個先行驗證。後續我們會把它推廣到更多現行的版本里。我們可以看到,現在是我做的一個非常簡單的 Demo 場景,在這個場景裡我用一個 button 控制 y 軸,讓它上下移動,非常簡單,只有一個指令碼。可以看一下 Move 指令碼里的內容,非常簡單的一段程式碼。我們首先做一個沒有經過加密的安卓版本,因為大家也知道,現在最容易受到攻擊的版本,基本上就是安卓和 Windows,並且攻擊成本是非常低的。我們現在已經 build 出了一個 apk,把它解壓一下。拿到 apk 內容後,現在幹一點壞事,找到一個工具開啟它,比如說剛才介紹的 ilSpy。我一個鍵都沒有按,只是拖動了一下。我們現在在 ilSpy 裡能看到的基本就是我的原始碼。大家可以做簡單的對比,基本上沒有什麼差別。如果這是一個上線遊戲的話,恭喜你,你的程式碼被攻擊者者完全掌握,他可以為所欲為了。

如何避免這樣的事情發生呢?我們重新構建一個新的版本,只需要勾選 Enable Security Build。按照剛才的步驟再進行反編譯。大家可以看到這個地方是一個紅紅的叉,告訴你失敗了。我們再找其他的工具反編譯 Assembly-CSharp.dll,發現其他工具也失敗了。可以看到,如果在構建遊戲時勾選了加密選項,你的遊戲進行加密後,攻擊者是沒有辦法通過反編譯工具直接獲取遊戲指令碼程式碼,從而危害你的遊戲。因為現場環境的限制,我這邊沒有 Windows 平臺,實際上 Windows 上 Unity-Editor 有同樣的功能。我們現在支援 Windows/Android 平臺遊戲的加密,包括 Mono/IL2CPP 模式。

大家現在還不能拿到 Security 版本的 Unity,但是我們會盡快把它釋出出來,希望大家能隨時關注我們公眾號上的一些資訊。如果有後續資訊,我們會在第一時間跟大家進行溝通,也歡迎大家試用。同時也希望大家多關注我們合作伙伴騰訊遊戲安全平臺,也會有更多的安全設施和安全技術加入到我們 Unity 這邊來。我的演示結束了,謝謝大家。

主持人:今天的分享到此結束,謝謝大家參與。

來源:INDIENOVA
地址:https://indienova.com/indie-game-development/unite-2019-shanghai-unity-security-build/

相關文章