- PVSM.RU - https://www.pvsm.ru -
Это статья о том, как мы делали систему защиты браузерной HTML5 игры от взлома и подделки результатов, с какими трудностями мы при этом столкнулись, как их решали и что получили в итоге. Основной и всем знакомой проблемой таких игр является возможность написания бота, который эту игру автоматически пройдет. Разработку подобного бота облегчает тот факт, что код игры находится в публичном доступе. Ситуация осложнялась тем, что были объявлены реальные призы, среди которых iPad, билеты на концерт, USB флеш накопители и т.п.

Статья будет полезна в основном тем, кто делает HTML5 / Flash игры и заботится об их безопасности; тем, кто платит за разработку этих игр; и немного тем, кто призван бороться с ботами. Ну и, конечно, тем, кто написал эту статью. Потому что мы надеемся, что она станет началом продуктивной дискуссии о том, как разработчики браузерных игр могут противостоять кибер-мошенникам.
Немного о самой игре.
К сожалению, саму игру мы показать не можем по требованию заказчика. Несмотря на все описанные ниже приемы, к сожалению, «незнание» является ключевым элементом защиты. То есть раскрытие методов в привязке к конкретной игре, существенно снизит их эффективность.
Мы — web-разработчики, но разработкой игр ранее не занимались. До разработки этой игры gamedev представлялся нам чем-то не понятным. Поэтому в самом начале мы родили много смешных решений. Например, мы сделали важную архитектурную ошибку — решили генерировать уровень на клиенте в браузере; а в качестве защиты уповали на обфускацию JS кода. Правда товарищи из соседних отделов говорили, что для качественной защиты придется “проигрывать” игру на сервере и сравнивать с клиентом. Но мы посмеялись тогда, что это уж очень сложно.
Повторюсь, что главнейшим требованием было обеспечить защиту от накруток. Но наша команда решила сначала сделать так, чтобы игра в принципе работала. А разработку защиты отложили на попозже. Казалось логичным: сначала что-то делаем, и уже потом это “что-то” защищаем.
Как только мы начали заниматься защитой, мы сразу столкнулись с базовой проблемой всех браузерных игр, вытекающей из клиент-серверной архитектуры. А именно: игрок видит весь клиентский код игры и слепо доверять пришедшим на сервер данным нельзя. Если со второй частью проблемы мы обходиться умеем, то возможность анализа и изменения исходников любым пользователем нас реально озадачила.
Мы начали с простого решения — обфускации JS кода и шифрования данных, отправляемых клиентом на сервер. Но у заказчика была убойная команда безопасности, которая за 15 минут смогла записать нереальный игровой счет, имея полностью обфуцированный код. Шифрование данных при передаче тоже не вариант — ключи лежат у клиента, и их можно легко подставить в нужное место. Так что фактически оба этих решения оказывались действенными только для очень ленивых хакеров.
Более того, Flash-игры тоже подвержены подобному реверс-инжинирингу, и те разработчики тоже в поиске решения защиты.
Ситуация осложнялась еще и тем, что у нашей игры есть реальные призы. В этом случае ее взлом перешел из разряда “взломать для развлечения” в разряд “взломать ради денег”. Эта игра более чем привлекательна для специалистов более высокого класса, чем “начинающий хакер”.
Несмотря на то, что разработано уже очень много онлайн игр, информации о методах борьбы с их взломом удалось найти крайне мало. Вот какие рекомендации мы извлекли из просторов Интернета:
Мы провели мозговой штурм и тоже выработали много идей. Были удачные, были и не очень. К разряду не самых удачных можно отнести, например, вывод капчи “до”, “во время” и “после” игры. Или, допустим, получение скриншотов во время игры и отсылка их на сервер для проверки. Далее описаны наиболее интересные из реализованных методов.
После долгих размышлений и сопротивлений сложному решению, мы пришли к выводу, что проигрывание (эмуляция) игры на сервере — вещь явно необходимая. Если не сказать — неизбежная.
Для этого мы стали генерировать игру (расположение бонусов и препятствий) на сервере и
отправлять на сервер не конечный результат игры, а только события, которые в ней происходили: столкновения с препятствиями, бонусами и нажатия клавиш. Для каждого события мы знали время, координаты, нажатые клавиши или бонусы/препятствия с которыми игрок столкнулся.
Был вариант отправлять только нажатия клавиш, а на сервере рассчитывать результат в конце игры. Но мы столкнулись с проблемой разной скорости игры на разных устройствах и в разных браузерах. Велика вероятность сильного расхождения процесса игры на клиенте и на сервере, так как этот метод сильно чувствителен к несоответствиям. Например, если вдруг клиент не пришлет всего одно столкновение с препятствием, то эмулированная игра с этого момента пойдет совершенно по-другому. Ведь при столкновениях теряется энергия и скорость.
Другой вариант: обрабатывать события на сервере и немедленно отправлять результаты события на клиенте. Но при этом возникает очень большой трафик между сервером и клиентом, увеличивается время отклика игры и резко возрастает нагрузка на сервер. Так работают, например, MMO игры. Но для небольшой Collect & Run игры мы посчитали это нецелесообразным.
Особо хочется отметить тот факт, что устройства, на которых запускалась игра, имели разную производительность. На быстрых устройствах игра шла плавно, на медленных — рывками. Из-за этой разницы нам пришлось отказаться от привязки ко времени во время эмуляции. Вместо этого мы рассматривали события игры как нечто, происходящее в некоторых координатах. Например, сначала мы рассматривали прыжок за бонусом как “нажатие кнопки вверх на 10-ой секунде, столкновение с бонусом на 12-той секунде”. Но нам более подошло следующее: “нажатие кнопки вверх при Х-координате игрока равной 1000, столкновение с бонусом при Х-координате игрока равной 1100 и Y-координатой игрока равной 300”. В таком случае и быстрое и медленное устройства эмулировались более-менее одинаково.
В итоге мы решили после игры эмулировать на сервере каждое событие, присланное клиентом, и дополнительно рассчитывать вероятность его возникновения. Одной из задач, которые мы при этом решали, было создание одинаковых алгоритмов расчета столкновений на сервере и на клиенте. Необходимо было добиться такой же точности, в том числе округления.
В результате работы эмулятора мы получаем на сервере последовательность игровых событий в том же виде, что и при реальной игре. После эмуляции событий мы переходим к анализу того, что у нас получилось.
Это самый интересный блок. Тут собраны наиболее удачные методы обнаружения читеров. Все они разные, запускаются последовательно, можно добавлять при необходимости еще.

