近日,研究人员观察到 Redline Stealer 木马的新变种,开始利用 Lua 字节码逃避检测。
遥测分布
根据遥测数据,Redline Stealer 木马已经日渐流行,覆盖北美洲、南美洲、欧洲和亚洲甚至大洋洲。
感染链
感染链
微软官方账户的 vcpky 仓库被攻击者滥用部署了恶意文件,恶意 URL 为 https[:]//github[.]com/microsoft/vcpkg/files/14125503/Cheat.Lab.2.7.2.zip
。
该压缩文件中包含 MSI 安装程序:
MSI 文件
MSI 安装程序包含两个 PE 文件和一个文本文件。
文件内容
Compiler.exe 和 lua51.dll 都是 Lua 开发的二进制文件,攻击者会稍微定制化修改这些文件。而 readme.txt 其中包含 Lua 字节码,配合使用可以在运行时编译和执行。
Lua JIT 是 Lua 编程语言的即时编译器(JIT):
字节码
通常来说,1B 4C 4A 02
也就表示着是 Lua 5.1 字节码。这种方式可以将恶意攻击进行混淆,避免安全软件检测到好识别的脚本文件(如 wscript、JScript 或 PowerShell 脚本),进一步增强了攻击的规避能力。
用户点击执行 MSI 安装程序后,就会显示一个用户界面:
安装界面
安装过程中会提示用户将恶意软件安装到其他朋友的计算机上,就可以获得完整的应用程序。
提示信息
在安装过程中,可以发现有三个文件被写入 C:\program Files\Cheat Lab Inc\ Cheat Lab\
中。
写入文件
后续这三个文件会被移动到指定路径中:
特定路径
可以看到,compiler.exe 由 msiexec.exe 执行,并以 readme.txt 作为参数。而 lua51.dll 会被加载到 compiler.exe 中,lua51.dll 是 compiler.exe 运行需要的 DLL,攻击者将该 DLL 文件与程序文件放在一起。
操作行为
安装过程中,msiexec.exe 会创建一个计划任务来执行 compiler.exe,并将 readme.txt 作为参数。
计划任务
除了上述持久化技术外,恶意软件还使用另一种备用方式确保恶意软件能够得到执行。恶意软件会将前述三个文件复制到另一个文件夹中,路径非常长而且很随机。
文件移动
请注意,compiler.exe 已经改名为 NzUW.exe。随后在 C:\Windows\Setup\Scripts\ 中释放文件 ErrorHandler.cmd。文件的内容如下所示,攻击者以新名称 NzUw.exe 执行 compiler.exe,并以 Lua 字节码作为参数。
执行命令
执行 ErrorHandler.cmd 会调用 system32 文件夹中的恶意文件。
进程创建
为此还会创建另一个计划任务,程序不带任何参数启动 C:\Windows\system32\oobe\Setup.exe。
计划任务
事实证明,如果将 Payload 放在 c:\WINDOWS\Setup\Scripts\ErrorHandler.cmd 中,则 c:\WINDOWS\system32\oobe\Setup.exe 将在发生错误时加载它。
官方文档
c:\WINDOWS\system32\oobe\Setup.exe 的执行需要参数,如果不提供参数就会触发错误。从而执行 ErrorHandler.cmd 调用 compiler.exe 加载恶意 Lua 代码。
进程树
可以确认 c:\WINDOWS\system32\oobe\Setup.exe 以 ErrorHandler.cmd 脚本作为参数启动 cmd.exe,该脚本运行 NzUw.exe。
继续通过 API 查看所在 IP 的信息:
IP 信息
IP 相关信息会以 JSON 形式写入 inetCache 文件夹中。
写入文件
文件内容如下所示:
文件内容
C&C 通信
恶意软件的 C&C 通信使用 HTTP 协议:
C&C 流量
C&C 服务器响应了名为 OTMsOTYs 的任务 ID,包含在 base64 编码的字符串中:
响应信息
响应信息
通过 /loader/screen 的 HTTP PUT 请求发送到攻击者控制的服务器。服务器 IP 地址归属于 Redline,许多引擎都将其标记为恶意。
IP 地址
进一步查看,该数据包传输的是名为 Screen.bmp 的图片文件。值得注意的是,请求使用的 User-Agent 为 Winter。
PUT 请求
图片如下所示,为回传的受害者的屏幕截图。
屏幕截图
字节码
字节码的分析很有挑战,使用很多开源的反编译器可以得到不同的 Lua 脚本。
反编译
调试过程如下所示:
调试信息
通过将数据值传递给两个函数来填充 var_0_19,调试时可以发现 base64 编码的值存储在 var_0_19 中。这些 base64 字符串多是编码数据,而不是字符串。
函数传递
var_0_19 中的所有数据都会被分配给 var_0_26:
调试信息
同样的方式填充第二个 table(var_0_20),其中包含编码数据的替换密钥:
解密代码
解密代码如上所示,逐个元素迭代 var_0_26 并进行解密。循环很长并且包含很多垃圾代码,循环结束时将解密的值还给 var_0_26。
恶意代码
调试信息
断点设置在 1174 行并监测 var_0_26:
调试信息
当多次命中断点时,监视窗口可以看到更多加密数据:
调试信息
解密的字符串例如 var_0_26 中的 Tamper Detected!
。
加载 LuaJIT 字节码
在加载 LuaJIT 字节码前,会创建一个新状态。每个 Lua 状态都维护其全局环境、堆栈与加载的库,从而在不同的 Lua 代码间提供隔离。
恶意代码
恶意软件使用 Lua_openlib 函数加载库,并加载 debug、io、math、ffi 和其他支持的库。
恶意代码
使用 lua51 的导出函数 luaL_loadfile 加载 LuaJIT 字节码,会使用 fread 函数读取 JIT 字节码,然后使用 memmove 函数移动到分配的内存。
调试信息
调试信息
文件中的字节码使用 memmove 函数将字节码从一个偏移量更改为另一个偏移量。使用 memmove 函数复制 JIT 字节码中 200 字节定长数据。
调试信息
获取 table 的值并使用浮点算术或异或指令对其进行处理:
调试信息
使用 memmove 函数将字节从源缓冲区移动到目标缓冲区。
调试信息
进一步分析后,该脚本中将使用变量和参数进行定义:
调试信息
API 会使用 ffi 从 Lua 代码中直接访问 Windows API,定义 API 函数如下所示:
函数信息
它会使用 CreateMutexExW 创建名为 Winter750 的互斥量:
调试信息
也会使用 ntdll.dll 中的 LdrLoaddll 函数在运行时加载 dll,使用 LuaJIT ffi 调用该函数。
调试信息
使用 ffi 使用 RegQueryValueEx 函数从 Windows 注册表检索 MachineGuid 项。使用 RegOpenKeyExA 打开注册表项SOFTWARE\Microsoft\Cryptography 并从打开的注册表项查询 MachineGuid 的值。
调试信息
使用 ffi 的 GetComputerNameA 函数从 Windows 注册表中检索 ComputerName。
调试信息
收集以下信息并将其发送到 C&C 服务器:
回传信息
回传信息
微软已经从官方存储库中删除了存在问题的文件。
IOC
5e37b3289054d5e774c02a6ec4915a60156d715f3a02aaceb7256cc3ebdc6610 873aa2e88dbc2efa089e6efd1c8a5370e04c9f5749d7631f2912bcb640439997 751f97824cd211ae710655e60a26885cd79974f0f0a5e4e582e3b635492b4cad dfbf23697cfd9d35f263af7a455351480920a95bfc642f3254ee8452ce20655a 213[.]248[.]43[.]58 hxxps://github.com/microsoft/STL/files/14432565/Cheater.Pro.1.6.0.zip https[:]//github[.]com/microsoft/vcpkg/files/14125503/Cheat.Lab.2.7.2.zip