吾爱破解 - LCG - LSG |安卓破解|病毒分析|www.52pojie.cn

 找回密码
 注册[Register]

QQ登录

只需一步,快速开始

查看: 4017|回复: 30
收起左侧

[Android 原创] 某游戏的另类lua加密方式的解密

  [复制链接]
Light紫星 发表于 2023-2-14 18:13
本帖最后由 Light紫星 于 2023-2-15 09:47 编辑

某游戏的另类lua加密方式的解密
今日下午,群中一个小伙伴突然发了一个data.lua文件,并且问是什么编码,我下载一看,内容是加密的,但是有个头“FFSZ”,当时心想,这不是xxtea吗,有手就行啊,然后让小伙伴发来apk给我,遂有此贴。


目标apk包名:Y29tLmZ1bnBsdXMuZmFtaWx5ZmFybWNoaW5hLmh1YXdlaQ==


下载打开一看,是个农场类游戏,然后看一下lib目录,3264位的都有,就拿arm64-v8a目录下手吧,里面就三个so文件,有一个最大的30m,叫libgame.sook,不用想就知道今天的目标就是它了。


拖入IDA,等加载(大文件ida加载是真的慢啊,不知道各位有没有加速的方式),然后搜索xxteaokxxtea_decrypt字样,点进去,看一下参数,然后直接hookhook代码如下:

[Python] 纯文本查看 复制代码
# -*- coding: utf-8 -*-
import codecs
import frida
import sys
import threading

str_host = '192.168.1.10:9999'
manager = frida.get_device_manager()
device = manager.add_remote_device(str_host)

pending = []
sessions = []
scripts = []
event = threading.Event()

jscode = """   

  function readStdString(str){
    var isTiny = (str.readU8() & 1) == 0; 
    if(isTiny){
        return str.add(1).readUtf8String();
    }
    return str.add(2*Process.pointerSize).readPointer().readUtf8String();
}
  
  function inline_hook() {
    while(1)
    {
      var so_addr = Module.findBaseAddress("libgame.so");
      console.log("so_addr:", so_addr);  
      if (so_addr) { 
          var addr = Module.findExportByName("libgame.so", "xxtea_decrypt")
          console.log("addr:", addr); 
          if(!addr)
          {
            continue;
          } 
            Interceptor.attach(new NativePointer(addr), { 
            onEnter: function (args)
            {  
               console.log("xxtea key:",readCString(args[2])); 
            },
            onLeave: function (retval)
            {   
            
            } 
        });  
        

        break;
    }
    
    }
}

inline_hook() 
  
""" 

pid = device.spawn(["com.funplus.familyfarmchina.huawei"])
 
session = device.attach(pid)
print(" Attach Application id:",pid)
device.resume(pid) 
script = session.create_script(jscode) 
print(' Running CTF')
script.load()
sys.stdin.read()

Hook成功,看到打印出ffs字样,嗯,这应该就是key了,下载一个xxtea解密工具,设置参数,解密:
image.png

