【病毒分析】888勒索家族再出手!幕后加密器深度剖析

时间: 2025-05-14 16:21:17 浏览量:14

1.背景

  2025年3月,Solar应急响应团队成功捕获了888勒索家族的加密器样本。实际上,我们最早接触该家族是在2024年10月,彼时888家族活跃度极高,频繁针对医疗行业发起攻击,受害对象以药店、医院等医疗机构为主。

  在攻击方式上,888家族主要通过MSSQL数据库弱口令爆破实现初始入侵,成功获取权限后,将自制的加密器投放至服务器路径中的Music\misc目录,以隐藏其恶意文件,随后迅速对服务器内的重要数据实施加密勒索。

1.1 加密器特征

  该勒索家族较为狡猾,通过ping空地址绕过本地安全机制监测最终实现自删除。

  加密器启动后运行的命令行指令

  在成功加密后,桌面上会生成名为“!RESTORE_FILES!.txt”的勒索信,要求受害者将信内ID发到下方的邮箱中,以取得初步联系获得赎金报价。

  勒索信

  被加密后的目录

1.2 攻击链路与IOC

  888勒索家族惯用的手段是通过数据库对外暴露入口弱口令入侵数据库,并在数据执行提权操作,获取高权限账户或将木马加载到受害者设备,随后再进行加密器的加载运行。

## 1.3 IOC

详细信息类型关联文件/主机/备注
d15ab1e89fc94d9b4dff7cb5b8d392eca74a0a65Sha1netpass64.exe
7ab128659ad586761ea68009d59a1ccf1547a039Sha1netpass64.exe
8b0e4650f1a7080b78066a61152e571ca8b6816bSha1svchost.exe
86803bbc26ed08e863ab17c765577a74637afaa7Sha1svchost.exe
a0bdfac3ce1880b32ff9b696458327ce352e3b1dSha1processhacker.exe
729fd507a1118b2d9008a097b7330c52760ceb9eSha1processhacker.exe
31.43.176.57IP波兰
36.152.235.38IP中国 江苏省 徐州市
185.132.176.32IP荷兰 南荷兰省 纳尔德韦克
58.211.56.222IP中国 江苏省 苏州市
nemesis@888recover.4wrd.ccMail_addr勒索邮箱
nemesissupport@firemail.ccMail_addr勒索邮箱
!RESTORE_FILES!.txtFile勒索信文件名
.888Suffix勒索后缀名

2.恶意文件基础信息

2.1 恶意文件基本信息

文件名svchost.exe
编译器Microsoft Visual C/C++(19.36.33923)C++
大小2.43 MB
操作系统Windows(Vista)AMD64, 64位, GUI
模式64 位
类型EXEC
字节序LE
MD55315bdbf85ad2b3bb13ae8ee62489f7f
SHA18b0e4650f1a7080b78066a61152e571ca8b6816b
SHA256dee0fde2d096c79e138890f958b9440e87cce38504b654a97de50bb7969a9c98

2.2 勒索信

+----------------------------------------------------------------------------+
|   !!!ALL YOUR FILES ARE ENCRYPTED, AS A RESULT OF A BREACH IN SECURITY!!!  |
+----------------------------------------------------------------------------+

No worries - you can get them back!
It's impossible to decrypt without contacting us.

+----------------------------------------------------------------------------+
|   !!!DON'T TRY TO CHANGE ENCRYPTED FILES!!!                                |
|   !!!DON'T RENAME ENCRYPTED FILES!!!                                       |
|   !!!DON'T USE ADDITIONAL RECOVERY SOFTWARE!!!                             |
|   !!!IT WILL MAKE THEM IMPOSSIBLE TO DECRYPT!!!                            |
+----------------------------------------------------------------------------+

How to return all your data back in safe:

1. Copy and sent us your KEY.
2. We can decrypt 2 small files, no databases (.jpg, .txt, .doc, ets.. (up to 3mb)) as your warranty.
3. After payment, you will receive a special software for decryption.

-----------------------------------------------------------------------------------------------------------------
KEY: 
-----------------------------------------------------------------------------------------------------------------

EMAILS:
nemesis@888recover.4wrd.cc
nemesissupport@firemail.cc

Zero cheats, all integrity.

3.加密后文件分析

3.1威胁分析

病毒家族888
首次出现时间/捕获分析时间2024/10/19 || 2025/03/27
威胁类型勒索软件,加密病毒
加密文件扩展名.888
勒索信文件名!RESTORE_FILES!.txt
有无免费解密器?
联系邮箱nemesis@888recover.4wrd.cc
感染症状无法打开存储在计算机上的文件,以前功能的文件现在具有不同的扩展名(例如,solar.docx.888)。桌面上会显示一条勒索要求消息。网络犯罪分子要求支付赎金(通常以比特币)来解锁您的文件。
感染方式受感染的电子邮件附件(宏)、恶意广告、漏洞利用、恶意链接
受灾影响所有文件都经过加密,如果不支付赎金就无法打开。其他密码窃取木马和恶意软件感染可以与勒索软件感染一起安装。

3.2 加密的测试文件

文件名

  sierting.txt

具体内容:

加密文件名特征:

  加密文件名 = 原始文件名+888 ,例如:sierting.txt.888

加密文件数据特征:

加密算法:

AES密钥生成:

  通过随机生成的两个guid来生成key和iv

程序执行流程:

4.逆向分析

4.1加密器逆向分析

勒索信密钥初始化

  初始化了几个常量如下

5FC92AFFB28BE14BD3A8B1843E9F8E8BB394A50F7E3E599D0316E97D8B98BEDF
FC5A714EFBF1AE255D0071443A0D08FE70B2DE19F1F288115EDF3E6FA5263DBF
.888
AC11CD9E6DA7311B9804D8EB421DB7EFEC8ABB7EACC999CA64F3C7A99686E826
!RESTORE_FILES!.txt
9139F9BF04FB5ED3A8DF78E10110710C4134C2A37CBE912B6428B7FE19D22689
06FEECBAD923B75FA5B35A7A949C479AA67D838884BDA14963DC1903ACCD3E37
171C88018769B3D2B33D7065A162D3731ECEFB18A54054075A16614A468925B4
24AD21C4C3E2A430DF77EC0A190E2021976059732C696FADC61F62490E5EC202
B502B9C8546259BC27DAA82287C4ADA92A16B7A81665FAF9EFD20A4C3FD6233A
A9C3ED26735E74CC8939D5D7875BC9AEC04E5A91607BE48E6897CB7A96E1170D
45AB92864D45D54123C980CD245B31ED37A6EDDDF952A342CC5D9CB777B3942E

  查找同路径下是否存在p.txt文件,如果有,则读取,并将读取到的内容进行sha256哈希计算之后再进行base64编码,然后再将此文件移动到C:\Windows\Temp\!wwwGdddf#.txt

