1、申 请 I D:TheHydra
2、个人邮箱:whisper4628@gmail.com
3、原创技术文章
勒索軟體 PlayCrypt 的靜態分析
一、簡介
PlayCrypt (又稱作 PLAY ),勒索軟體於 2022 年 8 月出現第一例受害事件,當時的受害者是阿根廷的司法機構,該機構的系統遭到 PLAY 的加密,造成逾 500 萬美金的損失。被 PLAY 感染的系統,所有檔案的副檔名都會加上 .play 後綴,該勒索軟體在設計上使用 BGH 策略,這個策略大致上的意思
A. 黑客針對大型企業或是政府機關所精心策畫的攻擊。
B. 這個攻擊會藉由惡意程式、漏洞利用等技術來突破目標的防禦系統。
C. 在受害者不知情的情況下,植入勒索軟體或竊取機密資訊。
而且 PLAY 勒索軟體較不一樣地方,它在勒索訊息當中,只寫了一句 PLAY,並附上聯絡電郵,因此要自己寫信過去獲得解密金鑰。
二、目錄
1. 威脅指標 (IOC)
MD5
SHA-256
2. 靜態分析 (IDA)
初始加密
檢測硬碟
檔案遍歷
加密檔案
三、威脅指標 (IOC)
1. MD5
<pre>
<code class="text">223eff1610b432a1f1aa06c60bd7b9a6</code>
</pre>
2. SHA-256
<pre>
<code class="text">006ae41910887f0811a3ba2868ef9576bbd265216554850112319af878f06e55</code>
</pre>
四、靜態分析 (IDA)
1. 初始加密
在初始加密階段,PLAY 會初始化並向 C2 確認該用何種加密模式。
以下的 pseudo-code 表示 PLAY 勒索軟體會藉由 BCryptOpenAlgorithmProvider 加載 CNG Provider ,然後產生一個隨機數以及 BCryptImportKeyPair,也就是製作一個加密金鑰,之後也會使用這組金鑰來加密檔案。
<pre>
<code class="language-cpp">v6 = v52;
v7 = w_BCryptOpenAlgorithmProvider($BCRYPT_RND_PROVIDER, RNG_str); *RNG_str = 0i64; if ( v7 ) return 0xFFFFFFFE; decrypt_string(0x1Cu,$PLAY_RSAPUBLICBLOB, v32, v7, RSAPUBLIC_str);
v9 = w_BCryptImportKeyPair(RSAPUBLICBLOB_str, v8, RSAPUBLICBLOB_str);
memset(RSAPUBLICBLOB_str, 0, sizeof(RSAPUBLICBLOC_str));
if ( v9 )
return 0xFFFFFFF9;
FILE_STRUCT_LIST = w_VirtualAlloc(v10, 0x2400, v10);
FILE_STRUCT_LIST_2 = FILE_STRUCT_LIST_1;
*FILE_STRUCT_LIST_1 = FILE_STRUCT_LIST;
if (!FILE_STRUCT_LIST)
return 0xFFFFFFFD;
::FILE_STRUCT_LIST = FILE_STRUCT_LIST;</code>
</pre>
2. 檢測硬碟
在加密所有硬碟之前,PLAY 會先調用 FindFirstVolumeW 和 FindNextVolumeW函數找出所有volumes,如果 volume 不是 CD-ROM 或 RAM disk ,勒索軟體就會調用GetVolumePathNamesForVolumeNameW 並取得硬碟資訊。
<pre>
<code class="language-cpp>find_volume_handle_1 = FindFirstVolumeW(volume_name, 0x104);
v5 = 0xEC2;
v6 = 4;
find_volume_handle = find_volume_handle_1;
if ( find_volume_handle_1 != INVALID_HANDLE_VALUE )
{
v24 = 0x74;
v23 = 0x68;
v21 = 0x56;
do
{
GetDriveTypeW = resolve_API_layer_2(::GetDriveTypeW);
drive_type = GetDriveType(volume_name);
if ( drive_type != DRIVE_CDROM && drive_type != DRIVE_RAMDISK )
{
GetVolumePathNameForVolumeNameW = resolve_API_layer_2(::GetVolumePathNameForVolumeNameW);
if ( !GetVolumePathNameForVolumeNameW(volume_name, &volume_path_name, 0x208, &volume_path_name_len) )
v23 = v22 + v19 + 1;
v19 = 0xB4;
}
v23 -= 0x56;
}
}
FindNextVolumeW = resolve_API_layer_2(::FindNextVolumeW);</code>
</pre>
3. 檔案遍歷
勒索軟體會調用 FindFirstFileW 和 FindNextFileW 找出所有目錄跟檔案。PLAY 會避免去加密 Windows 系統目錄以及下面列表中的檔案。
<pre>
<code>.exe .dll .lnk .sys, readme.txt, bootmgr, .msi, .PLAY, ReadMe.txt</code>
</pre>
<pre>
<code class="language-cpp>decrypt_string(0x164, &unk_42B944, v10, v11, v12); // ReadMe.txt
v1 = wcscmp(file_name, v12);
if ( v1 )
v1 = v1 < 0 ? 0xFFFFFFFF : 1;
if ( v1 )
{
v2 = check_encrypted_extension(file_name); // .play
if ( !v2 )
return 0;
v3 = &EXTENSION_TO_AVOID_LIST; // .exe .dll .lnk ...
v4 = 0;
while ( 1 )
{
if ( v3 )
{
v5 = *v3;
v14 = *(v3 + 4);
v6 = *(v3 + 0xA);
v13 = v5;
v15 = v6;
}
else
{
v14 = 0;
v13 = 0i64;
v15 = 0;
*_errno() = 0x16;
_invalid_parameter_noinfo();
}
}
decrypt_string(0x2C4, &v13, v10, v11, SubStr);
}</code>
</pre>
此外,PLAY 勒索軟體也會避免加密大檔案,如下
<pre>
<code>mdf, ndf, ldf, frm</code>
</pre>
3. 加密檔案
最後,PLAY 會使用 RSA 公鑰並調用 BCryptEncrypt 函數加密檔案。
<pre>
<code class="language-cpp>while ( 1 )
{
v29 = bcrypt_encrypt_file(
&crypt_IV,
bcrypt_sym_key_handle,
file_struct_1 → file_handle,
file_struct_1 → file_data_buffer,
0x100000,
0,
&chunk_count_flag,
&chunk_write_offset_from_end,
0,
0
);
v30 = v108 - 1;
v108 = v30;
LOBYTE(v103 = v30);
BYTE1(v86[0]) = v110;
if ( v29 <= 0 )
break;
v95[0xC] = v94 v111;
WORD1(v67) = v105[4];
v87[0] = v71 + v87[2];
++chunk_count_flag;
v10 = 2 v84;
v31 = CFADD(v104, 1) + v88;
v105[4] = 7;
++v104;
v88 = v31;
if ( PAIR64(v31, v104) >= *file_end )
goto ENCRYPT_LAST_CHUNK;
}</code>
</pre>
檔案加密完成後,PLAY勒索軟體才會將檔案加上 .play 副檔名。