Основы реверсивной инженерии или как взламывают игры

Реверсивная инженерия — изучение того, как устроено какое-то программное обеспечение, с целью понять механизм его работы. Эта информация может использоваться в будущем для создания похожего продукта или внесения изменения в уже существующий.

Я хочу рассказать о том, как с помощью реверсивной инженерии можно вносить изменения в игры на ПК. Не обязательно с целью взлома, иногда это используется для исправления багов, которые разработчики не исправили по каким-то причинам. Так, например, существует проект Forged Alliance Forever, будучи участником которого я исправил пару багов в игре Supreme Commander, которая пользуется большой популярностью до сих пор, но из-за проблем между издателем и разработчиком поддержка игры была прекращена.

Эта статья будет интересна тем, кто занимается разработкой программного обеспечения на языках высокого уровня и интересуется тем, как оно работает на более низком уровне. А также всем тем, кто просто любит игры и хочет знать об их устройстве больше.

Как это работает

Когда мы пишем какое-то ПО, то чаще всего, мы выбираем инструментарий, подходящий лучше всего под эту задачу. В современных играх код пишется на компилируемых языках высокого уровня. Конечно, можно вспомнить Minecraft на Java, который в конечном итоге все-таки переписали на плюсах.

Здесь стоит уточнить, что часто та часть приложения, которая критична для производительности, пишется на компилируемом языке, в то время как логика может быть на чем-то скриптовом, типа Lua, который уже обращается к ядру движка.

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

А как мы можем на это повлиять?

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

Дебаггер — программа, которая подключается к (например) игре и позволяет ковыряться в ней во время ее работы. Она позволяет выполнять инструкции последовательно, менять содержимое регистров и стека.

Надеюсь, вы еще не запутались окончательно.
Надеюсь, вы еще не запутались окончательно.

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

Стек используется для хранения информации, которая используется программой. Он нам мало интересен, кроме его особенности в хранении информации в упорядоченном виде.

Вот так выглядит приложение под в режиме отладки (дебага) в x64dbg
Вот так выглядит приложение под в режиме отладки (дебага) в x64dbg

Хватит нудятины, когда будем взламывать?

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

Получение дополнительных ресурсов

Тут все предельно просто — находим ячейку в памяти, в которой хранится количество патронов или жизней, меняем на то, которое позволяет собственная жадность. Главное, чтобы жадность не превышала размер типа данных, иначе приложение рухнет. Этим многие из нас баловались еще во времена ArtMoney.

Хочу видеть через стены!

Это посложнее, здесь мы уже перехватываем выполнение функций графической подсистемы. (Чаще всего DirectX или OpenGL). Для этого мы создаем динамическую библиотеку DLL, которая меняет адрес нужной нам функции на нашу, которая потом вызывает и оригинальную функцию, и наш код, рисующий врагов!

DLL подменяет адрес функции в таблице адресов программы, кажется, мы подсмотрели это поведение у кукушек. 
DLL подменяет адрес функции в таблице адресов программы, кажется, мы подсмотрели это поведение у кукушек. 

Хочу раздавать хэдшоты в каэсочке!

Здесь мы тоже получаем информацию о противниках из памяти игры, а разница между позицией игрока и противника и будет вектором, куда нам надо стрелять. Останется только повернуть игрока в нужном направлении, раз он сам не в состоянии.

Ну что народ, погнали?

madskillz 
madskillz 

Поскольку в реальной жизни отладка занимает просто колоссальное количество времени, мы опробуем свои силы на чем-то простом, чтобы уложиться в рамки статьи. У меня под рукой оказалась The Outer Worlds, над которой мы сегодня и будем паразитировать.

В игре есть механика заточки оружия, платим деньги — получаем улучшенное оружие.

Основы реверсивной инженерии или как взламывают игры

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

Находим количество денег, тратим немного, фильтруем те значения, которые нас устраивают. В итоге остается одно значение, которое и является нашим количеством денег.
Находим количество денег, тратим немного, фильтруем те значения, которые нас устраивают. В итоге остается одно значение, которое и является нашим количеством денег.

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

