前段时间红烧天堂国服内测,有人问我为什么替换文件之后启动游戏会重新下载文件,是不是有文件验证。

随便找一个文件修改一下,丢进去,启动游戏看看logcat有什么信息。

那答案很明显了,是crc32校验。如何绕过检测呢?有大致三条思路。

第一种方法,修改libunity.so,跳过crc校验逻辑。但是国服红烧天堂用了libtprt.so保护,直接修改so是很困难的,不过在国际服上可以实现这一点,在IDA中查找`CRC Mismatch.`查找报错相关的字符串常量就可以锁定相关逻辑,该nop的nop,还有一些改成无条件跳转就行。确实能绕过crc校验替换文件。

但是这种方法既不能绕过libtprt.so的保护,又需要root权限替换so或者修改apk文件,而且不同架构的so都要改。总之既麻烦又不优雅。

第二种方法,修改manifest文件。文件被修改后,游戏是怎么知道预期的crc值的呢?答案是这个值会被存储在manifest文件中。看了一下红烧天堂的manifest文件,似乎是加密的,就没有尝试修改了。因为这个方法也不够优雅,每次修改文件都要去改动manifest文件,对于只会直接替换文件的用户一点都不友好,当修改的文件很多的时候会很麻烦。一点都不优雅。

那么什么样的方法可以称之为优雅呢?最理想的情况肯定是改动的文件越少,修改后的运行逻辑越贴合原始流程越好,能只修改数据就不修改流程。那么有可能修改文件之后保持CRC不变吗?答案是肯定的。

具体原理这里不展开讲,可以参考看雪论坛上的这个04年的帖子。结论就是可以通过在已有数据的末端添加额外四个字节使得最终的CRC值为任意给定的CRC32。但是直接计算ab文件的crc会发现这个值和logcat里显示的不一样,因为Unity在计算ab文件的crc时使用的是解压缩后的数据块,也就是不包括头部数据,对余下的数据解压缩之后再求crc。根据ab文件的结构,只要在数据块的末尾添加四字节修正数据就行,但是Unity并不是直接读取头信息余下的内容,而是根据头信息里的size信息读取对应长度,所以头信息里的size也要修改,好在这部分数据不参与计算crc所以先计算crc再修改也行。

修改后替换回游戏,打开,确实成功的替换了没有被crc校验发现,好耶!

Unity_CRC32_Bypass,让我们一起来修改Unity游戏吧!