__int64 __fastcall sub_7FF643B1AF70(__int64 a1, __int64 a2)
{
  __int64 v4; // rax
  __int64 v5; // rax
  __int64 v6; // rax
  __int64 v7; // rax

if ( !(unsignedint)S_P_CoreLib_System_IO_File__Exists(a1) )
  {
    if ( (unsignedint)S_P_CoreLib_System_IO_File__Exists(a2) )
    {
      if ( *(&qword_7FF643BB5520 - 1) )
        sub_7FF643A11806();
      v6 = read_file(a2, *(_QWORD *)(qword_7FF643CDBB28 + 8));
      v7 = sha256_base64(v6);
      if ( v7 )
      {
        if ( *(_DWORD *)(v7 + 8) )
          return v7;
      }
    }
    return0i64;
  }
if ( (unsignedint)S_P_CoreLib_System_IO_File__Exists(a2) )
    S_P_CoreLib_System_IO_File__Delete(a2);
  move_file(a1, a2, 0);
if ( *(&qword_7FF643BB5520 - 1) )
    sub_7FF643A11806();
  v4 = read_file(a2, *(_QWORD *)(qword_7FF643CDBB28 + 8));
  v5 = sha256_base64(v4);
if ( !v5 || !*(_DWORD *)(v5 + 8) )
    return0i64;
return v5;
}

  用于测试的p.txt的内容为sdjfpisjpdfajspfas[pfpasjf计算后的结果为Yatspzm25UgfTLY0KDmz8Gi6SZVhA1tIk4HTqwpOBcs=

  获取mac地址信息并转换为hex字符串

char **sub_7FF643B1C6C0()
{
char **v0; // rbx
  __int64 NetworkInterfaces; // rsi
int v2; // edi
int v3; // ebp
  __int64 *v4; // r14
  __int64 v5; // r15
  __int64 v6; // rcx
  __int64 v7; // rax
int v8; // edx
  __int64 v9; // rax
  __int64 v11; // [rsp+28h] [rbp-40h] BYREF
  __int64 v12; // [rsp+30h] [rbp-38h]

  v11 = 0i64;
  v12 = 0i64;
  v0 = &off_7FF643B92330;
  NetworkInterfaces = System_Net_NetworkInformation_System_Net_NetworkInformation_SystemNetworkInterface__GetNetworkInterfaces();
  v2 = 0;
  v3 = *(_DWORD *)(NetworkInterfaces + 8);
if ( v3 > 0 )
  {
    do
    {
      v4 = *(__int64 **)(NetworkInterfaces + 8i64 * (unsignedint)v2 + 16);
      v5 = *v4;
      if ( (*(unsignedint (__fastcall **)(__int64 *))(*v4 + 64))(v4) != 24
        && (*(unsignedint (__fastcall **)(__int64 *))(v5 + 48))(v4) == 1 )
      {
        v6 = *(_QWORD *)((*(__int64 (__fastcall **)(__int64 *))(v5 + 56))(v4) + 8);
        if ( v6 )
        {
          v7 = v6 + 16;
          v8 = *(_DWORD *)(v6 + 8);
        }
        else
        {
          v7 = 0i64;
          v8 = 0;
        }
        v11 = v7;
        LODWORD(v12) = v8;
        v9 = S_P_CoreLib_System_Convert__ToHexString_1(&v11);
        v0 = (char **)String__Concat_5(v0, v9);
      }
      ++v2;
    }
    while ( v3 > v2 );
  }
return v0;
}

  获取计算机名称,截断字符串FC5A714EFBF1AE255D0071443A0D08FE70B2DE19F1F288115EDF3E6FA5263DBF的部分字节结果如下FC5A714EFBF1AE255D0071443A0D08FE,将其进行sha256计算之后再将刚刚获得的mac信息和计算机名称进行拼接,然后再计算sha256并编码为base64。最后得到如下结果 akflLG7b++2vAPZZP62WLtO5XDpblwfcnVbR+65Y1/U=

__int64 sub_7FF643B1C0E0()
{
  __int64 v0; // rbx
  __int64 v1; // rsi
  __int64 v2; // rax
  __int64 v3; // rax
  __int64 v4; // rax

  v0 = get_mac();
  v1 = get_computer_name();
if ( qword_7FF643BB56F0[-1] )
    sub_7FF643A11BA6();
  v2 = String__Substring_0(*(_QWORD *)(qword_7FF643CDBD68 + 16), 0i64, 32i64);
  v3 = sha256_base64_0(v2, 16);
  v4 = String__Concat_6(v0, v1, v3);
return sha256_base64_0(v4, 32);
}

  首先将常量字符串FC5A714EFBF1AE255D0071443A0D08FE70B2DE19F1F288115EDF3E6FA5263DBF按照12个字符的顺序截取,首先是开头部分的FC5A714EFBF1,然后是AE255D007144,以此类推。最后再截取出末尾的字符3DBF。

  接着再将前面计算得到的字符串akflLG7b++2vAPZZP62WLtO5XDpblwfcnVbR+65Y1/U=用同样的方式计算。

__int64 __fastcall key_init(__int64 a1, unsigned int a2)
{
  __int64 v4; // rdi
  __int64 v5; // rdx
int v6; // ebp
int v7; // r14d
char **v8; // rax
  __int64 v9; // rcx
  __int64 v10; // rdx

  v4 = RhpNewFast(&unk_7FF643BCDCA0);
  RhpAssignRefAVLocation((unsigned __int64 *)(v4 + 8), *(_QWORD *)(qword_7FF643CDBE80 + 8));
  v5 = 0i64;
  v6 = *(_DWORD *)(a1 + 8);
if ( v6 > 0 )
  {
    do
    {
      v7 = v5 + a2;
      if ( (int)(v5 + a2) > v6 )
      {
        v8 = String__Substring(a1, v5);
        ++*(_DWORD *)(v4 + 20);
        v9 = *(_QWORD *)(v4 + 8);
        v10 = *(unsignedint *)(v4 + 16);
        if ( *(_DWORD *)(v9 + 8) <= (unsignedint)v10 )
        {
LABEL_6:
          S_P_CoreLib_System_Collections_Generic_List_1_System___Canon___AddWithResize(v4, v8);
          goto LABEL_7;
        }
      }
      else
      {
        v8 = (char **)String__Substring_0(a1, v5, a2);
        ++*(_DWORD *)(v4 + 20);
        v9 = *(_QWORD *)(v4 + 8);
        v10 = *(unsignedint *)(v4 + 16);
        if ( *(_DWORD *)(v9 + 8) <= (unsignedint)v10 )
          goto LABEL_6;
      }
      *(_DWORD *)(v4 + 16) = v10 + 1;
      RhpAssignRefAVLocation((unsigned __int64 *)(v9 + 8 * v10 + 16), (unsigned __int64)v8);
LABEL_7:
      v5 = (unsignedint)v7;
    }
    while ( v6 > v7 );
  }
return v4;
}

  最后通过如下方式计算出勒索信中显示的key:++2vAPZZAE255D007144akflLG7bFC5A714EFBF1P62WLtO53A0D08FE70B2nVbR+65Y5EDF3E6FA526XDpblwfcDE19F1F288111/U=3DBF

def split_string_by_segments(input_str,segment_length):
    segments = []
    for i in range(0, len(input_str) - 4, segment_length):
        segment = input_str[i:i + segment_length]
        segments.append(segment)

    last_segment = input_str[-4:]
    segments.append(last_segment)

    return segments

str1 = "FC5A714EFBF1AE255D0071443A0D08FE70B2DE19F1F288115EDF3E6FA5263DBF"#常量字符串
result1 = split_string_by_segments(str1,12)
list1=[]
for i, seg in enumerate(result1):
    list1.append(seg)

str2 = "akflLG7b++2vAPZZP62WLtO5XDpblwfcnVbR+65Y1/U="#通过计算机信息计算出来的hash
result2 = split_string_by_segments(str2,8)
list2=[]
for i, seg in enumerate(result2):
    list2.append(seg)
print(list2[1]+list1[1]+list2[0]+list1[0]+list2[2]+list1[2]+list2[4]+list1[4]+list2[3]+list1[3]+list2[5]+list1[5])

  将通过mac和计算机名称计算得到的hash写入C:\Windows\Temp\!wwkdsfdsfewt.txt

__int64 __fastcall sub_7FF643AE6930(
        __int64 a1,
        const void *lpBuffer_1,
        DWORD nNumberOfBytesToWrite_1,
        DWORD *lpNumberOfBytesWritten_1,
        struct _OVERLAPPED *lpOverlapped)
{
void *hFile_1; // r14
unsignedint v9; // ebx
  DWORD LastError; // esi
  _BYTE v12[44]; // [rsp+28h] [rbp-A0h] BYREF
  LPDWORD lpNumberOfBytesWritten; // [rsp+54h] [rbp-74h]
  LPCVOID lpBuffer; // [rsp+5Ch] [rbp-6Ch]
  HANDLE hFile; // [rsp+64h] [rbp-64h]
  DWORD nNumberOfBytesToWrite; // [rsp+6Ch] [rbp-5Ch]
  DWORD *lpNumberOfBytesWritten_2; // [rsp+70h] [rbp-58h]
  __int128 v18; // [rsp+78h] [rbp-50h] BYREF

  v18 = 0i64;
  *(_QWORD *)&v18 = a1;
  S_P_CoreLib_System_Runtime_InteropServices_SafeHandle__DangerousAddRef(a1, (char *)&v18 + 8);
  lpNumberOfBytesWritten_2 = lpNumberOfBytesWritten_1;
  hFile_1 = *(void **)(v18 + 8);
  SetLastError(0);
  hFile = hFile_1;
  lpBuffer = lpBuffer_1;
  nNumberOfBytesToWrite = nNumberOfBytesToWrite_1;
  lpNumberOfBytesWritten = lpNumberOfBytesWritten_1;
  RhpPInvoke(v12);
  v9 = WriteFile(hFile, lpBuffer, nNumberOfBytesToWrite, lpNumberOfBytesWritten, lpOverlapped);
  RhpPInvokeReturn(v12);
  LastError = GetLastError();
  lpNumberOfBytesWritten_2 = 0i64;
if ( BYTE8(v18) )
    S_P_CoreLib_System_Runtime_InteropServices_SafeHandle__InternalRelease(v18, 0i64);
  *(_DWORD *)(_GetThreadStaticBase_S_P_CoreLib_Internal_Runtime_ThreadStatics_9() + 168) = LastError;
return v9;
}

sha256_base64函数

  对输入的字符串进行sha256哈希,然后根据输入的a2参数进行截断,最后将截断后的字符串进行base64编码

__int64 __fastcall sha256_base64_0(__int64 a1, unsigned int a2)
{
  __int64 Bytes; // rsi
  __int64 v5; // rdi
  __int64 v6; // rsi
  __int64 v7; // rdi
  __int64 v8; // rbx
  __int64 v10; // [rsp+20h] [rbp-28h]

if ( *(&qword_7FF643BB5520 - 1) )
    sub_7FF643A11806();
  Bytes = S_P_CoreLib_System_Text_UTF8Encoding_UTF8EncodingSealed__GetBytes(*(_QWORD *)(qword_7FF643CDBB28 + 8), a1);
  v5 = RhpNewFast(&unk_7FF643BC7D88);
  System_Security_Cryptography_System_Security_Cryptography_SHA256Managed___ctor(v5);
  v10 = v5;
  v6 = sub_7FF643AFB200(v5, Bytes);
  v7 = RhpNewArray(&unk_7FF643BFE7C0, (int)a2);
  S_P_CoreLib_System_Array__Copy_1(v6, v7, a2);
  v8 = str_to_base64(v7);
  unk_7FF643BB7AA0(v10);
return v8;
}

加密

  遍历文件,并排除以下目录

  对文件名进行判断

  如果包含以下文件名,就跳过

!RESTORE_FILES!.txt
svchost.exe
bootmgr
bootmgr.efi
bootmgr.efi.mui
bootmgr.exe
bootmgr.exe.mui
img___XXX.jpg

  接着判断后缀是否为.888,如果是,就跳过。

  接着对进行计算并得到一个常量。

if ( v17 > 1 )
  {
    do
    {
      if ( v15 )
      {
        v18 = (char *)v15 + 12;
        v19 = *((_DWORD *)v15 + 2);
      }
      else
      {
        v18 = 0i64;
        v19 = 0;
      }
      LODWORD(v39) = *(unsigned __int16 *)(v14 + 2i64 * (unsignedint)v16 + 12);
      S_P_CoreLib_System_Globalization_CultureInfo__get_CurrentCulture();
      TextInfo = S_P_CoreLib_System_Globalization_CultureInfo__get_TextInfo();
      HIDWORD(v39) = S_P_CoreLib_System_Globalization_TextInfo__ToLower(TextInfo, (unsignedint)v39);
      *(_QWORD *)&v38 = v18;
      DWORD2(v38) = v19;
      *(_QWORD *)&v37 = (char *)&v39 + 4;
      DWORD2(v37) = 1;
      v15 = (char **)String__Concat_8(&v38, &v37);
      v16 += 2;
    }
    while ( v17 > v16 );
  }

  计算方式如下

 byte[] byteArray ={ 0x32, 0x00, 0x34, 0x00, 0x41, 0x00, 0x44, 0x00, 0x32, 0x00,
0x31, 0x00, 0x43, 0x00, 0x34, 0x00, 0x43, 0x00, 0x33, 0x00,
0x45, 0x00, 0x32, 0x00, 0x41, 0x00, 0x34, 0x00, 0x33, 0x00,
0x30, 0x00, 0x44, 0x00, 0x46, 0x00, 0x37, 0x00, 0x37, 0x00,
0x45, 0x00, 0x43, 0x00, 0x30, 0x00, 0x41, 0x00, 0x31, 0x00,
0x39, 0x00, 0x30, 0x00, 0x45, 0x00, 0x32, 0x00, 0x30, 0x00,
0x32, 0x00, 0x31, 0x00, 0x39, 0x00, 0x37, 0x00, 0x36, 0x00,
0x30, 0x00, 0x35, 0x00, 0x39, 0x00, 0x37, 0x00, 0x33, 0x00,
0x32, 0x00, 0x43, 0x00, 0x36, 0x00, 0x39, 0x00, 0x36, 0x00,
0x46, 0x00, 0x41, 0x00, 0x44, 0x00, 0x43, 0x00, 0x36, 0x00,
0x31, 0x00, 0x46, 0x00, 0x36, 0x00, 0x32, 0x00, 0x34, 0x00,
0x39, 0x00, 0x30, 0x00, 0x45, 0x00, 0x35, 0x00, 0x45, 0x00,
0x43, 0x00, 0x32, 0x00, 0x30, 0x00, 0x32 };
        string sum= "";
        for (int i = 1; i * 2 < byteArray.Length; i += 2)
        {

            sum+= (char)byteArray[i * 2];
        }

  接着再根据输入的文件名进行计算

  v21 = (unsigned __int64 *)RhpNewArray(&qword_7FF643BFE520, 5i64);
  v22 = String__Substring_0(v35, 0i64, 8i64);
  RhpAssignRefAVLocation(v21 + 2, v22);
  RhpAssignRefAVLocation(v21 + 3, name_no_ext);
  RhpAssignRefAVLocation(v21 + 4, v12);
  v23 = String__Substring(v35, (unsigned int)(*(_DWORD *)(v35 + 8) - 8));
  RhpAssignRefAVLocation(v21 + 5, (unsigned __int64)v23);
  RhpAssignRefAVLocation(v21 + 6, a2);
  v24 = String__Concat_12((__int64)v21);
  v25 = sha256_base64_0((__int64)v24, 8);
  v26 = sha256_base64_0(name_no_ext, 16);
  v27 = (unsigned __int64 *)RhpNewArray(&qword_7FF643BFE520, 5i64);
  RhpAssignRefAVLocation(v27 + 2, v26);
  v28 = String__Substring(*(_QWORD *)(v13 + 16), 32i64);
  v29 = sha256_base64_0((__int64)v28, 32);
  RhpAssignRefAVLocation(v27 + 3, v29);
  RhpAssignRefAVLocation(v27 + 4, a2);
  v30 = String__Substring(v35, (unsigned int)(*(_DWORD *)(v35 + 8) - 10));
  RhpAssignRefAVLocation(v27 + 5, (unsigned __int64)v30);
  RhpAssignRefAVLocation(v27 + 6, (unsigned __int64)v15);
  v31 = String__Concat_12((__int64)v27);
  v32 = sha256_base64_0((__int64)v31, 32);
return String__Concat_6(v32, &off_7FF643BAFBC0, v25);

  首先计算v32,计算方法如

    //Program.const_str是输入的密钥文件sha256加密后再使用base64编码后的结果
    string filename = Path.GetFileNameWithoutExtension(Path.GetFileName(encryptedFilePath));
    string name = Path.GetFileNameWithoutExtension(filename);
    byte[] name_sha256 = ComputeTruncatedHash(sha256, name, 16);
    string base_name = Convert.ToBase64String(name_sha256);
    string concat_str0 = base_name + "kJxdORYN/Ls2XC9oCqio+0ZY63esndX7jYcy4GGrLrI=" + Program.const_str + "FE19D226894d143240f" + "7ca9e017093c9fd6f29ee22";
    byte[] concat_str0_sha256 = ComputeTruncatedHash(sha256, concat_str0, 32);
    string base_concat_str0 = Convert.ToBase64String(concat_str0_sha256);

  接下来计算v25,计算方法如下

  string input = "9139F9BF" + name + "B33D7065A162D3731ECEFB18A540540719D22689" + Program.const_str;
  byte[] hash = ComputeTruncatedHash(sha256, input, 8);
  string input_hash = Convert.ToBase64String(hash);

  然后通过||将这个两个计算出来的字符串拼接在一起

  接着随机生成两个guid

          guid1 = S_P_CoreLib_System_Guid__ToString_1((__int64)&v66 + 8, (__int64)&off_7FF643BAD1D0, 0i64, v16);
          guid2 = S_P_CoreLib_System_Guid__ToString_1((__int64)&v65, (__int64)&off_7FF643BAD1D0, 0i64, v17);
          v60 = sha256_base64_0(guid1, 32);
          v59 = sha256_base64_0(guid2, 32);
          v47 = sha256_base64_0(v13[11], 32);
          v18 = sha256_base64_0(v13[11], 32);
          v46 = String__Substring(v47, (unsigned int)(*(_DWORD *)(v18 + 8) - 12));
          v19 = sha256_base64_0(v13[13], 32);
          v20 = String__Substring_0(v19, 0i64, 16i64);
          v58 = String__Concat_5(v46, v20);
          v45 = sha256_base64_0(v13[13], 32);
          v21 = sha256_base64_0(v13[11], 32);
          v44 = String__Substring(v45, (unsigned int)(*(_DWORD *)(v21 + 8) - 12));
          v22 = sha256_base64_0(v13[11], 32);
          v23 = String__Substring_0(v22, 0i64, 16i64);
          v57 = String__Concat_5(v44, v23);
          v43 = sha256_base64_0(v13[13], 32);
          v24 = sha256_base64_0(v13[11], 32);
          v42 = String__Substring(v43, (unsigned int)(*(_DWORD *)(v24 + 8) - 16));
          v41 = sha256_base64_0(FileNameFromPathBuffer, 16);
          v25 = sha256_base64_0(v13[11], 32);
          v40 = String__Substring_0(v25, 0i64, 12i64);
          v26 = String__Substring(v13[9], (unsigned int)(*(_DWORD *)(v13[9] + 8) - 16));
          v56 = String__Concat_7(v42, v41, v40, v26);
          v39 = sha256_base64_0(v13[11], 32);
          v27 = sha256_base64_0(v13[11], 32);
          v38 = String__Substring(v39, (unsigned int)(*(_DWORD *)(v27 + 8) - 16));
          v37 = sha256_base64_0(FileNameFromPathBuffer, 16);
          v28 = sha256_base64_0(v13[13], 32);
          v36 = String__Substring_0(v28, 0i64, 12i64);
          v29 = String__Substring(v13[10], (unsigned int)(*(_DWORD *)(v13[10] + 8) - 12));
          v48 = String__Concat_7(v38, v37, v36, v29);
          v55 = sha256_base64(v58);
          v54 = sha256_base64(v57);
          v53 = sha256_base64(v56);
          v52 = sha256_base64(v48);
          v30 = String__Concat_6(*(_QWORD *)(v6 + 16), v60, v59);
          v31 = sha256_base64(v30);

  还原后的代码如下

 //随机生成的guid,这里使用固定值进行测试
string guid1 = "c6d47a10-0cf3-4d5c-a500-267db6a41545";
byte[] guid1_byte = ComputeTruncatedHash(sha256, guid1, 32);
string base_guid1_byte = Convert.ToBase64String(guid1_byte);
//随机生成的guid,这里使用固定值进行测试
string guid2 = "8184cff9-01c7-4f07-ac38-d80ed77d4b58";
byte[] guid2_byte = ComputeTruncatedHash(sha256, guid2, 32);
string base_guid2_byte = Convert.ToBase64String(guid2_byte);
byte[] hex4_byte = ComputeTruncatedHash(sha256, hex4, 32);
string base_hex4_byte = Convert.ToBase64String(hex4_byte);
byte[] hex5_byte = ComputeTruncatedHash(sha256, hex5, 32);
string base_hex5_byte = Convert.ToBase64String(hex5_byte);
string hex5_hex4_cat = hex4_cat + base_hex5_byte.Substring(0, 16);
string base_hex5_cat = base_hex5_byte.Substring(base_concat_str0.Length - 12, 12);
string base_hex4_cat = base_hex4_byte.Substring(0, 16);
string concat5 = base_hex5_cat + base_hex4_cat;
//filename为文件名
byte[] filename_byte = ComputeTruncatedHash(sha256, filename, 16);
string base_filename_byte = Convert.ToBase64String(filename_byte);
string concat6 = "e9+zXBNtL8ALaRk=" + base_filename_byte + "IewroqVNVUV0" + "5A16614A468925B4";
string concat7 = "D8NSVR1FARLvFrc=" + base_filename_byte + "Q9584Xb6oe9J" + "62490E5EC202";
byte[] byte7 = ComputeTruncatedHash(sha256, "VR1FARLvFrc=Q9584Xb6oe9J5Vxk", 32);
string base_byte7 = Convert.ToBase64String(byte7);
byte[] byte8 = ComputeTruncatedHash(sha256, "XBNtL8ALaRk=IewroqVNVUV0G/DZ", 32);
string base_byte8 = Convert.ToBase64String(byte8);
byte[] filename_concat_byte_sha256 = ComputeTruncatedHash(sha256, concat6, 32);
string base_filename_concat_byte_sha256 = Convert.ToBase64String(filename_concat_byte_sha256);
byte[] filename_concat2_byte_sha256 = ComputeTruncatedHash(sha256, concat7, 32);
string base_filename_concat2_byte_sha256 = Convert.ToBase64String(filename_concat2_byte_sha256);
//上文通过mac信息和计算机名称计算得到的hash
string const_str = "akflLG7b++2vAPZZP62WLtO5XDpblwfcnVbR+65Y1/U=";
string concat_str = const_str + base_guid1_byte + base_guid2_byte;
byte[] concat_str_byte_sha256 = ComputeTruncatedHash(sha256, concat_str, 32);
string base_concat_str_byte_sha256 = Convert.ToBase64String(concat_str_byte_sha256);

  然后再拼接生成salt和password

string password= base_concat_str_byte_sha256 + base_concat_str0;
string salt= input_hash+ base_guid2_byte;

  通过salt和password生成key和iv,然后再将待加密的数据末尾添加上时间,接着使用aes对文件进行加密

  v42 = String__Concat_5(file_ext, a5);
  sub_7FF643ACBDA0(file_ext, v42, 0);
if ( *(&qword_7FF643BB5520 - 1) )
    sub_7FF643A11806();
  v31 = qword_7FF643CDBB28;
  Bytes = S_P_CoreLib_System_Text_UTF8Encoding_UTF8EncodingSealed__GetBytes(*(_QWORD *)(qword_7FF643CDBB28 + 8), a3);
if ( a4 && *(_DWORD *)(a4 + 8) )
  {
    v40 = S_P_CoreLib_System_Text_UTF8Encoding_UTF8EncodingSealed__GetBytes(*(_QWORD *)(v31 + 8), a4);
  }
else
  {
    v16 = RhpNewArray(&unk_7FF643BFE7C0, 16i64);
    *(_OWORD *)(v16 + 16) = xmmword_7FF643C3FAA0;
    v40 = v16;
  }
  v35 = sub_7FF643A13B30(&unk_7FF643BC2078);
  S_P_CoreLib_System_IO_FileStream___ctor_13(v35, v42, 3, 3, 3, 4096, 0, 0i64);
  v32 = RhpNewFast(&unk_7FF643BC73B0);
  System_Security_Cryptography_System_Security_Cryptography_Aes___ctor();
  (*(void (__fastcall **)(__int64, __int64))(*(_QWORD *)v32 + 112i64))(v17, 256i64);
  (*(void (__fastcall **)(__int64, __int64))(*(_QWORD *)v32 + 64i64))(v32, 128i64);
if ( qword_7FF643BB56F0[-1] )
    sub_7FF643A1132C();
  v45 = qword_7FF643BB56F0[0];
  v34 = RhpNewFast(&unk_7FF643BC7C70);
  System_Security_Cryptography_System_Security_Cryptography_Rfc2898DeriveBytes___ctor_7(
    v34,
    Bytes,
    v40,
    v45,
    (__int64)&off_7FF643BA93E0,
    0);
  v18 = (*(__int64 (__fastcall **)(__int64))(*(_QWORD *)v32 + 104i64))(v32);
  v19 = System_Security_Cryptography_System_Security_Cryptography_Rfc2898DeriveBytes__GetBytes(
          v34,
          (unsignedint)(v18 / 8));
  (*(void (__fastcall **)(__int64, __int64))(*(_QWORD *)v32 + 96i64))(v32, v19);
  v20 = (*(__int64 (__fastcall **)(__int64))(*(_QWORD *)v32 + 56i64))(v32);
  v21 = System_Security_Cryptography_System_Security_Cryptography_Rfc2898DeriveBytes__GetBytes(
          v34,
          (unsignedint)(v20 / 8));
  (*(void (__fastcall **)(__int64, __int64))(*(_QWORD *)v32 + 80i64))(v32, v21);
  v37 = sub_7FF643AF7900(v32);
  v22 = S_P_CoreLib_System_IO_File__GetLastWriteTime(v42);
  v23 = S_P_CoreLib_System_DateTimeFormat__Format_0(v22, &off_7FF643BAD360, 0i64, 0x8000000000000000ui64);
  v36 = S_P_CoreLib_System_Text_UTF8Encoding_UTF8EncodingSealed__GetBytes(*(_QWORD *)(v31 + 8), v23);
  sub_7FF643ACCEC0(v35, 0i64, 2i64);
  v44 = *(_DWORD *)(v36 + 8);
if ( (*(unsignedint (__fastcall **)(_QWORD))(**(_QWORD **)(v35 + 16) + 240i64))(*(_QWORD *)(v35 + 16)) )
    sub_7FF643A9D1D0();
  (*(void (__fastcall **)(_QWORD, __int64, _QWORD, _QWORD))(**(_QWORD **)(v35 + 16) + 216i64))(
    *(_QWORD *)(v35 + 16),
    v36,
    0i64,
    v44);
  sub_7FF643ACCEC0(v35, 0i64, 0i64);
  v33 = RhpNewFast(&unk_7FF643BC7578);
  sub_7FF643AF7EA0(v33, v35, v37, 1, 0);
  v24 = RhpNewArray(&unk_7FF643BFE7C0, Enumerator);
  v48 = 0i64;
while ( sub_7FF643ACCBB0(v35) > v48 )
  {
    v47 = sub_7FF643ACCC00(v35);
    v43 = *(_DWORD *)(v24 + 8);
    if ( (*(unsignedint (__fastcall **)(_QWORD))(**(_QWORD **)(v35 + 16) + 240i64))(*(_QWORD *)(v35 + 16)) )
      sub_7FF643A9D1D0();
    v46 = (*(__int64 (__fastcall **)(_QWORD, __int64, _QWORD, _QWORD))(**(_QWORD **)(v35 + 16) + 200i64))(
            *(_QWORD *)(v35 + 16),
            v24,
            0i64,
            v43);
    v48 += v46;
    sub_7FF643ACCC50(v35, v47);
    System_Security_Cryptography_System_Security_Cryptography_CryptoStream__Write(v33, v24, 0, v46);
  }

  其中生成key和iv的方法如下,iterations和hashAlgorithm可以通过动态调式得到

int iterations = 50000;
using (var deriveBytes = new Rfc2898DeriveBytes(
    password: passwordBytes,
    salt: saltBytes,
    iterations: iterations,
    hashAlgorithm: HashAlgorithmName.SHA256))
{
    byte[] key = deriveBytes.GetBytes(32); // AES-256密钥
    byte[] iv = deriveBytes.GetBytes(16); 

  接着拼接字符串 Done||文件名,然后使用

 string salt = "Ed5w7OB07XyYegT57in85K82oHdRSx0bLKOKDCCGGKI=";
 string password = "+7Qvnh2QKaffTK+NQYapC6DwoJGM1StCA/9R9fCdR6o=";

  生成密钥,接着对其进行aes加密,然后将生成的密文的长度转换为字符串,再用刚刚的密钥进行加密   接着再用相同的密钥对前面生成的guid1进行加密。

  通过文件名生成密钥来对guid2进行加密

  byte[] filename_byte = ComputeTruncatedHash(sha256, filename, 16);
  string base_filename = Convert.ToBase64String(filename_byte);
  string file_concat1 = "e9+zXBNtL8ALaRk=" + base_filename + "IewroqVNVUV0" + "5A16614A468925B4";
  byte[] guid2_password_byte = ComputeTruncatedHash(sha256, file_concat1, 32);
  string guid2_password = Convert.ToBase64String(guid2_password_byte);
  string file_concat2 = "D8NSVR1FARLvFrc=" + base_filename + "Q9584Xb6oe9J" + "62490E5EC202";
  byte[] guid2_salt_byte = ComputeTruncatedHash(sha256, file_concat2, 32);
  string guid2_salt = Convert.ToBase64String(guid2_salt_byte);

  最后再加密字符串encr,密钥跟加密文件的密钥相同

创建勒索信快捷方式

  在网络位置处创建勒索信的快捷方式

__int64 __fastcall sub_7FF643B1A7D0(__int64 a1, __int64 a2, unsigned int n0xEB)
{
  __int64 EnvironmentVariable_1; // rax
  __int64 v7; // rbx
  __int64 EnvironmentVariable; // rax
  __int64 EnvironmentVariable_2; // r14
  __int64 result; // rax
  __int64 v11; // r15
  __int64 v12; // r13
  __int64 v13; // rax
  __int64 v14; // rsi
  __int64 v15; // rax
  __int64 v16; // rax
  __int64 v17; // rax
  __int64 v18; // rax
  __int64 v19; // rax
  __int64 v20; // rax
  __int64 v21; // rbx
  __int64 UTF8BomThrowing; // rdi

  EnvironmentVariable_1 = sub_7FF643A87F00();
  v7 = sub_7FF643ACEA80(EnvironmentVariable_1, a1);
  EnvironmentVariable = S_P_CoreLib_System_Environment__GetEnvironmentVariable(&off_7FF643B9C708);
  EnvironmentVariable_2 = String__Concat_5(EnvironmentVariable, &off_7FF643BAC628);
  result = S_P_CoreLib_System_Environment__GetEnvironmentVariable(&off_7FF643BAF580);
if ( result )
  {
    if ( *(_DWORD *)(result + 8) )
    {
      v11 = sub_7FF643ACEAC0(result, &off_7FF643BAA6C8, &off_7FF643BAEE08);
      v12 = RhpNewFast(&unk_7FF643BC0858);
      v13 = String__Concat_5(a2, &off_7FF643B94780);// !RESTORE_FILES!.url
      v14 = sub_7FF643ACEA80(EnvironmentVariable_2, v13);
      *(_DWORD *)(v12 + 32) = 0x7FFFFFFF;
      v15 = RhpNewArray(&unk_7FF643BFE858, 16i64);
      RhpAssignRefAVLocation(v12 + 8, v15);
      S_P_CoreLib_System_Text_StringBuilder__AppendLine_0(v12, &off_7FF643BAC580);
      v16 = String__Replace_1(v7, 92i64, 47i64);// C:/Windows/System32/!RESTORE_FILES!.txt
      v17 = String__Concat_5(&off_7FF643BAB7A8, v16);// URL=file:///C:/Windows/System32/!RESTORE_FILES!.txt
      S_P_CoreLib_System_Text_StringBuilder__AppendLine_0(v12, v17);
      v18 = String__Concat_5(&off_7FF643BA4450, v11);
      S_P_CoreLib_System_Text_StringBuilder__AppendLine_0(v12, v18);// IconFile=C:\Windows\System32\shell32.dll
      v19 = S_P_CoreLib_System_Number__Int32ToDecStr(n0xEB);// 235
      v20 = String__Concat_5(&off_7FF643BA4478, v19);
      S_P_CoreLib_System_Text_StringBuilder__AppendLine_0(v12, v20);// IconIndex=235
      v21 = S_P_CoreLib_System_Text_StringBuilder__ToString(v12);
      UTF8BomThrowing = S_P_Xml_System_Xml_XmlTextReaderImpl__get_UTF8BomThrowing();
      sub_7FF643ACBE50(v14, UTF8BomThrowing);
      return sub_7FF643ACBEA0(v14, 2i64, v21, UTF8BomThrowing);
    }
  }
return result;
}

如下

删除密钥文件

删除如下文件

C:\Windows\Temp\!wwwGdddf#.txt   //密钥文件
C:\windows\temp\!wwkdsfdsfewt.txt //通过计算机信息计算出来的hash

替换壁纸

  通过修改注册表键值来替换壁纸

  解析base64编码的图片

将其写入C:\Users\Public\img___XXX.jpg,图片如下

  修改后的注册表如下

自删除

  执行如下指令进行自删除

/C @echo off && ping -n 1 127.0.0.1 > nul && del /q /f "加密器路径"

5.病毒分析概览

  根据对样本的深入逆向工程分析,得出该勒索病毒分析结果概览:

  该恶意软件是一个勒索软件,主要行为总结如下:

  • 加密方式:
    • 使用AES-256算法,密钥基于随机GUID、MAC地址和计算机名动态生成。
    • 排除系统目录(如System32),跳过白名单文件(如勒索信!RESTORE_FILES!.txt)。
  • 生成勒索信:
    • 桌面生成勒索信快捷方式(.url),图标伪装为系统文件。
    • 修改注册表键值(HKCU\Control Panel\Desktop\Wallpaper)替换壁纸。
  • 反分析策略:
    • 动态拼接关键字符串,规避静态检测。
    • 删除临时密钥文件(如C:\Windows\Temp\!wwkdsfdsfewt.txt)。

总结:

  高度组织化的勒索攻击,技术复杂且对抗性强,需结合动态行为监控与纵深防御体系阻断传播链。

6.安全建议

  针对888家族的攻击行为,Solar团队已发布专项防护与加固建议,包括数据库弱口令治理、MSSQL安全基线检查、服务器目录权限收紧、异常文件投放监测等措施,详情可参考【漏洞与预防】MSSQL数据库弱口令漏洞预防

1. 风险消减措施

  资产梳理排查目标: 根据实际情况,对内外网资产进行分时期排查

  服务方式: 调研访谈、现场勘查、工具扫描

  服务关键内容: 流量威胁监测系统排查、互联网暴露面扫描服务、技术加固服务、集权系统排查

2. 安全设备调优

目标

  通过对安全现状的梳理和分析,识别安全策略上的不足,结合目标防御、权限最小化、缩小攻击面等一系列参考原则,对设备的相关配置策略进行改进调优,一方面,减低无效或低效规则的出现频次;另一方面,对缺失或遗漏的规则进行补充,实现将安全设备防护能力最优化。

主要目标设备

  网络安全防护设备、系统防护软件、日志审计与分析设备、安全监测与入侵识别设备。

3. 全员安全意识增强调优

目标:

  通过网络安全意识宣贯、培训提升全方位安全能力

形式:

  培训及宣贯

  线下培训课表

  若无法组织线下的集体培训,考虑两种方式:

    1.提供相关的安全意识培训材料,由上而下分发学习

    2.组织相关人员线上开会学习。线上培训模式。

  线上学习平台

  以下是solar安全团队近期处理过的常见勒索病毒后缀:后缀.360勒索病毒,.halo勒索病毒,.phobos勒索病毒,.Lockfiles勒索病毒,.stesoj勒索病毒,.src勒索病毒,.svh勒索病毒,.Elbie勒索病毒,.Wormhole勒索病毒.live勒索病毒, .rmallox勒索病毒, .mallox 勒索病毒,.hmallox勒索病毒,.jopanaxye勒索病毒, .2700勒索病毒, .elbie勒索病毒, .mkp勒索病毒, .dura勒索病毒, .halo勒索病毒, .DevicData勒索病毒, .faust勒索病毒, ..locky勒索病毒, .cryptolocker勒索病毒, .cerber勒索病毒, .zepto勒索病毒, .wannacry勒索病毒, .cryptowall勒索病毒, .teslacrypt勒索病毒, .gandcrab勒索病毒, .dharma勒索病毒, .phobos勒索病毒, .lockergoga勒索病毒, .coot勒索病毒, .lockbit勒索病毒, .nemty勒索病毒, .contipa勒索病毒, .djvu勒索病毒, .marlboro勒索病毒, .stop勒索病毒, .etols勒索病毒, .makop勒索病毒, .mado勒索病毒, .skymap勒索病毒, .aleta勒索病毒, .btix勒索病毒, .varasto勒索病毒, .qewe勒索病毒, .mylob勒索病毒, .coharos勒索病毒, .kodc勒索病毒, .tro勒索病毒, .mbed勒索病毒, .wannaren勒索病毒, .babyk勒索病毒, .lockfiles勒索病毒, .locked勒索病毒, .DevicData-P-XXXXXXXX勒索病毒, .lockbit3.0勒索病毒, .blackbit勒索病毒等。

  勒索攻击作为成熟的攻击手段,很多勒索家族已经形成了一套完整的商业体系,并且分支了很多团伙组织,导致勒索病毒迭代了多个版本。而每个家族擅用的攻击手法皆有不同,TellYouThePass勒索软件家族常常利用系统漏洞进行攻击;Phobos勒索软件家族通过RDP暴力破解进行勒索;Mallox勒索软件家族利用数据库及暴力破解进行加密,攻击手法极多防不胜防。

  而最好的预防方法就是针对自身业务进行定期的基线加固、补丁更新及数据备份,在其基础上加强公司安全人员意识。如果您想了解有关勒索病毒的最新发展情况,或者需要获取相关帮助,请关注“solar专业应急响应团队”。

团队介绍

  团队坚持自主研发及创新,在攻防演练平台、网络安全竞赛平台、网络安全学习平台方面加大研发投入,目前已获得十几项专利及知识产权。团队也先后通过了ISO9001质量管理体系、ISO14000环境管理体系、ISO45001职业安全健康管理体系 、ITSS(信息技术服务运行维护标准四级)等认证,已构建了网络安全行业合格的资质体系;

我们的数据恢复服务流程

  多年的数据恢复处理经验,在不断对客户服务优化的过程中搭建了"免费售前+安心保障+专业恢复+安全防御"一体化的专业服务流程。

① 免费咨询/数据诊断分析

​   专业的售前技术顾问服务,免费在线咨询,可第一时间获取数据中毒后的正确处理措施,防范勒索病毒在内网进一步扩散或二次执行,避免错误操作导致数据无法恢复。

​   售前技术顾问沟通了解客户的机器中毒相关信息,结合团队数据恢复案例库的相同案例进行分析评估,初步诊断分析中毒数据的加密/损坏情况。

② 评估报价/数据恢复方案

​   您获取售前顾问的初步诊断评估信息后,若同意进行进一步深入的数据恢复诊断,我们将立即安排专业病毒分析工程师及数据恢复工程师进行病毒逆向分析及数据恢复检测分析。

​   专业数据恢复工程师根据数据检测分析结果,定制数据恢复方案(恢复价格/恢复率/恢复工期),并为您解答数据恢复方案的相关疑问。

③ 确认下单/签订合同

​   您清楚了解数据恢复方案后,您可自主选择以下下单方式:

  双方签署对公合同:根据中毒数据分析情况,量身定制输出数据恢复合同,合同内明确客户的数据恢复内容、数据恢复率、恢复工期及双方权责条款,双方合同签订,正式进入数据恢复专业施工阶段,数据恢复后进行验证确认,数据验证无误,交易完成。

④ 开始数据恢复专业施工

  安排专业数据恢复工程师团队全程服务,告知客户数据恢复过程注意事项及相关方案措施,并可根据客户需求及数据情况,可选择上门恢复/远程恢复。

  数据恢复过程中,团队随时向您报告数据恢复每一个节点工作进展(数据扫描 → 数据检测 → 数据确认 → 恢复工具定制 → 执行数据恢复 → 数据完整性确认)。

⑤ 数据验收/安全防御方案

  完成数据恢复后,我司将安排数据分析工程师进行二次检查确认数据恢复完整性,充分保障客户的数据恢复权益,二次检测确认后,通知客户进行数据验证。

     客户对数据进行数据验证完成后,我司将指导后续相关注意事项及安全防范措施,并可提供专业的企业安全防范建设方案及安全顾问服务,抵御勒索病毒再次入侵。

                      我们在此郑重承诺:

                     不成功不收费

                     全程一对一服务

                     365天不间断服务

                     免费提供安全方案

                     24h服务热线:

                     18894665383

                     17864099776

                     18299173318