Этот документ представляет собой технический анализ процесса запуска и работы античита EasyAntiCheat_EOS.sys (EAC) на уровне ядра. Исследование разбивает работу драйвера на этапы: от инициализации до непрерывного мониторинга системы.
Ниже приведено подробное описание ключевых фаз работы EAC:
1. Начальная инициализация и виртуализация
Сразу после загрузки драйвер выполняет подготовительные действия:
Диагностика: EAC записывает четыре значения в реестр (состояние сервиса, время начала инициализации, адрес базы драйвера и его размер). Это необходимо для отладки и анализа причин сбоев при последующих загрузках.
Слой виртуализации: Основная логика скрыта внутри собственной виртуальной машины (секция .sec7 занимает 33,3 МБ из 37 МБ общего объема драйвера). Она содержит более тысячи уникальных обработчиков, которые скрывают дерево принятия решений античита.
2. Основные «защитные ворота» (Anti-Debug)
EAC использует несколько техник для обнаружения отладчиков и эмуляторов на раннем этапе:
Ловушка INT 1 и SEH: Это главный механизм проверки. Драйвер намеренно вызывает исключение (Single-Step), ожидая, что оно будет обработано локальным обработчиком исключений (SEH). Если отладчик перехватывает это событие сам, EAC прекращает загрузку с ошибкой STATUS_DRIVER_UNABLE_TO_LOAD.
Проверка времени (RDTSC): Проводится серия замеров времени между вызовами инструкций для обнаружения задержек, вносимых инструментами отладки или виртуализации. Количество итераций цикла рандомизируется при каждом запуске.
Ловушка INT 3: Аналогично проверке INT 1, используется для подтверждения того, что механизмы обработки исключений в системе не скомпрометированы.
3. Сбор информации об окружении (Anti-VM)
Драйвер агрессивно собирает данные для идентификации виртуальных сред и аппаратного обеспечения:
Обнаружение гипервизора: EAC запрашивает информацию о разделяемой странице гипервизора (через NtQuerySystemInformation класс 0xC5).
Hardware Fingerprinting: Собираются данные SMBIOS (серийные номера плат, версия BIOS, UUID системы) и сканируется пространство конфигурации PCI (512 вызовов HalGetBusDataByOffset).
Черные списки: Проверяется наличие специфических драйверов для виртуальных машин (VirtualBox, VMware, Hyper-V) и инструментов взлома (Cheat Engine, Process Monitor).
4. Рабочие потоки и непрерывный мониторинг
После прохождения первичных проверок создаются рабочие потоки (обычно 5), которые берут на себя основную нагрузку:
База доверенных сертификатов: EAC очень агрессивно сканирует хранилища сертификатов Windows (около 1000 запросов значений), выстраивая базу для последующей проверки подписей кода.
Проверка каталогов: Верифицируются файлы .cat в директории CatRoot для подтверждения целостности системных файлов.
Мониторинг процессов и потоков: Постоянно сканируются списки активных процессов, их токены и дескрипторы (handles) на предмет подозрительной активности.
Сканирование памяти: Используется MmCopyVirtualMemory для поиска инъекций кода, «трамплинов» (trampolines) и подозрительных паттернов в адресном пространстве процессов.
5. Контроль целостности ядра
EAC следит за тем, чтобы важные системные модули не были модифицированы:
Анализ таблиц экспорта: Драйвер многократно считывает код и таблицы экспорта таких модулей, как FLTMGR.SYS (более 10 000 чтений), hal.dll, CI.dll и cng.sys. Это позволяет обнаруживать установленные «инлайн-хуки» (inline hooks).
Проверка драйвера диска: Проверяется таблица диспетчеризации драйвера disk, чтобы убедиться в отсутствии перехватов.
Собственная целостность: В коде присутствует сложная функция VerifyCodeIntegrityOrCrashB, которая использует обфусцированные таблицы для вычисления хеш-суммы критических регионов самого античита. Если хеш не совпадает, система вызывает __fastfail или провоцирует сбой через обнуление регистра CR3.
Резюме
Исследование показывает, что функция DriverEntry является лишь подготовительным этапом. Основная анти-отладочная защита завязана на корректную работу механизмов SEH. Вся реальная работа по мониторингу перекладывается на системные рабочие потоки, которые продолжают функционировать даже в тех случаях, когда основной поток инициализации возвращает ошибку отсутствия объекта. Драйвер практически не меняет своего поведения в зависимости от вендора процессора (AMD или Intel), используя идентичные пути выполнения кода для обеих платформ.