如图,所有文件全部解密失败,此时我眉头一皱,心想事情并不简单,难道是key错了,还是根本就不是xxtea的加密方式,此时,回到ida,从xxtea_decrypt往上找
image.png 好的,我们找到了cocos2dx_lua_loader,然后看了一下流程,key设置成ffs,然后解密,好像是没错,但是和我们测试的结果不一致,所以整体看一下这个函数的流程,此函数如下:
[C] 纯文本查看 复制代码
__int64 __fastcall cocos2dx_lua_loader(__int64 a1)
{
  const char *v2; // x20
  __int64 v3; // x0
  const char *v4; // x20
  unsigned __int64 v5; // x21
  __int64 v6; // x22
  const char *v7; // x21
  __int64 v8; // x0
  const char *v9; // x8
  const char *v10; // x23
  __int64 v11; // x24
  __int64 v12; // x0
  const char *v13; // x24
  __int64 first_of; // x0
  cocos2d::CCFileUtils *v15; // x0
  __int64 v16; // x0
  const char *v17; // x1
  unsigned __int8 *v18; // x0
  unsigned __int8 *v19; // x20
  __int64 v20; // x0
  __int64 ProcessedBuffSize; // x21
  __int64 ProcessedBuffData; // x1
  const char *v23; // x3
  const char *v24; // x21
  char v25; // w22
  const char *v26; // x23
  __int64 v27; // x3
  const char *v28; // x2
  const char *v29; // x21
  char v30; // w22
  const char *v31; // x23
  const char *v32; // x4
  const char *v33; // x3
  __int64 v34; // x0
  __int64 v35; // x22
  unsigned __int64 *v36; // x23
  void *v37; // x21
  unsigned __int64 v38; // x4
  const char *v39; // x3
  const char *v40; // x22
  char v41; // w23
  const char *v42; // x24
  __int64 v43; // x3
  const char *v44; // x2
  const char *v45; // x22
  char v46; // w23
  const char *v47; // x24
  const char *v48; // x4
  const char *v49; // x3
  __int64 v50; // x0
  __int64 v51; // x22
  int *v52; // x23
  void *v53; // x21
  unsigned __int64 v54; // x4
  const char *v55; // x3
  const char *v56; // x22
  char v57; // w23
  const char *v58; // x24
  __int64 v59; // x3
  const char *v60; // x2
  const char *v61; // x22
  char v62; // w23
  const char *v63; // x24
  const char *v64; // x4
  const char *v65; // x3
  const char *v66; // x21
  unsigned __int64 v67; // x23
  unsigned __int64 v68; // x0
  const char *v69; // x3
  const char *v70; // x21
  char v71; // w22
  const char *v72; // x23
  __int64 v73; // x3
  const char *v74; // x2
  const char *v75; // x21
  char v76; // w22
  const char *v77; // x23
  const char *v78; // x4
  const char *v79; // x3
  const char *v81; // x23
  __int64 v82; // x0
  const char *v83; // x21
  unsigned __int64 v84; // x23
  unsigned __int64 v85; // x0
  const char *v86; // x21
  unsigned __int64 v87; // x23
  unsigned __int64 v88; // x0
  const char *v89; // x21
  unsigned __int64 v90; // x23
  unsigned __int64 v91; // x0
  const char *v92; // x21
  unsigned __int64 v93; // x23
  unsigned __int64 v94; // x0
  const char *v95; // x21
  unsigned __int64 v96; // x23
  unsigned __int64 v97; // x0
  const char *v98; // x21
  unsigned __int64 v99; // x23
  unsigned __int64 v100; // x0
  const char *v101; // x21
  unsigned __int64 v102; // x23
  unsigned __int64 v103; // x0
  const char *v104; // x21
  unsigned __int64 v105; // x23
  unsigned __int64 v106; // x0
  const char *v107; // x21
  char v108; // w22
  const char *v109; // x23
  __int64 v110; // x3
  const char *v111; // x2
  const char *v112; // x21
  char v113; // w22
  const char *v114; // x23
  const char *v115; // x4
  const char *v116; // x3
  const char *v117; // x23
  __int64 v118; // x0
  const char *v119; // x23
  __int64 v120; // x0
  const char *v121; // x23
  __int64 v122; // x0
  const char *v123; // x23
  __int64 v124; // x0
  const char *v125; // x23
  __int64 v126; // x0
  const char *v127; // x23
  __int64 v128; // x0
  const char *v129; // x23
  __int64 v130; // x0
  const char *v131; // x23
  __int64 v132; // x0
  _BYTE v133[72]; // [xsp+0h] [xbp-510h] BYREF
  __int64 v134[38]; // [xsp+48h] [xbp-4C8h] BYREF
  __int128 v135; // [xsp+278h] [xbp-298h] BYREF
  const char *v136; // [xsp+288h] [xbp-288h]
  unsigned __int64 v137; // [xsp+4A8h] [xbp-68h] BYREF
  __int128 v138; // [xsp+4B0h] [xbp-60h] BYREF
  const char *v139; // [xsp+4C0h] [xbp-50h]

  v2 = (const char *)luaL_checklstring(a1, 1LL, 0LL);
  v138 = 0uLL;
  v139 = 0LL;
  v3 = std::char_traits<char>::length(v2);
  std::string::__init(&v138, v2, v3);
  if ( (v138 & 1) != 0 )
    v4 = v139;
  else
    v4 = (char *)&v138 + 1;
  if ( (v138 & 1) != 0 )
    v5 = *((_QWORD *)&v138 + 1);
  else
    v5 = (unsigned __int64)(unsigned __int8)v138 >> 1;
  v6 = std::char_traits<char>::length(".lua");
  v7 = &v4[v5];
  v8 = std::__find_end<bool (*)(char,char),char const*,char const*>(
         v4,
         v7,
         ".lua",
         &aLua[v6],
         std::char_traits<char>::eq);
  if ( (v6 == 0 || v8 != (_QWORD)v7) && v8 - (_QWORD)v4 != -1 )
  {
    std::string::basic_string(&v135, &v138, 0LL, v8 - (_QWORD)v4, &v138);
    LOBYTE(v134[0]) = 0;
    if ( (v138 & 1) != 0 )
    {
      std::char_traits<char>::assign(v139, v134);
      *((_QWORD *)&v138 + 1) = 0LL;
    }
    else
    {
      std::char_traits<char>::assign((char *)&v138 + 1, v134);
      LOBYTE(v138) = 0;
    }
    std::string::reserve(&v138, 0LL);
    v9 = v136;
    v136 = 0LL;
    v139 = v9;
    v138 = v135;
    v135 = 0uLL;
    std::string::~string(&v135);
  }
  while ( 1 )
  {
    v10 = (v138 & 1) != 0 ? v139 : (char *)&v138 + 1;
    v11 = (v138 & 1) != 0 ? *((_QWORD *)&v138 + 1) : (unsigned __int64)(unsigned __int8)v138 >> 1;
    v12 = std::char_traits<char>::length(".");
    if ( !v12 )
      break;
    if ( !v11 )
      break;
    v13 = &v10[v11];
    first_of = std::__find_first_of_ce<char const*,char const*,bool (*)(char,char)>(
                 v10,
                 v13,
                 ".",
                 &aFerrorInFuncti_1677[v12 + 36],
                 std::char_traits<char>::eq);
    if ( (const char *)first_of == v13 || first_of - (_QWORD)v10 == -1 )
      break;
    std::string::replace((int)&v138, first_of - (_DWORD)v10, 1, "/");
  }
  v15 = (cocos2d::CCFileUtils *)std::string::append((int)&v138, ".lua");
  v137 = 0LL;
  v16 = cocos2d::CCFileUtils::sharedFileUtils(v15);
  if ( (v138 & 1) != 0 )
    v17 = v139;
  else
    v17 = (char *)&v138 + 1;
  v18 = (unsigned __int8 *)(*(__int64 (__fastcall **)(__int64, const char *, const char *, unsigned __int64 *))(*(_QWORD *)v16 + 32LL))(
                             v16,
                             v17,
                             "rb",
                             &v137);
  v19 = v18;
  if ( v18 )
  {
    if ( v137 >= 4 )
    {
      switch ( *(_DWORD *)v18 )
      {
        case 0x43534646:
          FunPlus::CDesDecryptor::CDesDecryptor((FunPlus::CDesDecryptor *)&v135);
          memset(v134, 0, 24);
          v20 = std::char_traits<char>::length("FP_F_ENC");
          std::string::__init(v134, "FP_F_ENC", v20);
          FunPlus::CDesDecryptor::setKey(&v135, v134);
          std::string::~string(v134);
          FunPlus::CCryptor::setForceUse64Bit((FunPlus::CCryptor *)&v135, 1);
          if ( (FunPlus::CDecryptor::processBuffer((FunPlus::CDecryptor *)&v135, v19 + 4, v137 - 4) & 1) != 0 )
          {
            ProcessedBuffSize = FunPlus::CCryptor::getProcessedBuffSize((FunPlus::CCryptor *)&v135);
            ProcessedBuffData = FunPlus::CCryptor::getProcessedBuffData((FunPlus::CCryptor *)&v135);
            if ( (v138 & 1) != 0 )
              v23 = v139;
            else
              v23 = (char *)&v138 + 1;
            if ( (unsigned int)luaL_loadbuffer(a1, ProcessedBuffData, ProcessedBuffSize, (__int64)v23) )
            {
              v24 = (const char *)lua_tolstring(a1, 1LL, 0LL);
              v25 = v138;
              v26 = v139;
              v27 = lua_tolstring(a1, 0xFFFFFFFFLL, 0LL);
              if ( (v25 & 1) != 0 )
                v28 = v26;
              else
                v28 = (char *)&v138 + 1;
              cocos2d::CCLog((cocos2d *)"error loading module %s from file %s :\n\t%s", v24, v28, v27);
              v29 = (const char *)lua_tolstring(a1, 1LL, 0LL);
              v30 = v138;
              v31 = v139;
              v32 = (const char *)lua_tolstring(a1, 0xFFFFFFFFLL, 0LL);
              if ( (v30 & 1) != 0 )
                v33 = v31;
              else
                v33 = (char *)&v138 + 1;
              luaL_error(a1, "error loading module %s from file %s :\n\t%s", v29, v33, v32);
            }
            FunPlus::CDesDecryptor::~CDesDecryptor((FunPlus::CDesDecryptor *)&v135);
LABEL_99:
            operator delete[](v19);
            goto LABEL_100;
          }
          FunPlus::CDesDecryptor::~CDesDecryptor((FunPlus::CDesDecryptor *)&v135);
          break;
        case 0x5A534646:
          FunPlus::CDesDecryptor::CDesDecryptor((FunPlus::CDesDecryptor *)v134);
          v136 = 0LL;
          v135 = 0uLL;
          v34 = std::char_traits<char>::length("FP_F_ENC");
          std::string::__init(&v135, "FP_F_ENC", v34);
          FunPlus::CDesDecryptor::setKey(v134, &v135);
          std::string::~string(&v135);
          FunPlus::CCryptor::setForceUse64Bit((FunPlus::CCryptor *)v134, 1);
          if ( (FunPlus::CDecryptor::processBuffer((FunPlus::CDecryptor *)v134, v19 + 4, v137 - 4) & 1) != 0 )
          {
            v35 = FunPlus::CCryptor::getProcessedBuffSize((FunPlus::CCryptor *)v134);
            v36 = (unsigned __int64 *)FunPlus::CCryptor::getProcessedBuffData((FunPlus::CCryptor *)v134);
            *(_QWORD *)&v135 = *(int *)v36;
            v37 = (void *)operator new[](v135);
            if ( (FunPlus::CCompressUtil::UnCompress(
                    (FunPlus::CCompressUtil *)v37,
                    &v135,
                    v36 + 1,
                    (const void *)(((v35 << 32) - 0x800000000LL) >> 32),
                    v38) & 1) != 0 )
            {
              if ( (v138 & 1) != 0 )
                v39 = v139;
              else
                v39 = (char *)&v138 + 1;
              if ( (unsigned int)luaL_loadbuffer(a1, (__int64)v37, v135, (__int64)v39) )
              {
                v40 = (const char *)lua_tolstring(a1, 1LL, 0LL);
                v41 = v138;
                v42 = v139;
                v43 = lua_tolstring(a1, 0xFFFFFFFFLL, 0LL);
                if ( (v41 & 1) != 0 )
                  v44 = v42;
                else
                  v44 = (char *)&v138 + 1;
                cocos2d::CCLog((cocos2d *)"error loading module %s from file %s :\n\t%s", v40, v44, v43);
                v45 = (const char *)lua_tolstring(a1, 1LL, 0LL);
                v46 = v138;
                v47 = v139;
                v48 = (const char *)lua_tolstring(a1, 0xFFFFFFFFLL, 0LL);
                if ( (v46 & 1) != 0 )
                  v49 = v47;
                else
                  v49 = (char *)&v138 + 1;
                luaL_error(a1, "error loading module %s from file %s :\n\t%s", v45, v49, v48);
              }
              operator delete[](v37);
              FunPlus::CDesDecryptor::~CDesDecryptor((FunPlus::CDesDecryptor *)v134);
              goto LABEL_99;
            }
            operator delete[](v37);
          }
          FunPlus::CDesDecryptor::~CDesDecryptor((FunPlus::CDesDecryptor *)v134);
          break;
        case 0x457:
          FunPlus::CXXTeaDecryptor::CXXTeaDecryptor((FunPlus::CXXTeaDecryptor *)v133);
          v136 = 0LL;
          v135 = 0uLL;
          v50 = std::char_traits<char>::length("ffs");
          std::string::__init(&v135, "ffs", v50);
          FunPlus::CXXTeaDecryptor::setKey(v133, &v135);
          std::string::~string(&v135);
          if ( (FunPlus::CXXTeaDecryptor::processBuffer((FunPlus::CXXTeaDecryptor *)v133, v19 + 4, v137 - 4) & 1) != 0 )
          {
            v51 = FunPlus::CCryptor::getProcessedBuffSize((FunPlus::CCryptor *)v133);
            v52 = (int *)FunPlus::CCryptor::getProcessedBuffData((FunPlus::CCryptor *)v133);
            *(_QWORD *)&v135 = *v52;
            v53 = (void *)operator new[](v135);
            if ( (FunPlus::CCompressUtil::UnCompress(
                    (FunPlus::CCompressUtil *)v53,
                    &v135,
                    (unsigned __int64 *)(v52 + 1),
                    (const void *)(((v51 << 32) - 0x400000000LL) >> 32),
                    v54) & 1) != 0 )
            {
              if ( (v138 & 1) != 0 )
                v55 = v139;
              else
                v55 = (char *)&v138 + 1;
              if ( (unsigned int)luaL_loadbuffer(a1, (__int64)v53, v135, (__int64)v55) )
              {
                v56 = (const char *)lua_tolstring(a1, 1LL, 0LL);
                v57 = v138;
                v58 = v139;
                v59 = lua_tolstring(a1, 0xFFFFFFFFLL, 0LL);
                if ( (v57 & 1) != 0 )
                  v60 = v58;
                else
                  v60 = (char *)&v138 + 1;
                cocos2d::CCLog((cocos2d *)"error loading module %s from file %s :\n\t%s", v56, v60, v59);
                v61 = (const char *)lua_tolstring(a1, 1LL, 0LL);
                v62 = v138;
                v63 = v139;
                v64 = (const char *)lua_tolstring(a1, 0xFFFFFFFFLL, 0LL);
                if ( (v62 & 1) != 0 )
                  v65 = v63;
                else
                  v65 = (char *)&v138 + 1;
                luaL_error(a1, "error loading module %s from file %s :\n\t%s", v61, v65, v64);
              }
              operator delete[](v53);
              FunPlus::CXXTeaDecryptor::~CXXTeaDecryptor((FunPlus::CXXTeaDecryptor *)v133);
              goto LABEL_99;
            }
            operator delete[](v53);
          }
          FunPlus::CXXTeaDecryptor::~CXXTeaDecryptor((FunPlus::CXXTeaDecryptor *)v133);
          break;
      }
    }
    if ( (v138 & 1) != 0 )
      v66 = v139;
    else
      v66 = (char *)&v138 + 1;
    if ( (v138 & 1) != 0 )
      v67 = *((_QWORD *)&v138 + 1);
    else
      v67 = (unsigned __int64)(unsigned __int8)v138 >> 1;
    v68 = std::char_traits<char>::length("/");
    if ( v67 >= v68 )
    {
      if ( !v68
        || (v81 = &v66[v67],
            v82 = std::__search<bool (*)(char,char),char const*,char const*>(
                    v66,
                    v81,
                    "/",
                    &asc_1A19AA4[v68 + 1],
                    std::char_traits<char>::eq),
            v81 != (const char *)v82)
        && v82 - (_QWORD)v66 != -1 )
      {
        v83 = (v138 & 1) != 0 ? v139 : (char *)&v138 + 1;
        v84 = (v138 & 1) != 0 ? *((_QWORD *)&v138 + 1) : (unsigned __int64)(unsigned __int8)v138 >> 1;
        v85 = std::char_traits<char>::length("common/");
        if ( v84 < v85
          || v85
          && ((v117 = &v83[v84],
               v118 = std::__search<bool (*)(char,char),char const*,char const*>(
                        v83,
                        v117,
                        "common/",
                        &aSpineCommon[v85 + 7],
                        std::char_traits<char>::eq),
               v117 == (const char *)v118)
           || v118 - (_QWORD)v83 == -1) )
        {
          v86 = (v138 & 1) != 0 ? v139 : (char *)&v138 + 1;
          v87 = (v138 & 1) != 0 ? *((_QWORD *)&v138 + 1) : (unsigned __int64)(unsigned __int8)v138 >> 1;
          v88 = std::char_traits<char>::length("game_loading/");
          if ( v87 < v88
            || v88
            && ((v119 = &v86[v87],
                 v120 = std::__search<bool (*)(char,char),char const*,char const*>(
                          v86,
                          v119,
                          "game_loading/",
                          &aGameLoading[v88],
                          std::char_traits<char>::eq),
                 v119 == (const char *)v120)
             || v120 - (_QWORD)v86 == -1) )
          {
            v89 = (v138 & 1) != 0 ? v139 : (char *)&v138 + 1;
            v90 = (v138 & 1) != 0 ? *((_QWORD *)&v138 + 1) : (unsigned __int64)(unsigned __int8)v138 >> 1;
            v91 = std::char_traits<char>::length("version_logo");
            if ( v90 < v91
              || v91
              && ((v121 = &v89[v90],
                   v122 = std::__search<bool (*)(char,char),char const*,char const*>(
                            v89,
                            v121,
                            "version_logo",
                            &aVersionLogo[v91],
                            std::char_traits<char>::eq),
                   v121 == (const char *)v122)
               || v122 - (_QWORD)v89 == -1) )
            {
              v92 = (v138 & 1) != 0 ? v139 : (char *)&v138 + 1;
              v93 = (v138 & 1) != 0 ? *((_QWORD *)&v138 + 1) : (unsigned __int64)(unsigned __int8)v138 >> 1;
              v94 = std::char_traits<char>::length("fast_switch/");
              if ( v93 < v94
                || v94
                && ((v123 = &v92[v93],
                     v124 = std::__search<bool (*)(char,char),char const*,char const*>(
                              v92,
                              v123,
                              "fast_switch/",
                              &aFastSwitch[v94],
                              std::char_traits<char>::eq),
                     v123 == (const char *)v124)
                 || v124 - (_QWORD)v92 == -1) )
              {
                v95 = (v138 & 1) != 0 ? v139 : (char *)&v138 + 1;
                v96 = (v138 & 1) != 0 ? *((_QWORD *)&v138 + 1) : (unsigned __int64)(unsigned __int8)v138 >> 1;
                v97 = std::char_traits<char>::length("ab_test/");
                if ( v96 < v97
                  || v97
                  && ((v125 = &v95[v96],
                       v126 = std::__search<bool (*)(char,char),char const*,char const*>(
                                v95,
                                v125,
                                "ab_test/",
                                &aAbTest_0[v97],
                                std::char_traits<char>::eq),
                       v125 == (const char *)v126)
                   || v126 - (_QWORD)v95 == -1) )
                {
                  v98 = (v138 & 1) != 0 ? v139 : (char *)&v138 + 1;
                  v99 = (v138 & 1) != 0 ? *((_QWORD *)&v138 + 1) : (unsigned __int64)(unsigned __int8)v138 >> 1;
                  v100 = std::char_traits<char>::length("novice_guide/");
                  if ( v99 < v100
                    || v100
                    && ((v127 = &v98[v99],
                         v128 = std::__search<bool (*)(char,char),char const*,char const*>(
                                  v98,
                                  v127,
                                  "novice_guide/",
                                  &aNoviceGuide[v100],
                                  std::char_traits<char>::eq),
                         v127 == (const char *)v128)
                     || v128 - (_QWORD)v98 == -1) )
                  {
                    v101 = (v138 & 1) != 0 ? v139 : (char *)&v138 + 1;
                    v102 = (v138 & 1) != 0 ? *((_QWORD *)&v138 + 1) : (unsigned __int64)(unsigned __int8)v138 >> 1;
                    v103 = std::char_traits<char>::length("neighbor/");
                    if ( v102 < v103
                      || v103
                      && ((v129 = &v101[v102],
                           v130 = std::__search<bool (*)(char,char),char const*,char const*>(
                                    v101,
                                    v129,
                                    "neighbor/",
                                    &aNeighbor_1[v103],
                                    std::char_traits<char>::eq),
                           v129 == (const char *)v130)
                       || v130 - (_QWORD)v101 == -1) )
                    {
                      v104 = (v138 & 1) != 0 ? v139 : (char *)&v138 + 1;
                      v105 = (v138 & 1) != 0 ? *((_QWORD *)&v138 + 1) : (unsigned __int64)(unsigned __int8)v138 >> 1;
                      v106 = std::char_traits<char>::length("spine-lua/");
                      if ( v105 < v106
                        || v106
                        && ((v131 = &v104[v105],
                             v132 = std::__search<bool (*)(char,char),char const*,char const*>(
                                      v104,
                                      v131,
                                      "spine-lua/",
                                      &aSpineLua[v106],
                                      std::char_traits<char>::eq),
                             v131 == (const char *)v132)
                         || v132 - (_QWORD)v104 == -1) )
                      {
                        v107 = (const char *)lua_tolstring(a1, 1LL, 0LL);
                        v108 = v138;
                        v109 = v139;
                        v110 = lua_tolstring(a1, 0xFFFFFFFFLL, 0LL);
                        if ( (v108 & 1) != 0 )
                          v111 = v109;
                        else
                          v111 = (char *)&v138 + 1;
                        cocos2d::CCLog((cocos2d *)"error loading module %s from file %s :\n\t%s", v107, v111, v110);
                        v112 = (const char *)lua_tolstring(a1, 1LL, 0LL);
                        v113 = v138;
                        v114 = v139;
                        v115 = (const char *)lua_tolstring(a1, 0xFFFFFFFFLL, 0LL);
                        if ( (v113 & 1) != 0 )
                          v116 = v114;
                        else
                          v116 = (char *)&v138 + 1;
                        luaL_error(a1, "error loading module %s from file %s :\n\t%s", v112, v116, v115);
                      }
                    }
                  }
                }
              }
            }
          }
        }
      }
    }
    if ( (v138 & 1) != 0 )
      v69 = v139;
    else
      v69 = (char *)&v138 + 1;
    if ( (unsigned int)luaL_loadbuffer(a1, (__int64)v19, v137, (__int64)v69) )
    {
      v70 = (const char *)lua_tolstring(a1, 1LL, 0LL);
      v71 = v138;
      v72 = v139;
      v73 = lua_tolstring(a1, 0xFFFFFFFFLL, 0LL);
      if ( (v71 & 1) != 0 )
        v74 = v72;
      else
        v74 = (char *)&v138 + 1;
      cocos2d::CCLog((cocos2d *)"error loading module %s from file %s :\n\t%s", v70, v74, v73);
      v75 = (const char *)lua_tolstring(a1, 1LL, 0LL);
      v76 = v138;
      v77 = v139;
      v78 = (const char *)lua_tolstring(a1, 0xFFFFFFFFLL, 0LL);
      if ( (v76 & 1) != 0 )
        v79 = v77;
      else
        v79 = (char *)&v138 + 1;
      luaL_error(a1, "error loading module %s from file %s :\n\t%s", v75, v79, v78);
    }
    goto LABEL_99;
  }
  if ( (v138 & 1) != 0 )
    cocos2d::CCLog((cocos2d *)"can not get file data of %s", v139);
  else
    cocos2d::CCLog((cocos2d *)"can not get file data of %s", (const char *)&v138 + 1);
LABEL_100:
  std::string::~string(&v138);
  return 1LL;
}

