iOS平臺Unity引擎的IL2CPP機制分析及安全性評估

研究背景

Iphone5S以上(包括5S以上的機型)的機器中都採用了64位的CPU,蘋果爲了更好發揮64位CPU運行速度,APP Store發佈規定:全新App必須在15年2月1日支持64位CPU,已經上架的遊戲必須在15年6月1日更新的時候支持64位,否則不能通過蘋果官方的審覈

Unity引擎4.6.2之前的版本採用Mono的AOT機制提前將C#代碼編譯爲機器識別的二進制代碼,Unity官方爲了支持IOS平臺下64位的APP遊戲,4.6.2之後的版本採用IL2CPP機制編譯和處理IOS平臺下的遊戲。Unity的IL2CPP並不是對整個.NET或者Mono工具進行重新改寫,依然支持繼續使用Mono的C#編譯過程,唯一不同點爲:IOS平臺的Unity在4.6.2之後的版本不在使用Mono的AOT編譯機制,重新實現一套預編譯程序,可在預編譯將中間層的IL指令轉換爲C++代碼,然後在利用標準的C++編譯程序來產生原生二進制文件。IL2CPP同時實現虛擬機,虛擬機負責處理函數之間調度、管理調度所需內存等。

本文主要分析如下幾個點:Unity引擎 IOS版本中C#代碼和轉換之後的C++代碼對應關係、以三劍豪IOS爲例分析其中的C#邏輯函數調用方式和關鍵信息分析、IL2CPP機制的遊戲安全性評估。

 

實現原理

Unity引擎作爲目前最爲主流的3D遊戲開發引擎,遊戲平臺移植性非常好,Unity引擎4.6.2之後的版本採用了IL2CPP機制支持IOS平臺64位遊戲編譯,針對IL2CPP機制進行深入分析之後有利於評估IOS平臺的Unity遊戲安全性。

一、IOS平臺Unity引擎IL2CPP機制生成代碼對比

Unity引擎提供了支持蘋果Mac系統的版本,測試過程中下載了Unity引擎的最新版本(5.1.2f1版本),安裝好Mac版的Unity引擎之後便可創建遊戲工程。

Unity引擎通過File菜單Build&run項可編譯IOS版的Unity遊戲代碼,點擊之後會彈出下圖所示的框:

需要點擊PlayerSetting選項設置編譯方式和代碼框架,對應設置選項內容如下圖所示:

               

上圖界面信息中需要重點關注兩項設置,首先需要將“Scripting BackEnd”設置爲IL2CPP方式,之後需要將“Architecture”設置爲Universal(表示同時支持ArmV7和Arm64兩種指令集)。設置完之後便可點擊Build按鈕編譯工程,編譯成功之後會生成一個XCode工程,以供遊戲開發方在Mac平臺的XCode工具中編譯生成最終的APP文件。

Unity引擎採用IL2CPP機制在Mac平臺成功編譯之後,會生成一個完整的XCode工程,Unity遊戲邏輯代碼採用C#編寫,遊戲開發方的C#代碼最終會生成在/Classes/Native目錄中,對應文件結構如下圖所示:

Unity會將使用的C#庫代碼編譯爲Bulk_Name.cpp的文件,對應截圖如下:

        

同時Unity會生成IL2CPP轉換之後的相關結構、初始化、調用等信息,文件名以L2CPP命令,對應截圖如下所示:

                     

以上爲Unity在Mac平臺中針對IOS版本利用IL2CPP機制編譯生成C#代碼。

下面針對Unity的IL2CPP機制,對比並分析C#邏輯代碼經過IL2CPP機制生成的CPP文件代碼,測試原始的C#代碼如下所示:

測試代碼中C#代碼的ActivateTrigger類有一個OnTriggerEnter函數和幾個成員變量,對應生成的代碼如下:

其中C#類的成員變量被定位爲結構體成員,類的成員函數被定義爲C導出的函數,例如ActivateTrigger::OnTriggerEnter 成員函數被IL2CPP機制編譯爲ActivateTrigger_OnTriggerEnter_m409函數名,同時增加了兩個參數,兩個參數爲:所屬的類結構指針(類似每個類的This指針)、MethodInfo結構體指針,方便函數內部調用類的成員變量。通過以上方法可知Unity所採用的IL2CPP機制實際利用C語言的方式表示C#對象的成員變量和成員函數。其中ActivateTrigger::OnTriggerEnter函數內部調用了DoActivateTrigger函數,由於DoActivateTrigger上層由C#調用,所以該函數在編譯編譯生成XCode工程時以直接調用方式編入ActivateTrigger_OnTriggerEnter_m409函數代碼中。

 

二、逆向分析IL2CPP機制中C#函數調用方式

第一部分以正向的方式分析Unity引擎IL2CPP機制將IL指令轉換爲CPP的方式及代碼結構。該部分以逆向的方式分析Unity3D遊戲(三劍豪遊戲採用Unity引擎的4.6.2f版本)中所採用的IL2CPP處理機制。

1、IL2CPP機制中C#函數調用處理方式

三劍豪遊戲採用Unity引擎開發,IOS平臺中採用Unity的IL2CPP機制支持64系統,其中Android平臺依然採用Unity的Mono Jit編譯機制。

三劍豪遊戲中C#函數FDynamicSceneTrigger::OnTriggerEnter對應代碼如下圖所示:

