本文作者为易盾实验室工程师。
随着移动互联网的高速发展,移动游戏市场也得到了快速发展,与之对应的移动游戏外挂和破解市场也是风生水起,外挂和破解的发展对游戏的玩家体验,以及厂商收益产生了极大的消极影响。为维护游戏运营安全,保障玩家公平的游戏环境,对游戏的保护必不可少。
移动游戏最重要的是部分是资源和逻辑,而游戏引擎则是处理资源和逻辑的关键所在。恶意玩家可以通过游戏引擎获取解密后的游戏脚本或游戏资源,然后修改脚本或资源到达破解的目的;也能通过修改引擎的逻辑达到破解的目的;还可以通过引擎插入自己的脚本或资源实现外挂功能。
因此游戏引擎的保护是迫切的,在Android 游戏中游戏引擎是SO文件,如何保护SO文件成了游戏需要面临的问题。游戏,再怎么考虑安全,也必须要考虑到游戏体验,顺畅的游戏体验对玩家至关重要,一切安全解决方案必须在不影响游戏性能和玩家体验的基础上进行。
目前SO文件保护方案大概可以分为有源保护和无源保护,有源保护分为自解密、混淆、源码VMP等,无源保护分为加壳、VMP保护。
有源保护中的自解密保护的原理是:先加密需要加密的函数或者段,然后再加载SO文件,解密先前加密的函数和段。由于运行后需要解密相关的逻辑,因此破解者只需要在SO文件运行后,DUMP内存,即可获取解密后的逻辑,破解门槛低,因此自解密的保护方式存在安全强度低、维护成本高的缺点。
市面上常用SO源码保护是基于LLVM的混淆,通过指令替换、控制流扁平化和虚假控制流等角度去混淆源码。如下源码为测试源码,试试一个简单的校验函数,测试程序是ARMV7A架构下的编译。
下面是混淆前的控制流程图展示:
对上面的源码进行一些混淆,在增加了虚假控制流、指令替换和控制流平坦化的处理后,控制流的复杂度增加。如下图所示,增加了控制流程图复杂度,加大了逆向分析的难度。基于LLVM的源码混淆比较灵活,可以根据不同的安全需求配置不同的安全策略,混淆程度越高,则性能影响越大,文件膨胀越多。在对游戏影响很小的前提下,混淆能做的比较有限,导致安全强度不够,混淆存在安全强度和性能不可兼得的问题,不好找到平衡点。
由于源码混淆的方案在安全强度方面不够,因而出现源码VMP的解决方案。
相对基于LLVM的混淆,VMP安全强度更高,并且对SO文件的体积影响也较小,加固后的SO主要分为虚拟数据VMData和解释器handler,如下图所示为例子的VMData数据。
解释器handler的控制流
采用VMP保护对原函数执行的性能有比较大的影响,对所有方法VMP是无法满足游戏方对性能的要求。VMP的在不了解VMData和handler的对应关系的情况下,安全强度非常高,若相关的对应关系被破解者掌握,则也可以被还原,不过handler的复杂性一般比较高,并且对应关系可以做到随机处理,因此安全强度是完全满足游戏方的要求。上面说的基于源码的保护都存在一个相同的问题是接入成本高,需要处理源码就需要有本地工具,特别有些游戏引擎非开源,那基于源码的保护则无法接入。
无源码保护的加壳,市面上对应的加壳的方式有很多,安全强度差异也较大,不过核心是自定义linker。在壳SO文件被执行后需要先解密、还原被保护的SO文件,然后使用自定义linker加载被保护的SO,最后将执行权还给被保护的SO。加固的静态保护强度很高,原SO的蛛丝马迹完全抹去,但是动态执行后会还原部分内容,开发者也可以配合反调试、反Dump等技术使用,弥补SO加固在内存安全强度上的弱点。虽然加固存在着比较明显的弱点,然而加固也存在极大的优势,加固是对游戏性能影响最小,在游戏运行中不会增加任何开支,并且接入成本低,不需要有任何接入的成本。
无源码VMP与基于源码的VMP原理上是相通的,加固处理后最关键的部分依然是虚拟数据VMData和指令解释执行器handler。VMP处理时需要将原指令处理成VMData虚拟数据,并且插入解释器handler,如下图所示为无源VMP的handler。
VMP处理的安全强度高,逆向分析成本高,当然同样存在性能的问题。
根据上面对目前SO文件保护方案的说明,可以发现SO加壳是性能影响最小,VMP是安全强度最高,无源码方案是接入成本最低的方案。采用SO加固+无源码VMP结合的方式即可满足游戏对性能影响最小化的需求,最大程度的减少安全措施对游戏性能的影响,同时满足对游戏引擎的保护需求,在游戏引擎关键地方采用VMP防止破解者逆向分析,保障了游戏的安全。