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_MethodInfo,MethodInfo结构中详细记录函数相关所有信息,其中包括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机制会大大降低逆向分析的难度,通过搜索关键字便可快速找到函数名和函数地址对应关系,从而分析清楚相关功能处理方式。

淘宝花钱买的最新版!需要的拿去! This asset obfuscates your code to make it harder for bad guys to reverse engineer your projects. Specifically designed for Unity, it seamlessly links in with its build process. The top priority of this package is to work straight out of the box with no extra steps required. While other obfuscators can stop a game from working, Beebyte's obfuscator looks for specific Unity related code that must be protected. The contents of your source files are unchanged, the obfuscation targets the compiled assembly. Features: - Supports IL2CPP - Supports Assembly Definition Files (Unity 2017.3+) - Removes Namespaces without any conflicts - Recognises Unity related code that must not be changed - Renames Classes (including MonoBehaviours) - Renames Methods - Renames Parameters - Renames Fields - Renames Properties - Renames Events - String literal obfuscation - Adds fake methods - Easy and extensive customisation using the Unity inspector window - Consistent name translations are possible across multiple builds and developers - Semantically secure cryptographic naming convention for renamed members The asset works for both Unity Free and Unity Pro version 4.2.0 onwards (including Unity 5 & 2017 & 2018). Build targets include Standalone, Android, iOS, WebGL, UWP. Other platforms are not guaranteed or supported but may become supported at a future date. IL2CPP builds are much harder to reverse engineer but strings and member information (class, method names etc) are visible in the global-metadata.dat file. Obfuscation will apply to this file adding further security. Why not complement your security with the Anti-Cheat Toolkit - a great third party asset. For more information about the Obfuscator, please see the FAQ
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值