针对cocos2d图片资源自定义加密的解密
来源:互联网 发布:淘宝上有没有卖视频的 编辑:程序博客网 时间:2024/05/16 14:25
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 std::string &path){ //cache中是否已经有这个图片 auto it = _textures.find(fullpath); if( it != _textures.end() ) texture = it->second; //没有 if (! texture) { do { image = new (std::nothrow) Image(); CC_BREAK_IF(nullptr == image); //初始化image bool bRet = image->initWithImageFile(fullpath); CC_BREAK_IF(!bRet); texture = new (std::nothrow) Texture2D(); //再用image初始化texture if( texture && texture->initWithImage(image) ) { //hold 住 _textures.insert( std::make_pair(fullpath, texture) ); } else { CCLOG("cocos2d: Couldn't create texture for file:%s in TextureCache", path.c_str()); } } while (0); } CC_SAFE_RELEASE(image); return texture;}
然后追到
bool Image::initWithImageFile(const std::string& path){ ... //从文件读入数据 Data data = FileUtils::getInstance()->getDataFromFile(_filePath); ...}
其实也就是CCFileUtils.cpp
中的Data FileUtils::getDataFromFile(const std::string& filename)
这个CCFileUtils.cpp
是平台相关的, 每个平台有每个平台的具体实现. android的版本是CCFileUtils-android.cpp
文件
Data FileUtilsAndroid::getData(const std::string& filename, bool forString){ ... //上面一大堆, 主要就是先判断这个filename是绝对目录还是assets目录, //如果是assets目录则用AssetManager 来打开并读取,再做些分配内存什么的事情 // int bytesread = AAsset_read(asset, (void*)data, fileSize); size = bytesread; AAsset_close(asset); ...}
在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 xxxxx(unsigned char* fileData, int fileSize){ int v5,v6,v7,v8,v9,i; v5=0x00000000; v6=0; while(1) { v7=v6+v5; if( v6 >= fileSize / 4) break; v8= 4 * v6; v9 = *(int *)&fileData[4 * v6++]; *(int *)&fileData[v8] = v7 ^ v9; } for ( i = 0; ; *(&fileData[fileSize] + i) = *(&fileData[fileSize] + i) ^ 0xCC ) { --i; if ( ~i >= fileSize % 4 ) break; }}int main(int argc,char** args){ if(argc <= 2){ printf("paramters wrong\n"); return 1; } char* filePath = args[1]; char* savePath = args[2]; printf("%s => %s\n",filePath,savePath); FILE *fp = fopen(filePath, "r"); if(!fp) { printf("read file %s fail !!\n",filePath); return 1; } fseek(fp,0,SEEK_END); size_t size = ftell(fp); fseek(fp,0,SEEK_SET); unsigned char* buffer = (unsigned char*)malloc(sizeof(unsigned char) * size); size_t readsize = fread(buffer, sizeof(unsigned char), size, fp); fclose(fp); xxxxx(buffer,readsize); FILE *pFile = fopen(savePath, "w"); if(!pFile) { printf("write file %s fail !!\n",savePath); return 1; } fwrite (buffer , sizeof(char), readsize, pFile); fclose (pFile); return 0;}
- 针对cocos2d图片资源自定义加密的解密
- AES加密解密图片资源
- Cocos2d-x 资源加密解密实践总结
- Cocos2d-x 资源加密解密实践总结
- Cocos2d-x 资源加密解密实践总结
- 图片,音频,视频的文件加密,解密,保护自身资源
- Cocos2d-x 游戏资源(图片、XML、TXT等)打包加密 之 解密读取
- 【加密】Cocos2d-x PNG图片资源加密
- VC对自定义资源加密解密(AES)
- quick-cocos2d-x图片资源加密(续)
- Cocos2d-x PNG图片资源加密
- quick-cocos2d-x 图片资源加密
- quick-cocos2d-x图片资源加密(续)
- Cocos2d-lua 3.10 图片资源加密
- 加密、解密web.config文件(针对某些要加密的字段加密、解密)
- 【加密】Cocos2d-x PNG图片资源加密(修改版)
- Cocos2d-x 图片资源加密,Lua文件加密
- 【转】【加密】Cocos2d-x PNG图片资源加密
- 二分+贪心
- OpenVPN下载、安装、配置及使用详解
- C#类的理解
- 用presentingViewController实现左右切换视图
- 数据库基线
- 针对cocos2d图片资源自定义加密的解密
- Android Intent-Filter中的action
- PowerDesigner列名、注释内容互换
- gcc编译静态库和动态库
- Objective-C NSString字符串操作总结
- OC基础:类和对象
- SDL显示一张图片
- 使用运行快速启动程序----整理桌面的小技巧
- 2015百度之星资格赛1005