Unity目前已经全面覆盖到各个游戏平台,超50%的手机游戏、PC游戏和主机游戏基于Unity引擎制作而成,全球月活跃创作者多达150万,遍布190多个国家和地区。此外,2019年全球收入前一百的工作室中,有93%的开发者在使用Unity的产品。
”可以看到,Unity作为目前市场的第一大游戏引擎占有者,受到越来越多的游戏开发者和制作者的青睐,同时Unity游戏会被一些攻击者和“别有用心”的人盯着,不仅影响到了游戏市场与游戏玩家的公平,而且或缩短游戏自身的生命周期。本文将重点围绕“反破解”讲述这些安全风险,以及网易易盾团队如何对unity游戏进行全方位的矩阵化保护升级。
从上图可以发现,面对unity的破解问题,游戏开发商可采取了一个全方位的矩阵化保护方案。方案中首当其冲的是对于代码的保护,其中包括脚本和引擎文件保护。
通过使用dnSpy.exe对Assembly-CSharp.dll进行反编译,如下图所示可以清晰看到其中的逻辑代码,以及通过修改IL指令就可以达到进一步的作弊效果。对于上面这种dll文件被修改的情况,我们研发了对于dll文件保护的迭代,如下所示:2.1.1 整体加密
大部分的加固厂商刚开始都是着手于对于DLL文件的整体加密,通过阅读mono的源码可知通过修改 mono_image_open_from_data_with_name函数能够对DLL脚本进行解密。或者在加固的时对于mono_image_open_from_data_with_name进行HOOK处理;且对于“4D 5A 90”这样的关键魔术字抹掉,防止攻击者在内存中搜索dump;但是对于整体加密存在的问题比较容易分析,通过动态调试或者寻找内存中的特征点进行完整还原。故而对于这种情况,游戏厂商可以采取“函数加密”方法自保,详情如下:2.1.2 函数加密
面对以上整体加密,细致的“函数加密”不可或缺:在函数运行前进行解密,而不是在内存中整体解密,这个时候边运行边解密,这时候通过hook mono_image_open_from_data_with_name拿到的dll是不完整的解密,method code还是加密的状态,这样大大加强了dll的加密难度,使用dnSpy.exe 和 Reflector.exe 进行反编译可以看到很多的方法是看不到的,这里不做展示。
2.1.3 结构自定义
面对上述的函数加密,部分攻击者通过内存定位hook函数,内存中去还原dll 的method code,这个时候我们研发了dll的自定义结构,通过对dll的文件结构进行自定义话,同时配合上面的整体加密和函数加密,最后的效果如下:对于“结构自定义”的情况,攻击者需要去分析游戏的文件自定义结构,不仅是到内存中进行解密,而且得还原我们自己的结构形式。双重破解“门槛”,使攻击者的行动难度加深。
随着MONO Vm在各个平台的难移植性、MONO版权的受限,以及性能等影响的受限,unity引入了il2cpp机制,加入静态语言特性把代码转化到native层,虽然在某种程度上提高了游戏的安全性,但是会把C#中的重要的方法类名等符号信息存储在一个叫global-metadata.dat 文件中,这个时候可以借助于Il2cppDumper,如下图所示对一个Demo可以解析到敏感的方法名与类名。对此,游戏保护依然可以通过分析il2cpp.so得到游戏的代码逻辑。对于这个情况,我们研发了对global-metadata.dat 的加密方法的迭代:2.2.1 global-metadata落地加密
第一代是研究了落地加密方式,如下所示为加密前后展示:这个时候同时对libil2cpp.so文件进行加固,可以阻挡上面对于符号表的解析以及libil2cpp.so文件中重要的关键字段的解析,这里不再展示。
2.2.2 global-metadata内存加密
对于第一代的落地加密方式,很容易在运行的时候在本地找到解密的global-metadata.dat文件,这个时候研发了内存加密方法,只是会在内存中进行解密,同时抹掉关键的标识等,加大分析的难度。对于上面两种方式的加密均不需要符号表,方便快捷,一键式加密。
2.2.3 global-metadata分块加密
同时,为了进一步的加强对于global-metadata文件的保护,我们又研发了分块加密,只有在函数运行的时候才会进行解密,这个时候在内存中拿到的文件永远是不完整的,进一步加强对于global-metadata文件的保护。这样dump出来再次使用会报错:2.2.4 反global-metadata内存Dump
在上面静态加密保护的基础上,面对一些通过使用在内存中反射获取关键信息的攻击方式,团队研究了防动态dump的方法,这样静动态的结合极大的加强了对于global-metadata.dat文件的保护。
Unity自从接入il2cpp以后,通过使用xlua和tolua等进行热更,这个时候热更的lua、luac、luajit成为了攻击者的分析目标。我们提供对于的lua文件的加密保护以及对应的热更引擎的保护,防止攻击者去分析热更中lua的代码逻辑。
通过对Assembly-CSharp.dll转为il2cpp.so结合global-metadata.dat文件使用IDA分析,可见清晰的逻辑如下:对于unity引擎中的libil2cpp.so以及自定义的libmono.so文件,通过独家研发的引擎文件进行加固保护,同时对于热更的lua引擎以及unity引擎进行加固保护,团队制定了多种的引擎加固方案,“轻量级”与“高强度”并行的加固方案。
ab资源作为unity引擎中的核心资源,将所有的资源形式打包成了UnityFS的格式,通过AssetStudio可以对ab资源进行提取,如下图所示,部分资源的暴露可能带来资源被窃取、被修改,以及游戏内存在剧透的风险。为了防止对于资源的分析以及拷贝,游戏开发商可采取 “ab资源加密”的保护措施。
在某些特殊情况下,部分unity的包会以静态资源而不是ab资源的形式存在安装包中,为了保护自己的美术资源,易盾团队研发了针对静态资源的保护,在同样的强度上边运行边解密,同时由于ab资源在一个APP中所占的体积较大,尽可能小的降低ab的压缩率,且考虑到APP运行的性能问题,只会加密部分重要的结构信息,这样就达到了对应的要求。对于效果同上的ab资源处理,这里不做具体的效果展示。
针对dll文件、global-metadata文件、lua文件、资源文件,以及引擎文件的保护,是Unity游戏安全运行的必经之路。游戏开发商必须在保障兼容性的前提下,根据强度与性能的不同要求进行自动化加固,真正做到游戏安全的全方位升级。