破解cocos2dx-lua脚本加密资源加密

工具篇:


IDA Pro (32-bit)7.0 神器不多说 百度网盘 提取码6666

ApkToolBox 功能很强大的拆包工具 爱盘 - 最新的在线破解工具包

Visual Studio 随便什么版本可以执行c/c++就行,用于解密脚本,好处是伪代码能直接用.

notepad++ 自行百度很好用的文本工具

Demo 百度网盘 提取码6666

开始:

解密图片:


反编译apk
发现图片被加密了
发现代码也被加密了文件头不是lua开始的...
ida打开libgame.so
在导出表中搜索getFileData看安卓的实现
经过一番分析发现fopen之后对文件进行了funck!的前缀解析...
资源和配置文件都被弄成了这样..
这是上面对应的解密数组



// gamecenter_decrypt.cpp : 此文件包含 "main" 函数。程序执行将在此处开始并结束。

//

#include <iostream>

#include <fstream>

#include <cstring>        // for strcat()

#include <io.h>

#include <vector>

#include <Windows.h>

using namespace std;

#define _BYTE unsigned char;

#define _DWORD unsigned int;

const char *res_path = "D:\\tmp\\gamecenter-release-android-huakai-6162\\assets";

const char *des_path = "D:\\tmp\\gamecenter-release-android-huakai-6162\\assets_des";

void listFiles(const char * dir, vector<string> &file_list);

void decrypt_(const char *name);

bool exist(const char * lpPath);

void decrypt_data(const char *name, const void *buffer, const size_t &len);

int main()

{

vector<string> dirList;

char dir[300] = { 0 };

strcpy(dir, res_path);

    std::cout << "Hello World!\n";

listFiles(dir, dirList);

for (size_t i = 0; i < dirList.size(); i++)

{

//printf("%s\n", dirList[i].c_str());

decrypt_(dirList[i].c_str());

}

system("pause");

}

//是否是文件夹 #include <Windows.h>

bool isDir(const char *lpPath)

{

return GetFileAttributesA(lpPath)&FILE_ATTRIBUTE_DIRECTORY;

}

void listFiles(const char * dir, vector<string> &file_list)

{

char dirNew[200];

strcpy(dirNew, dir);

strcat(dirNew, "\\*.*");    // 在目录后面加上"\\*.*"进行第一次搜索

intptr_t handle;

_finddata_t findData;

handle = _findfirst(dirNew, &findData);

if (handle == -1)        // 检查是否成功

return;

do

{

if (findData.attrib & _A_SUBDIR)

{

if (strcmp(findData.name, ".") == 0 || strcmp(findData.name, "..") == 0)

continue;

//cout << findData.name << "\t<dir>\n";

// 在目录后面加上"\\"和搜索到的目录名进行下一次搜索

strcpy(dirNew, dir);

strcat(dirNew, "\\");

strcat(dirNew, findData.name);

listFiles(dirNew, file_list);

}

else

{

//cout << findData.name << "\t" << findData.size << " bytes.\n";

file_list.push_back(string(dir).append("\\").append(findData.name));

}

} while (_findnext(handle, &findData) == 0);

_findclose(handle);    // 关闭搜索句柄

}

void decrypt_(const char *name)

