1.背景
2025年3月,Solar应急响应团队成功捕获了888勒索家族的加密器样本。实际上,我们最早接触该家族是在2024年10月,彼时888家族活跃度极高,频繁针对医疗行业发起攻击,受害对象以药店、医院等医疗机构为主。
在攻击方式上,888家族主要通过MSSQL数据库弱口令爆破实现初始入侵,成功获取权限后,将自制的加密器投放至服务器路径中的Musicmisc目录,以隐藏其恶意文件,随后迅速对服务器内的重要数据实施加密勒索。
1.1 加密器特征
该勒索家族较为狡猾,通过ping空地址绕过本地安全机制监测最终实现自删除。
加密器启动后运行的命令行指令
在成功加密后,桌面上会生成名为“!RESTORE_FILES!.txt”的勒索信,要求受害者将信内ID发到下方的邮箱中,以取得初步联系获得赎金报价。
勒索信
被加密后的目录
1.2 攻击链路与IOC
888勒索家族惯用的手段是通过数据库对外暴露入口弱口令入侵数据库,并在数据执行提权操作,获取高权限账户或将木马加载到受害者设备,随后再进行加密器的加载运行。
1.3 IOC
详细信息 | 类型 | 关联文件/主机/备注 |
---|---|---|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
IP |
|
|
IP |
|
|
IP |
|
|
IP |
|
|
|
|
|
|
|
|
|
|
|
|
|
2.恶意文件基础信息
2.1 恶意文件基本信息
|
|
---|---|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
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:[email protected][email protected]Zero cheats, all integrity.
3.加密后文件分析
3.1威胁分析
病毒家族 |
|
---|---|
首次出现时间/捕获分析时间 |
|
威胁类型 |
|
加密文件扩展名 |
|
勒索信文件名 |
|
有无免费解密器? |
|
联系邮箱 |
|
感染症状 |
|
感染方式 |
|
受灾影响 |
|
3.2 加密的测试文件
文件名
sierting.txt
具体内容:
加密文件名特征:
加密文件名 = 原始文件名+888 ,例如:sierting.txt.888
加密文件数据特征:
加密算法:
AES密钥生成:
通过随机生成的两个guid来生成key和iv
程序执行流程:
4.逆向分析
4.1加密器逆向分析
勒索信密钥初始化
初始化了几个常量如下
5FC92AFFB28BE14BD3A8B1843E9F8E8BB394A50F7E3E599D0316E97D8B98BEDFFC5A714EFBF1AE255D0071443A0D08FE70B2DE19F1F288115EDF3E6FA5263DBF.888AC11CD9E6DA7311B9804D8EB421DB7EFEC8ABB7EACC999CA64F3C7A99686E826!RESTORE_FILES!.txt9139F9BF04FB5ED3A8DF78E10110710C4134C2A37CBE912B6428B7FE19D2268906FEECBAD923B75FA5B35A7A949C479AA67D838884BDA14963DC1903ACCD3E37171C88018769B3D2B33D7065A162D3731ECEFB18A54054075A16614A468925B424AD21C4C3E2A430DF77EC0A190E2021976059732C696FADC61F62490E5EC202B502B9C8546259BC27DAA82287C4ADA92A16B7A81665FAF9EFD20A4C3FD6233AA9C3ED26735E74CC8939D5D7875BC9AEC04E5A91607BE48E6897CB7A96E1170D45AB92864D45D54123C980CD245B31ED37A6EDDDF952A342CC5D9CB777B3942E
查找同路径下是否存在p.txt文件,如果有,则读取,并将读取到的内容进行sha256哈希计算之后再进行base64编码,然后再将此文件移动到C:WindowsTemp!wwwGdddf#.txt
__int64 __fastcall sub_7FF643B1AF70(__int64 a1, __int64 a2){ __int64 v4; // rax __int64 v5; // rax __int64 v6; // rax __int64 v7; // raxif ( !(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; // rsiint v2; // ediint v3; // ebp __int64 *v4; // r14 __int64 v5; // r15 __int64 v6; // rcx __int64 v7; // raxint 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, unsignedint a2){ __int64 v4; // rdi __int64 v5; // rdxint v6; // ebpint v7; // r14dchar **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
defsplit_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 segmentsstr1 = "FC5A714EFBF1AE255D0071443A0D08FE70B2DE19F1F288115EDF3E6FA5263DBF"#常量字符串result1 = split_string_by_segments(str1,12)list1=[]for i, seg in enumerate(result1): list1.append(seg)str2 = "akflLG7b++2vAPZZP62WLtO5XDpblwfcnVbR+65Y1/U="#通过计算机信息计算出来的hashresult2 = 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:WindowsTemp!wwkdsfdsfewt.txt
__int64 __fastcall sub_7FF643AE6930( __int64 a1,constvoid *lpBuffer_1, DWORD nNumberOfBytesToWrite_1, DWORD *lpNumberOfBytesWritten_1, struct _OVERLAPPED *lpOverlapped){void *hFile_1; // r14unsignedint 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, unsignedint 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!.txtsvchost.exebootmgrbootmgr.efibootmgr.efi.muibootmgr.exebootmgr.exe.muiimg___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信息和计算机名称计算得到的hashstring 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, unsignedint 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:WindowsSystem32shell32.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:WindowsTemp!wwwGdddf#.txt //密钥文件C:windowstemp!wwkdsfdsfewt.txt //通过计算机信息计算出来的hash
替换壁纸
通过修改注册表键值来替换壁纸
解析base64编码的图片
将其写入C:UsersPublicimg___XXX.jpg
,图片如下
修改后的注册表如下
自删除
执行如下指令进行自删除
/C @echo off && ping -n 1127.0.0.1 > nul && del /q /f "加密器路径"
5.病毒分析概览/总结
根据对样本的深入逆向工程分析,得出该勒索病毒分析结果概览:
该恶意软件是一个勒索软件,主要行为总结如下:
-
加密方式: -
使用AES-256算法,密钥基于随机GUID、MAC地址和计算机名动态生成。 -
排除系统目录(如 System32
),跳过白名单文件(如勒索信!RESTORE_FILES!.txt
)。 -
生成勒索信: -
桌面生成勒索信快捷方式( .url
),图标伪装为系统文件。 -
修改注册表键值( HKCUControl PanelDesktopWallpaper
)替换壁纸。 -
反分析策略: -
动态拼接关键字符串,规避静态检测。 -
删除临时密钥文件(如 C:WindowsTemp!wwkdsfdsfewt.txt
)。
总结:
高度组织化的勒索攻击,技术复杂且对抗性强,需结合动态行为监控与纵深防御体系阻断传播链。
6.安全建议
针对888家族的攻击行为,Solar团队已发布专项防护与加固建议,包括数据库弱口令治理、MSSQL安全基线检查、服务器目录权限收紧、异常文件投放监测等措施,详情可参考【漏洞与预防】MSSQL数据库弱口令漏洞预防
原文始发于微信公众号(solar应急响应团队):【病毒分析】888勒索家族再出手!幕后加密器深度剖析
- 左青龙
- 微信扫一扫
-
- 右白虎
- 微信扫一扫
-
评论