Чит своими руками. Обходим простой античит и исследуем игру на Unity

Содержание статьи

  • Античит
  • Quick Universal Anti-Cheat Kit
  • Архитектура Quack
  • Настраиваем Quack
  • Проверяем работоспособность Quack
  • Unity
  • Mono
  • IL2CPP
  • Изучаем и обходим античит
  • Обходим детект по HWID
  • Обходим детект сигнатур
  • Обходим черный список DNS
  • Обходим принудительное завершение Cheat Engine
  • Анализируем пакеты
  • Выводы

В этой статье я поп­робую показать, как соз­дать собс­твен­ный чит, который будет про­тивос­тоять исполь­зуемым в играх анти­чит‑сис­темам. Для это­го нам понадо­бит­ся поуп­ражнять­ся в ревер­се и поз­накомить­ся с устрой­ством игр, написан­ных на Unity. Дру­гие статьи цик­ла о написа­нии читов

  • Вскры­ваем компь­ютер­ную игру и пишем трей­нер на C++
  • Смот­рим сквозь сте­ны и дела­ем автопри­цели­вание для 3D-шутера

 

Античит

Итак, анти­чит — это некая прог­рамма, которая меша­ет игро­кам в онлай­новые игры получать нечес­тное пре­иму­щес­тво за счет исполь­зования сто­рон­него ПО. Не буду пытать­ся объ­яснить это на абс­трак­тном при­мере, луч­ше давай сра­зу перей­дем к прак­тике. По дороге все пой­мешь!

 

Quick Universal Anti-Cheat Kit

Так как нет (или я прос­то не нашел) анти­читов уров­ня ядра с откры­тым исходным кодом, то выбирать будем из опен­сор­сных анти­читов, в которых при­сутс­тву­ет толь­ко анти­чит поль­зователь­ско­го уров­ня. Мой выбор пал на анти­чит Quick Universal Anti-Cheat Kit (далее Quack).

Сра­зу пре­дуп­реждаю, что Quack — это лишь прос­тень­кая опен­сор­сная демонс­тра­ция кон­цепции. Обой­ти ее про­ще, чем сис­темы, которые исполь­зуют­ся в популяр­ных играх. Все ком­мерчес­кие анти­читы работа­ют как на поль­зователь­ском уров­не, так и  на уров­не ядра. При­чем самые важ­ные защит­ные фун­кции обыч­но реали­зова­ны имен­но в виде драй­вера.

Од­нако для обу­чения Quack сго­дит­ся как нель­зя луч­ше, и изло­жен­ное даль­ше дол­жно стать фун­дамен­том для будущих изыс­каний.

warning

Статья име­ет озна­коми­тель­ный харак­тер и пред­назна­чена для оцен­ки защищен­ности кода игр. Автор и редак­ция не несут ответс­твен­ности за любой вред, при­чинен­ный с при­мене­нием изло­жен­ной информа­ции. Обратная раз­работ­ка анти­читов наруша­ет поль­зователь­ские сог­лашения игр, поэто­му, пов­торяя опи­сан­ное в этой статье на прак­тике, ты дей­ству­ешь на свой страх и риск!

 

Архитектура Quack

Да­вай пос­мотрим на общую архи­тек­туру анти­чита гла­зами ее авто­ра. Далее я объ­ясню, для чего нужен каж­дый выделен­ный на схе­ме ком­понент.

Ар­хитек­тура Quack

Зе­леным цве­том я выделил кли­ент­скую часть (то, что будет работать на компь­юте­ре игро­ка):

  • Protected video game — игра, которую мы запус­каем на сво­ем компь­юте­ре и которую будет защищать анти­чит;
  • Anti-cheat .DLL — поль­зователь­ская часть анти­чита, DLL, которая сущес­тву­ет в кон­тек­сте соз­данно­го про­цес­са игры и которая отве­чает за защиту памяти про­цес­са игры;
  • Standalone usermode anti-cheat process — поль­зователь­ская часть анти­чита. Это глав­ный модуль анти­чита (оркес­тра­тор), который обща­ется с поль­зователь­ской и ядер­ной час­тями, а так­же дер­жит связь с сер­вером анти­чита;
  • Kernel mode anti-cheat — ядер­ная часть анти­чита. Отве­чает за защиту двух дру­гих модулей анти­чита. Не реали­зова­но.

Си­ним цве­том я выделил сер­верную часть (то, что будет работать вне компь­юте­ра игро­ка):

  • Master server — отве­чает за хра­нение учет­ной записи игро­ка и управле­ние ею;
  • Game server — отве­чает за отсле­жива­ние сос­тояния эле­мен­тов в игре, а так­же мес­тополо­жения игро­ков и вра­гов на кар­те;
  • Anti-cheat database — база дан­ных игро­ков.

 

Настраиваем Quack