{

unsigned char byte_A5DF0F[] = {

0xA4, 0x11, 0x98, 0xD3, 0xB2, 0x41, 0x27, 0x8F, 0x56,

0x14, 0xF1, 0x74, 0xF6, 0xCA, 0xE0, 0x7D, 0x32, 0xFF,

0x92, 0xE2, 0x36, 0xA8, 0x94, 0x6E, 0xF0, 0x10, 0xDC,

0xF7, 0xC6, 0x66, 0x81, 0x91, 0xE4, 0xA1, 0x12, 0x28,

0xF5, 0x3B, 0xAE, 0x1B, 0xD9, 0x6E, 0x64, 0x19, 0xC4,

0xD2, 0x19, 0x59, 0x93, 0x23, 0x2D, 0xA1, 0x92, 0x54,

0xDD, 0xF2, 0xEF, 0x24, 0xD0, 0x9B, 0x3A, 0x20, 0xBE,

0x7C, 0xF2, 0x6D, 0x3A, 0x66, 0x85, 0x77, 0x9B, 0x2B,

0x1A, 0xC8, 0xC6, 0x64, 0xFA, 0x62, 0xCB, 0xCA, 0xAB,

0xC1, 0xC9, 0x21, 0x71, 0x96, 0xA3, 0xA9, 0xC7, 0xB0,

0x9A, 0xC2, 0x6B, 0x46, 0x9A, 0xBF, 0xFC, 0x6C, 0xFA,

0x16, 0x5C, 0xEF, 0x90, 0xED, 0x9F, 0x6C, 0xAB, 0x25,

0x94, 0x5A, 0x5C, 0xAF, 0x4E, 0x2A, 0xC4, 0xC6, 0xB0,

0xD8, 0x71, 0x50, 0x38, 0x82, 0x1A, 0xF7, 0x2A, 0x45,

0xE8, 0x2E, 0x64, 0x9E, 0x65, 0x32, 0x7A, 0x3C, 0x33,

0x13, 0x51, 0x1F, 0xA7, 0x82, 0x67, 0x8D, 0xE9, 0x2C,

0x4C, 0x7F, 0xA7, 0xCF, 0x9E, 0x2E, 0x79, 0x72, 0xB9,

0x72, 0xBF, 0x4F, 0x14, 0x53, 0x9B, 0xFC, 0xD9, 0x3B,

0xEE, 0x15, 0xF8, 0xB0, 0x4C, 0xF1, 0xCB, 0x79, 0x9B,

0x5D, 0x42, 0xF7, 0xEB, 0xAE, 0xEB, 0x8F, 0xB9, 0xBC,

0xBE, 0xA1, 0x7E, 0x9E, 0x38, 0xBE, 0xE9, 0x7D, 0xB2,

0x8D, 0x3D, 0x82, 0x90, 0x39, 0xCD, 0x17, 0x49, 0xCF,

0x4B, 0xF2, 0x1C, 0x59, 0x2A, 0xA3, 0x73, 0x72, 0x66,

0xFE, 0x3E, 0x30, 0xD5, 0xE4, 0xB9, 0x19, 0xD7, 0xAC,

0x72, 0x5F, 0x21, 0x37, 0x2E, 0x6B, 0x14, 0xA4, 0x8C,

0x35, 0xC1, 0x16, 0xFF, 0xCC, 0xB3, 0x3F, 0x1D, 0x1A,

0xA4, 0xA5, 0xF1, 0x83, 0xD1, 0x99, 0x29, 0x80, 0x25,

0xBD, 0xD0, 0x4E, 0xD8, 0x9C, 0xBE, 0xE9, 0xB8, 0xDD,

0xCB, 0x21, 0x94, 0x49, 0

};

unsigned __int8 *v8 = NULL;

size_t file_len = 0;

size_t *v6 = &file_len;

//if (*name == 47)

{

FILE *v11 = fopen(name, "rb");

FILE *v12 = v11;

if (v11)

{

fseek(v11, 0, 2);

long v13 = ftell(v12);

fseek(v12, 0, 0);

v8 = (unsigned __int8 *)operator new[](v13);

size_t v14 = fread(v8, 1u, v13, v12);

fclose(v12);

//if (!v6)

// __und(0xFDEEu);

*v6 = v14;

if (v14 > 7)

{

unsigned __int8 v15 = *v8;

unsigned __int8 v16 = v15 == 102;

if (v15 == 102)

v16 = v8[1] == 117;

if (v16)

{

unsigned __int8 v17 = v8[2];

unsigned __int8 v18 = v17 == 99;

if (v17 == 99)

v18 = v8[3] == 107;

if (v18)

{

unsigned __int8 v19 = v8[4];

unsigned __int8 v20 = v19 == 121;

if (v19 == 121)

v20 = v8[5] == 111;

if (v20)

{

unsigned __int8 v21 = v8[6];

unsigned __int8 v22 = v21 == 117;

if (v21 == 117)

v22 = v8[7] == 33;

if (v22)

{

unsigned int v23 = v14 - 8;

*v6 = v23;

//_aeabi_memmove(v8, v8 + 8);

v8 += 8;

if (v23)

{

unsigned int v24 = 0;

do

{

v8[v24] ^= byte_A5DF0F[(signed int)v24 % 256];

++v24;

} while (v24 < v23);

//解密完成写入图片

decrypt_data(name, v8, *v6);

goto LABEL_60;

}

v8 -= 8;

}

}

}

}

}

//goto LABEL_60;

}

goto LABEL_58;

}

LABEL_60:

//printf("%s\n", name);

return;

//声音没有加密, 加密的是luac

LABEL_58:

printf("%s\n", name);

}

void decrypt_data(const char *name, const void *buffer, const size_t &len)

{

string des(name);

des.replace(des.find(res_path), strlen(res_path), des_path);

string parent_dir = des.substr(0, des.rfind("\\"));

if (!exist(parent_dir.c_str()))

system(string("md ").append(parent_dir).c_str());

//printf(des.c_str());

FILE * fd = fopen(des.c_str(), "wb+");

if (fd) {

if (fwrite(buffer, len, 1, fd) > 0) {

//printf("write success .");

}

fclose(fd);

}

}

//是否存在

bool exist(const char * lpPath)

{

/* Check for existence */

if ((_access(lpPath, 0)) != -1)

{

return true;

}

else {

return false;

}

}



lua解密:

上面是解密的代码分析好相应的变量之后直接拷贝伪代码,完成之后发现图片解密了代码还是原样...

中间也踩了很多坑,找.lua xxtea aes之类的加密函数或者具有嫌疑的字符串都失败了.最后luaLoadBuffer看到了...

接着搜索luaLoadBuffer函数

看了下_byds_d_的解密逻辑比较复杂,解密完还要解压缩,索性就hook dump吧
hook luaL_loadbuffer函数

hook工具很多都只停留在4.4版本,这点坑了我许久,nexus5x最低支持6.0无奈.

经过各种论坛百度,最后找到注入解决方案 基于Xposed和Substrate的通用性SO注入 - 大星星的专栏 - CSDN博客 该应该适用于8.0

不改变原包体,xposed入口注入substrate.so 和自己的so 进行hook dlopen函数  dlopen 检测到libgame.so打开之后得到符号直接hook其函数.

打印日志,buffer len path都出来了...
接下来就是提取lua脚本到内存卡,这里有个坑 1.文件夹不能直接创建,2.开始写入到/data/local/tmp目录创建不了
以二进制写的方式打开文件,打开之后写入
写入完成之后用adb pull命令拷贝到解密文件夹内.
原以为luac还要在解密一次为lua打开一看多虑了,直接明文...


交流可加qq99939534

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 157,298评论 4 360
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 66,701评论 1 290
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 107,078评论 0 237
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 43,687评论 0 202
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 52,018评论 3 286
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 40,410评论 1 211
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 31,729评论 2 310
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 30,412评论 0 194
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 34,124评论 1 239
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 30,379评论 2 242
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 31,903评论 1 257
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 28,268评论 2 251
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 32,894评论 3 233
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 26,014评论 0 8
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 26,770评论 0 192
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 35,435评论 2 269
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 35,312评论 2 260

推荐阅读更多精彩内容