Каждый метод имеет свой вес при расчете, значение которого настраивается. Кстати, имеет смысл выносить в настройки максимально возможное количество параметров. Ибо заранее не понятно, насколько чувствительным или грубым получится тот или иной алгоритм в реальности.
Анализатор при работе выставляет каждому методу значения от 0 до 1 (0 — игра вне подозрений, 1 — тест полностью провален) и в конце вычисляет “Индекс подозрительности игры” (тоже от 0 до 1).
Этот индекс используется для автоматической пометки игры. Если он больше порога, то игра считается взломанной. Конкретное пороговое значение подбирается опытным путем, у нас оно получилось 0.4.
Но это еще не все. Надо что-то делать со всеми этими расчетами. Одно дело — запрограммировать описанные выше алгоритмы, другое — подать администраторам игры результаты работы в удобочитаемом виде. Заблокированный за хакерство игрок может обратиться в поддержку с претензиями, и у них должны быть доказательства принятого решения. Поэтому рекомендуется давать администраторам максимальное количество информации, чтобы они разобрались и обосновали, почему та или иная игра была определена как взломанная.
Для этого в админке мы сделали 4 страницы.
К моменту запуска игры мы не успели сделать автоматическое блокирование подозрительных пользователей. Это значительно упростило бы работу администраторам игры, так как человек не в состоянии просмотреть тысячи подозрительных игр за день.

Анализировать топ игроков через несколько дней после запуска игры было весьма занятно. Один взломщик пошел по простому пути и собрал все элементы, но ни разу не прыгнул. Он также собрал все “ложные” элементы. Другой “чемпион” эволюционировал последовательно. Сначала у него было с десяток честных игр, затем — очень много “пустых”. А в самых последних играх индекс подозрительности зашкаливал. Некоторые “победители” проходили игру менее чем за 10 секунд. Кое-кто играл в игру всего один раз и сразу попадал в топ. Это, кстати, можно использовать как метод анализатора — мало кто способен с первого раза сделать максимум. Были “рекордсмены” за одну секунду набиравшие нереальное количество очков. И так далее. Все они были заблокированы и до реальных призов не допущены. Жалоб от них не поступило.
Просмотрев несколько десятков реальных игр, мы обновили некоторые параметры пороговых значений в сторону увеличения. Например, максимальное значение индекса подозрительности игры, когда игра считается взломанной, можно увеличить. Иными словами, начальные настройки были очень подозрительными.
В реальности мы получили позитивный результат работы этой системы. Сильно помогало разбираться отображение результатов в админке. В целом можно сказать, что система показала себя вполне жизнеспособной, заказчик остался доволен.
При защите от накруток счета мы использовали данные только одной игры и старались поймать ее на внутренних несоответствиях. Мы исходили из того, что игра полностью уязвима: все исходники доступны игроку, а входящие данные недостоверны. Но есть у игры часть, недоступная хакерам — это данные всех игр. Есть предположение, что правильно используя базу данных, сыгранную тысячами игроков, можно повысить точность определения взлома. Сейчас мы считаем, что база данных результатов игр — это основное преимущество разработчиков перед хакерами.
А что думаете вы? Поделитесь своими соображениями и подходами к защите онлайн игр.
Автор: volopoglod
Источник [2]
Сайт-источник PVSM.RU: https://www.pvsm.ru
Путь до страницы источника: https://www.pvsm.ru/igry/85406
Ссылки в тексте:
[1] http://www.pixijs.com: http://www.pixijs.com
[2] Источник: http://habrahabr.ru/post/252699/
Нажмите здесь для печати.