Este repositorio contiene partes del código fuente de la válvula anti-trato para los sistemas de Windows recreados del código de la máquina.
La válvula anti-trato (VAC) es un sistema anti-trato no invasivo en modo de usuario desarrollado por Valve. Se entrega en forma de módulos (DLL) transmitidos desde el servidor remoto. steamservice.dll cargado en SteamService.exe (o Steam.exe si se ejecuta como administrador) prepara y ejecuta módulos anti-trato. La infraestructura de VAC del cliente se construye utilizando C++ (indicado por muchas funciones de la convención thiscall presentes en el desmontaje) pero este repositorio contiene el código C para simplificar. Los binarios anti-trato son actualmente 32-bit .
| IDENTIFICACIÓN | Objetivo | . Sección de texto TAMAÑO RAW | Carpeta de origen |
|---|---|---|---|
| 1 | Recopilar información sobre la configuración del sistema. Este módulo se carga primero y, a veces, incluso antes de que se lance cualquier juego seguro de vacío. | 0x5c00 | Módulos/systemInfo |
| 2 | Enumere procesos y manijas de ejecución. Este módulo se carga poco después de que se lance el juego, pero también repetidamente más tarde. | 0x4a00 | Módulos/ProcessHandLelist |
| 3 | Recopile datos VacProcessMonitor de FileMapping creados por steamservice.dll . Es el primer módulo observado para usar virtual methods (polymorphism) . | 0x6600 | Módulos/processmonitor |
VAC utiliza varios métodos de cifrado / hash:
NtQuerySystemInformation . Las cadenas son xor-ed con ^ o > o & char.Este módulo se carga primero y, a veces, incluso antes de que se lance cualquier juego seguro de vacío.
En el primer módulo invoca la función GetVersion para recuperar la versión del sistema mayor y de construcción , por ejemplo, 0x47BB0A00 , lo que significa:
18363 )10 ) El módulo llama a la función GetNativeSystemInfo y lee campos de la estructura SYSTEM_INFO resultante:
Luego llama a la función API de NtQuerySystemInformation con los siguientes valores SystemInformationClass (en orden de que aparecen en el código):
SYSTEM_TIMEOFDAY_INFORMATION struct, VAC usa dos campos:SYSTEM_CODEINTEGRITY_INFORMATION , el módulo guarda el campo CodeIntegrityOptionsSYSTEM_DEVICE_INFORMATION , el módulo guarda el campo NumberOfDisksSYSTEM_KERNEL_DEBUGGER_INFORMATION , VAC utiliza toda la estructuraSYSTEM_BOOT_ENVIRONMENT_INFORMATION , VAC Copias BootIdentifier GUIDSYSTEM_RANGE_START_INFORMATION que es simplemente void* . Anti-ideal guarda la dirección de inicio del espacio de núcleo devuelto y firmar esa dirección (para verificar si el ejecutable dentro del que se ejecuta VAC está vinculado con la opción LARGEADDRESSAWARE ) Para obtener más información sobre SYSTEM_INFORMATION_CLASS Enum, consulte la página de Geoff Chappell.
A continuación, las llamadas anti-trato GetProcessImageFileNameA funcionan para recuperar la ruta del ejecutable actual y lee los últimos 36 caracteres (por ejemplo Program Files (x86)SteamSteam.exe ).
Más tarde, VAC recupera la ruta del directorio del sistema (p. Ej. C:WINDOWSsystem32 ) utilizando GetSystemDirectoryW , la convierte de una cadena de ancho a múltiple a múltiple y lo almacena (longitud máxima de la cadena multibitos - 200). La carpeta de consultas anti-trato FILEID (usando GetFileInformationByHandleEx ) y el número de serie de volumen ( GetVolumeInformationByHandleW ). Además, hace lo mismo con el directorio de Windows obtenido de la API GetWindowsDirectoryW .
El módulo lee el archivo NtDll.dll desde el directorio del sistema y hace algo de procesamiento (aún no se invierte).
VAC guarda manijas (direcciones base) de DLLS de sistema importados (MAX 16, este módulo VAC carga 12 dlls) y punteros a las funciones de Winapi (Max 160, el módulo usa 172 funciones). Esto se hace para detectar el enganche de la tabla de direcciones de importación en el módulo anti-trato, si la dirección de función es más baja que la base del módulo correspondiente, la función se ha enganchado.
Anti-trato obtiene la base de los módulos auto realizando bitwise y en la dirección de retorno ( _ReturnAddress() & 0xFFFF0000 ). Luego se acumula:
A continuación, enumera los volúmenes utilizando FindFirstVolumeW / FindNextVolumeW API. Información de volumen de consultas de VAC llamando GetVolumeInformationW , GetDriveTypeW y GetVolumePathNamesForVolumeNameW Funciones y llena la siguiente estructura con datos recopilados:
struct VolumeData {
UINT volumeGuidHash;
DWORD getVolumeInformationError;
DWORD fileSystemFlags;
DWORD volumeSerialNumber;
UINT volumeNameHash;
UINT fileSystemNameHash;
WORD driveType;
WORD volumePathNameLength;
DWORD volumePathNameHash;
}; // sizeof(VolumeData) == 32VAC reúne datos de Max. 10 volúmenes.
Si este módulo se transmitió después de que comenzara el juego seguro de VAC, se entera para manejar el proceso del juego (usando la API OpenProcess ).
Finalmente, el módulo cifra los datos (2048 bytes), dWord por dWord xoring con clave recibida del servidor (por ejemplo, 0x1d4855d3)
Para ser revelado ...
Este módulo parece ser relativamente new o deshabilitado durante mucho tiempo. La primera vez que vi este módulo en January 2020 . Tiene la capacidad de realizar muchos tipos diferentes de escaneos (actualmente 3 ). Los escaneos adicionales dependen de los resultados de los anteriores.
Cada tipo de escaneo implementa four methods de una clase base.
Inicialmente, el servidor VAC instruye al cliente que realice scan #1 .
La primera función de escaneo se intenta abrir Steam_{E9FD3C51-9B58-4DA0-962C-734882B19273}_Pid:%000008X FileMapping. El mapeo tiene el siguiente diseño:
struct VacProcessMonitorMapping {
DWORD magic; // when initialized - 0x30004
PVOID vacProcessMonitor;
}; // sizeof(VacProcessMonitorMapping) == 8 VacProcessMonitorMapping::vacProcessMonitor es un puntero al objeto VacProcessMonitor (el tamaño del cual es 292 bytes ).
VAC luego lee todo el objeto VacProcessMonitor (292 bytes) y su VMT (tabla de métodos virtuales) que contienen punteros a 6 métodos (24 bytes). La dirección base de steamservice.dll también se recopila.
Estos datos probablemente se usan en los servidores VAC para detectar el enganche VacProcessMonitor . El procedimiento puede estar siguiendo:
if (method_ptr & 0xFFFF0000 != steamservice_base)
hook_detected ();