加入收藏 | 设为首页 | 会员中心 | 我要投稿 李大同 (https://www.lidatong.com.cn/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 百科 > 正文

针对cocos2d图片资源自定义加密的解密

发布时间:2020-12-14 21:30:32 所属栏目:百科 来源:网络整理
导读:http://zhaoxiaodan.com/cocos2dx/%E9%92%88%E5%AF%B9cocos2d%E5%9B%BE%E7%89%87%E8%B5%84%E6%BA%90%E8%87%AA%E5%AE%9A%E4%B9%89%E5%8A%A0%E5%AF%86%E7%9A%84%E8%A7%A3%E5%AF%86.html 发现某游戏其assets目录的图片打开是雪花,而且用二进制打开查看文件,找魔

http://zhaoxiaodan.com/cocos2dx/%E9%92%88%E5%AF%B9cocos2d%E5%9B%BE%E7%89%87%E8%B5%84%E6%BA%90%E8%87%AA%E5%AE%9A%E4%B9%89%E5%8A%A0%E5%AF%86%E7%9A%84%E8%A7%A3%E5%AF%86.html


发现某游戏其assets目录的图片打开是雪花,而且用二进制打开查看文件,找魔数啊什么的,都没发定义,是新的文件格式? 还是被加密了?

google到这篇文章破解TexturePacker加密资源 - 使用IDA才想起来,可以使用ida进行反编译.(调试后发现,该游戏并不是使用TexturePacker提供的加密方式)

在哪里解密的?

虽然游戏没有源码,但是cocos2dx是有源码的,参考进行调试,还是蛮简单的,而且记得一句话,不管你怎么加密,最后你在内存里,肯定有一份解密之后的数据.

好,按这个思路,那我首先看,这个解密之后的数据到底放在哪里?

根据以前的经验,cocos2dx的图片资源加载,是在Image::initWithImageData(const unsigned char * data,ssize_t dataLen)函数,按照函数名称顾名思义:用数据初始化Image,好了,在ida 给这个函数下个断点,先看看这个传进来的data

可以看到,data这个内存地址是debug148:797363E8,而且这个地址的内容跟上面打开看到的完全不一样,再再而且,前4个字节就是png文件的魔数!.png

那也就是说,图片文件是在被读入内存之后,在被初始化之前就解密了;

那图片在哪里被读入?

cocos2dx的图片资源加载,一般都是从TextureCache::addImage(const std::string &path)这个函数开始的,参考源码

Texture2D * TextureCache::addImage(const stdstring &path)
{
    //cache中是否已经有这个图片
    auto it = _textures.find(fullpath);
    if( != end() )
        texture it->second;

    //没有
    if (! texture)
    {
        do 
        {
            image = new nothrow) Image();
            CC_BREAK_IFnullptr == image);

            //初始化image
            bool bRet imageinitWithImageFile);
            !bRet);

            Texture2D();
            //再用image初始化texture
            && textureinitWithImage) )
            {
                //hold 住
                insertmake_pair, );
            }
            else
            {
                CCLOG("cocos2d: Couldn't create texture for file:%s in TextureCache"c_str());
            }
        } while (0);
    }

    CC_SAFE_RELEASE);

    return ;
}

然后追到

Imagestring& {
    ...

    //从文件读入数据
    Data data FileUtilsgetInstance()getDataFromFile_filePath);

    ...
}

其实也就是CCFileUtils.cpp中的Data FileUtils::getDataFromFile(const std::string& filename)

这个CCFileUtils.cpp是平台相关的,每个平台有每个平台的具体实现. android的版本是CCFileUtils-android.cpp文件

FileUtilsAndroidgetDatafilenameforString...
    //上面一大堆,主要就是先判断这个filename是绝对目录还是assets目录,//如果是assets目录则用AssetManager 来打开并读取,再做些分配内存什么的事情
    //
   int bytesread AAsset_readasset(void*)datafileSize);
   size bytesread;

   AAsset_close}

在ida中找到相应的代码查看

发现在AAsset_read之后多了一个FileUtils::xxxxxxxxx函数的调用,并且,v10这个指针指向的就是文件读入后的内存,传给了这个函数.

进到函数看一眼:

哦? 内存每4个字节位与一个数再存回去? 得了,基本是解密函数无疑. 验证下

在115行也就是AAsset_read之后下个断

看到文件被读入内存,并且内存中的数据跟文件是一致的

再在FileUtils::xxxxxxxxx之后下个断

看到,v10 这个内存变化了,出现了png的魔数.png

那么FileUtils::xxxxxxxxx函数就是解密函数无疑

知道解密算法了,怎么把图还原出来?

很简单,照着这个函数写一个c函数,读文件进内存,调这个函数解密,就可以了

#include <stdio.h>
#include <stdlib.h>
void xxxxxunsigned charfileData{
    v5v6v7v8v9i;
    v5=0x00000000v6=;
    while1{
        v7=+;
        v6 >= fileSize / 4)
            break;
        v8= 4 v9 = int )[++];
        [] v7 ^ ;
    }
    for i ; ; + ) ^ 0xCC {
        --( ~% 4 }
}

int mainargc** args{
    argc <= 2){
        printf"paramters wrongn");
        return }
    filePath ];
    savePath ];
    "%s => %sfilePathsavePath);

    FILE *fp fopen"r"fp"read file %s fail !!}
    fseekSEEK_END);
    size_t ftell);
    SEEK_SETbuffer = mallocsizeofcharsizereadsize freadbuffer),161)">fclosexxxxxreadsizepFile "w"pFile"write file %s fail !!fwrite buffer fclose }

(编辑:李大同)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    推荐文章
      热点阅读