吾爱破解 - 52pojie.cn

 找回密码
 注册[Register]

QQ登录

只需一步,快速开始

查看: 4015|回复: 8
收起左侧

[Android 求助] lua文件解密算法

[复制链接]
梦影流离 发表于 2020-5-18 11:04
本帖最后由 梦影流离 于 2020-5-18 11:07 编辑

loadbuffer解密算法用IDA的f5如下:

[C++] 纯文本查看 复制代码
int __fastcall luaL_loadbufferx(int a1, int a2, size_t size, int a4, int a5)
{
  int v5; // r10
  size_t v6; // r4
  unsigned __int8 *v7; // r6
  int v8; // r9
  int v9; // r8
  int v10; // r0
  _BYTE *v11; // r0
  int v12; // r1
  signed int v13; // r2
  int *v14; // r0
  __int64 v15; // r4
  size_t v16; // r11
  int v17; // r9
  unsigned int v18; // r0
  unsigned __int8 v19; // r0
  int v20; // r0
  uInt v21; // r0
  int v22; // r1
  int v23; // r2
  uInt v24; // r0
  signed int v25; // r9
  bool v26; // zf
  uInt v27; // r9
  bool v28; // zf
  char v29; // r1
  int v30; // r2
  int v31; // r6
  int v32; // r4
  __int64 v33; // r0
  bool v34; // zf
  int *v36; // [sp+8h] [bp-2080h]
  int v37; // [sp+Ch] [bp-207Ch]
  int v38; // [sp+10h] [bp-2078h]
  _BYTE *v39; // [sp+14h] [bp-2074h]
  size_t v40; // [sp+18h] [bp-2070h]
  int *v41; // [sp+1Ch] [bp-206Ch]
  int v42; // [sp+20h] [bp-2068h]
  int v43; // [sp+24h] [bp-2064h]
  int v44; // [sp+28h] [bp-2060h]
  int v45; // [sp+2Ch] [bp-205Ch]
  z_stream strm; // [sp+202Ch] [bp-5Ch]

  v5 = a1;
  v6 = size;
  v7 = (unsigned __int8 *)a2;
  v8 = a5;
  v9 = a4;
  v39 = (_BYTE *)a2;
  v40 = size;
  v10 = *(unsigned __int8 *)a2;
  if ( v10 == 61 )
  {
    if ( (signed int)(3 * ((size + 3) >> 2)) <= 256 )
      v14 = (int *)&v41;
    else
      v14 = (int *)j_lua_newuserdata(v5);
    v36 = v14;
    if ( !v6 )
    {
      v37 = 0;
      goto LABEL_49;
    }
    v16 = 0;
    v37 = 0;
    while ( 1 )
    {
      v17 = 0;
      v38 = 0;
      do
      {
        while ( 1 )
        {
          if ( v16 >= v6 )
            ((void (__fastcall *)(int, const char *))j_luaL_error)(v5, "Invalid base64 text");
          if ( v16 )
          {
            v18 = v7[v16];
            if ( v18 < 0x2B || (v19 = v18 - 43, v19 >= 0x50u) )
            {
              *((_DWORD *)&strm.next_in + v17) = -1;
              goto LABEL_24;
            }
          }
          else
          {
            v19 = 29;
          }
          v20 = dword_318D8[v19];
          *((_DWORD *)&strm.next_in + v17) = v20;
          if ( v20 != -1 )
            break;
LABEL_24:
          ++v16;
        }
        if ( v20 == -2 )
          ++v38;
        ++v17;
        ++v16;
      }
      while ( v17 != 4 );
      switch ( v38 )
      {
        case 2:
          v27 = strm.avail_in;
          v28 = strm.next_out == (Bytef *)-2;
          if ( strm.next_out == (Bytef *)-2 )
            v28 = strm.total_in == -2;
          if ( !v28 || strm.avail_in & 0xF )
            ((void (__fastcall *)(int, const char *))j_luaL_error)(v5, "Invalid base64 text");
          *((_BYTE *)v36 + v37++) = 4 * LOBYTE(strm.next_in) | (v27 >> 4);
          break;
        case 1:
          v25 = strm.total_in;
          v26 = strm.next_out == (Bytef *)-2;
          if ( strm.next_out == (Bytef *)-2 )
            v26 = (strm.total_in & 3) == 0;
          if ( !v26 )
            ((void (__fastcall *)(int, const char *))j_luaL_error)(v5, "Invalid base64 text");
          v24 = ((_DWORD)strm.next_in << 10) | (v25 >> 2) | 16 * strm.avail_in;
          *((_BYTE *)v36 + v37) = BYTE1(v24);
          v22 = (int)v36 + v37;
          v23 = v37 + 2;
LABEL_37:
          *(_BYTE *)(v22 + 1) = v24;
          v37 = v23;
          break;
        case 0:
          v21 = (strm.avail_in << 12) | ((_DWORD)strm.next_in << 18) | (strm.total_in << 6) | (_DWORD)strm.next_out;
          *((_BYTE *)v36 + v37) = BYTE2(v21);
          v22 = (int)v36 + v37;
          v23 = v37 + 3;
          *((_BYTE *)v36 + v37 + 2) = v21;
          v24 = v21 >> 8;
          goto LABEL_37;
        default:
          ((void (__fastcall *)(int, const char *))j_luaL_error)(v5, "Invalid base64 text");
          break;
      }
      if ( v16 >= v6 )
      {
LABEL_49:
        HIDWORD(v15) = v37;
        v7 = (unsigned __int8 *)j_lua_pushlstring(v5, v36, v37);
        j_lua_settop(v5, -2);
        v10 = *v7;
        v8 = a5;
        goto LABEL_50;
      }
    }
  }
  if ( v10 == 27 )
  {
    if ( *(_BYTE *)(a2 + 1) != 76 )
    {
      v11 = malloc(size);
      if ( v6 )
      {
        *v11 = 27;
        if ( v6 != 1 )
        {
          v12 = 0;
          v13 = 1;
          do
          {
            v12 += v6;
            v11[v13] = (v12
                      + ((unsigned int)(((unsigned __int64)(-2139062143LL * v12) >> 32) + v12) >> 7)
                      + ((signed int)(((unsigned __int64)(-2139062143LL * v12) >> 32) + v12) < 0)) ^ v7[v13];
            ++v13;
          }
          while ( v6 != v13 );
        }
      }
      v39 = v11;
    }
  }
  else
  {
    HIDWORD(v15) = size;
LABEL_50:
    if ( v10 == 28 )
    {
      LODWORD(v15) = malloc(HIDWORD(v15));
      if ( HIDWORD(v15) )
      {
        v29 = 0;
        v30 = 0;
        do
        {
          v29 ^= v7[v30];
          *(_BYTE *)(v15 + v30++) = v29;
        }
        while ( HIDWORD(v15) != v30 );
      }
      else
      {
        HIDWORD(v15) = 0;
      }
      *(_BYTE *)v15 = 120;
      strm.zalloc = 0;
      strm.zfree = 0;
      if ( inflateInit_(&strm, "1.2.3", 56) )
        ((void (__fastcall *)(int, const char *))j_luaL_error)(v5, "load error");
      *(_QWORD *)&strm.next_in = v15;
      v44 = v5;
      v43 = 0;
      v42 = 0x2000;
      v41 = &v45;
      do
      {
        strm.next_out = (Bytef *)j_luaL_prepbuffsize(&v41, 0x2000);
        strm.avail_out = 0x2000;
        v31 = inflate(&strm, 4);
        v32 = v31 + 5;
        if ( (unsigned int)(v31 + 5) > 6 || !((1 << v32) & 0x61) )
          j_luaL_error(v5, "load error %s");
        v43 += 0x2000 - strm.avail_out;
      }
      while ( !strm.avail_out );
      *(_BYTE *)v41 = 28;
      LODWORD(v33) = j_luaL_resultBuffer(&v41);
      HIDWORD(v33) = strm.total_out;
      v34 = v31 == 1;
      *(_QWORD *)&v39 = v33;
      if ( v31 != 1 )
        v34 = v32 == 0;
      if ( v34 )
        inflateEnd(&strm);
      else
        j_luaL_error(v5, "load error %s", strm.msg);
      v8 = a5;
    }
  }
  return j_lua_load(v5, sub_EB76, &v39, v9, v8);
}


