某游戏的另类lua加密方式的解密

查看 99|回复 9
作者:Light紫星   
某游戏的另类lua加密方式的解密
今日下午,群中一个小伙伴突然发了一个data.lua文件,并且问是什么编码,我下载一看,内容是加密的,但是有个头“FFSZ”,当时心想,这不是xxtea吗,有手就行啊,然后让小伙伴发来apk给我,遂有此贴。
目标apk包名:Y29tLmZ1bnBsdXMuZmFtaWx5ZmFybWNoaW5hLmh1YXdlaQ==
下载打开一看,是个农场类游戏,然后看一下lib目录,32和64位的都有,就拿arm64-v8a目录下手吧,里面就三个so文件,有一个最大的30多m,叫libgame.so,ok,不用想就知道今天的目标就是它了。
拖入ida,等加载(大文件ida加载是真的慢啊,不知道各位有没有加速的方式),然后搜索xxtea,ok有xxtea_decrypt字样,点进去,看一下参数,然后直接hook,hook代码如下:
[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 (47.05 KB, 下载次数: 0)
下载附件
2023-2-14 18:10 上传

如图,所有文件全部解密失败,此时我眉头一皱,心想事情并不简单,难道是key错了,还是根本就不是xxtea的加密方式,此时,回到ida,从xxtea_decrypt往上找


image.png (132.31 KB, 下载次数: 0)
下载附件
2023-2-14 18:11 上传

好的,我们找到了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::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::length(".lua");
  v7 = &v4[v5];
  v8 = std::__find_end(
         v4,
         v7,
         ".lua",
         &aLua[v6],
         std::char_traits::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::assign(v139, v134);
      *((_QWORD *)&v138 + 1) = 0LL;
    }
    else
    {
      std::char_traits::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::length(".");
    if ( !v12 )
      break;
    if ( !v11 )
      break;
    v13 = &v10[v11];
    first_of = std::__find_first_of_ce(
                 v10,
                 v13,
                 ".",
                 &aFerrorInFuncti_1677[v12 + 36],
                 std::char_traits::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::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::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),
                    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::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),
                    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::length("/");
    if ( v67 >= v68 )
    {
      if ( !v68
        || (v81 = &v66[v67],
            v82 = std::__search(
                    v66,
                    v81,
                    "/",
                    &asc_1A19AA4[v68 + 1],
                    std::char_traits::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::length("common/");
        if ( v84 ::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::length("game_loading/");
          if ( v87 ::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::length("version_logo");
            if ( v90 ::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::length("fast_switch/");
              if ( v93 ::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::length("ab_test/");
                if ( v96 ::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::length("novice_guide/");
                  if ( v99 ::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::length("neighbor/");
                    if ( v102 ::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::length("spine-lua/");
                      if ( v105 ::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 (107.93 KB, 下载次数: 0)
下载附件
2023-2-14 18:12 上传

好了,至此此文件的解密完成,总结一下,平常我们遇到的都是xxtea的lua加密,但是这个lua的so里面虽然也有xxtea,但是用了des加密并且进行了压缩,所以遇到lua的游戏的时候不要慌,冷静分析,也是可以搞定的 最后附一下常见各种压缩算法的头特征:gzip 1f 8b 08lzma 6c 00zlib 78 9c

宋体, 文件

wasm2023   

情人节快乐
8jUmJL   

大老,情人节被群友白嫖是一种什么样的体验?
daoxun   

厉害了,我的哥
taoxwl666   

厉害!!!!!
Pwaerm   

厉害了 我的哥
takklong   

原来如此,学到了
8jUmJL   

表哥带带
taoxwl666   

啊啊啊 高手  
佩服佩服佩服
Pwaerm   

大佬牛逼
您需要登录后才可以回帖 登录 | 立即注册