- Статус
- Оффлайн
- Регистрация
- 13 Фев 2026
- Сообщения
- 251
- Реакции
- 6
Приветствую, коллеги.
Наткнулся тут на любопытную механику работы Vanguard Restrictions Messager. Если кто-то копает в сторону обхода уведомлений или взаимодействия с античитом, этот дамп может быть полезен для понимания того, как именно он отрабатывает вызовы.
Суть в том, что сам месседжер можно обойти через хуки:
Ну или реализовать свой метод, если есть другие наработки. Для удобства прикладываю основной фрагмент кода для анализа:
Также, для тех, кто ищет способы легитимизации или просто изучает сигнатуры, вот актуальный список вайтлистед хешей:
Вопрос к знающим: кто-то уже пробовал полноценно дергать эти функции через перехват в рантайме? Есть ли смысл упарываться в хуки, или проще идти через кастомный драйвер и прямой манипуляцией с объектами сессий?
Разбираем, обсуждаем, делимся опытом.
Наткнулся тут на любопытную механику работы Vanguard Restrictions Messager. Если кто-то копает в сторону обхода уведомлений или взаимодействия с античитом, этот дамп может быть полезен для понимания того, как именно он отрабатывает вызовы.
Суть в том, что сам месседжер можно обойти через хуки:
- WTSSendMessageW
- WaitForSingleObject
- CreateProcessAsUserW
Ну или реализовать свой метод, если есть другие наработки. Для удобства прикладываю основной фрагмент кода для анализа:
Код:
__int64 __fastcall sub_D7BA0(unsigned __int64 a1, unsigned __int64 a2, __int64 a3)
{
HANDLE v4; // rax
void *v5; // rbx
DWORD CurrentProcessId; // eax
HMODULE LibraryW; // rdi
FARPROC ProcAddress; // rbx
FARPROC v9; // rax
void (*v10)(void); // rsi
HANDLE CurrentProcess; // rax
__int64 v12; // r8
DWORD active; // eax
__int128 *v14; // rcx
__int64 v15; // rbx
__int128 *v16; // r9
__m128 *p_Parameter; // rcx
__m128 *v18; // r8
WCHAR LibFileName[8]; // [rsp+60h] [rbp-A0h] BYREF
__m128 v21; // [rsp+70h] [rbp-90h]
CHAR ProcName[16]; // [rsp+80h] [rbp-80h] BYREF
__m128 v23; // [rsp+90h] [rbp-70h]
CHAR v24[16]; // [rsp+A0h] [rbp-60h] BYREF
__m128 v25; // [rsp+B0h] [rbp-50h]
__m128 Parameter; // [rsp+C0h] [rbp-40h] BYREF
__m128 v27; // [rsp+D0h] [rbp-30h]
_BYTE ProcessInformation[32]; // [rsp+E0h] [rbp-20h] BYREF
HANDLE hToken; // [rsp+100h] [rbp+0h] BYREF
void *TokenHandle; // [rsp+108h] [rbp+8h] BYREF
LPVOID lpEnvironment; // [rsp+110h] [rbp+10h] BYREF
DWORD pSessionId; // [rsp+118h] [rbp+18h] BYREF
__int128 v33; // [rsp+120h] [rbp+20h] BYREF
__m128i si128; // [rsp+130h] [rbp+30h]
struct _STARTUPINFOW StartupInfo; // [rsp+140h] [rbp+40h] BYREF
hToken = 0LL;
lpEnvironment = 0LL;
v33 = 0LL;
si128 = _mm_load_si128((const __m128i *)&xmmword_4EAC20);
LOWORD(v33) = 0;
Parameter.m128_u64[0] = a1;
Parameter.m128_u64[1] = a2;
v27.m128_u64[0] = 30LL;
v27.m128_i32[2] = 0;
v4 = CreateThread(0LL, 0LL, (LPTHREAD_START_ROUTINE)StartAddress, &Parameter, 0, 0LL);// WTSSendMessageW
v5 = v4;
if ( v4 )
{
WaitForSingleObject(v4, 0x7918u);
CloseHandle(v5);
if ( v27.m128_i32[2] )
{
if ( v27.m128_i32[1] == 1 )
{
if ( a3 )
{
pSessionId = 0;
CurrentProcessId = GetCurrentProcessId();
ProcessIdToSessionId(CurrentProcessId, &pSessionId);
*(_QWORD *)ProcessInformation = 0x3CBF9C9FFF72D2DLL;
*(_QWORD *)&ProcessInformation[8] = 0x6A1932D85C1EE862LL;
*(_QWORD *)&ProcessInformation[16] = 0xDE2087BD6B2BC7FLL;
*(_QWORD *)&ProcessInformation[24] = 0x69CFA552E40CE5D4LL;
Parameter.m128_u64[0] = 0x3B9F9ACFF842D78LL;
Parameter.m128_u64[1] = 0x6A3732AE5C70E807LL;
v27.m128_u64[0] = 0xDE20817D6DEBC1BLL;
v27.m128_u64[1] = 0x69CFA552E40CE5D4LL;
*(__m128 *)LibFileName = _mm_xor_ps(Parameter, *(__m128 *)ProcessInformation);
v21 = _mm_xor_ps(v27, *(__m128 *)&ProcessInformation[16]);
LibraryW = LoadLibraryW(LibFileName);
if ( LibraryW )
{
*(_QWORD *)ProcessInformation = 0x3CBF9C9FFF72D2DLL;
*(_QWORD *)&ProcessInformation[8] = 0x6A1932D85C1EE862LL;
*(_QWORD *)&ProcessInformation[16] = 0xDE2087BD6B2BC7FLL;
*(_QWORD *)&ProcessInformation[24] = 0x69CFA552E40CE5D4LL;
Parameter.m128_u64[0] = 0x6D8E9CBD9E925F6ELL;
Parameter.m128_u64[1] = 0x47C5FB6336C8114LL;
v27.m128_u64[0] = 0xDE26318B9DEFE0BLL;
v27.m128_u64[1] = 0x69CFA552E40CE5D4LL;
*(__m128 *)ProcName = _mm_xor_ps(Parameter, *(__m128 *)ProcessInformation);
v23 = _mm_xor_ps(v27, *(__m128 *)&ProcessInformation[16]);
ProcAddress = GetProcAddress(LibraryW, ProcName);
*(_QWORD *)ProcessInformation = 0x3CBF9C9FFF72D2DLL;
*(_QWORD *)&ProcessInformation[8] = 0x6A1932D85C1EE862LL;
*(_QWORD *)&ProcessInformation[16] = 0xDE2087BD6B2BC7FLL;
*(_QWORD *)&ProcessInformation[24] = 0x69CFA552E40CE5D4LL;
Parameter.m128_u64[0] = 0x46B296BB8B844869LL;
Parameter.m128_u64[1] = 0xF745CB72E779E0CLL;
v27.m128_u64[0] = 0xD896B14BAF0C811LL;
v27.m128_u64[1] = 0x69CFA552E40CE5D4LL;
*(__m128 *)v24 = _mm_xor_ps(Parameter, *(__m128 *)ProcessInformation);
v25 = _mm_xor_ps(v27, *(__m128 *)&ProcessInformation[16]);
v9 = GetProcAddress(LibraryW, v24);
v10 = (void (*)(void))v9;
if ( ProcAddress && v9 )
{
if ( pSessionId )
goto LABEL_32;
TokenHandle = 0LL;
CurrentProcess = GetCurrentProcess();
if ( OpenProcessToken(CurrentProcess, 0xF01FFu, &TokenHandle) )
{
*(_QWORD *)ProcessInformation = 0x3CBF9C9FFF72D2DLL;
*(_QWORD *)&ProcessInformation[8] = 0x6A1932D85C1EE862LL;
*(_QWORD *)&ProcessInformation[16] = 0xDE2087BD6B2BC7FLL;
*(_QWORD *)&ProcessInformation[24] = 0x69CFA552E40CE5D4LL;
Parameter.m128_u64[0] = 0x3A8F99DFF922D7ELL;
Parameter.m128_u64[1] = 0x6A7032AA5C4EE800LL;
v27.m128_u64[0] = 0xD870817D6DBBC09LL;
v27.m128_u64[1] = 0x69CFA552E469E5B3LL;
Parameter = _mm_xor_ps(Parameter, *(__m128 *)ProcessInformation);
v27 = _mm_xor_ps(v27, *(__m128 *)&ProcessInformation[16]);
LOBYTE(v12) = 1;
sub_F8AA0(TokenHandle, &Parameter, v12);
CloseHandle(TokenHandle);
}
active = WTSGetActiveConsoleSessionId();
if ( (unsigned int)QueryUserToken(active, &hToken) )
{
LABEL_32:
if ( ((unsigned int (__fastcall *)(LPVOID *, HANDLE, __int64))ProcAddress)(&lpEnvironment, hToken, 1LL)
&& (unsigned __int8)sub_D7740(hToken, &v33) )
{
v14 = &v33;
if ( si128.m128i_i64[1] > 7uLL )
v14 = (__int128 *)v33;
v15 = (int)sub_E21B0(v14, a3);
Parameter = 0LL;
v27 = (__m128)_mm_load_si128((const __m128i *)&xmmword_4EAC20);
Parameter.m128_i16[0] = 0;
sub_CD860(&Parameter, v15 + 1);
v16 = &v33;
if ( si128.m128i_i64[1] > 7uLL )
LODWORD(v16) = v33;
p_Parameter = &Parameter;
if ( v27.m128_u64[1] > 7 )
LODWORD(p_Parameter) = Parameter.m128_i32[0];
sub_E2140((_DWORD)p_Parameter, v15 + 1, si128.m128i_i32[0], (_DWORD)v16, a3);
memset(&StartupInfo.cb + 1, 0, 100);
StartupInfo.cb = 104;
memset(ProcessInformation, 0, 24);
v18 = &Parameter;
if ( v27.m128_u64[1] > 7 )
v18 = (__m128 *)Parameter.m128_u64[0];
if ( CreateProcessAsUserW(
hToken,
0LL,
(LPWSTR)v18,
0LL,
0LL,
0,
0x420u,
lpEnvironment,
0LL,
&StartupInfo,
(LPPROCESS_INFORMATION)ProcessInformation) )
{
CloseHandle(*(HANDLE *)ProcessInformation);
CloseHandle(*(HANDLE *)&ProcessInformation[8]);
}
VGC_WStr_Destroy(&Parameter);
}
}
}
if ( lpEnvironment )
v10();
FreeLibrary(LibraryW);
if ( hToken )
CloseHandle(hToken);
}
}
}
}
}
return VGC_WStr_Destroy(&v33);
}
Также, для тех, кто ищет способы легитимизации или просто изучает сигнатуры, вот актуальный список вайтлистед хешей:
Код:
"6b3b4992ac7003797b25510e2142e68cde4c762b","83fa0fb4bfb2eafcb60b2213a521f9cb66368e27","0027bb9f956056b469b1dfd7cebd23c53b8f6f79","97b52574e15ef740531fca85e1cae85b5a2a81da","672499b0d7c7681aa42cebf22eb4368813d7d4b3","5a3ab2cac8775a050d8dd38d56cf28871a95db8d","92e520459e7f93d8d91ec5d78d0fe1bdefdb0e06","38c7b3846244f87b702fad14a7f54fe5a29ad34e","824bdcff868a17043ccd8909299650b5ad5c9dee","d686c8d1c7bc340ccaabf2a23b7fb74ce9fe178b","7f530281c5ba86b81ae4230dab1617cb55260d9e","13516890a00a9b004ef8b2e9a9901504b8c84dae","f45c326eb377ab9667e0d0d3ec72c4417dbb2286","48b2f27c3468a11a693a115a510c96c32468c734","c521025c55687c1f29b1f3a3c69b3d152ce84981","2bbb5e521ca92fd885873b76af07d58053e39067","e1b50088ed92b60a1400cd60c2afae9808ea15b3","fbfef415104e20b86d86c051653d5ed61e003943","0ef4679521b05f40eba025ef063d8061b49c93e8","92de6eafef2a0fad235b69f1f1a00d8c50a121d1","e9a35d72ad9c0f35c77912d454915d5f76356c41","91180ed89976d16353404ac982a422a707f2ae37","42c3957e46997d88b257315be61c1c9c7cda5bf1","1f15ac2ba806275afa35ab9373bacd5f5f8533d2","234e3ed163f6d1f9b93368d83112d4340ceafe2f","dd7195ffa375b3e2b6d32bfae755f474641f049a","3f64c98f22da277a07cab248c44c56eedb796a81","3d824f6aa75611478e56f4f56d0a6f6db8cb1c9b","e4e3f6bbad17b41a42687b3d75ade4a10b0870ec","ddb988b23c7516d2accfcd1796aceb2de705fbe1","660e47d00af463cdb615026565f06d9edb896fee","1b199e0dc32b76eca078f2878f1880f8ef330799","6c8be217856ca0378fb0e0a62c24a62771fce049","4568aff6010b4eabde4e141e7eebc4b53deb7ba0","3d26b0dc519e04999118f4a02ea8acd5f1db8feb","4f58be64ebff5be3132122612cbd3983cf7d05f7","341af85b4fe8b55c6f9875abd76dfea3a0e1f29d","8b9c5f448f8c08f3162638ce455a3a52ba6d9ee7","07d0249357b792bd35cdc0d23a2b2fa2b1fdbd4b","e3ce7157dc3334a1d95f2aad137d9ca66160b71c","73ccf556516c5e8a450f4d9b44b004dfad57d7b1","953fb3d50404336d9e3b220fd15f770e90a369a0","06395febb61b01844e23f42eec0a01b3bd4f65a8","944bb7170090377d57b65aa3aedb4068f474184e","2c33d4573e21c7d18de1d3f337bacd7c4e58fe87","e88efd65b405e1821c6e427500d78b57fe9ef20b","b74c93f07fa1bfe70950f0f71f5fbcb7cfd2bb98","026123af200ca87911e62b46a578afcf7479d6c4","f948a4c5e01a74b17d0f966615834ba76dc1badc","c2342aadac5b6dc6c9d2ff2e6ba5af0c40ed329c","73569b302c7811efdaa387b24d7bf4ad28e6d687","def9de1a7310f464ddd6b770e34de0205d650b45","200055b8a095a51e7d1604865d32f458ff72d540","098ad48e3787adbcda57c4e39a45ac8a6ca35359","964c42a4b15f0456d21673129a30fb9e78f219cb","a44b02c5c4750258566f0709b2ec8063802d5037","0811c39fd76395ed47646310bf5ecf57a0ac8ce4"
Вопрос к знающим: кто-то уже пробовал полноценно дергать эти функции через перехват в рантайме? Есть ли смысл упарываться в хуки, или проще идти через кастомный драйвер и прямой манипуляцией с объектами сессий?
Разбираем, обсуждаем, делимся опытом.