手游防破解防外挂技术方案(一)客户端篇(2)

需要注意的是,实际项目中应全面地对任何游戏界面可见的关键性数据做加密,比如金币,血量,攻击力等。而且,所有会和关键性数据做运算的相关数据,也得用加密类型。比如,有一个游戏内弹框界面,上面可以让玩家自由选择要购买的道具数量及对应的金币花费,那么此处的金币花费的变量也应做加密。否则,玩家通过多次更改道具数量,就能用工具很容易地搜索出金币花费对应的地址,然后将其修改为0或者负数,再进行购买,就能达到买道具不花钱或者买完金币增加的效果。防破解这种事,百密一疏就会导致严重的问题,所以在防御上要尽量考虑全面。

 

代码混淆

网上有各种工具能对Unity游戏的dll文件做反编译,或者对so文件做反汇编。Dll反编译后,所有代码就非常可读,毫无安全性。所以我们需要把代码中的各种元素,比如类名,函数名,变量名,改成无意义或很难看懂的名字,使得破解者即使反编译了代码也很难读懂,从而加大破解难度。常用的Unity代码混淆工具有Obfuscator,Obfuscar,CodeGuard等,这些工具大部分都是在.Net IL层修改字节码,不影响正常开发流程。另外,还有很多针对iOS和安卓原生层的工具。

 

以Obfuscator插件为例,有一个名为ObfuscatorOptions的配置文件,其中很多设置会影响混淆的强度。值得注意的设置有:

1 Name mapping history

勾选,混淆时会生成符号映射文件,记录混淆前后的名字映射关系。

2 Rename

选择哪些被混淆。对于上层接入了lua的项目,就只勾选private和protected的函数和变量,不对public成员做混淆。因为public函数可能被lua层调用,如果做混淆,那么lua代码也要相应做修改,无法方便地维护。

函数名被混淆后,会带来一些不便:

(1)崩溃统计后台显示的是混淆后的名字,如果是private或protected函数,就需要查符号映射表得到混淆前的名字。

(2)若接入了xlua代码热修复,那么热修复private或protected函数时,也需要查符合映射表,调用xlua_hotfix时得传入混淆后的函数名。

3 Fake code

勾选后会增加垃圾代码,通过改变一些fake相关的参数可以调整混淆的强度。需要注意fake code加得越多会导致代码尺寸越大,一是会增加包体,二是在IL2CPP模式下,iOS包体代码尺寸可能会超过苹果规定的限制,从而导致审核上传时被拒。

4 Unity methods

该列表中的函数不会被混淆,可根据项目自身需求删减。除了这个列表,对于自己写的lua层回调函数,使用了反射调用的函数,和Inspector里绑定的事件函数,还可以在函数声明前加[SkipRename]属性来避免被混淆。

 

代码混淆的作用除了增加破解难度以外,还能用于应付苹果审核。苹果对马甲包的审核很严格,如果你的app和其他app在代码和资源上相似度很高,就会有审核被拒的风险。代码混淆工具就可以用来人为制造二进制包的差异化。但是,由于流行的混淆工具都是在IL层把各种名字改为随机的类似乱码的名字,二进制的特征和正常app是不同的,可能会在苹果机审阶段被查出来,导致被拒。很多开发者就因为过度使用了混淆工具,收到了苹果爸爸类似这种回信:

 

We discovered that your app contains obfuscated code, selector mangling, or features meant to subvert the App Review process by changing this app's concept after approval to the App Store. The next submission of this app may require a longer review time, and this app will not be eligible for an expedited review until this issue is resolved.

 

所以,为了避免不必要的审核风险,建议大家不要过度依赖这些混淆工具,可以自己写一些脚本,在源代码层或IL层处理字符串替换。

 

破解apk

破解apk包的危害很大。破解者可以把包破解后,传到网上供人下载。对于Unity apk包,网上已经有比较统一的破解流程,这里做一个简单的总结。下面的方法能处理未做加固加壳处理的,若做了加固加壳,就会使得一些文件结构被修改,方法就不一定奏效了。

 

Unity有两种脚本后端模式:mono和il2cpp。mono比较老,现在大部分游戏使用了il2cpp。Apk解包后,通过里面的文件信息能判断是哪一种模式:

1 如果assets/bin/Data/Managed/下有一堆dll文件,其中有Assembly-CSharp.dll,则是mono

2 如果assets/bin/Data/Managed/下有三个文件夹:etc/,Metadata/,Resources/,则是il2cpp

 

不管是mono或il2cpp,破解流程都大致如下:

1 解包

可用apktool运行命令解包abc.apk:

apktool d -r abc.apk

得到同名文件夹。注意用命令行解包,若把apk的后缀改为zip解压缩,得到的文件夹中会缺少apktool.yml文件,到后面重新打包时会报错:

brut.directory.PathNotExist: apktool.yml

 

2 修改代码

解包后根据文件信息判断是mono还是il2cpp。

 

对于mono包:

(1)Windows机器上安装.Net Reflector和Reflexil插件,用它打开assets/bin/Data/Managed/Assembly-CSharp.dll。

(2)查看反编译的dll代码,尝试去找需要破解的逻辑,直接修改IL代码,或写源代码然后用Reflexil编译成IL。

(3)将修改后的代码导出为新的Assembly-CSharp.dll,覆盖前面解包目录下的同名文件。

 

对于il2cpp包:

(1)用il2cppDumper工具[2],根据这两个文件:

- lib/armeabi-v7a/libil2cpp.so:包含所有可执行汇编代码

- assets/bin/Data/Managed/Metadata/global-metadata.dat:包含符号表信息

运行il2cppDumper,会生成两个文件:

- dump.cs:包含所有函数及地址信息

- script.py或ida.py(由il2cppDumper版本决定):作为IDA的脚本后面使用

(2)查看dump.cs,尝试去找自己感兴趣的函数信息。

内容版权声明:除非注明,否则皆为本站原创文章。

转载注明出处:https://www.heiqu.com/f8cab0ea1e3d03dfe0b7b18cfcbef368.html