Jump to content

Как EAC обнаруживает окна читов через EnumWindows и как это обойти


_xvi

379 views

EAC (Easy Anti-Cheat) - это программное обеспечение, используемое для защиты онлайн-игр от читеров. Одной из его функций является обнаружение процессов и окон, связанных с читом. В этой статье мы рассмотрим, как EAC использует функцию EnumWindows для обнаружения читерских окон.

Функция EnumWindows является частью библиотеки Windows API и используется для перечисления всех окон в системе. Когда EAC запускается, он начинает перечислять все верхние окна в системе с помощью этой функции. Однако EAC не просто перечисляет все окна, он ищет определенные характеристики окон, связанные с читом.

Какие именно характеристики EAC ищет в окнах? Некоторые из них могут быть:

  • Имя окна: некоторые читы имеют уникальные имена окон, которые могут быть использованы для их обнаружения.
  • Размер окна: если окно читера имеет фиксированный размер, EAC может проверить все окна на этот размер.
  • Стили окна: например, окно пропускает клики или отображается на весь экран.
  • Идентификатор процесса: если EAC уже знает идентификатор процесса читера, он может проверить все окна на принадлежность к одному процессу.

Если EAC находит окно, которое соответствует одной из этих характеристик, то он может сделать вывод, что в системе запущен чит. В этом случае EAC может "пометить" игрока или даже заблокировать доступ к онлайн-игре.

Функция EnumWindows является очень мощным инструментом обнаружения чит-окон для EAC. Однако разработчики читов могут попытаться обойти это обнаружение, используя такие методы, как изменение имени или размера окна, внедрение его в легитимный (подписанный) процесс, удаление окна из NtUserBuildHwndList и подобных функций.

  • В Windows легитимный процесс с подписью означает процесс, который подписан цифровой подписью с действительным сертификатом, выданным доверенным центром сертификации. Цифровая подпись обеспечивает надежный способ проверки подлинности и целостности программного обеспечения перед его выполнением.
  • NtUserBuildHwndList - это функция в операционной системе Windows, которая строит список всех окон верхнего уровня, принадлежащих рабочему столу вызывающего потока. Эта функция является частью Win32 API и используется приложениями для итерационного просмотра всех окон, которые в данный момент открыты на рабочем столе.

Псевдокод от chatgpt >3:

void __fastcall enum_windows_callbacks(__int64 context) 
{
    struct_v10* v10 = v1;
    __int64 window1 = context;
    __int64 window2 = getGetForegroundWindow_pid(context, v2);
    
    // Check if windows are valid
    if (!window2 || window2 == window1) 
        return;
    
    // Get window styles and check if window is visible
    eAc_Get_api_callback(&unk_D8CB8, Get_GetWindowLongPtrW, &GetWindowLongPtrW);
    __int64 window_exstyle = GetWindowLongPtrW ? GetWindowLongPtrW(window1, 0xFFFFFFECi64) : 0i64;
    
    if (_bittest64(&window_exstyle, 0x13u)) {
        unsigned int (__fastcall* IsWindowVisible)(__int64);
        __int64 user32 = get_user32();
        IsWindowVisible = (unsigned int(__fastcall*)(__int64))get_exp(user32, &unk_C9288, 0i64);
        
        if (!IsWindowVisible || !IsWindowVisible(window1))
            return;
        
        // Get window dimensions and check if it's within foreground window
        tagRECT window_rect, window_Rect;
        eAc_Get_api_callback(&unk_D8CC0, Get_GetWindowRect, &GetWindowRect);
        
        if (!GetWindowRect || !(unsigned int)GetWindowRect(window1, &window_rect)) 
            return;
        
        if (!GetWindowRect || !(unsigned int)GetWindowRect(window2, &window_Rect)) 
            return;
        
        int width = window_rect.right - window_rect.left;
        int height = window_rect.bottom - window_rect.top;
        
        if (width <= 0 || height <= 0) 
            return;
        
        if (window_rect.left >= window_Rect.right ||
            window_rect.right <= window_Rect.left ||
            window_rect.top >= window_Rect.bottom ||
            window_rect.bottom <= window_Rect.top)
            return;
        
        // Get window title and class name
        __int128 WindowText, ClassName;
        sub_59E58(&WindowText, 0i64, 148i64);
        
        if ((signed int)imp_GetWindowTextW(window1, &v51, 0x40i64) > 0)
            cus_memcpy(&WindowText, 0x40i64, &v51);
            
        if ((signed int)imp_GetClassNameW(window1, &v51, 0x40i64) > 0)
            cus_memcpy(&ClassName, 0x40i64, &v51);
            
        // Get window thread/process IDs and styles
        eAc_Get_api_callback(&unk_D8CB8, Get_GetWindowLongPtrW, &GetWindowLongPtrW);
        int window_style = GetWindowLongPtrW ? GetWindowLongPtrW(window1, 0xFFFFFFF0i64) : 0;
        int window_exstyle_1 = window_exstyle;
        int pid = 0, tid = imp_GetWindowThreadProcessId(window1, &pid);
        int pid_1 = 0, tid_2 = tid_1 = imp_GetWindowThreadProcessId(window1, &pid_1);
        tagRECT window_rect_1 = window_rect;
        
        // Check window properties
        if ((unsigned int)eAc_Crc_or_Xor(&WindowText, get_bytes_Count(&WindowText), 0i64) != 0x3BC41165 ||
            (unsigned int)eAc_Crc_or_Xor(&ClassName, get_bytes_Count(&ClassName), 0i64) != 0x3BC41165 ||
            window_style != 2483027968 || window_exstyle_1 != 0x8280028 ||
            pid != pid_1 || tid_2 != tid_1 ||
            (unsigned int)cmp_window_size((unsigned __int8*)&window_Rect, (unsigned __int8*)&window_rect, 16i64)) {
            return;
        }
        
        // Store window data in struct and increment result count
        __int64 v29 = v10->qword10;
        __int64 v30 = *(_QWORD*)(v29 + 8);
        
        if ((_QWORD*)(v29 + 0x10) == v30)
            sub_AB2E4(v29, v30, &WindowText);
        else {
            *(_OWORD*)v30 = WindowText;
            *(_OWORD*)(v30 + 16) = ClassName;
            *(_DWORD*)(v30 + 48) = pid;
            *(_DWORD*)(v30 + 52) = tid;
            *(_QWORD*)(v30 + 56) = window_style;
            *(_QWORD*)(v30 + 64) = window_exstyle_1;
            *(_QWORD*)(v30 + 72) = width;
            *(_QWORD*)(v30 + 80) = height;
        
        	v10->qword10 += 88i64;
        	++v10->dword8;
    	}
}

Источники:

https://blog.adeltax.com/window-z-order-in-windows-10/

https://blog.renjing.wang/702.html

https://www.unknowncheats.me/forum/anti-cheat-bypass/581931-fullscreen-overlays-window-bands.html

https://www.unknowncheats.me/forum/anti-cheat-bypass/306271-ring-1-bypass.html

0 Comments


Recommended Comments

There are no comments to display.

Guest
Add a comment...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

×
×
  • Create New...