通过分析,我们知道,他先是读入lua文件,然后判断文件头,根据不同的文件头走不同的流程,我们的文件头是FFSZ,走的应该是des解密的流程,des解密之后还有一个zlib的解压缩,ok按照这个思路开始写代码。 一开始写的时候,我去掉文件头直接des解密,但是得出来的结果一直不符合预期,所以我直接跳过了12个字节重新解密,别问我为什么跳过12个字节,我也是猜的,然后解密出的结果,第九个字节刚好是789c,标准的zlib头,这里再进行zlib解压,好家伙,直接出明文了,解密代码如下:
[Python] 纯文本查看 复制代码
import pyDes,base64,zlib
from pyDes import des, ECB
def des_descrypt(s,KEY): 
    secret_key = KEY
    iv = secret_key
    k = des(secret_key, ECB,IV=iv, pad=None)
    de = k.decrypt(s)
    return de 
 
f=open('data.lua','rb').read()
f=f[12:]
ret = des_descrypt(f,b'FP_F_ENC') 

new_data = zlib.decompress(ret[8:])

print(new_data)

open('data_decrypt.lua','wb').write(new_data)

看一下解密出来的文件,完美!
image.png
好了,至此此文件的解密完成,总结一下,平常我们遇到的都是xxtealua加密,但是这个luaso里面虽然也有xxtea,但是用了des加密并且进行了压缩,所以遇到lua的游戏的时候不要慌,冷静分析,也是可以搞定的