Синяя линия внизу — текущая команда процессора. Именно в этом месте и меняется значение денег. Огибающие линии сверху показывают, что мы находимся в нескольких уровнях вложенности, а команды <b>jl</b> как раз и являются проверками каких-то условий.
Синяя линия внизу — текущая команда процессора. Именно в этом месте и меняется значение денег. Огибающие линии сверху показывают, что мы находимся в нескольких уровнях вложенности, а команды jl как раз и являются проверками каких-то условий.

Далее мы поднимаемся немного наверх, добираемся до начала функции и попеременно меняем условия, которые в дебаггере подсвечиваются желтым цветом. Опытным путем мы узнаем, что если третье условие сработает, то мы не потратим деньги. Почему? Хороший вопрос, для этого надо проследить ход выполнения программы более внимательно, но результат не хочет ждать, поэтому вместо условия jl ставим безусловный переход командой jmp и наслаждаемся бесплатными улучшениями.

Измененная команда в дебаггере. 
Измененная команда в дебаггере. 

Самое сложное в реверсивной инженерии то, что изначально мы как слепые котята тыкаемся и меняем условия с надеждой на достижение результата. Но если разобраться в том, что делают команды и как работают компиляторы, то со временем вы начнете находить логические последовательности, понимать, как передаются в функции аргументы и т.д.

Исправление ошибки с максимальным уровнем снаряжения

Еще в игре есть досадная ошибка разработчиков, влияющая на баланс, — оружие можно улучшать только на пять уровней выше персонажа. Что ж, исправим это!

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

Когда нужно что-то найти в памяти, <b>Cheat Engine </b>приходится очень кстати. Чаще всего необходимо найти базовый адрес, это делается довольно просто, но немного выходит за рамки статьи.
Когда нужно что-то найти в памяти, Cheat Engine приходится очень кстати. Чаще всего необходимо найти базовый адрес, это делается довольно просто, но немного выходит за рамки статьи.

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

Редактируем команду — заменяем обращение к адресу в памяти <b>[rax+310]</b> константным значением <b>1000</b>
Редактируем команду — заменяем обращение к адресу в памяти [rax+310] константным значением 1000

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

Обратите внимание на уровень персонажа и уровень винтовки, теперь можно отыгрывать <b>Men In Black</b>, у нас же все-таки рпг, не так ли?
Обратите внимание на уровень персонажа и уровень винтовки, теперь можно отыгрывать Men In Black, у нас же все-таки рпг, не так ли?

Фиксируем прибыль

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

Список изменений в программе, которые будут внесены в исполняемый файл
Список изменений в программе, которые будут внесены в исполняемый файл

Таким образом мы с вами познакомились с чудесным миром реверсивной инженерии, разобрались, как взламывают игры и, на примере The Outer Worlds, исправили несколько багов в игре. Конечно, в реальной жизни это занимает гораздо больше времени и чаще всего взлому подвергаются онлайн-игры, которые имеют свою специфику из-за клиент-серверной архитектуры, но принципы работы остаются те же.

Реверсивная инженерия довольно непростой инструмент, требующий огромного количества времени и усидчивости, но цена чаще всего оправдывает себя.

375375
124 комментария

Кому интересна эта тема, рекомендую познакомиться со статьёй про взлом графики Age of Empires 3.
https://medium.com/@lancelot.deferriere/cracking-age-of-empires-iii-over-shader-quality-settings-7f729528cf1d

Перевод этой же статьи на Хабре.
https://habr.com/ru/post/500542/

27

Тоже в догонку крутая статья по Batman arkham knight
https://m.habr.com/ru/post/266385/

16

Реверсивная инженерия

Я впервые за мильён лет в интернете вижу, чтобы реверс инжиниринг писали не так как я выше, лол.

22

Или обратная разработка, на худой конец 

3

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

15

Насколько мне известно - зависит от движка. Как он пакует ресурсы. В некоторых случаях есть анпакеры. В некоторых танцы с бубном. 

10

К сожалению, общего подхода тут просто нет, каждый случай уникален. Как верно было замечено, зависит как минимум от движка игры. Мне лично приходилось иметь дело с No Man's Sky и Astroneer, и нюансов там куча.

2