Се­год­ня мы с тобой напишем чит для сетево­го шутера. Мы реали­зуем хаки типа extrasensory perception (ESP) и aimbot. ESP отоб­ража­ет информа­цию об игро­ках над их голова­ми. Здесь может быть здо­ровье игро­ка, имя или текущее исполь­зуемое ору­жие. Aimbot авто­мати­чес­ки нацели­вает­ся на дру­гих игро­ков.

info

В пре­дыду­щей статье «Чит сво­ими руками. Вскры­ваем компь­ютер­ную игру и пишем трей­нер на C++» я заложил базу для будущих читов и объ­яснил основные понятия. Рекомен­дую озна­комить­ся с ней, что­бы луч­ше понимать, что мы будем сегод­ня делать.

 

Выбор игры

Мой выбор пал на AssaultCube — бес­плат­ный мно­гополь­зователь­ский шутер от пер­вого лица, осно­ван­ный на движ­ке CUBE. Исполь­зует­ся гра­фичес­кая биб­лиоте­ка OpenGL.

warning

Ис­поль­зование читов наруша­ет поль­зователь­ское сог­лашение игры и может пов­лечь юри­дичес­кое прес­ледова­ние. Мы обсужда­ем здесь соз­дание чита исклю­читель­но в целях обу­чения. Автор и редак­ция не несут ответс­твен­ности за воз­можные пос­ледс­твия при­мене­ния и рас­простра­нения такого ПО.

 

Поиск значений

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

Оконный режим
Окон­ный режим

Так­же соз­дадим локаль­ный сер­вер. Нуж­но будет нас­тро­ить его, а имен­но задать вре­мя игры, что­бы тай­мер не торопил нас. Кон­фиг лежит по сле­дующе­му пути:

C:\Program Files (x86)\AssaultCube 1.3.0.2\config\maprot.cfg
Стандартные настройки времени
Стан­дар­тные нас­трой­ки вре­мени

По­меня­ем вре­мя на мак­сималь­ное — 100 минут.

Новые настройки времени
Но­вые нас­трой­ки вре­мени

А пос­ле уже запус­каем сам сер­вер.

Запуск сервера
За­пуск сер­вера

И под­клю­чаем­ся к нему.

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

За­пус­каем Cheat Engine и под­клю­чаем­ся к про­цес­су игры.

Подключимся к процессу игры
Под­клю­чим­ся к про­цес­су игры
 

Поиск показателя здоровья

Для тес­тирова­ния нам понадо­бит­ся вто­рой игрок. Можешь под­клю­чить­ся со вто­рого устрой­ства или, как сде­лал я, из вир­туаль­ной машины. Для поис­ка показа­теля здо­ровья выс­тавля­ем парамет­ры ска­ниро­вания в Cheat Engine и вто­рым игро­ком наносим урон пер­вому. Пос­ле это­го ищем здо­ровье в Cheat Engine.

Получение урона
По­луче­ние уро­на

Бу­дем наносить урон до тех пор, пока не най­дем адрес, по которо­му хра­нит­ся показа­тель здо­ровья нашего игро­ка.

Найденный адрес HP
Най­ден­ный адрес HP

На этом все зна­комые по прош­лой статье дей­ствия в Cheat Engine закан­чива­ются и начина­ются новые. Наша цель — реали­зовать extrasensory perception и aimbot. Для это­го нам нуж­но узнать класс игро­ка и его ста­тичес­кий адрес. Что­бы най­ти класс, кли­каем пра­вой кноп­кой мыши по нашему адре­су и выбира­ем Find out what writes to this address (мож­но прос­то нажать F6).

Поиск места, где идет запись по адресу
По­иск мес­та, где идет запись по адре­су

По­явит­ся новое окно, где будут отоб­ражать­ся инс­трук­ции, которые про­изво­дят запись по нашему адре­су. Что­бы они появи­лись, сно­ва наносим урон вто­рым игро­ком пер­вому.

