最近我们要开一个新项目,UI与交互打算借鉴当前正火的《圣火英雄传》,程序开发为了和美术制作并行,打算用圣火的资源暂代使用。我解压圣火apk,发现用TexturePacker命令行无法把它的pvr.ccz资源文件转成png,稍微了解一下,才知道TP提供了加密功能。我最近做Unity开发,只需要TP最基本的打图集功能,所以一直用v2.4.5,很久没有升级了,out了。

圣火资源加密了,没有密钥无法打开

美术同学可以先截图或画草图给程序用,但是,截图/草图跟原图比:大小规格不对,质量差,图元叠在一起,也会缺漏很多。不说耗费美术大量精力做繁重的体力活,这样做出的东西也会“惨不忍睹”,等正式美术资源来了,所有美术显示也都需要程序重新调整,这是不小的工作量。所以,最好的方法是研究破解圣火的加密资源。工程师的工作就是减小人的劳动,提高生产效率。

动态库注入与API拦截

开始时,我心里一点底儿也没有,因为我是开发游戏的,从来没做过破解。仅有的一点相关经验是几年前看《Windows核心编程》时用DLL注入和API拦截,做过一些游戏的反外挂工作。几年没做PC开发,具体实现早忘光了,只记得大致原理是通过注入自己的DLL到目标进程,劫持某些API,替换成自己的实现。

android内核是基于linux的,我想linux下是否也可以通过注入拦截API呢?只要能劫持API,就能破解。google "linux + inject",linux下果然也可以注入,更进一步发现有人已经开源了自己写的注入库,LibInject,核心的系统API是ptrace,还有几个操作动态链接库的API,dlopen、dlsym、dlclose、dlerror。注入之后,就是劫持,遍历got表,找到接口的地址然后替换成自己写的接口即可。

注入和劫持都ok之后,我试着劫持printf,替换成自己的函数,成功,我心里对破解有底了。下面是一些具体的操作过程。

首先要把手机root,把注入进程和劫持库拷贝到手机上,比如/data目录下,adb push命令。如果提示“Permission Denied”,就先把/data挂载(mount),然后改变文件权限(chmod)。

然后,打开圣火包里面lib目录,发现圣火用的是cocos2d-js v2.2开发,去cocos2d-x官方下载v2.2.5。然后,找到加载pvr.ccz的模块,都在ZipUtils.h/.cpp文件中。

1 void ZipUtils::ccSetPvrEncryptionKeyPart(int index, unsigned int value)// 设置密钥的接口
2
3 int ZipUtils::ccInflateCCZFile(const char *path, unsigned char **out) // 加载ccz文件的接口

我本想劫持设置密钥的用户自定义接口:ccSetPvrEncryptionKeyPart,这样可以直接获取密码。但是,从soinfo->symtab中获取的符号名始终是乱码,目前我还没搞明白原因,请知道的朋友指导。我就转而看ccInflateCCZFile的实现,这个接口会读取ccz文件的二进制数据,然后根据前四个字节判断是否合法的ccz文件(“CCZ!”)或者是否加密的ccz文件(“CCZp”),如果是加密的,就解密。接着,调用了libz的解压缩接口:

1 int uncompress(Bytef *dest, uLongf *destLen, const Bytef *source, uLong sourceLen);  

原来ccz也是一种zip压缩格式。这里需要用到source和destLen这两个参数,source是解密出来的ccz文件数据,*destLen是压缩前的大小。既然如此,我只要把uncompress接口劫持了,就可以破解出资源。ps. 除了劫持uncompress,还可以劫持opengl接口,毕竟所有图都要送到opengl绘制。

破解

看看ccz的文件头:

1 /** @struct CCZHeader
2 */
3 struct CCZHeader {
4 unsigned char sig[4]; // signature. Should be 'CCZ!' 4 bytes
5 unsigned short compression_type; // should 0
6 unsigned short version; // should be 2 (although version type==1 is also supported)
7 unsigned int reserved; // Reserverd for users.
8 unsigned int len; // size of the uncompressed file
9 };

source是不包含文件头的,所以需要自己把文件头填充进去。sig是“CCZ!”,compress_type是0,version是2,reserved是0,len是*destLen。创建一个ccz文件,把文件头和source写入。然后,把生成的ccz文件拷回本机,adb pull,“Permission Denied”?chmod。怀着激动地心情用TexturePacker打开,却报告失败。然后用Notepad++的Hex Editor打开,转成16进制,发现文件头的大小端逆序了。比如version,在大端机器上16进制表示是0x00 02,小端机器上是0x02 02。如果是小端,逆序写就可以了。改了之后重新生成ccz,成功打开。

解密出来的圣火资源——Activity.pvr.ccz

文件命名

劫持uncompress是无法知道文件名的。写一个文件扫描圣火资源目录,根据以文件size为key,文件名为value。然后,根据文件size做匹配就可以了。因为文件的size是精确到byte的,一般不会有文件是同样大小。我检查了圣火,211个ccz文件,没有同样大小的。

转png与切图

TexturePacker可以直接命令行把ccz转png,然后再写一个工具,读plist切散图就可以了,可以用CocosStudio,网上也有人用python写的。至此,我们已经完美的破解了圣火所有的资源,获得了所有美术资源。

切出来的圣火美术资源散图

除了《圣火英雄传》,还有很多游戏也是用TexturePacker加密资源,都可以用这个方法破解。为了避免争端,暂不放出工具及代码。

ps. 两篇相关的操作blog:

查看android进程信息 http://blog.csdn.net/ynnmnm/article/details/38417829

使用adb在电脑和手机间传文件 http://blog.csdn.net/ynnmnm/article/details/38415221

转载请注明出处: http://blog.csdn.net/ynnmnm/article/details/38392795。作者:夜风。

最新文章

  1. NLog在Asp.Net MVC的实战应用
  2. 关于LESS
  3. _MSC_VER详细介绍
  4. python :开关,开灯关灯
  5. <开心一笑> 码农 黑客和2B程序员之间的区别
  6. linux命令每日一练习 创建新文件 列出文件的时候带着行号
  7. yii2接收activeform表单信息
  8. 应用HTK搭建语音拨号系统2:创建单音素HMM模型
  9. Js中的一个日期处理格式化函数
  10. CSS的sprite和单位
  11. MySQL操作数据库和表的常用命令新手教程
  12. 统计Oracle数据库文件的大小
  13. android——使用pull解析xml文件
  14. 解决PhpStorm卡顿的问题
  15. C语言颜色转换宏
  16. 用递归方法求n的阶乘
  17. CentOS 7下安装Python3.6
  18. phpBB3导入帖子的Python脚本
  19. innerHTML、outerHTML、innerText、outerText的区别及兼容性问题
  20. php 无法正确获取系统当前时间的解决办法

热门文章

  1. panel面板
  2. 清除IE中Ajax缓存,Chrome不需要
  3. 【转】oracle查询不到表的问题
  4. JavaScript的DOM操作(2)
  5. BackgroundWorker
  6. Codeforces Round #231 (Div2) 迟到的解题报告
  7. hdu 1698 线段树 区间修改
  8. 用vs2010 编写C语言程序,VS2010 C++编译报错LINK : fatal error LNK1123: 转换到 COFF 期间失败: 文件无效或损坏
  9. c++11 内存模型解读
  10. vim使用指北 ---- Advanced Editing