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 wrong\n");
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 }