工具篇:
IDA Pro (32-bit)7.0 神器不多说 百度网盘 提取码6666
ApkToolBox 功能很强大的拆包工具 爱盘 - 最新的在线破解工具包
Visual Studio 随便什么版本可以执行c/c++就行,用于解密脚本,好处是伪代码能直接用.
notepad++ 自行百度很好用的文本工具
Demo 百度网盘 提取码6666
开始:
解密图片:
// gamecenter_decrypt.cpp : 此文件包含 "main" 函数。程序执行将在此处开始并结束。
//
#include
#include
#include
#include
#include
#include
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
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
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
bool isDir(const char *lpPath)
{
return GetFileAttributesA(lpPath)&FILE_ATTRIBUTE_DIRECTORY;
}
void listFiles(const char * dir, vector
{
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
// 在目录后面加上"\\"和搜索到的目录名进行下一次搜索
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函数
hook工具很多都只停留在4.4版本,这点坑了我许久,nexus5x最低支持6.0无奈.
经过各种论坛百度,最后找到注入解决方案 基于Xposed和Substrate的通用性SO注入 - 大星星的专栏 - CSDN博客 该应该适用于8.0
不改变原包体,xposed入口注入substrate.so 和自己的so 进行hook dlopen函数 dlopen 检测到libgame.so打开之后得到符号直接hook其函数.
交流可加qq99939534