查看: 818|回复: 1
收起左侧

[原创分析] CT脚本解码 1x

[复制链接]
Raven95676
发表于 2024-12-30 21:02:52 | 显示全部楼层 |阅读模式
本帖最后由 Raven95676 于 2024-12-30 21:59 编辑

https://bbs.kafan.cn/thread-2277676-1-1.html继续讨论。

打开相关文件后发现其包含经过编码的Lua脚本内容。


脚本中的decodeFunction由Cheat Engine提供,用于加载经过encodeFunction编码的Lua函数。

由于Cheat Engine是开源项目,因此我们可以查看decodeFunction的具体实现。该函数位于LuaHandler.pas文件中:

  1. function lua_decodeFunction(L: Plua_State): integer; cdecl;
  2. var
  3.   ds: Tdecompressionstream;
  4.   s: TMemoryStream;

  5.   decompressed: TMemoryStream;
  6.   i: integer;

  7.   size: integer;
  8.   input, output: pchar;
  9. begin
  10.   result:=1;
  11.   if (lua_gettop(L)=1) and lua_isstring(L,1) then
  12.   begin
  13.     input:=lua.lua_tostring(L,1);

  14.     size:=(length(input) div 5)*4+(length(input) mod 5);
  15.     getmem(output, size*2);


  16.     size:=Base85ToBin(input, output);
  17.     lua_pushlstring(L, output, size);

  18.     s:=TMemoryStream.Create;
  19.     s.WriteBuffer(output^, size);
  20.     s.position:=0;
  21.     ds:=Tdecompressionstream.create(s);

  22.     decompressed:=TMemoryStream.create;
  23.     decompressed.CopyFrom(ds,0);

  24.     decompressed.position:=0;
  25.     lua_load(L, @lreader, decompressed,'cechunk', 'b');


  26.     freeandnil(decompressed);
  27.     freeandnil(ds);
  28.     freeandnil(s);
  29.     FreeMemAndNil(output);

  30.     result:=1;
  31.   end;

  32. end;
复制代码


上述代码将Base85编码字符串解码为二进制数据,并在解压缩后加载。

接下来我们需要分析Base85ToBin的实现。其完整代码请前往GitHub查看。

该函数加载了自定义的Base85字符集,每5个Base85字符将被转换为4个字节的二进制数据。如果输入的Base85字符串长度不是5的倍数,则会进行填充处理。

为了方便,我们直接使用现有的CEFunctionDecoder。得到的lua字节码使用luadec进行处理,得到1.lua


推测l_0_0为自定义解密算法,l_0_1为密文,l_0_2为解密相关参数。
解码l_0_0,得到2.lua

传入参数为l_0_0与l_0_1。我们先来看看l_0_14函数到底干了什么。可见其内容是由l_0_2经过变换后调用decodeFunction得出的,其内容如下:
  1. while l_0_1 ~= 0 do
  2.   upval_0.z = l_0_0
  3.   l_0_0 = l_0_1
  4.   l_0_1 = upval_0.z % l_0_1
  5. end
  6. return l_0_0
复制代码

其作用为求最大公约数。

结合1.lua的内容,我们使用Python复现其解密算法为:
  1. import math

  2. def l_0_14(a, b):
  3.     while b:
  4.         a, b = b, a % b
  5.     return a

  6. l_0_0 = 数据
  7. l_0_1 = 13

  8. l_0_15 = len(l_0_0)
  9. l_0_1 = int(l_0_1 / l_0_14(l_0_1, l_0_15) % l_0_15)
  10. l_0_16 = (math.floor(int(l_0_15 / 2)) + l_0_1) % l_0_15
  11. l_0_17 = {}
  12. l_0_18 = ""

  13. for l_0_24 in range(1, l_0_15 + 1):
  14.     l_0_25 = 1 + (l_0_24 * l_0_1 + l_0_16) % l_0_15
  15.     l_0_37 = ord(l_0_0[l_0_24 - 1])
  16.     l_0_17[l_0_25] = l_0_37
  17.    
  18.     if 33 <= l_0_37 <= 126:
  19.         l_0_37 = l_0_17[l_0_25]
  20.         l_0_37 = l_0_37 - 33
  21.         l_0_37 = l_0_37 + l_0_1 * (l_0_24 % (126 + 1 - 33))
  22.         l_0_37 = l_0_37 - l_0_24
  23.         l_0_37 = l_0_37 % (126 + 1 - 33)
  24.         l_0_37 = l_0_37 + 33
  25.         l_0_17[l_0_25] = l_0_37

  26. for l_0_29 in range(1, l_0_15 + 1):
  27.     l_0_18 += chr(l_0_17[l_0_29])

  28. print(l_0_18)
复制代码

需要注意的是Lua的索引从1开始,而Python的索引从0开始。Python的除法默认会算出浮点数,故需要显式转换。
最终,输出的内容通过CEFunctionDecoder处理后再反编译即可得到完整的Lua脚本3.lua:

本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有帐号?快速注册

x

评分

参与人数 8人气 +19 收起 理由
DisaPDB + 2
GDHJDSYDH + 3 神马都是浮云
ANY.LNK + 1 好好好!
落华无痕 + 3 原创内容
zhuzhu009 + 3 版区有你更精彩: )

查看全部评分

DisaPDB
发表于 2024-12-31 17:48:55 | 显示全部楼层
本帖最后由 DisaPDB 于 2024-12-31 17:50 编辑

就喜欢看这种ai风(严谨の书面表达+逻辑清晰)的分析报告
您需要登录后才可以回帖 登录 | 快速注册

本版积分规则

手机版|杀毒软件|软件论坛| 卡饭论坛

Copyright © KaFan  KaFan.cn All Rights Reserved.

Powered by Discuz! X3.4( 沪ICP备2020031077号-2 ) GMT+8, 2025-2-6 04:39 , Processed in 0.131116 second(s), 18 queries .

卡饭网所发布的一切软件、样本、工具、文章等仅限用于学习和研究,不得将上述内容用于商业或者其他非法用途,否则产生的一切后果自负,本站信息来自网络,版权争议问题与本站无关,您必须在下载后的24小时之内从您的电脑中彻底删除上述信息,如有问题请通过邮件与我们联系。

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