最后附一下常见各种压缩算法的头特征:
gzip 1f 8b 08
lzma 6c 00
zlib 78 9c

免费评分

参与人数 15威望 +1 吾爱币 +40 热心值 +13 收起 理由
zhenzhenaidami + 1 + 1 谢谢@Thanks!
object86 + 1 我很赞同!
junjia215 + 1 + 1 用心讨论,共获提升!
淡化的忧伤丶 + 1 + 1 谢谢@Thanks!
cfxxh300 + 1 + 1 谢谢@Thanks!
lsy832 + 1 + 1 用心讨论,共获提升!
18651876024 + 1 + 1 请勿灌水,提高回帖质量是每位会员应尽的义务!
arctan1 + 1 + 1 谢谢@Thanks!
pjy612 + 1 我很赞同!
Rickroll + 1 + 1 用心讨论,共获提升!
我是不会改名的 + 4 + 1 我很赞同!
侃遍天下无二人 + 4 + 1 我很赞同!
quitidle + 1 + 1 用心讨论,共获提升!
正己 + 1 + 20 + 1 感谢发布原创作品,吾爱破解论坛因你更精彩!
janstk + 1 + 1 我很赞同!

查看全部评分

发帖前要善用论坛搜索功能,那里可能会有你要找的答案或者已经有人发布过相同内容了,请勿重复发帖。