FDynamicSceneTrigger::OnTriggerEnter函數C#代碼經過Unity的IL2CPP機制轉換並在XCode工程編譯之後生成的彙編代碼如下所示: 

_FDynamicSceneTrigger_OnTriggerEnter_m25168爲IL2CPP機制轉換之後C#函數對應的函數名,_FDynamicSceneTrigger_OnTriggerEnter_m25168函數對應地址爲:0x43A824,通過交叉引用發現該函數並無直接調用的函數,交叉引用只有一處,及屬於該函數對應的MethodInfo結構,該函數對應的MethodInfo結構如下所示: 

其中FDynamicSceneTrigger::OnTriggerEnter函數經過IL2CPP機制轉換之後對應生成的MethodInfo變量名爲:_FDynamicSceneTrigger_OnTriggerEnter_m25168_MethodInfoMethodInfo結構中詳細記錄函數相關所有信息,其中包括C#函數上層調用函數。MethodInfo定義如下所示:

通過上圖MethodInfo結構可知C#函數方法對應的函數名字,所屬類信息,方法對應地址、上層調用等信息,其中幾個重要的變量解釋如下:

 Name:爲C#函數名;

 Method:爲C#函數代碼地址;

 Declaring_type:爲C#函數所屬類信息,其中包括類名、命名空間等信息。

 Invoker_method:爲C#函數對應的上層調用函數地址,Unity的IL2CPP機制按照不同C#函數參數定義了不同的上層C調用函數(其中調用方式爲間接調用)。

通過_FDynamicSceneTrigger_OnTriggerEnter_m25168_MethodInfo結構可知_FDynamicSceneTrigger_OnTriggerEnter_m25168函數的上層調用RuntimeInvoker_Void_t2689_Object_t(MethodInfo const*, void *, void **),其中對應的間接調用代碼如下圖所示:

上圖中R3爲MethodInfo 結構變量,R3+4對應C#函數經過編譯處理之後的函數代碼地址,上層通過間接的方式調用C#函數。

其中RuntimeInvoker_Void_t2689_Object_t函數的上層調用也是通過間接方式實現,對應調用接口函數爲:il2cpp::vm::Runtime::Invoke(該函數定義爲:il2cpp::vm::Runtime::Invoke(MethodInfo const*, void *, void **, Il2CppObject **)),該函數爲Unity爲實現IL2CPP機制而添加的VM虛擬機,該函數負責調度處理C#函數,其中il2cpp::vm::Runtime::Invoke函數間接調用RuntimeInvoker_Void_t2689_Object_t函數代碼如下圖所示:

其中R6爲MethodInfo變量,MethodInfo+0x10偏移對應C#函數的上層調用函數地址,在獲取每個C#函數對應的RuntimeInvoker函數之後,便通過間接的方式進行調用。

Unity引擎採用的IL2CPP機制爲每個C#函數生成上層的RuntimeInvoker間接調用函數,生成的函數規則爲:RuntimeInvoker_+函數返回類型+_函數編號_+函數參數信息,通過爲每類C#函數生成上層調用函數並填入對應C#函數的MethodInfo結構中,從而實現間接動態動用方式。

Unity引擎的IL2CPP機制中VM虛擬機針對C#函數調用方式的調用如下所示:

il2cpp::vm::Runtime::Invoke  -> RuntimeInvoker 函數 -> C#函數代碼(C#函數經過IL2CPP轉換之後的C++代碼函數)

 

三、IOS平臺Unity IL2CPP機制安全性分析

通過以上兩節的分析可瞭解到Unity引擎採用IL2CPP機制編譯代碼方式及調度處理C#函數代碼方式,分析過程中提到的重點結構爲MethodInfo,每個C#函數編譯之後會生成MethodInfo結構,該結構中揭露詳細的函數信息,包括函數名、參數名、所屬類名、函數地址、命名空間等信息。IOS平臺Unity引擎採用的IL2CPP爲每個C#函數編譯生成MethodInfo結構,通過逆向方法可推測出每個C#函數對應的函數名、類型等信息,如下圖所示爲部分函數名信息:

通過函數名交叉引用可確認C#函數名對應MethodInfo結構,通過MethodInfo可獲取C#函數所有相關重要信息,包括函數所屬類名、函數地址、函數參數等信息。

IL2CPP爲每個C#函數生成的Methodinfo結構相當於爲逆向分析者提供一份Map文件,逆向分析者可根據字符串搜索快速定位到函數地址,從而大大降低了遊戲分析難度。通過以上分析得出結論:IOS平臺中Unity引擎採用的IL2CPP機制會大大降低遊戲逆向的分析難度,給遊戲帶來較大的安全隱患

 

總結

以上對IOS平臺Unity引擎IL2CPP新機制進行相關分析,其中包括C#的IL指令轉換爲CPP的代碼生成規則、IL2CPP的VM虛擬機針對C#函數的調用方式,同時針對Unity引擎的IL2CPP機制安全性進行分析,最終得出結論爲:Unity所採用的IL2CPP機制會大大降低逆向分析的難度,通過搜索關鍵字便可快速找到函數名和函數地址對應關係,從而分析清楚相關功能處理方式。

發佈了20 篇原創文章 · 獲贊 23 · 訪問量 27萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章