腾讯手游全民枪王DLL加密的研究

今天我的群里面有人分享了全民枪王这个游戏的破解版,有自瞄功能。我玩了玩感觉还不错,然后我很好奇是怎么修改做到自瞄的,于是引发了一系列的研究。
我先把apk解包看了看,根据目录结构可以猜测这是个用Unity3D制作的游戏。
然后分析了一会,可以基本确定游戏内的代码都在DLL里了,Java层只是一些加载与交互的操作。
我以前对Unity3D稍有研究,代码一般都保存在Assembly-CSharp.dll里面。
所以我们只要反编译这个DLL即可。
这时候要用到工具:.NET Reflector
载入后发现提示:

翻译下就是没有找到可执行文件的MZ标志,我们再用WinHex打开这个DLL看下:

可以确定DLL被加密了 ,MZ头没有了。我们打开一个正常的DLL对比下:

通过对比可以知道,原DLL里面的数据被做了异或或者移位的算法处理,我观察了一会,只看出大部分的00都变成了5D,其他的难以得出规律。
通过人工计算分析不出加密算法,只能找其他的办法来解密了。
我查阅了一些资料,得知加密了Assembly-CSharp.dll的一般都在libmono.so的mono_image_open_from_data_with_name函数里面做了手脚。
有几种方法可以解密:
1.HOOKlibmono.so中的关键函数,取得解密后的dll。
2.动态调试。在关键地方下断,dump出解密后的数据。
3.反编译关键函数,根据伪代码自己写一个解密算法。
4.用gdb动态调试gcore内存提取,然后搜索MZ头和尾巴original filename:assembly-csharp.dll,即可得到。
5.一些不可告人的方法。
这几种方法看起来很简单,但是实际操作起来非常困难,而且很多我都没有尝试过,但是我并没有放弃,我选择了方法3来进行解密。
这里要用到一个神器:交互式反汇编工具 IDA
说实话上一次用IDA进行修改还是在好几年前做节奏大师秒过版的时候,那时候和游人客栈里的大神们学的,现在都忘的差不多了。。
于是我翻起以前的笔记看了看,回忆起来了如何操作。(这也是我写这些日记的目的之一,若干年后看自己成长了多少)
把libmono.so拖入IDA,然后看导出表,找到mono_image_open_from_data_with_name双击进去:

来到这里,

这里可以看到他里面调用的是mono_image_open_from_data_with_name_0,再双击进去来到这里:

这里就是关键函数了,我好久没读ARM汇编了,大概还是可以看懂,是一些赋值和函数调用操作
好在IDA有把ARM转换成伪代码的插件。只要在这个函数里按F5即可:

这样一来就清晰多了。
这里进行了一些赋值操作,然后调用了三个函数,我们来一个一个查看分析。
通过查资料得到mono_image_open_from_data_with_name函数的第一个参数就是文件的指针,第二参数是文件长度
对应这里面 a1、v8是文件的指针,a2、v9是文件的长度。
我们先进入第一个子程序sub_3D21CC,他传入了这两个参数。

现在这个子程序里面的形参result是文件的指针。a2是文件的长度。
v2和v3都是bool型的数据。分别代表指针是否为空,和是否无效。
程序的流程大概是这样:
result(也就是文件指针)有效的话判断result指向内存的第一个字节是否不等于77,第二个字节是否不等于90,(也就是判断是否没有可执行文件的MZ头)是的话就执行循环,否则直接返回
循环里面就是解密的过程了。和我猜想的一样,只是一些简单的异或操作。
我用Java还原了解密代码:

为了方便,我们把文件重命名为1.dll,放到C盘根目录进行解密,保存为2.dll:

解密出的文件已经很清晰了:

载入.NET Reflector试试:

又报错了,提示的是元数据头 BSJB 签名无效。
由于解密后的文件结构很清晰了,猜想可能是TX还另外做了一些手脚

我们用CFF Explorer打开DLL,发现元数据头的签名值被修改为0了

我们将此处改为424A5342(也就是BSJB,具体原因得学习.NET文件结构)保存即可

再次载入.NET Reflector:

所有函数的都可以正常反编译了,接下来我们就要找修改点了。
这里主要靠猜想关键词搜索。比如瞄准是aimed,伤害是damage等等。。
修改过程我就不说了,网上的教程有很多。

(经过漫长的修改,打包,安装测试)(这里并不需要再加密,因为解密只对不是MZ头的处理)

最后我找到以下可以修改的地方:

改PVE伤害:

返回值就是伤害值,这里改成了10000

自动开枪:

返回值改为true即可全模式自动开枪

自动瞄准:

这个是游戏内自带的辅助瞄准,我们只要修改他的扫描半径radius和吸附速度adsorbSpeed即可达到全屏毫秒级别自瞄

改专精点:

可以实现全屏刀的效果

改掉落伤害:

清空函数即可无视掉落伤害

就贴出这些吧。其他的大家有兴趣可以自己研究。

总结:
Unity3D类的游戏的DLL一般都是这种形式加密,如果不加密,代码很容易就能被修改。
这个游戏的加密逻辑还存在漏洞,解密后并不需要再加密回去就能使用。
如果需要的话破解难度将又上升一大截。(当然我们也可以解密后直接替换掉他加密的libmono.so为官方版的,或者修改跳过里面的解密函数)
所以如果想最大化保护,不仅要验证主要的dll是否为加密过的,还需要在native层进行libmono.so的md5验证,并且改用更复杂的加密算法,或者对加密子程序进行隐藏。这样一来像我这样的小白就只能望而却步了。
Specher
2017年3月18日

作者: Specher

中文网名风生·水起,擅长安卓逆向与开发、Windows软件破解与补丁制作,喜欢IT与电子音乐,热爱运动,追求自由。

发表评论

电子邮件地址不会被公开。 必填项已用*标注