Как ломаются JS игры в мессенджерах

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

Всем участникам N-ого чата, Салам Алейкум)

1. Дано

Для примера мы возьмем игру, в которую играли в чате. https://prizes.gamee.com/game-bot/motofx2-b18fcb02ab73db0ab6cf9a4b38b98e64b9a0da12

Управляя мотоциклом, игроку надо выполнять трюки не убив себя. За это он получаете очки. Чем больше очков, тем выше в рейтинге.

Для работы нам хватит браузера с возможностью отладки JS кода. Я буду использовать Google Chrome.

2. Принцип

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

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

3. Реализация

Запускаем игру, открываем дебаггер. (Правая кнопка на странице -> Inspect или F12) Наша первая задача, определить в каком .js файле происходит подсчет очков.

Можно перейти на вкладку Sources и пытаться анализировать каждый исходник, но это долго и муторно.

Окно игры

Если мы разберем страницу и доберемся до канваса, на котором рисуется сама игра, мы увидим, что он грузится в iframe из https://games.cdn.gamee.io/games/game-229/data/index.html.

iframe

Посмотрим, какие js файлы тянутся с этим канвасом. Для этого возвращаемся к дереву исходных файлов и находим нужный каталог.

Файлы загруженные с CDN

Phaser и box2d я сразу вычеркнул, т.к. это библиотеки игрового и физического движка (можно погуглить) и обычно в них не хранится код отдельно нашего приложения.

MotoFX2.js это уже файл с исходниками игры. После открытия кликаем на иконку с скобками в левом нижнем углу кода, чтобы дебаггер форматировал код. Пробежавшись по нему, мы увидим, что разработчики его обфусцировали, сделав менее читаемым. В нем скорее всего есть, то что нам нужно, но не будем идти сразу сложным путем.

Файл с кодом MotoFx

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

Пойдем простым путем и начнем искать слово очки (score) в файле.

Поиск по ключевому слову score

Первым же пунктом видим функцию, которая как-то обновляет наши очки (updateScore). Допускаю, что она будет вызываться при их изменении в процессе игры. score: parseInt(t, 10) Тут мы видим, что из переменной t парсится 10-тичное число. Ее и будем пробовать менять.

Ставим брейкпоинт

Ставим брейкпоинт на строке с условием и запускаем игру. Немного прокатившись и получив 1 очко, видим, что отладчик поймал брейкпоинт и исполнение кода остановилось. Это хорошо.

Исполнение кода остановилось на брейкпоинте

Справа в отладчике видим переменные, переданные в функцию. Около t, как положено, стоит число 1. Меняем его на другое.

Меняем переменную

Т.к. брейпоинт нам уже не нужен, снимаем его и продолжаем выполнение программы.

Продолжаем работу

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

Смотрим результат

Written on March 21, 2022