Ес­ли пос­ле раз­верты­вания Quack (как это сде­лать, смот­ри в руководс­тве на GitHub и на YouTube) у тебя ничего работа­ет, то советую пов­ниматель­нее изу­чить сле­дующие фай­лы и нас­тро­ить сетевые адре­са и пор­ты в соот­ветс­твии с реаль­ными усло­виями.

GameDevCAServerProgram.cs var settings = MongoClientSettings.FromConnectionString(env["DB_URI"]);settings.ServerApi = new ServerApi(ServerApiVersion.V1);var mongoClient = new MongoClient(settings);database = mongoClient.GetDatabase(env["DB_NAME"]);Quack-serversrcmain.js class Config { static DB_URI = process.env.DB_URI static DB_NAME = process.env.DB_NAME static PORT = process.env.PORT static CLIENT = new MongoClient(this.DB_URI) static DEV_MODE = true static VERSION = process.env.npm_package_version}Quack-internalconstants.hpp namespace constants { const LPCWSTR W_DLL_NAME { L"Quack-internal" }; const LPCSTR DLL_NAME{ "Quack-internal" }; const std::string VERSION { "0.6.5" }; constexpr unsigned IPC_PORT = 5175; // Local machine communications port constexpr unsigned NET_PORT = 7982; // Foreign network communications port static constexpr bool DBG = false;}Quack-clientconstants.hpp namespace constants { const std::string VERSION{ "0.4.2" }; const std::string NAME{ "Quack" }; constexpr unsigned IPC_PORT = 5175; // Local machine communications port constexpr unsigned NET_PORT = 7982; // Foreign network communications port static constexpr bool DBG = false;}Quack-clientflashpoint.cpp http::Client cli{ "localhost", constants::NET_PORT };  

Проверяем работоспособность Quack

Для начала нам нуж­но убе­дить­ся в том, что все работа­ет. Для это­го так же, как и автор анти­чита, будем исполь­зовать его игру Inertia, инжектор Destroject и внут­ренний чит Inertia-cheat. Под­клю­чим­ся к сер­веру по адре­су lh (localhost) с ником xakep0.

Под­клю­чение к игро­вому сер­веру

В кон­соли игро­вого сер­вера видим, что про­изош­ло под­клю­чение.

Лог игро­вого сер­вера

Так­же в базе дан­ных анти­чита видим, что появи­лась запись.

Ба­за дан­ных анти­чита

На­чина­ем тест. Для это­го в коман­дной стро­ке выпол­ним Destroject.exe Inertia (не забыв рядом положить Inertia-cheat.dll). Видим, что инжект чита успешно выпол­нен.

Внед­ренный чит

Ак­тивиру­ем чит нажати­ем кла­виши E.

Ак­тивиро­ван­ный чит

Ви­дим, что чит акти­виро­ван, но сра­зу же про­исхо­дит бан.

Со­обще­ние о бане в игре

Пос­мотрев в БД анти­чита, мы можем узнать, из‑за чего нас забани­ли.

Со­обще­ние о бане в БД

Про­буем сме­нить ник­нейм, но нас все рав­но не пус­кают.

По­пыт­ка сме­ны ника

Ес­ли попытать­ся открыть Cheat Engine, он через пару секунд зак­роет­ся, но бан не при­летит.

 

Unity

Преж­де чем рас­чехлять IDA Pro и прис­тупать к ревер­су анти­чита, сде­лаем неболь­шое отступ­ление. Если ты уже заг­лянул в код чита, то мог заметить сле­дующий учас­ток:

Inertia-cheatplayer.cpp std::optional<Player> GetPlayer() { auto start_point = reinterpret_cast<std::uintptr_t>(GetModuleHandleA("UnityPlayer.dll")); start_point += offsets::player.start_point; // Get a pointer to health const auto health_ptr = TraverseChain(start_point, offsets::player.ptr_chain).value_or(0u); if (!health_ptr) return std::nullopt; const auto ammo_ptr = health_ptr - 0x4; const Player player{ .health = reinterpret_cast<std::int32_t*>(health_ptr), .ammo = reinterpret_cast<std::int32_t*>(ammo_ptr) }; return player;}

Здесь сто­ит обра­тить вни­мание на строч­ку "UnityPlayer.dll". Дело в том, что игра написа­на на движ­ке Unity.

Inertia-cheatdata.cpp namespace offsets { PointerChain player = { .start_point = 0x13A1340, .ptr_chain { 0xC2C, 0xDC8, 0xEA8, 0x18, 0x38 } };}

Так­же мы име­ем цепоч­ку ука­зате­лей для UnityPlayer.dll. Откро­ем ее в IDA Pro по адре­су base+0x13A1340. Видим, что здесь раз­мещено зна­чение перемен­ной из сте­ка и даль­ше поиск клас­са игро­ка идет в сте­ке.

UnityPlayer.dll без заг­ружен­ных отла­доч­ных сим­волов

Источник: xakep.ru

Ответить

Ваш адрес email не будет опубликован. Обязательные поля помечены *