Найденная инструкция
Най­ден­ная инс­трук­ция

По­каза­тель здо­ровья записы­вает все­го одна инс­трук­ция, она рас­положе­на по сме­щению 0xEC. Зна­чит, зна­чение, хра­няще­еся в регис­тре edx, — это адрес клас­са игро­ка (но адрес в куче, а не ста­тичес­кий). Поэто­му добавим его вруч­ную.

Структура
Струк­тура
 

Поиск статического адреса объекта игрока

В прош­лый раз я исполь­зовал отладчик, что­бы наг­лядно показать, что собой пред­став­ляет ста­тичес­кий адрес. В этот раз для поис­ка ста­тичес­кого адре­са мы будем исполь­зовать Cheat Engine. Жмем на ранее добав­ленный адрес 0x6AED20 пра­вой кноп­кой мыши и выбира­ем Pointer scan for this address.

Выбор сканирования адреса
Вы­бор ска­ниро­вания адре­са

Как видишь, у нас есть мно­жес­тво парамет­ров для поис­ка ука­зате­ля, но нас инте­ресу­ет Max level. Это зна­чение отве­чает за то, сколь­ко раз будет разыме­нован наш ука­затель (ста­тичес­кий адрес). Оно‑то и поможет нам получить иско­мый адрес.

Стандартные настройки сканирования указателя
Стан­дар­тные нас­трой­ки ска­ниро­вания ука­зате­ля

Ис­полня­емый файл игры занима­ет мало, и кода в нем тоже негус­то. Это наводит на мысль, что клас­сов и струк­тур в игре не так мно­го и не будет боль­шого количес­тва сме­щений. Поэто­му глу­бину поис­ка мы уста­новим рав­ной еди­нице.

Новые настройки сканирования указателя
Но­вые нас­трой­ки ска­ниро­вания ука­зате­ля

Мы видим сле­дующий резуль­тат. Об адре­сах вида "ac_client.exe"+YYYYYYYY мы уже писали в прош­лой статье. Имен­но они нам и понадо­бят­ся. А вот адре­са фор­мата "THREADSTACKX"-YYYYYYYY говорят нам о том, что иско­мый нами адрес был най­ден в сте­ке.

Результаты сканирования указателя
Ре­зуль­таты ска­ниро­вания ука­зате­ля

До­бавим най­ден­ные пять адре­сов в спи­сок.

Добавленные указатели
До­бав­ленные ука­зате­ли

И выс­тавим для каж­дого адре­са сме­щение до показа­телей здо­ровья.

Добавленный указатель на HP
До­бав­ленный ука­затель на HP

Да­лее переза­пус­каем игру, и Cheat Engine пред­ложит сох­ранить наши адре­са. Мы их сох­раня­ем, что­бы заг­рузить при пов­торном под­клю­чении.

Сохраняем наш cheat table
Сох­раня­ем наш cheat table

Пос­ле перепод­клю­чения к игре в спис­ке адре­сов Cheat Engine видим, что толь­ко два адре­са ука­зыва­ют на показа­тель здо­ровья: "ac_client.exe"+0017E0A8 и "ac_client.exe"+0018AC00.

После перезапуска AC
Пос­ле переза­пус­ка AC

Поп­робу­ем пов­торно получить урон и пос­мотреть, что будет с дру­гими адре­сами. Как видим, еще в двух адре­сах появил­ся наш показа­тель здо­ровья. Зна­чит, в спис­ке мы оставля­ем толь­ко два упо­мяну­тых ранее адре­са.

Повторное получение урона
Пов­торное получе­ние уро­на

До­бавим ста­тичес­кий адрес "ac_client.exe"+0017E0A8 под име­нем Player_ptr_1.

Добавляем первый указатель
До­бав­ляем пер­вый ука­затель

До­бавим ста­тичес­кий адрес "ac_client.exe"+0018AC00 под име­нем Player_ptr_2.

Добавляем второй указатель
До­бав­ляем вто­рой ука­затель
 

Класс игрока

