このリポジトリには、マシンコードから再現されたWindowsシステム用のValve Anti-Cheatのソースコードの一部が含まれています。
Valve Anti-Cheat(VAC)は、Valveによって開発されたユーザーモードの非侵襲的アンチチートシステムです。リモートサーバーからストリーミングされたモジュール(DLL)の形式で配信されます。 steamservice.dll SteamService.exe (または管理者として実行される場合はSteam.exe )にロードされます。クライアントVACインフラストラクチャは、 C++を使用して構築されています(分解に存在する多くのthiscallコンベンション関数で示されています)が、このレポは単純化のためのCコードが含まれています。現在、アンチチートバイナリは32-bitです。
| id | 目的 | .textセクションRAWサイズ | ソースフォルダー |
|---|---|---|---|
| 1 | システム構成に関する情報を収集します。 このモジュールは、最初にロードされ、時にはVACが担保されたゲームが起動する前にさえロードされます。 | 0x5C00 | モジュール/SystemInfo |
| 2 | 実行中のプロセスとハンドルを列挙します。 このモジュールは、ゲームが起動された直後にロードされますが、後で繰り返し繰り返します。 | 0x4a00 | モジュール/ProcessHandleList |
| 3 | steamservice.dllによって作成されたFileMappingからVacProcessMonitorデータを収集します。これは、 virtual methods (polymorphism)を使用するために観察された最初のモジュールです。 | 0x6600 | モジュール/ProcessMonitor |
VACはいくつかの暗号化 /ハッシュメソッドを使用します。
NtQuerySystemInformation 。文字列は、 ^ or >または& chでXor-edです。このモジュールは、最初にロードされ、時にはVACが担保されたゲームが起動する前にさえロードされます。
最初にモジュールがGetVersion関数を呼び出してメジャーおよび構築システムバージョンなどの0x47BB0A00ビルドします。
18363年数)10進10)モジュールは、 GetNativeSystemInfo関数を呼び出し、結果のSYSTEM_INFO structからフィールドを読み取ります。
次に、次のSystemInformationClass値を持つNtQuerySystemInformation API関数を呼び出します(コードに表示されるため):
SYSTEM_TIMEOFDAY_INFORMATION structを返し、VACは2つのフィールドを使用します。SYSTEM_CODEINTEGRITY_INFORMATIONを返し、モジュールはCodeIntegrityOptionsフィールドを保存しますSYSTEM_DEVICE_INFORMATIONを返し、モジュールはNumberOfDisksフィールドを保存しますSYSTEM_KERNEL_DEBUGGER_INFORMATIONを返す、VACは完全なstructを使用しますSYSTEM_BOOT_ENVIRONMENT_INFORMATIONを返し、vac Copies BootIdentifier GuidSYSTEM_RANGE_START_INFORMATIONを返しますvoid* Anti-Cheat Saves Returned Kernel Space Startアドレスとそのアドレスのビットに署名します(実行中のVACが実行されているかどうかを確認するには、 LARGEADDRESSAWAREオプションにリンクされています) SYSTEM_INFORMATION_CLASS enumの詳細については、Geoff Chappellのページを参照してください。
次に、アンチチートはGetProcessImageFileNameA機能を呼び出して現在の実行可能ファイルのパスを取得し、最後の36文字(eg Program Files (x86)SteamSteam.exe )を読み取ります。
その後、VACは、 GetSystemDirectoryWを使用してシステムディレクトリパス( C:WINDOWSsystem32など)を取得し、ワイドチャーからマルチバイトストリングに変換し、保存します(マルチバイト文字列-200の最大長)。アンチチートクエリフォルダーFileID( GetFileInformationByHandleExを使用)およびボリュームシリアル番号( GetVolumeInformationByHandleW )。さらに、 GetWindowsDirectoryW APIから取得したWindowsディレクトリでも同じことが行われます。
モジュールは、システムディレクトリからNtDll.dllファイルを読み取り、いくつかの処理を行います(まだ逆転していません)。
VACは、インポートされたシステムDLL(最大16、このVACモジュールが12 DLLをロードする)のハンドル(ベースアドレス)を保存し、 Winapi関数(最大160、モジュールは172関数を使用します)にポインターを保存します。これは、機能アドレスが対応するモジュールベースよりも低い場合、アンチチートモジュールでのインポートアドレステーブルのフックを検出するために行われ、機能がフックされています。
アンチチートは、ビットワイズを実行して返品アドレス( _ReturnAddress() & 0xFFFF0000 )で実行することにより、セルフモジュールベースを取得します。それからそれは収集します:
次に、 FindFirstVolumeW / FindNextVolumeW APIを使用してボリュームを列挙します。 VACは、 GetVolumeInformationW 、 GetDriveTypeW 、 GetVolumePathNamesForVolumeNameWの関数を呼び出してボリューム情報をクエリし、収集されたデータで構造体に続いて埋めます。
struct VolumeData {
UINT volumeGuidHash;
DWORD getVolumeInformationError;
DWORD fileSystemFlags;
DWORD volumeSerialNumber;
UINT volumeNameHash;
UINT fileSystemNameHash;
WORD driveType;
WORD volumePathNameLength;
DWORD volumePathNameHash;
}; // sizeof(VolumeData) == 32VACは最大のデータを収集します。 10巻。
このモジュールがVAC-Securedゲームが開始された後にストリーミングされた場合、ゲームプロセス( OpenProcess APIを使用)を処理することができます。
最終的に、モジュールはデータ(2048バイト)を暗号化し、DWORDによるDWORD XORINGを使用してサーバーから受信したキー(例:0x1D4855D3)
開示される...
このモジュールは比較的newように見えるか、長い間無効になっていたようです。 January 2020にこのモジュールを初めて見ました。さまざまな種類のスキャンを実行する機能があります(現在3 )。さらなるスキャンは、以前の結果の結果に依存します。
各スキャンタイプは、ベースクラスのfour methodsを実装します。
当初、VACサーバーはクライアントにscan #1実行するよう指示します。
Steam_{E9FD3C51-9B58-4DA0-962C-734882B19273}_Pid:%000008X filemapping。マッピングには次のレイアウトがあります。
struct VacProcessMonitorMapping {
DWORD magic; // when initialized - 0x30004
PVOID vacProcessMonitor;
}; // sizeof(VacProcessMonitorMapping) == 8 VacProcessMonitorMapping::vacProcessMonitor 、 VacProcessMonitorオブジェクトへのポインターです(サイズは292 bytesです)。
VACは、 6方法(24バイト)へのポインターを含むVacProcessMonitorオブジェクト全体(292バイト)とそのVMT(仮想メソッドテーブル)を読み取ります。 steamservice.dllのベースアドレスも収集されます。
これらのデータは、おそらくVACサーバーで使用されて、 VacProcessMonitorフックを検出します。手順は次のとおりです。
if (method_ptr & 0xFFFF0000 != steamservice_base)
hook_detected ();