• 设为首页
  • 点击收藏
  • 手机版
    手机扫一扫访问
    迪恩网络手机版
  • 关注官方公众号
    微信扫一扫关注
    公众号

cocos2dx lua 反编译

原作者: [db:作者] 来自: [db:来源] 收藏 邀请

原文章:https://bbs.pediy.com/thread-216800.htm
网上各种教程、各种工具用不了,才会有这个文章。附件是我修改的支持luajit 2.1.0-beta2反编译的LJD

lua bytecode解密

知己知彼很重要,搜索“cocos2dx lua 加密”大概可以找到类似下面的代码。

bool AppDelegate::applicationDidFinishLaunching()

{

    ...

  

    CCLuaStack *pStack = pEngine->getLuaStack();

  

    // 如果设置了 -e 和 -ek 要加上下面这句

    // pStack->setXXTEAKeyAndSign("aaa", 3);

    // 如果设置了 -e 和 -ek -es 则要加上下面这句

    pStack->setXXTEAKeyAndSign("aaa", 3, "XT", 2);

    // load framework

    pStack->loadChunksFromZip("res/framework_precompiled.zip");

    pStack->loadChunksFromZip("res/game.zip");

    pStack->executeString("require 'main'");

  

    return true;

}

我的目标是一个ANDROID游戏,APK文件直接解压。一般情况是libcocos2dlua.so,IDA 打开,函数窗口直接搜索applicationDidFinishLaunching,就能带你飞,可惜只有loadChunksFromZip,没有setXXTEAKeyAndSign,这保存解密KEY的被编译优化了。怎么办?IDA字符串窗口帮你忙,编译器编译代码的时候都是就近原则,只要是差不多地方出现的字符串,都会被放在一起。加密的ZIP文件,文件头几个字符就是setXXTEAKeyAndSign的SIGN参数,加上ZIP文件本身的路径,搜索目标ZIP文件就可以了。如图,IDA显示附近也就几个字符串,剩下的KEY参数是哪个,一个一个试就可以了。

加密的ZIP文件:

IDA中的字符串,第一个黑块是SIGN参数,非常幸运,尝试第二个黑块就是KEY:

https://github.com/cocos2d/cocos2d-x/search?p=1&q=loadChunksFromZip&type=&utf8=✓ 找到cocos2dx的loadChunksFromZip的源码

 if (isXXTEA) { // decrypt XXTEA

            xxtea_long len = 0;

            buffer = xxtea_decrypt(bytes + stack->_xxteaSignLen,

                                   (xxtea_long)size - (xxtea_long)stack->_xxteaSignLen,

                                   (unsigned char*)stack->_xxteaKey,

                                   (xxtea_long)stack->_xxteaKeyLen,

                                   &len);

            zip = ZipFile::createWithBuffer(buffer, len);

        } else {

            if (size > 0) {

                zip = ZipFile::createWithBuffer(bytes, (unsigned long)size);

            }

        }

这里我遇到一点困难,cocos2dx的源码项目,没有xxtea的源码!不过还是让我在github搜索出来了,源码在此:

https://github.com/xxtea/xxtea-c

直接写个C++代码,就把加密的ZIP解出来了。顺带一提,Sign就是用来跳过,跟什么PE,MZ是一样的。

HANDLE hFileOUT = CreateFile(L"e:\\tmp\\y1\\xxx\\assets\\res\\de_xxx.zip", GENERIC_ALL, 0, 0, CREATE_ALWAYS, 0, 0);

HANDLE hFile = CreateFile(L"e:\\tmp\\y1\\xxx\\assets\\res\\xxx.zip",GENERIC_ALL, 0,0,OPEN_EXISTING,0,0);

if (hFile != INVALID_HANDLE_VALUE)