Пред­положим, что ста­тичес­кий адрес Player_ptr_1 — тот, что мы ищем (что на самом деле не так, пра­виль­ным ста­тичес­ким адре­сом будет Player_ptr_2, но в этом мы убе­дим­ся поз­же). Что­бы прос­мотреть класс игро­ка в памяти, нажима­ем пра­вой кноп­кой мыши на адрес и выбира­ем Browse this memory region (или жмем Ctrl-B).

Открытие региона памяти
От­кры­тие реги­она памяти

К счастью, у Cheat Engine есть инс­тру­мент, который поз­воля­ет нам луч­ше визу­али­зиро­вать струк­туры памяти, а не прос­матри­вать бай­ты в дам­пе. Прос­то жми пра­вой кноп­кой мыши по выделен­ному бай­ту и выбирай Open in dissect data/structure.

Открытие анализа структур
От­кры­тие ана­лиза струк­тур

От­кро­ется новое окно с адре­сом выб­ранно­го бай­та. Наж­ми Structures, затем Define new structure (или Ctrl-N).

Создание структуры
Соз­дание струк­туры

На­зовем струк­туру Player. Осталь­ные нас­трой­ки оста­вим по умол­чанию: пред­положи­тель­ный тип поля и раз­мер струк­туры (4096).

Создание класса игрока
Соз­дание клас­са игро­ка

Пос­тавив галоч­ку Guess field type, мы поп­росили Cheat Engine уга­дать тип поля. И он неп­лохо с этим спра­вил­ся.

Полученная структура
По­лучен­ная струк­тура

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

Проверка класса
Про­вер­ка клас­са

Так­же мож­но по сме­щению 0x205 обна­ружить имя игро­ка.

Имя игрока
Имя игро­ка

В даль­нейшем нам нужен этот класс, но, к сожале­нию, Cheat Engine не поз­воля­ет экспор­тировать струк­туру, а делать это вруч­ную — зна­чит под­вергать себя мучени­ям. Это не нуж­но, пос­коль­ку сущес­тву­ет готовый инс­тру­мент — ReClass.NET. Он дает воз­можность нап­рямую выг­рузить струк­туру в виде кода на C++. Ска­чива­ем, уста­нав­лива­ем и под­клю­чаем­ся к про­цес­су игры.

Подключение к процессу
Под­клю­чение к про­цес­су

Пос­ле при­соеди­нения к про­цес­су соз­дает­ся класс по базово­му адре­су 400000, он называ­ется N0000004E. Дваж­ды кли­каем по адре­су и выс­тавля­ем нуж­ный нам: 0066ED48. Ана­логич­но изме­няем имя клас­са на Player и добав­ляем для отоб­ражения еще 4096 байт.

В дан­ном кон­тек­сте отоб­ража­емое количес­тво бай­тов СE вос­при­нима­ет как класс, который мы экспор­тиру­ем. Если раз­мер нашего клас­са боль­ше, чем стан­дар­тное количес­тво отоб­ража­емых бай­тов, нуж­но вруч­ную уве­личить раз­мер.

Настройка ReClass.NET
Нас­трой­ка ReClass.NET

Пе­рехо­дим к сме­щению 0xEC, к показа­телю здо­ровья. Меня­ем зна­чение типа поля на DWORD (мы выс­тавим зна­чения типов для сме­щений, что поз­волит нам в даль­нейшем экспор­тировать класс с нуж­ными полями).

Присвоение типа
Прис­воение типа
 

Поиск координат

На­чиная с это­го мес­та, мы будем искать зна­чения, нуж­ные непос­редс­твен­но для реали­зации ESP и aimbot. Для ESP нам понадо­бят­ся коор­динаты самого игро­ка и его головы в трех­мерном прос­транс­тве.

www

Тем, кто не зна­ет или забыл, как работа­ет трех­мерная сис­тема коор­динат в компь­ютер­ной гра­фике, рекомен­дую статью «3D сво­ими руками» на «Хаб­рахаб­ре».

