USE AT OWN RISK Как работает EAC [часть 2] | OverlayHack - Good cheats for good users
  • Читы на CS:GO

    Counter-Strike: Global Offensive

    Читы на CS:GO — это запрещенные программы которые дают значительное преимущество в игре Counter-Strike: Global Offensive. За использование неактуальных читов в 2020 вы можете быть забанены VAC. На overlayhack.ru вы можете скачать читы на КС ГО бесплатно, без вирусов и хайдов. Актуальность топика означает что чит работает на последней версии Steam CS: GO и не обнаружен античитом VAC (undetected).

Приветствую всех ещё раз! Сегодня уже будет подготовка по обходу EAC, это лишь метод, который поможет ОБОЙТИ, ведь обойти EAC не значит удержать.

Сброшенные модули
Easy Anticheat использует драйверы ядра и модули пользовательского режима. Вы не можете подключить отладчик, пока не обойдете EAC, поэтому отреверсить EAC становится проблемой. Но, если вы можете войти в ядро, вы можете сбрасывать модули, что позволит вам статически сделать их анализ позже. Эти модули часто обновляются, но у нас есть несколько дампинг. Это ваша первая остановка для изучения того, как обойти EAC, вы можете статически проанализировать эти двоичные файлы и узнать, как работает Easy Anti Cheat.


ВНИМАНИЕ!!!! СЕЙЧАС БУДЕТ ЧАСТЬ С ОТКРЫТЫМ КОДОМ ОБХОДА! ЭТО НЕ ЗНАЧИТ ЧТО ВЫ 100% ОБОЙДЁТЁ EAC, ЭТО ЛИШЬ МЕТОД CVEAC

CVEAC-2020: байпасс EAC
"Разработчики читов особенно заинтересованы в проверках самоконтроля против античитов. Если вы можете их обойти, вы сможете эффективно исправить или "перехватить" любой античит-дамп, который может привести к пику или даже бану. В случае EasyAntiCheat, они используют драйвер режима ядра, который содержит некоторые интересные процедуры обнаружения. Мы обязаны изучить, как работают их проверки целостности и как их обходить, что позволяет эффективно отключить античит.

Обратный процесс
Первое, что нужно сделать, это определить, есть ли какая-либо проверка целостности. Самый простой способ - пропатчить любой лог из .text и посмотреть, решит ли античит выгнать или забанить вас через некоторое время. Примерно через 10-40 секунд после того, как я исправил случайную функцию, меня выгнали, показав, что они действительно проводят проверки целостности в своем модуле ядра. С помощью моего отладчика на основе визора, который использует возможности EPT, я установил точку останова памяти для функции, которая была вызвана их подпрограммой уведомления LoadImage ( PsSetLoadImageNotifyRoutine). Через некоторое время я смог найти, где они обращались к памяти.

Изучив внешние ссылки в IDA Pro и установив некоторые точки останова для инструкций, я обнаружил, откуда вызывается функция проверки целостности, одна из которых находится внутри подпрограммы уведомления CreateProcess (см. PsSetCreateProcessNotifyRoutine). Эта процедура заботится о некоторых частях инициализации античита, таких как создание внутренних структур, которые будут использоваться для представления игрового процесса.

Список регистрируемых модулей EAC.

  1. Dumper.dll
  2. Glob.dll
  3. mswsock.dll
  4. perl512.dll
  5. vmclientcore.dll
  6. vmwarewui.dll
  7. virtualbox.dll
  8. qtcorevbox4.dll
  9. vboxvmm.dll
  10. netredirect.dll
  11. atmfd.dll
  12. cdd.dll
  13. rdpdd.dll
  14. vga.dll
  15. workerdd.dll
  16. msvbvm60.dll

