这是我个人对于Unity逆向汉化的总结,这里默认游戏没有采用额外的安全措施,使用的Demo是使用Unity直接生成的,实际应用中,大部分需要先绕开游戏的安全机制,或者在汉化结束后需要进行重新签名等。
主要工具:
AssetStudio(地址:https://www.perfare.net/tag/assetstudio)
il2cppdumper:https://www.perfare.net/tag/il2cppdumper,和AssetStudio是一个作者,具体操作也在他的网站上有
UABE(地址:https://7daystodie.com/forums/showthread.php?22675-Unity-Assets-Bundle-Extractor)
一、基础知识之Unity的资源文件
这里说的资源文件不是做游戏过程中使用的资源,而是在序列化之后得到的资源文件,在Android平台下,Unity的资源文件都放在Asset/bin/Data文件夹下,也就是AssetStudio读取的文件夹,这下面的文件就是Unity的资源文件,子文件夹Manager里面放的是代码相关的文件,其他都是资源文件,如果读过Asset Studio的源码,类SerialiableFile解析的文件,就是最常用的资源文件格式,我在汉化过程中基本就是跟这种文件打交道了。这种序列化文件的基本构造是文件头部+数据区,数据区里放序列化的Asset对象,
Asset的类型很多,可以参见官网(https://docs.unity3d.com/Manual/ClassIDReference.html),如果对他的序列化方式感兴趣好奇,可以用UABE导出文本和二进制对照着看看
关于Asset对象的序列化,有两个地方需要关注:
① 首先是对象之间会有引用关系,因此有个“指针”,指针由两个部分组成,如下:
class PPtr { Int32 fileID; // 在文件头部的引用文件列表中的第几个,0指代本文件 Int64 pathID; // 在该文件中的第几个对象,0表示空 }
② 然后是游戏制作过程中肯定会有自己的脚本,绑定在场景物体上的脚本大多会有参数,这些参数的数据会以静态资源的形式也写入资源文件。这部分会这么处理:
首先是类的信息(在哪一个DLL、命名空间、类名等)会放入MonoScript,然后具体某一个对象会放入一个MonoBehavior,MonoBehavior具体相关的东西我另外写成了博客,https://www.cnblogs.com/guobaoxu/p/12059225.html
在汉化过程中,资源的替换主要就是MonoBehavior、图片(Texture2D)、TextAsset三种,后两种都有插件,操作简单,写了篇简单的博客混一下:https://www.cnblogs.com/guobaoxu/p/12124226.html
二、基础知识之脚本后端
熟悉正向开发的朋友应该知道,Android平台会有两种脚本后端,Mono和il2cpp。
① Mono的话比较简单,脚本的代码会被编译成DLL,然后放在assets\bin\Data\Managed文件夹下,用dnSpy等工具可以进行反编译和修改,在没有安全措施的情况下,dnSpy可以看到十分清晰的代码,修改也方便,用来汉化更是绰绰有余
② il2cpp就麻烦多了,脚本最终会被编译进lib/libil2cpp.so文件夹,同时,脚本内的一些字符串等信息会被放入assets\bin\Data\Managed\Metadata文件夹下面的global-metadata.dat文件里,如果用IDA对so文件反编译的话,也只能看到汇编代码。所以想要对il2cpp脚本后端的游戏进行大改是十分麻烦的事情,但是汉化主要聚焦在字符串的修改上,所以会相对简单的多。
从目前的趋势来看,il2cpp脚本后端使用频率会越来越高,毕竟难以反编译出源码,又是官方推荐。
三、工具介绍
Asset Studio:这个工具主要用来预览,是开源的,建议看看他的源码,并不复杂,可以让自己对Unity的资源部分有一个很好的理解,但是他没有解析所有的资源类型,之多常用的做了解析。
UABE:这个工具主要用来替换,这个并不是开源的,实际上看一眼前面提到的被序列化的文件就知道,要解析所有的Unity的资源是个大工程了。主要功能是导出导入,可以二进制形式,也可以文本形式,针对图片、TextAsset等还有专门的插件。
il2cppdumper:和AssetStudio是一个作者,也是开源的。如果结合前面两节,会发现一个问题,解析MonoBehavior是需要类的参数列表的,但是il2cpp后端的代码都被编译成so了,所以这里就需要一个工具,把参数列表从metadata和so里面导出来,这就是il2cppdumper的主要功能了,在使用前两个工具的时候也需要用到这个工具导出的DLL。具体使用方法在官网上有介绍。
四、汉化之常见UI框架
这里简单说一下文字汉化中会遇到的三个UI框架
1.NGUI:在UGUI出现以前比较通用的UI实现方案
2.UGUI:Unity自己做的UI,是官方推荐使用的
3.TextMeshPro:简称TMPro,专注于文本的展示,用这个做的文本,在放大之后不会出现毛边,所以很多人都喜欢用来做一些固定文字的展示(需要用户输入的就基本不用这个了)
三种都有共同的特点,都需要字体跟文本内容两方面的替换。
五、字体替换
三个UI框架都有自己的字体表现形式,NGUI对应BMFont,UGUI对应TTF,TMPro对应自己的字体,其中BMFont和TMPro字体是类似的,都是图片+一个Asset描述字符切片的位置,然后在绑定一个纹理用于渲染,TTF则是有专门的FontAsset类型(大概这就是亲儿子吧),每一种的替换另外写成博客,请看:
BMFont字体:https://www.cnblogs.com/guobaoxu/p/12060397.html
TTF字体:https://www.cnblogs.com/guobaoxu/p/12060027.html
TMPro字体:https://www.cnblogs.com/guobaoxu/p/12091339.html
六、文字替换
文字的替换有两种,一种是资源文件中的,这种是在开发过程中,在检查器里直接输入的文字,一般是默认值或者固定的文本,另一种则是代码中的字符串,涉及代码,前面提到的两种脚本后端又需要拿出来说一说了。
资源文件中的修改很简单,不管是哪一个框架,所有的Text都是以脚本的形式呈现,如果你注意看Unity中的检查器,会发现他的组件名字都是“Text (Script)”,所以他的修改就是MonoBehavior的修改,还是看前面提到的那篇博客即可:https://www.cnblogs.com/guobaoxu/p/12059225.html
代码中字符串的修改就需要分脚本后端来说了
【1】Mono脚本后端
前面说了,Mono脚本后端把代码都放进了DLL里面,而DLL拿dnSpy直接修改就好了,很简单,具体过程我也写成了博客:https://www.cnblogs.com/guobaoxu/p/12126410.html
【2】il2cpp脚本后端
这个就很麻烦了,代码被编译成了libil2cpp.so、global-metadata.dat两个文件,字符串在global-metadata.dat里,这个目前没有现成工具,好在il2cppdumper是开源的,里面涉及到了对字符串信息的提取,所以我自己撸了一个小工具来做修改,具体过程另外写成博客:https://www.cnblogs.com/guobaoxu/p/12132379.html