Для реали­зации aimbot нам понадо­бят­ся зна­чения тан­гажа (pitch), рыс­канья (yaw) и кре­на (roll). Не зна­ешь, что это? Давай покажу на при­мере игро­вого движ­ка Godot.

Координаты XYZ
Ко­орди­наты XYZ

За­пись коор­динат может раз­нить­ся в зависи­мос­ти от движ­ка. Час­то раз­лича­ется нап­равле­ние осей и то, какая из них счи­тает­ся высотой.

Вариации координат
Ва­риации коор­динат

Для демонс­тра­ции возь­мем с GitHub го­тово­го пер­сонажа и пос­мотрим, как он будет дви­гать­ся, если менять коор­динаты.

Персонаж на нулевых координатах
Пер­сонаж на нулевых коор­динатах

Тан­гаж — дви­жение пер­сонажа отно­ситель­но оси X. Ниж­няя стрел­ка — фак­тичес­кое дви­жение пер­сонажа в дан­ный момент, вер­хняя — дру­гой вари­ант дви­жения.

Pitch
Pitch

Рыс­канье — дви­жение пер­сонажа отно­ситель­но оси Y.

Yaw
Yaw

Крен — дви­жение пер­сонажа отно­ситель­но оси Z.

Roll
Roll

Поиск координат игрока

С новыми зна­ниями воз­вра­щаем­ся к игре и окну Cheat Engine. Начина­ем переме­щать­ся по кар­те и вер­теть мыш­кой из сто­роны в сто­рону, а так­же вверх и вниз. В окне Cheat Engine можем видеть три пос­ледова­тель­нос­ти из зна­чений с пла­вающей запятой, которые менялись при наших дей­стви­ях. Зна­чит, это коор­динаты игро­ка, коор­динаты головы игро­ка и его поворот отно­ситель­но осей.

Мож­но заметить, что два набора из трех пов­торя­ются по X и Y, а вот коор­дината Z у них раз­ная. Отсю­да мы можем сде­лать вывод, что один набор — это коор­динаты игро­ка, а вто­рой — головы. Так как в OpenGL в качес­тве высоты исполь­зует­ся коор­дината Z, мы попыта­емся поменять высоту для каж­дого набора. Нач­нем с пер­вого, но пос­ле попыт­ки поменять зна­чение c -0.5 на дру­гое оно сно­ва ста­нет преж­ним. Зна­чит, это коор­динаты головы, вто­рой набор — коор­динаты игро­ка, а тре­тий — дви­жение отно­ситель­но осей. Но мы в этом еще дол­жны убе­дить­ся.

Неправильный выбор числа
Неп­равиль­ный выбор чис­ла

Те­перь давай поп­робу­ем сде­лать для вто­рого набора то, что мы делали для пер­вого.

Правильный выбор
Пра­виль­ный выбор

Для наг­лядной демонс­тра­ции вста­нем на ящик, а в Cheat Engine будем смот­реть на зна­чение по сме­щению 0x30.

Становимся на высоту
Ста­новим­ся на высоту

Поп­робу­ем изме­нить это зна­чение и уви­дим, как наш пер­сонаж про­валил­ся сквозь ящик.

Изменение высоты игрока
Из­менение высоты игро­ка

Это зна­чит, что наши пред­положе­ния вер­ны.

Наши координаты
На­ши коор­динаты

Вер­немся в окно ReClass.NET и выберем типы для этих сме­щений.

Переименовываем и задаем тип
Пе­реиме­новы­ваем и зада­ем тип

Поиск pitch, yaw, roll

Сде­лаем такую же про­вер­ку. Веди мышью из сто­роны в сто­рону, а потом вверх и вниз. Поп­робу­ем поменять зна­чения, и ока­зыва­ется, что наши пред­положе­ния были вер­ны.

Наши значения
На­ши зна­чения

Вер­немся в окно ReClass.NET и выберем типы для этих сме­щений.