一个加密的lua文件:
链接:https://pan.baidu.com/s/1UzbJ8eiD6AShcieO_Nevaw
提取码:cpi9

LABEL_50前的解密应该是解出来了,代码如下:
[Asm] 纯文本查看 复制代码
UINT32 dword_318D8[80] = { 0x3E, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0x3F, 0x34 ,0x35, 0x36, 0x37, 0x38, 0x39, 0x3A, 0x3B, 0x3C, 0x3D ,0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFE, 0xFFFFFFFF ,0xFFFFFFFF, 0xFFFFFFFF, 0, 1, 2, 3, 4, 5, 6, 7, 8 ,9, 0xA, 0xB, 0xC, 0xD, 0xE, 0xF, 0x10, 0x11, 0x12 ,0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0xFFFFFFFF ,0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF ,0x1A, 0x1B, 0x1C, 0x1D, 0x1E, 0x1F, 0x20, 0x21, 0x22 ,0x23, 0x24, 0x25, 0x26, 0x27, 0x28, 0x29, 0x2A, 0x2B ,0x2C, 0x2D, 0x2E, 0x2F, 0x30, 0x31, 0x32, 0x33 };
        z_stream strm;
        int v37 = 0;

        v14 = (int *)&v41;
        //v36 = v14;
        v10 = *(unsigned __int8 *)((int)buf);
        if (v10 == 61)
        {
                while (1)
                {
                        v38 = 0;
                        v17 = 0;
                        do
                        {
                                while (1)
                                {
                                        if (v16 >= s)
                                        {
                                                printf("Invalid base64 text1!\n");
                                        }
                                        if (v16)
                                        {
                                                v18 = buf1[v16];
                                                if (v18 < 0x2B || (v19 = v18 - 43, v19 >= (unsigned int)0x50))
                                                {
                                                        *((UINT32 *)&strm.next_in + v17) = -1;
                                                        goto LABEL_24;
                                                }
                                        }
                                        else
                                        {
                                                v19 = 29;
                                        }
                                        v20 = dword_318D8[v19];
                                        *((UINT32 *)&strm.next_in + v17) = v20;
                                        if (v20 != -1)
                                        {
                                                break;
                                        }
                                LABEL_24:
                                        ++v16;
                                }
                                if (v20 == -2)
                                        ++v38;
                                ++v17;
                                ++v16;
                        } while (v17 != 4);
                        switch (v38)
                        {
                        case 0:
                                v21 = (strm.avail_in << 12) | ((UINT32)strm.next_in << 18) | (strm.total_in << 6) | (UINT32)strm.next_out;
                                a = (v21 & 16711680) >> 16;
                                b = (v21 & 65280) >> 8;
                                c = v21 & 255;
                                buf1[kkk] = a;
                                buf1[kkk + 1] = b;
                                buf1[kkk + 2] = c;
                                kkk = kkk + 3;
                                break;
                        default:
                                printf("Invalid base64 text4!\n");
                                break;
                        }
                        if (v16 >= v6)
                        {
                                goto LABEL_50;
                        }
                }
        }