C++:
if ( AttachToProcess(process, (__int64)&v5) )
{
    if ( GetUsermodeModule((UNICODE_STRING *)(StringTable + 4830))// Dumper.dll
        && GetUsermodeModule((UNICODE_STRING *)(StringTable + 4852))// Glob.dll
        && GetUsermodeModule((UNICODE_STRING *)(StringTable + 4870))// mswsock.dll
        && GetUsermodeModule((UNICODE_STRING *)(StringTable + 4894))// perl512.dll
        || GetUsermodeModule((UNICODE_STRING *)(StringTable + 4918))// vmclientcore.dll
        || GetUsermodeModule((UNICODE_STRING *)(StringTable + 4952))// vmwarewui.dll
        || GetUsermodeModule((UNICODE_STRING *)(StringTable + 4980))// virtualbox.dll
        || GetUsermodeModule((UNICODE_STRING *)(StringTable + 5010))// qtcorevbox4.dll
        || GetUsermodeModule((UNICODE_STRING *)(StringTable + 5042))// vboxvmm.dll
        || GetUsermodeModule((UNICODE_STRING *)(StringTable + 5066)) )// netredirect.dll
    {
        v3 = 1;
    }
некоторые драйверы которые по дефолту ищет EAC.
  1. Dbgv.sys
  2. PROCMON23.sys
  3. dbk64.sys

C++:
LOBYTE(v11) = 1;
if ( !(unsigned int)strstr2((__int64)&a1, (const char *)(StringTable + 8038), v11) )// Dbgv.sys
    break;
LOBYTE(v16) = 1;
if ( !(unsigned int)strstr2((__int64)&a1, (const char *)(StringTable + 8047), v16) )// PROCMON23.sys
    break;
LOBYTE(v17) = 1;
if ( !(unsigned int)strstr2((__int64)&a1, (const char *)(StringTable + 8061), v17) )// dbk64.sys
    break;

Процедура обнаружения подозрительных потоков EAC для кода, отображаемого вручную

  • API-интерфейсы,
  • используемые для перечисления потоков и открытия для них дескрипторов: CreateToolhelp32Snapshot, Thread32First, Thread32Next, OpenThread

Получение информации о потоке:

  1. NtQueryInformationThread (ThreadBasicInformation и ThreadQuerySetWin32StartAddress)

Перемещение по стеку:

  • GetThreadContext, RtlLookupFunctionEntry и RtlVirtualUnwind


Шаги по обнаружению подозрительных потоков:

Получение информации от всех потоков в текущем процессе (идентификатор потока, информация о стеке, базовый адрес потока)

C++:
[CODE]//getting thread info
if ( thread_info_obtained )
    {
      thread_info.ExitStatus = thread_basic_info.ExitStatus;
      thread_info.TebBaseAddress = (__int64)thread_basic_info.TebBaseAddress;
      thread_info.Priority = thread_basic_info.Priority;
      thread_info.BasePriority = thread_basic_info.BasePriority;
      thread_info.StartAddress = v18;
      if ( thread_basic_info.TebBaseAddress )
      {
        thread_info.StackBase = *((_QWORD *)thread_basic_info.TebBaseAddress + 1);
        thread_info.StackLimit = *((_QWORD *)thread_basic_info.TebBaseAddress + 2);
      }
      stack_walk_thread(*v8, v14, &thread_info.RipsStackWalk);
LABEL_22:
      v15 = v1->CurrentEntry;
      if ( v1->LastEntry == v15 )
      {
        reallocate_vector_thread_information(v1, v15, &thread_info);
      }
      else
      {
        memcpy_thread_information(v11, v15, &thread_info);
        ++v1->CurrentEntry;
      }
    }
    reset_thread_information_struct(&thread_info);
    ++v8;
    v19 = v8;
  }
[/CODE]

C++:
//stack walking routine
run_count = 0;
  while ( run_count < 9 )
  {
    entry_pc = RtlLookupFunctionEntry(Context.Rip, &v20, 0i64);
    if ( entry_pc )
    {
      RtlVirtualUnwind_0(0i64, v20, Context.Rip, entry_pc, &Context, &v23, &v22, 0i64, thread_rip_1);
      if ( !Context.Rip )
        return vec_rips_stackwalk->FirstEntry != vec_rips_stackwalk->CurrentEntry;
      thread_rip_1 = Context.Rip;
      current_entry = vec_rips_stackwalk->CurrentEntry;
      if ( vec_rips_stackwalk->LastEntry == current_entry )
      {
        reallocate_vector_qword(vec_rips_stackwalk, current_entry, &thread_rip_1);
      }
      else
      {
        *current_entry = Context.Rip;
        ++vec_rips_stackwalk->CurrentEntry;
      }
    }
    ++run_count;
    RtlLookupFunctionEntry = *(__int64 (__fastcall **)(DWORD64, __int64 *, _QWORD))RtlLookupFunctionEntry_0;
  }
  return vec_rips_stackwalk->FirstEntry != vec_rips_stackwalk->CurrentEntry;

На сегодня всё, сегодня практически узнали способ обхода EAC, через 2-3 дня выйдет продолжение.