Комментарии 17
Ожидал увидеть криптографический ад или хотя бы сжатие данных, которое сбило бы всех с толку. Сейчас вроде уже нечасто встречаются приложения/игры без шифрования трафика?
Так же ожидал увидеть заворачивание трафика на свой MITM, чтобы трафик расшифровывать… Но если нет шифрования, то и свой MITM не нужен…
Может быть стоило добавить свой диссектор для wireshark?
Шифрование здесь только SSL на этапе получения информации о серверах для подключения, что будет описано в последней части.
Как по мне, сделать свой инструмент намного удобнее (часть 2), чем писать диссектор.
Хотя бы минимально добавить XOR уже отобьёт 99% желающих попортить трафик и совершенно не скажется на производительности (ну если не совсем в лоб сделать). SSL обычно снимается в mitmproxy + ssl kill switch на устройстве, он в принципе интереса не представляет.
Кроме того частой практикой является добавлять контрольную сумму к каждому пакету, но возможно в мобильных приложениях это действительно применяется реже.
Свой инструмент — это хорошо, но и диссектор для wireshark тоже интересно. По уму свой инструмент можно научить использовать диссектор wireshark, — прибить двух зайцев одним махом. Посмотрим, что будет во второй части.
Из вариантов вижу только античит by design на стороне сервера, который проверяет корректность приходящих от пользователя команд управления. Всё формируется на сервере, а пользователю отправляется уже результат действий. Конечно, в определённых рамках применимо. Т.к., например, я слабо представляю, как можно озвученное мной выше применить к шутеру.
Но посыл, в общем-то, всё равно остаётся. Нельзя довчерять данным, пришедшим от пользователя. Не важно, шифрованными они шли, или плэинтекстом, т.к. ничто не мешает особо умным вмешиваться не в сам поток трафика, а мождифицировать сам клиент, например.
Другое дело, что разработка серверной части усложняется. Но это уже на совести разработчка.
А вскрытое шифрование можно в любой момент сменить (при этом оставить поддержку старого, но в клиенте игры требовать обязательного обновления), — всех кто будет на старом шифровании занести в блокнотик и пройтись банхаммером.
Внутренности пакетов подозрительно напоминают формат protobuf — https://developers.google.com/protocol-buffers/docs/encoding. 0x08 обозначает "поле с идентификатором 1 типа varint", дальше следует собственно varint, как вы его расшифровали. Потом следующее поле, и следующее и т.д.
Вот сюда загляните, сильно упростит жизнь. Через protodec сразу получите .proto файл, поправите имена полей для читабельности, подключите библиотеку protobuf к своему приложению и жизнь станет прекрасна.
Обновлять статью скорее всего смысла нет, — тут половину статьи менять придётся. Вы говорили про вторую часть, — оно туда отлично подойдёт.
Я тоже делал подобное с Clash Royale, но только тогда было где подсмотреть и скопировать, но много пакетов доводилось разбирать самому. Там было шифрование (libsodium), во время игры соединение вообще перебрасывались на UDP, но использовался обычный TCP, если первый не смог. А чтобы подключится, вообще надо было изменить APK игры (подсунуть свой адрес сервера, который кстати должен быть фиксированной длины и свой публичный ключ). Потом они изменили протокол (номера пакетов) и шифрование и уже не хотелось продолжать работу над проектом.
Вообще, против ботов легко бороться — ввести так называемую "чексумму", которая может быть посчитана как на сервере, так и на клиенте, клиент должен отсылать её серверу, если не совпадает — гнать клиента подальше.
Контрольная сумма, зависящая от состояния мира. Я говорю про бот, поэтому там будет не хакнутый клиент, а просто свой клиент. Найти алгоритм подсчёта чексуммы в бинарнике (особенно с обфусцированными символами) не так просто, как кажется (например если мы заюзаем в чексумме детерминированный рандом, синхронизированный с сервером во время соединения, время с начала игры, ещё взять туда позиции игроков и всё это приправить ксором). Конечно, можно вытянуть это из бинаря, но на это уйдет немалое количество времени и сил, при этом ничего не мешает разработчикам изменить этот алгоритм на сервере и обновить клиент.
Защита от этого есть — сервер должен искать запущенные процессы, проверять таблицу распределения памяти и искать несоответствия, но самое важное, что код для этих проверок должен приходить во время каждой сессии с сервера, и он должен периодически меняться. Это всё постоянная работа команды безопасности, и понятно, что этот подход оправдан, только если вред от хакерства в игре больше зарплаты этих людей, что только в больших проектах происходит.
А если игра на Android? Патчить тоже не все умеют. И в чем смысл такого подхода? Например, я попробую открыть сундук. Чексумму мне взять неоткуда, и даже если смогу достать, то клиент не будет знать, что он открывает.
Вообще, в Clash Royale было две контрольные суммы:
- контрольная сумма от клиента во время любых действий в меню (открыть сундук, купить что-то в магазине и т.д.), не представляет проблем при разработке кастомного сервера. Отбивает желание делать кастомный клиент сразу (хотя её потом научились считать и делать ботов. Многих, кто их попробовал заюзать — перебанили).
- контрольная сумма от сервера во время игры. Вообще, во время игры сервер и клиент обмениваются только действиями (только поставить такой юнит в такой позиции, ещё смайлики). Там просто детерминированный локстеп. При этом сервер должен прикрепить чексумму игрового состояния (а там количество живих юнитов, их хп, позиции и это приправлено вроде crc32). Если она не совпала, то клиент останавливает игру и запрашивает у сервера полное состояние игры (в продакшене замечал такое только тогда, когда было плохое соединение, или оно пропадало на несколько секунд).
Как разобрать сетевой протокол мобильной MMORPG