LABEL_50前的解密结果存放到了buf1里,但是LABEL_50后的那段判断首字节为28进行的操作我直接复制f5反编译出来的进行解密,解出来的有问题,求大佬看看
LABEL_50前解密后的文件如下:
链接:https://pan.baidu.com/s/1JQMIHy0PIVw5nWLS_3cVgg
提取码:vzjr

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

oranges 发表于 2020-6-5 02:29
我也在看这个来着,lable50以后看着像是zlib,希望能同楼主一起研究
 楼主| 梦影流离 发表于 2020-6-6 15:34
oranges 发表于 2020-6-5 02:29
我也在看这个来着,lable50以后看着像是zlib,希望能同楼主一起研究

label50后的zlib我试了解密,但是解出来的有问题,然后我用动态调试的方式在内存里看到了解密后的文件内容,建议用ida动态调试,下断点直接看
oranges 发表于 2020-6-8 01:55
我自己也用ida动态调试看了,跟到后面的话,lua的文件头已经出现了,但感觉后面的内容不对劲,dump下来用unluac解不了,我真的服了
 楼主| 梦影流离 发表于 2020-6-8 17:21
oranges 发表于 2020-6-8 01:55
我自己也用ida动态调试看了,跟到后面的话,lua的文件头已经出现了,但感觉后面的内容不对劲,dump下来用un ...

我也发现了,那个luas没一点用,而且看下面的内容一点都不像是luac文件格式的东西,因为luac里的也应该能看到正常字符串那些,我猜测他用的可能不是正常的lua引擎,或者还有其他的加密???
oranges 发表于 2020-6-10 15:11
本帖最后由 oranges 于 2020-6-10 15:12 编辑

也许吧,听说有人用read函数进行dump,但是没有长度,因为这个函数在更底层,或许已经解密你可以试试。
 楼主| 梦影流离 发表于 2020-6-12 15:24
oranges 发表于 2020-6-10 15:11
也许吧,听说有人用read函数进行dump,但是没有长度,因为这个函数在更底层,或许已经解密你可以试试。

get,找机会试试
Daisy。。 发表于 2020-7-21 23:12
oranges 发表于 2020-6-8 01:55
我自己也用ida动态调试看了,跟到后面的话,lua的文件头已经出现了,但感觉后面的内容不对劲,dump下来用un ...

文件发出来我看看
Light紫星 发表于 2020-7-31 22:55
老哥的z_stream从哪里拿的,我用devcpp好像不行,导入zlib包也提示找不到
您需要登录后才可以回帖 登录 | 注册[Register]

本版积分规则

返回列表

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

GMT+8, 2024-12-23 17:08

Powered by Discuz!

Copyright © 2001-2020, Tencent Cloud.

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