记一次棋牌游戏 cocos2d-x LUA脚本解密
1.如何查看luac的key和sign
? ? 對一棋牌游戲反編譯后,可以在其assets目錄下面發現*.luac的腳本,打開下面的luac腳本,可以看到luac是加密的,如下圖:
?? ? ??
? ?
? ? 可以看到加密的luac文件的頭幾個字節,都是一個固定字符串值,而這個字符串值就是利用官方加解密Xxtea算法用的sign值,找到sign后,接下來找KEY,用IDA載入libcocos2dlua.so,搜索剛剛找到的固定字符串zhongrdhsakhfjasf,可以看到KEY位于其附近。
2.xxtea加解密實現
? ? 由于lua本身是開源的,其官方加解密實現方式很容易就能查找資料得到,根據得到key和sign就可以利用xxtea算法來對腳本進行解密,本人用c++實現了xxtea算法的解密過程,這個程序只需要三個參數:文件路徑,sign, key即可解密,附上代碼:
main.cpp
#include "stdafx.h" #include "xxtea.h" #include <fstream>int main(int argc, char *argv[]) {if (argc <= 1){printf("usage .\ConsoleApplication1 <filePath> <sign> <key>\n");return 0;}printf("filePath:%s sign:%s key:%s", argv[1], argv[2], argv[3]);std::string filePath = argv[1];std::string outFilePath = filePath;outFilePath.resize(filePath.rfind("\\")+ 1);size_t pos = filePath.rfind("\\");size_t pos2 = filePath.rfind(".");std::string temp = filePath.substr(pos + 1, pos2 - pos -1);outFilePath += "jiemi\\";outFilePath += temp;outFilePath += ".lua";int signLen = strlen(argv[2]);int keyLen = strlen(argv[3]);std::ifstream ifs(argv[1], std::ios::binary);unsigned char *content = NULL;int length = 0;if (ifs){ifs.seekg(0, std::ios::end);length = ifs.tellg();ifs.seekg(0, std::ios::beg);content = new unsigned char[length];memset(content, 0, length);ifs.read((char* )content, length);}ifs.close();xxtea_long retLen = 0;unsigned char * data = xxtea_decrypt(content + signLen, length - signLen, (unsigned char*)argv[3], keyLen, &retLen);if (data == NULL) {printf("%s decrypt fail\n", argv[1]);return -1;}std::ofstream ofs(outFilePath.c_str(), std::ios::binary);if (ofs){ofs.write((char*)data, retLen);}ofs.close();printf("%s->%s decrypt success\n", filePath.c_str(), outFilePath.c_str());delete[] content;return 0; }? ?xxtea.cpp /***********************************************************************Copyright 2006-2009 Ma BingyaoCopyright 2013 Gao Chunhui, Liu TaoThese sources is free software. Redistributions of source code mustretain the above copyright notice. Redistributions in binary formmust reproduce the above copyright notice. You can redistribute itfreely. You can use it with any free or commercial software.These sources is distributed in the hope that it will be useful,but WITHOUT ANY WARRANTY. Without even the implied warranty ofMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.github: https://github.com/liut/pecl-xxtea*************************************************************************/#include "xxtea.h" #include <memory.h> #include <stdlib.h>static void xxtea_long_encrypt(xxtea_long *v, xxtea_long len, xxtea_long *k) {xxtea_long n = len - 1;xxtea_long z = v[n], y = v[0], p, q = 6 + 52 / (n + 1), sum = 0, e;if (n < 1) {return;}while (0 < q--) {sum += XXTEA_DELTA;e = sum >> 2 & 3;for (p = 0; p < n; p++) {y = v[p + 1];z = v[p] += XXTEA_MX;}y = v[0];z = v[n] += XXTEA_MX;} }static void xxtea_long_decrypt(xxtea_long *v, xxtea_long len, xxtea_long *k) {xxtea_long n = len - 1;xxtea_long z = v[n], y = v[0], p, q = 6 + 52 / (n + 1), sum = q * XXTEA_DELTA, e;if (n < 1) {return;}while (sum != 0) {e = sum >> 2 & 3;for (p = n; p > 0; p--) {z = v[p - 1];y = v[p] -= XXTEA_MX;}z = v[n];y = v[0] -= XXTEA_MX;sum -= XXTEA_DELTA;} }static unsigned char *fix_key_length(unsigned char *key, xxtea_long key_len) {unsigned char *tmp = (unsigned char *)malloc(16);memcpy(tmp, key, key_len);memset(tmp + key_len, '\0', 16 - key_len);return tmp; }static xxtea_long *xxtea_to_long_array(unsigned char *data, xxtea_long len, int include_length, xxtea_long *ret_len) {xxtea_long i, n, *result;n = len >> 2;n = (((len & 3) == 0) ? n : n + 1);if (include_length) {result = (xxtea_long *)malloc((n + 1) << 2);result[n] = len;*ret_len = n + 1;} else {result = (xxtea_long *)malloc(n << 2);*ret_len = n;}memset(result, 0, n << 2);for (i = 0; i < len; i++) {result[i >> 2] |= (xxtea_long)data[i] << ((i & 3) << 3);}return result; }static unsigned char *xxtea_to_byte_array(xxtea_long *data, xxtea_long len, int include_length, xxtea_long *ret_len) {xxtea_long i, n, m;unsigned char *result;n = len << 2;if (include_length) {m = data[len - 1];if ((m < n - 7) || (m > n - 4)) return NULL;n = m;}result = (unsigned char *)malloc(n + 1);for (i = 0; i < n; i++) {result[i] = (unsigned char)((data[i >> 2] >> ((i & 3) << 3)) & 0xff);}result[n] = '\0';*ret_len = n;return result; }static unsigned char *do_xxtea_encrypt(unsigned char *data, xxtea_long len, unsigned char *key, xxtea_long *ret_len) {unsigned char *result;xxtea_long *v, *k, v_len, k_len;v = xxtea_to_long_array(data, len, 1, &v_len);k = xxtea_to_long_array(key, 16, 0, &k_len);xxtea_long_encrypt(v, v_len, k);result = xxtea_to_byte_array(v, v_len, 0, ret_len);free(v);free(k);return result; }static unsigned char *do_xxtea_decrypt(unsigned char *data, xxtea_long len, unsigned char *key, xxtea_long *ret_len) {unsigned char *result;xxtea_long *v, *k, v_len, k_len;v = xxtea_to_long_array(data, len, 0, &v_len);k = xxtea_to_long_array(key, 16, 0, &k_len);xxtea_long_decrypt(v, v_len, k);result = xxtea_to_byte_array(v, v_len, 1, ret_len);free(v);free(k);return result; }unsigned char *xxtea_encrypt(unsigned char *data, xxtea_long data_len, unsigned char *key, xxtea_long key_len, xxtea_long *ret_length) {unsigned char *result;*ret_length = 0;if (key_len < 16) {unsigned char *key2 = fix_key_length(key, key_len);result = do_xxtea_encrypt(data, data_len, key2, ret_length);free(key2);}else{result = do_xxtea_encrypt(data, data_len, key, ret_length);}return result; }unsigned char *xxtea_decrypt(unsigned char *data, xxtea_long data_len, unsigned char *key, xxtea_long key_len, xxtea_long *ret_length) {unsigned char *result;*ret_length = 0;if (key_len < 16) {unsigned char *key2 = fix_key_length(key, key_len);result = do_xxtea_decrypt(data, data_len, key2, ret_length);free(key2);}else{result = do_xxtea_decrypt(data, data_len, key, ret_length);}return result; }/* }}} */ ? ? XXTEA,又稱Corrected Block TEA,是XTEA的升級版,設計者是Roger Needham, David Wheeler加密過程:
????
? ? 其核心是:XXTEA算法使用128bit的密鑰對以32bit為單位的信息塊進行加密。
3.非官方xxtea加解密爆破方案
? ? 剛上述操作幾乎無障礙的就可以輕易獲得key和sign進行解密,所以比較的好的加固方案就是不使用官方加解密,并且對key字符串做混淆,那如果碰上這種加固方案,那如何進行爆破呢,答案是爆破libcocos2dlua.so里面的luaL_loadbuffer函數。Cocos引擎的lua加載器為cocos2dx_lua_loader,最終都是調用luaL_loadbuffer函數來加載,一般廠商會在這層上面對lua腳本進行解密,即是在luaL_loadbuffer函數獲取buff參數可得到解密后的lua腳本。
??
? ? lua引擎加載lua腳本最底層是到lua_reader函數。該函數負責最底層的腳本buff遍歷,因此在此處dump出來的lua腳本是最純正的lua腳本,所有加密都已經被去除(修改lua opcode或者引擎邏輯除外)。不過這個點的獲取不到足夠的文件信息(文件名、buff index等),需要配合上層函數拼湊lua腳本。
參考鏈接:
????Lua游戲逆向及破解方法介紹: http://www.freebuf.com/articles/system/103388.html
????淺析android手游lua腳本的加密與解密: https://bbs.pediy.com/thread-216969.htm? ??
總結
以上是生活随笔為你收集整理的记一次棋牌游戏 cocos2d-x LUA脚本解密的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 设置同时上内外网+文件共享
- 下一篇: 风机桨叶故障诊断(五) 修改隐含层神经元