Переименовываем и задаем тип
Пе­реиме­новы­ваем и зада­ем тип

Вот так теперь выг­лядит наш класс. Но что за VTable? Это поле не нуж­но, я добавил его для кра­соты. Под­робнее о том, что это и зачем, можешь про­читать в статье Understandig Virtual Tables in C++.

Наш класс
Наш класс

Те­перь экспор­тиру­ем наш класс (наж­ми на него пра­вой кноп­кой мыши и выбери соот­ветс­тву­ющий пункт меню). Можешь видеть, что есть поля, которые мы с тобой не иска­ли: armor, team и про­чие. Думаю, ты при желании смо­жешь най­ти их сам.

Экспортируем
Эк­спор­тиру­ем
 

Entity List

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

Доступ к адресу со здоровьем
Дос­туп к адре­су со здо­ровь­ем

С нас­кока ничего най­ти не уда­ется, но наметан­ный глаз заметит, что дос­туп к показа­телям здо­ровья нашего игро­ка идет через какой‑то ста­тичес­кий адрес. Ока­зыва­ется, мы выб­рали неп­равиль­ный! Пра­виль­ный адрес такой: "ac_client.exe"+0018AC00.

Правильный адрес
Пра­виль­ный адрес

Поп­робу­ем теперь поис­кать через имя игро­ка, которое находит­ся по сме­щению 0x205.

Имя игрока
Имя игро­ка

И получим спи­сок инс­трук­ций, которые обра­щают­ся к име­ни.

Добавляем адрес
До­бав­ляем адрес
Ищем доступ к адресу
Ищем дос­туп к адре­су

Пе­реби­раем вари­анты и находим такой, где дос­туп про­исхо­дит в цик­ле.

Цикл сущностей
Цикл сущ­ностей

Те, кто зна­ком с ассем­бле­ром, понима­ют, что в регис­тре ebx находит­ся адрес пер­вого эле­мен­та, esi — это индекс, а умно­жение индекса говорит нам о типе дан­ных, в дан­ном слу­чае это 4, DWORD.

Та­ким обра­зом, ста­тичес­кий адрес спис­ка сущ­ностей будет таким:

"ac_client.exe"+0018AC04
Список сущностей
Спи­сок сущ­ностей

Убе­дить­ся в этом мож­но, про­верив по сме­щению 0x205 имя игро­ка.

Имя другого игрока
Имя дру­гого игро­ка

Так­же нам понадо­бит­ся общее количес­тво игро­ков. Полис­тав вывод дизас­сем­бле­ра, в кон­це цик­ла уви­дим про­вер­ку. В регис­тре edi хра­нит­ся текущее количес­тво игро­ков.

Количество игроков
Ко­личес­тво игро­ков

Нем­ного подеба­жив, замеча­ем, что выше цик­ла находит­ся ста­тичес­кий адрес количес­тва игро­ков: "ac_client.exe"+0018AC0C.

Статический адрес для игроков
Ста­тичес­кий адрес для игро­ков

Пе­реза­пус­тим и про­верим, что адре­са пра­виль­ные.

 

Поиск View Matrix

Продолжение доступно только участникам

Вариант 1. Присоединись к сообществу «Xakep.ru», чтобы читать все материалы на сайте

Членство в сообществе в течение указанного срока откроет тебе доступ ко ВСЕМ материалам «Хакера», позволит скачивать выпуски в PDF, отключит рекламу на сайте и увеличит личную накопительную скидку! Подробнее

Вариант 2. Открой один материал

Заинтересовала статья, но нет возможности стать членом клуба «Xakep.ru»? Тогда этот вариант для тебя! Обрати внимание: этот способ подходит только для статей, опубликованных более двух месяцев назад.


  • Подпишись на наc в Telegram!

    Только важные новости и лучшие статьи

    Подписаться

  • Подписаться
    Уведомить о
    2 комментариев
    Старые
    Новые Популярные
    Межтекстовые Отзывы
    Посмотреть все комментарии