破解TexturePacker加密资源,寻找解密Key之旅

破解TexturePacker加密资源的方式有好多种。。最多的是hook uncompress然后获取到内容,加入ccz的文件头写入文件。 
例如:

http://blog.csdn.net/ynnmnm/article/details/38392795 
http://bbs.pediy.com/showthread.php?t=187332 
今天我用最直接的方法搞定,直接找到用户设置的秘钥。

void ZipUtils::ccSetPvrEncryptionKeyPart(int index, unsigned int value)// 设置密钥的接口
 
 
  • 1

inline void ZipUtils::ccDecodeEncodedPvr(unsigned int *data, int len)
{
    const int enclen = 1024;
    const int securelen = 512;
    const int distance = 64;
    
    // check if key was set
    // make sure to call caw_setkey_part() for all 4 key parts
    CCAssert(s_uEncryptedPvrKeyParts[0] != 0, "Cocos2D: CCZ file is encrypted but key part 0 is not set. Did you call ZipUtils::ccSetPvrEncryptionKeyPart(...)?");
    CCAssert(s_uEncryptedPvrKeyParts[1] != 0, "Cocos2D: CCZ file is encrypted but key part 1 is not set. Did you call ZipUtils::ccSetPvrEncryptionKeyPart(...)?");
    CCAssert(s_uEncryptedPvrKeyParts[2] != 0, "Cocos2D: CCZ file is encrypted but key part 2 is not set. Did you call ZipUtils::ccSetPvrEncryptionKeyPart(...)?");
    CCAssert(s_uEncryptedPvrKeyParts[3] != 0, "Cocos2D: CCZ file is encrypted but key part 3 is not set. Did you call ZipUtils::ccSetPvrEncryptionKeyPart(...)?");
    
    // create long key
    if(!s_bEncryptionKeyIsValid)
    {
        unsigned int y, p, e;
        unsigned int rounds = 6;
        unsigned int sum = 0;
        unsigned int z = s_uEncryptionKey[enclen-1];
        
        do
        {
#define DELTA 0x9e3779b9
#define MX (((z>>5^y<<2) + (y>>3^z<<4)) ^ ((sum^y) + (s_uEncryptedPvrKeyParts[(p&3)^e] ^ z)))
            
            sum += DELTA;
            e = (sum >> 2) & 3;
            
            for (p = 0; p < enclen - 1; p++)
            {
                y = s_uEncryptionKey[p + 1];
                z = s_uEncryptionKey[p] += MX;
            }
            
            y = s_uEncryptionKey[0];
            z = s_uEncryptionKey[enclen - 1] += MX;
            
        } while (--rounds);
        
        s_bEncryptionKeyIsValid = true;
    }
    
    int b = 0;
    int i = 0;
    
    // encrypt first part completely
    for(; i < len && i < securelen; i++)
    {
        data[i] ^= s_uEncryptionKey[b++];
        
        if(b >= enclen)
        {
            b = 0;
        }
    }
    
    // encrypt second section partially
    for(; i < len; i += distance)
    {
        data[i] ^= s_uEncryptionKey[b++];
        
        if(b >= enclen)
        {
            b = 0;
        }
    }
}
void ZipUtils::ccSetPvrEncryptionKeyPart(int index, unsigned int value)
{
    CCAssert(index >= 0, "Cocos2d: key part index cannot be less than 0");
    CCAssert(index <= 3, "Cocos2d: key part index cannot be greater than 3");
    
    if(s_uEncryptedPvrKeyParts[index] != value)
    {
        s_uEncryptedPvrKeyParts[index] = value;
        s_bEncryptionKeyIsValid = false;
    }
}

void ZipUtils::ccSetPvrEncryptionKey(unsigned int keyPart1, unsigned int keyPart2, unsigned int keyPart3, unsigned int keyPart4)
{
    ccSetPvrEncryptionKeyPart(0, keyPart1);
    ccSetPvrEncryptionKeyPart(1, keyPart2);
    ccSetPvrEncryptionKeyPart(2, keyPart3);
    ccSetPvrEncryptionKeyPart(3, keyPart4);
}


上appstore上随便找个cocos2d的游戏,拖入Hopper,搜索ccSetPvrEncryptionKeyPart,没有找到。然后搜索ZipUtils,如下图:

这里写图片描述 
ccDecodeEncodedPvr用来解密pvr.ccz文件,没有找到ccSetPvrEncryptionKeyPart,那么我们在ccDecodeEncodedPvr上下代码块里面试试运气

这里写图片描述

