EMACLAB Anticheat Driver, Part 5: Filter and Callbacks
- File Name: EMAC-Driver-x64.sys
- TimeDateStamp: 0x67CAFFCE (Friday, 7 March 2025 14:16:46 GMT)
- Protector: VMProtect 3.8+
Callbacks
Callbacks for threads, processes and images are registered, the only handler i could find without virtualization was image callback.
The image callback is a huge function, it will insert the newly module into a internal list, then some actions are done, such as:
- Get ntdll.dll addresses (DbgBreakPoint, DbgUiRemoteBreak, DbgUserBreakPoint, LdrLoadDll)
- Get kernel32.dll addresses (LoadLibraryA, LoadLibraryW, LoadLibraryExA, LoadLibraryExW)
- Get kernelbase.dll addresses (LoadLibraryA, LoadLibraryW, LoadLibraryExA, LoadLibraryExW)
- Get cs2.exe base and size, as well as engine2.dll base and size
- Get GamersClub launcher image base
- Will load EMAC-CSGO-x64.dll into the game process via driver using
NtCreateThreadEx
andKERNEL32.DLL!LoadLibraryW
You must think, if the driver loads the .DLL then i can simply overwrite it on disk so it loads my own, but remember there’s a minifilter with file signature checks:
Minifilter
EMACLAB Anticheat registers a FSFilter Activity Monitor with altitude 363570. Then a pre-operation callback is set on memory section creation, to intercept system image loading.
The whole file signature verification is done in kernel using CI.dll APIs.
__int64 __fastcall EmacFltCallback(PFLT_CALLBACK_DATA fltCallbackData)
{
unsigned int v2; // ebp
ULONG (__fastcall *FltGetRequestorProcessIdFn)(PFLT_CALLBACK_DATA); // rsi
NTSTATUS (__fastcall *FltGetFileNameInformationFn)(PFLT_CALLBACK_DATA, FLT_FILE_NAME_OPTIONS, PFLT_FILE_NAME_INFORMATION *); // r12
NTSTATUS (__fastcall *FltParseFileNameInformationFn)(PFLT_FILE_NAME_INFORMATION); // r15
NTSTATUS (__stdcall *FltReleaseFileNameInformationFn)(PFLT_FILE_NAME_INFORMATION); // r14
PFLT_IO_PARAMETER_BLOCK Iopb; // rdi
ULONG processId; // esi
struct _FLT_FILE_NAME_INFORMATION *v9; // rcx
PFLT_FILE_NAME_INFORMATION fileNameInformation; // [rsp+50h] [rbp+8h] BYREF
v2 = 1;
_InterlockedAdd(&g_EmacReferenceCount, 1u);
fileNameInformation = 0i64;
FltGetRequestorProcessIdFn = (ULONG (__fastcall *)(PFLT_CALLBACK_DATA))(((unsigned __int64)FltGetRequestorProcessId ^ qword_FFFFF801BCFACC40) & -(__int64)(((unsigned __int64)FltGetRequestorProcessId ^ qword_FFFFF801BCFACC40) > qword_FFFFF801BCFACC38));
FltGetFileNameInformationFn = (NTSTATUS (__fastcall *)(PFLT_CALLBACK_DATA, FLT_FILE_NAME_OPTIONS, PFLT_FILE_NAME_INFORMATION *))(((unsigned __int64)FltGetFileNameInformation ^ qword_FFFFF801BCFACC40) & -(__int64)(((unsigned __int64)FltGetFileNameInformation ^ qword_FFFFF801BCFACC40) > qword_FFFFF801BCFACC38));
FltParseFileNameInformationFn = (NTSTATUS (__fastcall *)(PFLT_FILE_NAME_INFORMATION))(((unsigned __int64)FltParseFileNameInformation ^ qword_FFFFF801BCFACC40) & -(__int64)(((unsigned __int64)FltParseFileNameInformation ^ qword_FFFFF801BCFACC40) > qword_FFFFF801BCFACC38));
FltReleaseFileNameInformationFn = (NTSTATUS (__stdcall *)(PFLT_FILE_NAME_INFORMATION))(((unsigned __int64)FltReleaseFileNameInformation ^ qword_FFFFF801BCFACC40) & -(__int64)(((unsigned __int64)FltReleaseFileNameInformation ^ qword_FFFFF801BCFACC40) > qword_FFFFF801BCFACC38));
if ( fltCallbackData )
{
Iopb = fltCallbackData->Iopb;
if ( Iopb )
{
if ( Iopb->Parameters.Read.Length == 1 && Iopb->Parameters.AcquireForSectionSynchronization.PageProtection == 0x10 )
{
((void (__fastcall *)(PFLT_CALLBACK_DATA))(((unsigned __int64)FltGetRequestorProcess ^ qword_FFFFF801BCFACC40) & -(__int64)(((unsigned __int64)FltGetRequestorProcess ^ qword_FFFFF801BCFACC40) > qword_FFFFF801BCFACC38)))(fltCallbackData);
processId = FltGetRequestorProcessIdFn(fltCallbackData);
if ( (processId == 4 || g_GameProcessId && processId == (_DWORD)g_GameProcessId)
&& (FltGetFileNameInformationFn(fltCallbackData, 0x101i64, &fileNameInformation) & 0xC0000000) != 0xC0000000
&& (FltParseFileNameInformationFn(fileNameInformation) & 0xC0000000) != 0xC0000000
&& processId == 4
&& EmacFltVerifyFileName(Iopb, fileNameInformation) )
{
fltCallbackData->IoStatus.Information = 0i64;
v2 = 4;
v9 = fileNameInformation;
fltCallbackData->IoStatus.Status = 0xC000009A;// Block from loading
if ( !v9 )
goto LABEL_17;
}
else
{
v9 = fileNameInformation;
}
if ( v9 )
FltReleaseFileNameInformationFn(v9);
}
}
}
LABEL_17:
_InterlockedDecrement(&g_EmacReferenceCount);
return v2;
}
They proceed to verify the file, based on name and code signature informations.
bool __fastcall EmacFltVerifyFileName(PFLT_IO_PARAMETER_BLOCK Iopb, PFLT_FILE_NAME_INFORMATION fileNameInformation)
{
char v3; // di
void (__fastcall *ExFreePoolWithTagFn)(_IMAGE_DOS_HEADER *, _QWORD); // r14
_IMAGE_DOS_HEADER *fileBuffer; // rbx
__int64 e_lfanew; // rax
_EMAC_IMAGE_SIGN_INFO a3; // [rsp+20h] [rbp-E0h] BYREF
unsigned __int64 fileSize; // [rsp+310h] [rbp+210h] BYREF
LODWORD(fileSize) = 0;
*(_QWORD *)&a3.VerificationStatus = 0i64;
a3.PolicyInfoSize = 0;
v3 = 0;
a3.IsVerified = 0;
memset(&a3.SigningTime, 0, 681);
ExFreePoolWithTagFn = (void (__fastcall *)(_IMAGE_DOS_HEADER *, _QWORD))(((unsigned __int64)ExFreePoolWithTag ^ qword_FFFFF801BCFACC40) & -(__int64)(((unsigned __int64)ExFreePoolWithTag ^ qword_FFFFF801BCFACC40) > qword_FFFFF801BCFACC38));
if ( !byte_FFFFF801BCFAC6D8 ) // Probably a master switch for file verification
{
if ( fileNameInformation && EmacCheckDbkProcessHackerByFileName(&fileNameInformation->Name) )
{
return 1;
}
else
{
fileBuffer = (_IMAGE_DOS_HEADER *)EmacFltReadFileToBuffer(Iopb->TargetInstance, Iopb->TargetFileObject, &fileSize);
if ( fileBuffer )
{
if ( fileBuffer->e_magic == 0x5A4D )
{
e_lfanew = fileBuffer->e_lfanew;
if ( (int)e_lfanew < 4096
&& (unsigned int)fileSize > 0x1000
&& *(_DWORD *)((char *)&fileBuffer->e_magic + e_lfanew) == 0x4550
&& *(USHORT *)((char *)&fileBuffer->e_lfarlc + e_lfanew) == 0x20B
&& *(USHORT *)((char *)fileBuffer[1].e_res + e_lfanew) == 1 )// Validate PE
{
if ( EmacVerifyFileSigned(fileBuffer, (unsigned int)fileSize, &a3) >= 0
&& LOBYTE(a3.Unknown1)
&& EmacVerifyFileCertificateName(a3.SubjectName) )
{
v3 = 1;
}
else
{
v3 = EmacVerifyFileUnknown((__int64)fileBuffer);
}
}
}
ExFreePoolWithTagFn(fileBuffer, 'CAME');
}
}
}
return v3;
}
EmacCheckSystemImageByName
will verify if image name is dbk64.sys
/dbk32.sys
(Cheat Engine) or kprocesshacker2.sys
(Process Hacker):
this is kinda of meme since it checks purely by the file name, you can try renaming a legitimate non-malicious driver and try load it to see what happens
bool __fastcall EmacCheckDbkProcessHacker(const wchar_t *imageName)
{
unsigned __int64 v1; // rbx
__m128 v2; // rdi
unsigned __int64 v4; // r8
unsigned __int64 v5; // r8
__m128 si128; // xmm0
__m128 v7; // xmm1
__int64 v8; // rbx
__int64 *v9; // rsi
bool v10; // di
__int64 i; // rbx
wchar_t *v12; // rdx
__m128 v14; // [rsp+20h] [rbp-69h] BYREF
__m128 v15; // [rsp+30h] [rbp-59h] BYREF
__m128 v16; // [rsp+40h] [rbp-49h] BYREF
__m128 v17; // [rsp+50h] [rbp-39h]
__int128 v18[2]; // [rsp+60h] [rbp-29h] BYREF
__int128 v19[2]; // [rsp+80h] [rbp-9h] BYREF
__int128 v20[2]; // [rsp+A0h] [rbp+17h] BYREF
char v21[32]; // [rsp+C0h] [rbp+37h] BYREF
char *v22; // [rsp+F8h] [rbp+6Fh] BYREF
__int128 *v23; // [rsp+100h] [rbp+77h] BYREF
v1 = -1i64;
v16.m128_u64[0] = 0xA5AE4945064F9i64;
v2.m128_u64[0] = 0x3C5A8F9432649Di64;
v14.m128_u64[0] = 0x3C5A8F9432649Di64;
v16.m128_u64[1] = 0x3AD429636D08232i64;
v2.m128_u64[1] = 0x3AD429636D08206i64;
v14.m128_u64[1] = 0x3AD429636D08206i64;
v16 = _mm_xor_ps((__m128)_mm_load_si128((const __m128i *)&v14), v16);// Decrypted UTF-16: dbk64
v4 = -1i64;
memset(v18, 0, sizeof(v18));
do
++v4;
while ( v16.m128_i16[v4] );
std_vector_push_back(v18, &v16, v4);
v14 = v2;
v16.m128_u64[0] = 0xF5AE4945064F9i64;
v16.m128_u64[1] = 0x3AD429636D08234i64;
v5 = -1i64;
v16 = _mm_xor_ps((__m128)_mm_load_si128((const __m128i *)&v16), v2);// Decrypted UTF-16: dbk34
memset(v19, 0, sizeof(v19));
do
++v5;
while ( v16.m128_i16[v5] );
std_vector_push_back(v19, &v16, v5);
v16 = v2;
v14.m128_u64[0] = 0x535AFD944264F6i64;
v14.m128_u64[1] = 0x3DE42E536B58265i64;
si128 = (__m128)_mm_load_si128((const __m128i *)&v14);
v15.m128_u64[0] = 0x454DEBE66E3527A7i64;
v15.m128_u64[1] = 0x3C2843EC1561C2DDi64;
v7 = (__m128)_mm_load_si128((const __m128i *)&v15);
v17.m128_u64[0] = 0x4526EB856E5427CFi64;
v17.m128_u64[1] = 0x3C2843EC1513C2B8i64;
v15 = _mm_xor_ps(v7, v17); // Decrypted Raw (unprintable): 51 43 77 fa 1b b1 1e 45 65 00 72 00 00 00 00 00
v14 = _mm_xor_ps(si128, v2); // Decrypted UTF-16: kpro2
memset(v20, 0, sizeof(v20)); // L"kprocesshacker"
do
++v1;
while ( v14.m128_i16[v1] );
std_vector_push_back(v20, &v14, v1);
v15.m128_u64[0] = 0i64;
v22 = v21;
v8 = 3i64;
v23 = v18;
v14 = 0i64;
std_vector_alloc_3((unsigned __int64 *)&v14, 3ui64, &v23, &v22);
v9 = (__int64 *)v21;
v10 = 1;
do
{
v9 -= 4;
sub_FFFFF801BCEF4B20(v9);
--v8;
}
while ( v8 );
for ( i = v14.m128_u64[0]; i != v14.m128_u64[1]; i += 32i64 )// // this is basically a range based loop to traverse vector elements
{
v12 = (wchar_t *)i;
if ( *(_QWORD *)(i + 24) > 7ui64 )
v12 = *(wchar_t **)i;
if ( wcsistr((wchar_t *)imageName, v12) )
goto LABEL_16;
}
v10 = 0;
LABEL_16:
sub_FFFFF801BCEF4A94((__int64)&v14);
return v10;
}
The next function goes beyong and verifies the file signature with known malicious subject names:
I am sorry, the static xor string decipher oftenly puts the words out of order
bool __fastcall EmacVerifyFileCertificateName(char *subjectName)
{
__int64 v1; // rdi
__int64 v3; // r8
bool v4; // bl
__int64 v5; // r8
__int64 v6; // r8
__int64 v7; // r8
__int64 v8; // r8
__int64 v9; // r8
__m128 v10; // xmm0
__int64 v11; // r8
__m128 si128; // xmm1
__int64 v13; // r8
__m128 v14; // xmm0
__m128 v15; // xmm1
__m128 v16; // xmm0
__int64 v17; // r8
__int64 v18; // r8
__m128 v19; // xmm0
__m128 v20; // xmm1
__m128 v21; // xmm0
__int64 v22; // r8
__m128 v23; // xmm0
__m128 v24; // xmm1
__m128 v25; // xmm0
__int64 v26; // r8
__m128 v27; // xmm0
__m128 v28; // xmm1
__m128 v29; // xmm0
__int64 v30; // r8
__m128 v31; // xmm0
__m128 v32; // xmm1
__int64 v33; // r8
__m128 v34; // xmm0
__m128 v35; // xmm1
__m128 v36; // xmm0
__int64 v37; // r14
__int64 *v38; // rdi
char v39; // si
unsigned __int64 v40; // rdx
__int64 v41; // rcx
__int64 v42; // r8
const char *v43; // rcx
__int64 i; // rdi
char *v45; // rdx
__m128 v47; // [rsp+20h] [rbp-E0h] BYREF
__m128 v48; // [rsp+30h] [rbp-D0h] BYREF
__m128 v49; // [rsp+40h] [rbp-C0h] BYREF
__m128 v50; // [rsp+50h] [rbp-B0h] BYREF
__m128 v51; // [rsp+60h] [rbp-A0h] BYREF
__m128 v52; // [rsp+70h] [rbp-90h]
__m128 v53; // [rsp+80h] [rbp-80h]
__m128 v54; // [rsp+90h] [rbp-70h]
__int128 v55[2]; // [rsp+A0h] [rbp-60h] BYREF
__int128 v56[2]; // [rsp+C0h] [rbp-40h] BYREF
__int128 v57[2]; // [rsp+E0h] [rbp-20h] BYREF
__int128 v58[2]; // [rsp+100h] [rbp+0h] BYREF
__int128 v59[2]; // [rsp+120h] [rbp+20h] BYREF
__int128 v60[2]; // [rsp+140h] [rbp+40h] BYREF
__int128 v61[2]; // [rsp+160h] [rbp+60h] BYREF
__int128 v62[2]; // [rsp+180h] [rbp+80h] BYREF
__int128 v63[2]; // [rsp+1A0h] [rbp+A0h] BYREF
__int128 v64[2]; // [rsp+1C0h] [rbp+C0h] BYREF
__int128 v65[2]; // [rsp+1E0h] [rbp+E0h] BYREF
__int128 v66[2]; // [rsp+200h] [rbp+100h] BYREF
__int128 v67[2]; // [rsp+220h] [rbp+120h] BYREF
__int128 v68[2]; // [rsp+240h] [rbp+140h] BYREF
__int128 v69[2]; // [rsp+260h] [rbp+160h] BYREF
char v70[48]; // [rsp+280h] [rbp+180h] BYREF
char *v71; // [rsp+2C8h] [rbp+1C8h] BYREF
__int128 *v72; // [rsp+2D0h] [rbp+1D0h] BYREF
v1 = -1i64;
v51.m128_u64[0] = 0x6E797AFBF5570CDEi64;
v47.m128_u64[0] = 0x3C5A8F9432649Di64;
v51.m128_u64[1] = 0x3AD429653BEEB61i64;
v47.m128_u64[1] = 0x3AD429636D08206i64;
v51 = _mm_xor_ps((__m128)_mm_load_si128((const __m128i *)&v51), v47);// Decrypted UTF-8: Cheat Engine
v3 = -1i64;
memset(v55, 0, sizeof(v55));
v4 = 0;
do
++v3;
while ( v51.m128_i8[v3] );
sub_FFFFF801BCEF2B2C(v55, &v51);
v47.m128_u64[0] = 0x3C5A8F9432649Di64;
v51.m128_u64[0] = 0x6E5537EEFE5C01DFi64;
v47.m128_u64[1] = 0x3AD429636D08206i64;
v51.m128_u64[1] = 0x3AD3BE65AB5C626i64;
v5 = -1i64;
v51 = _mm_xor_ps((__m128)_mm_load_si128((const __m128i *)&v51), v47);// Decrypted UTF-8: Benjamingine
memset(v56, 0, sizeof(v56));
do
++v5;
while ( v51.m128_i8[v5] );
sub_FFFFF801BCEF2B2C(v56, &v51);
v47.m128_u64[0] = 0x3C5A8F9432649Di64;
v51.m128_u64[0] = 0x205D33C5B45C01CAi64;
v47.m128_u64[1] = 0x3AD429636D08206i64;
v51.m128_u64[1] = 0x3AD429636A5EB4Ai64;
v6 = -1i64;
v51 = _mm_xor_ps((__m128)_mm_load_si128((const __m128i *)&v51), v47);// Decrypted UTF-8: Wen Jia Delpy
memset(v57, 0, sizeof(v57));
do
++v6;
while ( v51.m128_i8[v6] );
sub_FFFFF801BCEF2B2C(v57, &v51);
v47.m128_u64[0] = 0x3C5A8F9432649Di64;
v51.m128_u64[0] = 0x6D5511E8FA5D0CDEi64;
v47.m128_u64[1] = 0x3AD429636D08206i64;
v51.m128_u64[1] = 0x3AD42F857B8C126i64;
v7 = -1i64;
v51 = _mm_xor_ps((__m128)_mm_load_si128((const __m128i *)&v51), v47);// Decrypted UTF-8: ChongKimLiu
memset(v58, 0, sizeof(v58));
do
++v7;
while ( v51.m128_i8[v7] );
sub_FFFFF801BCEF2B2C(v58, &v51);
v47.m128_u64[0] = 0x3C5A8F9432649Di64;
v51.m128_u64[0] = 0x4B6E1BC7C76621D3i64;
v47.m128_u64[1] = 0x3AD429636D08206i64;
v51.m128_u64[1] = 0x3AD42FA51B1D126i64;
v8 = -1i64;
v51 = _mm_xor_ps((__m128)_mm_load_si128((const __m128i *)&v51), v47);// Decrypted UTF-8: NETSHARK Chan
memset(v59, 0, sizeof(v59));
do
++v8;
while ( v51.m128_i8[v8] );
sub_FFFFF801BCEF2B2C(v59, &v51);
v47.m128_u64[0] = 0x3C5A8F9432649Di64;
v51.m128_u64[0] = 0x547D1FC7D76134DBi64;
v47.m128_u64[1] = 0x3AD429636D08206i64;
v51.m128_u64[1] = 0x3AD429636D08255i64;
v9 = -1i64;
v51 = _mm_xor_ps((__m128)_mm_load_si128((const __m128i *)&v51), v47);// Decrypted UTF-8: FPSCHEAT Sagl
memset(v60, 0, sizeof(v60));
do
++v9;
while ( v51.m128_i8[v9] );
sub_FFFFF801BCEF2B2C(v60, &v51);
v51.m128_u64[0] = 0x3C5A8F9432649Di64;
v47.m128_u64[0] = 0x6D4934E6E05308CDi64;
v51.m128_u64[1] = 0x3AD429636D08206i64;
v47.m128_u64[1] = 0x6FCC36FF51B9C626i64;
v10 = _mm_xor_ps((__m128)_mm_load_si128((const __m128i *)&v47), v51);
v11 = -1i64;
v48.m128_u64[0] = 0x9069BF0012660EFi64;
v48.m128_u64[1] = 0x3C2843EC151381F4i64;
si128 = (__m128)_mm_load_si128((const __m128i *)&v48);
v52.m128_u64[0] = 0x4526EB856E5427CFi64;
v52.m128_u64[1] = 0x3C2843EC1513C2B8i64;
v48 = _mm_xor_ps(si128, v52); // Decrypted Raw (unprintable): 72 04 14 95 7f c1 3a 09 4c 43 00 00 00 00 00 00
v47 = v10; // Decrypted UTF-8: PlatinumS
memset(v61, 0, sizeof(v61));
do
++v11;
while ( v47.m128_i8[v11] );
sub_FFFFF801BCEF2B2C(v61, &v47);
v48.m128_u64[1] = 0x3C2843EC1513C2B8i64;
v47.m128_u64[0] = 0x531C12CCD16636D7i64;
v13 = -1i64;
v51.m128_u64[0] = 0x3C5A8F9432649Di64;
v47.m128_u64[1] = 0x23E30DDF6285CE49i64;
v14 = (__m128)_mm_load_si128((const __m128i *)&v47);
v48.m128_u64[0] = 0x4526EB856E546282i64;
v15 = (__m128)_mm_load_si128((const __m128i *)&v48);
v51.m128_u64[1] = 0x3AD429636D08206i64;
v52.m128_u64[0] = 0x4526EB856E5427CFi64;
v52.m128_u64[1] = 0x3C2843EC1513C2B8i64;
v48 = _mm_xor_ps(v15, v52); // Decrypted UTF-8: ME
v47 = _mm_xor_ps(v14, v51); // Decrypted UTF-8: JRTECH S Digital
memset(v62, 0, sizeof(v62));
do
++v13;
while ( v47.m128_i8[v13] );
sub_FFFFF801BCEF2B2C(v62, &v47);
v51.m128_u64[1] = 0x3AD429636D08206i64;
v51.m128_u64[0] = 0x3C36FDC71230D5i64;
v16 = (__m128)_mm_load_si128((const __m128i *)&v51);
v47.m128_u64[0] = 0x3C5A8F9432649Di64;
v17 = -1i64;
v47.m128_u64[1] = 0x3AD429636D08206i64;
v51 = _mm_xor_ps(v16, v47); // Decrypted Raw (unprintable): 02 06 74 16 31 24 20 53 20 44 69 67 69 74 61 6c
memset(v63, 0, sizeof(v63));
do
++v17;
while ( v51.m128_i8[v17] );
sub_FFFFF801BCEF2B2C(v63, &v51);
v51.m128_u64[0] = 0x3C5A8F9432649Di64;
v47.m128_u64[0] = 0x431C34EEF05C05D5i64;
v18 = -1i64;
v51.m128_u64[1] = 0x3AD429636D08206i64;
v47.m128_u64[1] = 0x64C32DD516A9F66Fi64;
v19 = _mm_xor_ps((__m128)_mm_load_si128((const __m128i *)&v47), v51);
v48.m128_u64[0] = 0x315582C14E3D46BBi64;
v48.m128_u64[1] = 0x77410FCC6170ABCAi64;
v20 = (__m128)_mm_load_si128((const __m128i *)&v48);
v49.m128_u64[0] = 0x4AC1249BE823DE60i64;
v49.m128_u64[1] = 0x5DC27D2DFBEB5206i64;
v50.m128_u64[0] = 0x21789A509F80B113i64;
v50.m128_u64[1] = 0x8BBE4558BC680C79ui64;
v53.m128_u64[0] = 0x23A060BBC844B001i64;
v53.m128_u64[1] = 0x2EA61242BCCB2B6Ai64;
v54.m128_u64[0] = 0x4C0CE831EFE5F533i64;
v47 = v19; // Decrypted UTF-8: Handan C
v21 = _mm_xor_ps((__m128)_mm_load_si128((const __m128i *)&v49), v53);
v54.m128_u64[1] = 0x8BBE4558BC1C621Cui64;
v52.m128_u64[0] = 0x4526EB856E5427CFi64;
v52.m128_u64[1] = 0x3C2843EC1513C2B8i64;
v48 = _mm_xor_ps(v20, v52); // Decrypted UTF-8: tai Dist
v50 = _mm_xor_ps((__m128)_mm_load_si128((const __m128i *)&v50), v54);// Decrypted UTF-8: Department
v49 = v21; // Decrypted UTF-8: ang Daily Goods
memset(v64, 0, sizeof(v64));
do
++v18;
while ( v47.m128_i8[v18] );
sub_FFFFF801BCEF2B2C(v64, &v47);
v51.m128_u64[0] = 0x3C5A8F9432649Di64;
v47.m128_u64[0] = 0x205B34E6FE5C05D3i64;
v22 = -1i64;
v51.m128_u64[1] = 0x3AD429636D08206i64;
v47.m128_u64[1] = 0x23C223FF4EB9EA5Ci64;
v23 = _mm_xor_ps((__m128)_mm_load_si128((const __m128i *)&v47), v51);
v48.m128_u64[0] = 0x314786F701324986i64;
v48.m128_u64[1] = 0x544B26B8357DADD1i64;
v24 = (__m128)_mm_load_si128((const __m128i *)&v48);
v49.m128_u64[0] = 0x608019DCA728DF6Fi64;
v49.m128_u64[1] = 0x2EA67636F0E70505i64;
v53.m128_u64[0] = 0x23A060BBC844B001i64;
v47 = v23; // Decrypted UTF-8: Nanjing ity Cong
v25 = (__m128)_mm_load_si128((const __m128i *)&v49);
v53.m128_u64[1] = 0x2EA61242BCCB2B6Ai64;
v52.m128_u64[0] = 0x4526EB856E5427CFi64;
v52.m128_u64[1] = 0x3C2843EC1513C2B8i64;
v49 = _mm_xor_ps(v25, v53); // Decrypted UTF-8: nology Cly Goods
v48 = _mm_xor_ps(v24, v52); // Decrypted UTF-8: Informatrict LiK
memset(v65, 0, sizeof(v65));
do
++v22;
while ( v47.m128_i8[v22] );
sub_FFFFF801BCEF2B2C(v65, &v47);
v51.m128_u64[0] = 0x3C5A8F9432649Di64;
v47.m128_u64[0] = 0x591C3DE1FD4311DBi64;
v51.m128_u64[1] = 0x3AD429636D08206i64;
v47.m128_u64[1] = 0x66E362F857A4EC73i64;
v26 = -1i64;
v27 = _mm_xor_ps((__m128)_mm_load_si128((const __m128i *)&v47), v51);
v48.m128_u64[0] = 0x2072CBEE1C3B50BBi64;
v48.m128_u64[1] = 0x70046D835633AADBi64;
v28 = (__m128)_mm_load_si128((const __m128i *)&v48);
v49.m128_u64[0] = 0x23A060BBC86AD475i64;
v49.m128_u64[1] = 0x2EA61242BCCB2B6Ai64;
v47 = v27; // Decrypted UTF-8: Fuqing YZhixiao
v29 = (__m128)_mm_load_si128((const __m128i *)&v49);
v53.m128_u64[1] = 0x2EA61242BCCB2B6Ai64;
v52.m128_u64[0] = 0x4526EB856E5427CFi64;
v52.m128_u64[1] = 0x3C2843EC1513C2B8i64;
v53.m128_u64[0] = 0x23A060BBC844B001i64;
v49 = _mm_xor_ps(v29, v53); // Decrypted Raw (unprintable): 74 64 2e 00 00 00 00 00 6f 2e 2c 4c 74 64 00 00
v48 = _mm_xor_ps(v28, v52); // Decrypted UTF-8: twork Teion Tech
memset(v66, 0, sizeof(v66));
do
++v26;
while ( v47.m128_i8[v26] );
sub_FFFFF801BCEF2B2C(v66, &v47);
v48.m128_u64[1] = 0x3C2843EC1513C2B8i64;
v47.m128_u64[0] = 0x205233E2FB4001D7i64;
v30 = -1i64;
v51.m128_u64[0] = 0x3C5A8F9432649Di64;
v47.m128_u64[1] = 0x6ADF07B64FB4ED45i64;
v31 = (__m128)_mm_load_si128((const __m128i *)&v47);
v48.m128_u64[0] = 0x4526EB856E5427ACi64;
v32 = (__m128)_mm_load_si128((const __m128i *)&v48);
v51.m128_u64[1] = 0x3AD429636D08206i64;
v52.m128_u64[0] = 0x4526EB856E5427CFi64;
v52.m128_u64[1] = 0x3C2843EC1513C2B8i64;
v48 = _mm_xor_ps(v32, v52); // Decrypted UTF-8: c
v47 = _mm_xor_ps(v31, v51); // Decrypted UTF-8: Jeromin untan Ne
memset(v67, 0, sizeof(v67));
do
++v30;
while ( v47.m128_i8[v30] );
sub_FFFFF801BCEF2B2C(v67, &v47);
v47.m128_u64[0] = 0x3C5A8F9432649Di64;
v51.m128_u64[0] = 0x6B5309AFFD590DD3i64;
v47.m128_u64[1] = 0x3AD429636D08206i64;
v51.m128_u64[1] = 0x3AD429640BFEE69i64;
v33 = -1i64;
v51 = _mm_xor_ps((__m128)_mm_load_si128((const __m128i *)&v51), v47);// Decrypted UTF-8: Niki SokCody Eri
memset(v68, 0, sizeof(v68));
do
++v33;
while ( v51.m128_i8[v33] );
sub_FFFFF801BCEF2B2C(v68, &v51);
v51.m128_u64[0] = 0x3C5A8F9432649Di64;
v47.m128_u64[0] = 0x205B34E6FE5B01DFi64;
v51.m128_u64[1] = 0x3AD429636D08206i64;
v47.m128_u64[1] = 0x66DD2DDE58B9ED4Ci64;
v34 = _mm_xor_ps((__m128)_mm_load_si128((const __m128i *)&v47), v51);
v48.m128_u64[0] = 0x11068EE20F396EEFi64;
v48.m128_u64[1] = 0x5B472F837B7BA1DDi64;
v35 = (__m128)_mm_load_si128((const __m128i *)&v48);
v49.m128_u64[0] = 0x23A04EDFBC089078i64;
v49.m128_u64[1] = 0x2EA61242BCCB2B6Ai64;
v47 = v34; // Decrypted UTF-8: Beijing olov
v36 = (__m128)_mm_load_si128((const __m128i *)&v49);
v53.m128_u64[1] = 0x2EA61242BCCB2B6Ai64;
v52.m128_u64[0] = 0x4526EB856E5427CFi64;
v52.m128_u64[1] = 0x3C2843EC1513C2B8i64;
v53.m128_u64[0] = 0x23A060BBC844B001i64;
v49 = _mm_xor_ps(v36, v53); // Decrypted UTF-8: y Ltd.
v48 = _mm_xor_ps(v35, v52); // Decrypted UTF-8: Image T
memset(v69, 0, sizeof(v69));
do
++v1;
while ( v47.m128_i8[v1] );
sub_FFFFF801BCEF2B2C(v69, &v47);
v48.m128_u64[0] = 0i64;
v71 = v70;
v72 = v55;
v47 = 0i64;
sub_FFFFF801BCEF2EC4(&v47, 15i64, &v72, &v71);
v37 = 15i64;
v38 = (__int64 *)v70;
v39 = 1;
do
{
v38 -= 4;
--v37;
v40 = v38[3];
if ( v40 > 15 )
{
v41 = *v38;
if ( v40 + 1 >= 0x1000 )
{
v42 = *(_QWORD *)(v41 - 8);
v43 = (const char *)(v41 - v42);
if ( (unsigned __int64)(v43 - 8) > 0x1F )
{
Xlength_error(v43);
JUMPOUT(0xFFFFF801BCEF3E7Eui64);
}
v41 = v42;
}
operator_delete(v41);
}
v38[2] = 0i64;
v38[3] = 15i64;
*(_BYTE *)v38 = 0;
}
while ( v37 );
if ( subjectName && *subjectName )
{
for ( i = v47.m128_u64[0]; i != v47.m128_u64[1]; i += 32i64 )// range based loop for vector possibly
{
v45 = (char *)i;
if ( *(_QWORD *)(i + 24) > 15ui64 )
v45 = *(char **)i;
if ( stristr(subjectName, v45) )
goto LABEL_48;
}
}
else
{
v39 = 0;
LABEL_48:
v4 = v39;
}
sub_FFFFF801BCEF4A08(&v47);
return v4;
}
EmacVerifyFileUnknown
is virtualized so i have no idea what’s being verified there.
IDA decompiled snippets
Conclusion
Very solid approaches, minifilter with signature verification on kernel is the today standard. Weak points surely are the global variables, anyone can manipulate the game process id, as well as the variables storing addresses from ntdll, kernel32, etc.