如何防止Unity3D代码被反编译?

在网上找了好久,还是没有找到可行的方法,市面上的除了腾讯的Unity3D游戏之外都可以使用DisUnity拆包,DotNetReflector很简单地进行反编译,再通过dot4net进行反混淆。想请教下,发布出去的Unity3D游戏如何防止代码和资源的泄露,或者说腾讯(如:天天打怪兽)是如何做到无法反编译的。。。

猪小花1号提问于 2018-05-02 10:40
1 个回答
  • 活动主持人2018-07-13 14:08

    网易云易盾移动游戏安全技术专家陈士留在2018年Unity技术路演演讲内容中对这个问题有过比较详细的介绍,摘录如下:

    防止Unity3D代码被反编译其实就是常见的Unity手游风险中的破解风险。


    一、Unity面临的破解风险

    Unity的破解风险主要有Unity mono脚本解密、Unity il2cpp脚本解析、Assetbundle资源篡改这三项。


    1.Unity mono脚本解密:

    以下两张图为mono脚本文件的二进制形式及源码转换。



    2.Unity il2cpp脚本解析:

    以libil2cpp.so和global-metadata.dat作为输入,使用Il2CppDumper即可进行解析:


    解析出来的效果如下所示,类名、函数名以及对应的偏移都能够被解析出来:


    目前iOS中还没有能够解析为源码的工具,但是如果可以解密或解析Android脚本,将会大大方便iOS的破解。因此Android的有效脚本加密非常有必要。

    3.Assetbundle资源篡改:

    透视功能可让使用修改版的玩家获取不对称优势。如下所示的某枪击游戏,将其中Assetbundle资源里面的材质属性修改为透明,即可达到透视的效果。


    除了资源被篡改的风险外,游戏中还存在资源被竞品盗取、分析的风险。


    4.存档数据被修改


    某些游戏存档数据以明文形式存在,如果这些数据不去服务端校验,或者是单机游戏的话,则存在巨大的安全风险,游戏的各种属性可以直接修改。

    如何保护Unity安全?很多开发团队可能也有自己开发加固保护系统的打算,如果要做好这套保护系统,需要解决很多问题,主要包括以下四个:

    第一、保护方案自研成本比较高,需要不断调研、不断改进,不但需要了解破解流程,还需要深度掌握Unity引擎的运行原理。

    第二、安卓的兼容性问题,安卓设备碎片化严重,系统版本升级、用户环境多样化。需要不断完善解决方案。网易在这一块积累了很长时间,才开发出一套在性能、兼容性和安全强度都满足的保护方案。如果游戏开发团队自研,兼容性会占用团队大量时间,降低游戏核心逻辑开发速度。

    第三、对于破解来说,本身保护工作是一个矛和盾的过程,是不断升级和不断对抗的过程。如果游戏开发团队要去自研保护系统,需要分析市面上的破解工具,并不断分析他们破解的方法,然后才能不断提高整个保护系统强度。

    第四、第三方服务的兼容性,游戏现在越来越是一个精细化开发的模式,很多游戏团队只做一些核心的逻辑玩法的开发,所以保护就需要兼容支付模块、热更新方案及质量跟踪等各种第三方服务。而兼容这些第三方的服务,又给游戏开发团队带来了很大的挑战。

    综上所述,如果游戏开发团队自主开发保护方案肯定会面临很大技术和资金挑战,所以不建议自主开发保护方案。


    二、那么易盾是怎么防止Unity3D代码被破解的呢?


    网易云易盾能够提供Unity mono DLL脚本加密、IL2CPP 加密、Assetbundle加密等加密解决方案!


    通过修改或者HOOK mono_image_open_from_data_with_name能够对DLL脚本加解密。mono_image_open_from_data_with_name是CSharp 脚本的加载函数,如果CSharpDLL脚本做了加密,需要在这个函数执行之前解密。因此只要在这个函数这里下断点或者HOOK,就可以解密出原始DLL,而不需要逆向加密算法。需要注意的是,这里有个memcpy拷贝操作,mono会把解密后的DLL在内存中留存一份拷贝。


    Unity mono DLL脚本加密经历了三代的技术演进。


    第一代加密直接对DLL文件进行加密,在mono_image_open_from_data_with_name函数开始处解密。对于这个的破解方法很简单,PE结构的文件,以4d 5a90 00这四个字节为magic head,这可以做为CSharp DLL脚本的特征,只要搜索0x905a4d这个数值就可以了,由于烧饼修改器是使用10进制数值,将其转换成10进制值:9460301。因此解密门槛很低,只要使用修改器就可以解密。


    第二代加密基于第一代加密的明显弱点,针对解密加强了防护。解密后,把下图所示的PE头抹掉,使得修改器无法定位到脚本位置。因此解密门槛比较高,需要非常强的逆向开发能力才能破解。


    第三代加密针对Csharp 函数做了加密,也就是方法级加密,需动态解密。


    原始未加密dnspy函数解析结果


    函数加密后dnspy函数解析报错


    IL2CPP加密

    Il2cpp脚本信息以lib2cpp.so形式存在,结合global-metadata.dat文件内的符号信息,即可进行解析,因此需要对libil2cpp.so做so加壳,如下图所示,原始libil2cpp.so用IDA可以看到475个导出函数:


    加固后的libil2cpp.so导出函数则为空:


    Assetbundle加密

    Assetbundle未加密时,Unity Studio可解析出各种资源:


    对Assetbundle加密后,Unity Studio就无法解析了:


    三、易盾保护方案特点

    网易易盾保护方案具有纯Native保护、对引擎SO做加壳、兼容性和稳定性高、性能影响小、支持Windows、Linux、Mac三平台加固等性能特点。

    1.纯Native保护

    游戏dex内部都是第三方SDK以及游戏内部不涉及到游戏逻辑的SDK。如果对DEX加壳的话,一方面容易造成Android碎片化,导致dex加壳会降低app的兼容性;另外Android存在Dalvik和Art两种虚拟机,所以dex加壳会为了兼容2种虚拟机而增加处理成本,从而导致启动耗时增加比较厉害。阿里和腾讯都有DEX加壳服务,但是支付宝、微信都没做DEX加壳。支付宝和微信的安全问题应该是所有APP中间最严重的,他们都没做DEX加壳,这很能说明问题,此外所有腾讯的游戏都没有做DEX加壳。所以如果手游保护需要依赖于DEX加壳的话,兼容性和安全性都是很难保证的。因此建议游戏不要使用DEX加壳。

    网易易盾可以提供纯Native保护,使游戏保护不依赖DEX加壳。DEX加壳和纯Native保护优缺点比较如下:


    2.对引擎SO做加壳

    基本上所有的破解都依赖于对引擎so的逆向分析,如果对so进行了加壳保护,会大大增加游戏被破解的门槛。除了对引擎SO加壳,网易易盾还会对敏感函数代码做校验。

    3.兼容性和稳定性高

    兼容强的原理在于所有保护都在SO层,不会对DEX进行修改,有效避免了Android碎片化导致的兼容问题。网易易盾的兼容性极高,可以兼容从Android 2.3到Android 9.0所有版本系统、所有模拟器以及所有游戏引擎使用的指令集。

    手游保护的稳定性,需要遵循如下发布流程:

    1. QA测试:在200台手机上以及各种模拟器上测试;

    2. 预线上测试:将安全模块集成到日活1000的APP上线测试2周;

    3. 版本发布:前面2轮都测试稳定后,正式发布;

    4. 线上回归:先在内部比较小的游戏上线测试,确保稳定性。

    4.性能影响小

    易盾保护方案还具有性能影响小的特点,无论是CPU占用、内存占用、启动时间、电量消耗等方面的影响几乎都可忽略不计。


    陈士留演讲全文请点击这里查看

    可点击查看网易云易盾手游加固保护介绍及免费试用