int sub_444200(int arg0, int arg1) {
    r1 = arg1;
    r0 = arg0;
    r3 = *(0x7d79d0 + r0 * 0x4);
    asm{ it         eq };
    if (r3 == r1) {
            return r0;
    }
    *(0x7d79d0 + r0 * 0x4) = r1;
    *(int8_t *)0x7d89e0 = 0x0;
    return 0x0;
}
 
 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12

这个有点像。。猜测arg0为index arg1为value 
写tweak验证:

int(*orgccSetPvrEncryptionKey)(int index,unsigned int key);
int myccSetPvrEncryptionKey(int index,unsigned int key);
int myccSetPvrEncryptionKey(int index,unsigned int key2key{
  NSLog(@"\n\n=====  keys: %d-%u    ======\n\n",index,key);
  orgccSetPvrEncryptionKey(key1,key2);
}
%ctor{
  NSLog(@"====== HOOKED ======");
  intptr_t module_vmaddr = _dyld_get_image_vmaddr_slide(0);
  intptr_t ccSetPvrEncryptionKey = module_vmaddr + 0x444200 + 1;
  MSHookFunction((void *)ccSetPvrEncryptionKey, (void*)myccSetPvrEncryptionKey, (void**)&orgccSetPvrEncryptionKey);
}
 
 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12

测试log

Jun  1 11:57:43 crean XXX[73393]:

    =====  keys: 0-405172683    ======
Jun  1 11:57:43 crean XXX[73393]:

    =====  keys: 1-1270815801    ======
Jun  1 11:57:43 crean XXX[73393]:

    =====  keys: 2-3663874658    ======
Jun  1 11:57:43 crean XXX[73393]:

    =====  keys: 3-2333226975    ======
将这4个Key转为16进制为
 
 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
182671CB4BBF1C39DA624A628B1237DF
 
 
  • 1

用TexturePacker打开加密的pvr.ccz的文件,它会提示你输入128位加密的KEY,输入直接解密验证:

这里写图片描述

我想,看了这篇教程学到的不紧紧是破解TexturePacker加密资源哦。。自己动手验证试试。。只随机了一个游戏测试。。有兴趣的朋友可以找个游戏验证验证是否通用。。

本文转自: creantan 
原文链接:http://www.jianshu.com/p/9562bc1cab72

A:在cocos2dx中,可以通过加密lua代码和图片资源来保护项目的安全性。下面是一些简单的步骤来加密解密lua代码和图片资源: 1. 加密Lua代码 可以使用luajit来编译Lua代码,然后使用gzip压缩和base64编码来加密Lua代码。以下是使用此方法加密Lua代码的示例代码: ``` local status, bytecodes = pcall(function() local bytecodeStream = io.popen("luajit -bg myScript.lua -") local bytecode = bytecodeStream:read("*all") bytecodeStream:close() return bytecode end) if not status then error(bytecodes) end local compressed = zlib.compress(bytecodes, 9) local cipher = mime.b64(compressed) ``` 2. 加密图片资源 可以使用图片加密工具,如TexturePacker,将图片打包成一个txp包。然后可以使用AES加密算法来加密txp包,以下是使用此方法加密图片资源的示例代码: ``` local Crypto = require "crypto" local data = cc.FileUtils:getInstance():getDataFromFile("myImage.txp") local iv = Crypto.digest("sha256", "mySecretKey", true) local key = Crypto.digest("md5", "mySecretKey", true) local encrypted = Crypto.encryptAES256(data, key, iv) cc.FileUtils:getInstance():writeDataToFile(encrypted, "myImageEncrypted") ``` 3. 解密Lua代码 可以使用base64解码和gzip解压缩函数解密加密的Lua代码,然后使用loadstring函数来运行解密后的代码。以下是使用此方法解密Lua代码的示例代码: ``` local cipher = "..." local compressed = mime.unb64(cipher) local bytecodes = zlib.decompress(compressed) local f = loadstring(bytecodes) f() ``` 4. 解密图片资源 使用AES解密算法来解密加密的图片资源。以下是使用此方法解密图片资源的示例代码: ``` local Crypto = require "crypto" local encrypted = cc.FileUtils:getInstance():getDataFromFile("myImageEncrypted") local iv = Crypto.digest("sha256", "mySecretKey", true) local key = Crypto.digest("md5", "mySecretKey", true) local decrypted = Crypto.decryptAES256(encrypted, key, iv) cc.FileUtils:getInstance():writeDataToFile(decrypted, "myImage") ```
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值