独木君 发表于 2023-2-14 18:15
情人节快乐

免费评分

参与人数 1吾爱币 +2 热心值 +1 收起 理由
Light紫星 + 2 + 1 别人的情人节vs我的情人节

查看全部评分

LineCat 发表于 2023-2-16 11:57
大佬好,我也有一个cocos2d的游戏不知道是什么加密方法,以下是我目前所知的内容:
apk的assets文件夹中有三个文件夹,“32”“64”“release”,前两个存放了一个数据库文件,里面用navicat查看后是所有游戏资源的索引,有源位置和加密后的位置,“release”文件夹内就是加密后的全部资源。我起初也觉得这或许是xxtea,但是一直没有什么进展。加密的资源中有许多是明文,比如json、awb和plist,加密的文件似乎只有png和lua(luac)。这两个文件只有前七个字节是相同的,是这些“@Y#Q+G&”,我自己在这方面的经验实在是少之又少,想听听大佬的意见
侃遍天下无二人 发表于 2023-2-14 18:37
本帖最后由 侃遍天下无二人 于 2023-2-14 18:52 编辑

大老,情人节被群友白嫖是一种什么样的体验?
wasm2023 发表于 2023-2-14 18:59
厉害了,我的哥
8jUmJL 发表于 2023-2-14 20:11
厉害!!!!!
daoxun 发表于 2023-2-14 20:18
厉害了 我的哥
taoxwl666 发表于 2023-2-14 21:24
原来如此,学到了
正己 发表于 2023-2-14 21:35
表哥带带
Pwaerm 发表于 2023-2-14 22:00
啊啊啊 高手  

佩服佩服佩服

takklong 发表于 2023-2-14 22:39
大佬牛逼
您需要登录后才可以回帖 登录 | 注册[Register]

本版积分规则 警告:本版块禁止灌水或回复与主题无关内容,违者重罚!

快速回复 收藏帖子 返回列表 搜索

RSS订阅|小黑屋|处罚记录|联系我们|吾爱破解 - LCG - LSG ( 京ICP备16042023号 | 京公网安备 11010502030087号 )

GMT+8, 2024-5-15 00:35

Powered by Discuz!

Copyright © 2001-2020, Tencent Cloud.

快速回复 返回顶部 返回列表