欢迎光临散文网 会员登陆 & 注册

逆向某游戏加密文本——IL2CPP

2022-05-06 14:45 作者:Anicca丶Y  | 我要投稿

    今天来解密一下一款名叫圣骑士莉卡的游戏。游戏的文本以及存档都做了加密,而且游戏打包用的IL2CPP这就加大了逆向的难度(一般用IL2CPP打包的游戏比较容易劝退)。

不过对于我这种没事就搞搞Unity逆向的人来说其实跟Mono差不多,只是增加了一点分析难度。

    首先老套路,先用IL2CppDumper对脚本进行初步的解析。一般来说,没动过手脚的脚本IL2CppDumper自动分析就行了。分析完后,主要用到dump.cs 和 stringliteral.json 这两个文件。dump.cs 用来分析脚本的大致逻辑,里面包含所有类和方法的基本信息。

当然,也可以用dnspy直接分析DummyDll目录下生成的C#脚本。

stringliteral.json 则包含了脚本内部会用到的字符串信息(需要在后续IDA分析中用到)。

本次主要是分析加密解密的方法,前期的方法的定位过程就大致略过了。

定位:

    首先要定位加密解密脚本,这里我发现,如果直接把部分游戏文本删掉的话,游戏依然能运行,缺失的文本位置,全部都会由索引用的字段代替。而且在游戏存档位置的log文件中,会看到报错。

    通过报错信息,可以大致得到加载文本涉及到的类和方法。

于是通过一系列分析,最终定位到了Crypt这个类。

Crypt类

    可以看到,该类有两个私有字符串类型的字段,pw和salt,非常明显,加密应该用到这两个字段,奇怪的是这两个字段没有初始值,应该是IL2CppDumper没分析出来,因为有.cctor类型初始化器的话,应该至少有一个字段是有初始值的,不然应该不会存在。

那只能继续用IDA分析了。

.cctor类型初始化器

进到IDA后直接跳到0x1819A4F90处查看类型初始化器。

.cctor类型初始化器(构造函数)

稍微做了一下备注(备注的有点不对),

其中

对应的是变量 pw

对应的是变量 salt

而图中的 pw, salt 其实是这两个变量的初始值的地址。

然后在stringliteral.json中搜索 pw和salt 对应的地址偏移

pw
salt
pw
salt

得到了两个字符串,

接下来就是分析解密方法,

解密方法

该类重载了两个Crypt方法,

  1. 一个参数是字符串类型,返回字符串类型,

  2. 另一个参数是字节数组,返回也是字节数组。

    也就是说理论上来讲,游戏应该存在两种形式的加密类型数据,一种是二进制文件,一种是字符串型的加密。而字符串类型应该都是base64的形式。

该游戏恰巧存在这两种类型的文件。

首先分析一下,参数是string的Decrypt。

string Decrypt(string xxx)

一些重要方法都已经将名字改回来了,

前面一大堆都是一些寻址初始化啥的(猜的,反正不影响),

这一块可以看到,输入的字符串经过FromBase64String后返回了字节数组,其实一般也就是这样,字符串基本都是经过base64的。

然后data之后输入到Decrypt_byte这个方法里,

之后返回值又经过get_UTF8的解码,

之后一大堆已经没有意义了,基本可以确定是返回了一串字符串。

在这一过程中,最重要的环节就是Decrypt_byte 这个方法。

Decrypt_byte 为了便于查看自己改了一下名字,其实就是另一个的输入为byte[] 的Decrypt。

显然解密的关键最终其实就是byte[] Decrypt(byte[] encrypted)

byte[] Decrypt(byte[] xxxxx)

接下来查看该方法

1
2
3

    从中可以看出,用了AES加密,然后KEY是128位(16字节),IV也是128位(16字节) 模式是CBC, 末尾补齐是PKCS7。

然后是KEY和IV的生成,可以看到用的是Rfc2898DeriveBytes这个类(即PBKDF2)

    主要是输入两个字符串,作为密钥和盐进行循环x次某种计算获得一串hash值。Hash值中截取一部分就可以作为AES加密用的KEY和IV了,

    从上面的伪代码中看出,所有的参数基本都是默认的,甚至是代码都可能是照着网上一些固定模板抄的,用到的字符串也是之前获得的两个字符串也就是说自己写个C#脚本,就能解密了。

附上C#代码:( pwd, salt )请自行查找

以及python版本:


逆向某游戏加密文本——IL2CPP的评论 (共 条)

分享到微博请遵守国家法律