{

DWORD dwSize = GetFileSize(hFile, 0);

  

size_t  dwOut = 0;

DWORD dwRead = 0;

LPBYTE p = new BYTE[dwSize];

  

ReadFile(hFile, p, dwSize, &dwRead, 0);

DWORD dwSignLen = 3;

LPBYTE p2 = (LPBYTE)xxtea_decrypt((void *)(p + dwSignLen), dwSize - dwSignLen,(void *) "key", &dwOut);

  

  

WriteFile(hFileOUT, p2, dwOut, &dwRead, 0);

delete p;

  

CloseHandle(hFileOUT);

CloseHandle(hFile);

}

de_xxx.zip的头两个字节变成喜闻乐见的PK,解压,搞定。

Luajit ASM

解压出来的文件,都是LuaJIT— a Just-In-Time Compiler for Lua,文件头长这样:

http://luajit.org/download.html 可以下载到LuaJIT的源码,不过兼容性有点糟糕,需要找到正确的版本才有效。回到IDA字符串窗口搜索luajit,可以确认目标APK使用的是2.1.0-beta2。下载源码,编译之后,使用类似下面的命令行:

luajit.exe -bl xxx.lua.bytecode xxx.lua.asm

可以看到LUA的ASM代码了,LUA ASM长这样:

0013 TGETV 4 4 1

0014 CALL 3 4 2

0015 ISNEXT 6 => 0019

0016 => MOV 8 7

0017 MOV 9 2

0018 CALL 8 1 2

0019 => ITERN 6 3 3

0020 ITERL 6 => 0016

0021 RET0 0 1

BYTECODE的定义在http://wiki.luajit.org/Bytecode-2.0 。不过我智商不够,看不懂,

Luajit decompiler

搜索了无数反编译文章,基本就是https://github.com/NightNord/ljd ,然而这货2014年之后就再没更新了,并不能用,没有选择,只能自己动手改。

  1. 由于新Opcode导致的失败

luajit 2.1.0-beta2源码的lj_bc.h里的#define BCDEF,下方就是长长一串Opcode定义。

Ljd源码的bytecode\instructions.py 和 rawdump\code.py的两张Opcode表必须跟luajit 2.1.0-beta2 的lj_bc.h一一对比,少了的就要补上。

这里不得不吐槽一下luajit,新增Opcode其实并没有人用,Opcode是通过数组维护的,随便加个新的Opcode都会导致原有的Opcode编码改变。。。

  1. 由于assert导致的失败,注释掉就好了。虽说有点不负责,但是反编译各种语法处理我也不懂。

LJD改好之后,main.py xxx.lua.bytecode > xxx.lua,终于可以看到正常的代码:

DeprecatedNetworkClass = {} or DeprecatedNetworkClass

  

local function deprecatedTip(old_name, new_name)

print("\n********** \n" .. old_name .. " was deprecated please use " .. new_name .. " instead.\n**********")

  

return

end

  

DeprecatedNetworkClass.WebSocket = function ()

deprecatedTip("WebSocket", "cc.WebSocket")

  

return cc.WebSocket

end

_G.WebSocket = DeprecatedNetworkClass.WebSocket()

  

return

请大家先确认自己的目标,再使用代码。如果版本不一致,你们需要先对比luajit源码中的lj_bc.h和https://github.com/NightNord/ljd的bytecode\instructions.py 和 rawdump\code.py中的OPCODE表,对得上,才能正确反编译,对不上就自己参照着来改。


鲜花

握手

雷人

路过

鸡蛋
该文章已有0人参与评论

请发表评论

全部评论

专题导读
上一篇:
lua tasklib 之lumen 分析发布时间:2022-07-22
下一篇:
quickcocos2dxlua内存释放发布时间:2022-07-22
热门推荐
热门话题
阅读排行榜

扫描微信二维码

查看手机版网站

随时了解更新最新资讯

139-2527-9053

在线客服(服务时间 9:00~18:00)

在线QQ客服
地址:深圳市南山区西丽大学城创智工业园
电邮:jeky_zhao#qq.com
移动电话:139-2527-9053

Powered by 互联科技 X3.4© 2001-2213 极客世界.|Sitemap