前言,一般项目发包基本会加密 lua代码,图片资源,现在3.12自带一套加密解密流程,但是这套加密流程只适用于lua代码解密,现在需要对框架进行修改,从而可以解密图片资源。
准备,首先要想好自己的加密解密的密钥 和 文件头签名。
{
如:
String key = "KEY_FOR_ENCRYPT_OR_DECRYPT";
String Sign = "SIGN_FOR_ENCRYPT_OR_DECRYPT";
}
一 加密流程,先将lua代码和图片资源进行加密,可以写批处理方法,使用刚才想好的密钥和签名调用cocos2d-x/external/xxtea/xxtea.cpp里面的加密方法(这个加密方法可以改成我们自己的, 同理解密也可改)。将需要加密的lua代码和图片资源进行加密即可。最好可以批处理文件。(注:函数参数不用去改它的)
二 cocos2dx 解密流程
1,首先要在Classes/AppDelegate.cpp里面设置解密密钥
applicationDidFinishLaunching(){
...
LuaStack* stack = engine->getLuaStack();
String key = "加密Key"; //想好的密钥
String Sign = "文件头签名"; //想好的签名
stack->setXXTEAKeyAndSign(key, strlen(key), Sign, strlen(Sign));
...
}
实际上就是将密钥和签名设置进去了CCLuaStack,可以用这些去解密lua文件代码 ,如下
(注:如果不做图片的加密,这一步做完lua代码的解密就已经完成了)
2,可以看下lua自带的代码解密流程,实际上就是加载Lua代码的时候CCLuaStack调用CCFileUtil去调用各个平台的FileUtil的GetContens函数,获取文件内容buff,然后在CCLuaStack里面在调用LoadBuff()将解密后的内容buff进行加载的解密流程 (此过程cocos2d 3.12已经自带,所以文章开头说lua代码可以做到自动解密) 如下:
CCLuaStack.cpp
int LuaStack::executeScriptFile(const char* filename)
{
...
//调用各平台的获取文件Utils
FileUtils *utils = FileUtils::getInstance();
std::string fullPath = utils->fullPathForFilename(filename);
...
//拿到了文件的**内容buff**, data
Data data = utils->getDataFromFile(fullPath);
int rn = 0;
if (!data.isNull()) {
//**luaLoadBuffer**此函数就是lua解密函数
if (luaLoadBuffer(_state, (const char*)data.getBytes(), (int)data.getSize(), fullPath.c_str()) == 0) {
rn = executeFunction(0);
}
}
return rn;
}
lualoadBuffer如下,红线圈的部分就是解密过程,调用了我们在AppDelegate.cpp设置的密钥进行内容buff的解密,当然,只有判断出文件头是我们设置的签名才会进入这个函数进行解密,其他没加密的文件走else里面的语句,直接加载lua代码
3, 接下来我们想让图片也支持解密,同理,我们可以通过lua解密加载流程推测出 加载图片的时候,肯定会调用FileUtil里面的GetContents获取文件的内容buff,然后通过内容buff进行图片的加载。那么我们需要做的就是->找到获取这个图片内容buff加载的地方(修改各个平台的调用函数),判断如果是加密过的内容buff那么就将内容buff解密了,然后在return回去,binggo!
想要获取图片加载 “内容buff” 的流程,我们可以在从Sprite::create打个断点,一步步跟下去,看看堆栈过程。
...
最终可以发现堆栈过程
FileUtilsWin32::getContents
Image::initWithImageFile
TextureCache::addImage
Sprite::initWithFile
Sprite::create
...
那么可以总结:
CCImages的initWithImageFile()函数
CCImages的initWithImageFileThreadSafe()函数
上面两个是加载图片读取文件内容buff的
还有另外一个CCFileutils里面的getValueMapFromFile()读取文件字典(plist等)
即是CCSAXParser.cpp里面的parse()函数读取内容buff来加载plsit
...
因此我们只需要将上面的3个函数加点料,即可实现解密 - -!
...
4,CCImages的修改如下 (图片加载文件地方)
先包含头文件:
然后修改initWithImageFile()函数
然后修改initWithImageFileThreadSafe()函数
5, CCSAXParser.cpp的修改(字典类文件读取地方)
6, CCBundle3D.cpp的修改(.c3b文件读取地方)
7, CCFileUtil.cpp的修改(.json文件读取地方,所有getStringFromFile需要解密的地方)
总结:至此图片解密也可以做到啦,其他粒子特效,图集文件,字体文件…. …. 的加密,是否可以通过找到加载文件内容buff的地方,然后对这个内容buff修改而达到解密的目的呢,留给大家去猜想和试探了!啊哈哈哈哈