Как защититься от чит-программ, изменяющих значения в памяти
Что проверяют
Понимаете ли вы, что клиент полностью в руках игрока и любую защиту на нём можно снять, вопрос только в цене. Для C# в Unity есть своя специфика: сборки Mono декомпилируются почти до исходного кода. Следом спрашивают, что изменится, если игра онлайновая.
Как отвечать
Начните с архитектуры, а не с трюков:
- авторитетный сервер: в онлайне единственная надёжная защита. Клиент отправляет действия, сервер сам считает урон, деньги и инвентарь и проверяет правдоподобие: скорость перемещения, частоту выстрелов, прирост валюты;
- маскировка значений: сканеры памяти вроде Cheat Engine ищут известное число и следят, как оно меняется. Если хранить
intкакvalue ^ keyсо случайным ключом, который меняется при каждой записи, простой поиск перестаёт работать. Делается структурой-обёрткой с неявными операторами и почти ничего не стоит; - контроль целостности: рядом с замаскированным значением хранят копию или контрольную сумму и сверяют при чтении. Сохранения подписывают HMAC, чтобы правка файла обнаруживалась;
- усложнение анализа: сборка через IL2CPP вместо Mono, обфускация.
Debugger.IsAttachedвидит только управляемый отладчик, нативный проверяют черезIsDebuggerPresentпо P/Invoke; - спидхак: игровое время сверяют с независимым источником, надёжнее всего с серверным. Расхождение выдаёт ускорение.
Реагировать лучше отложенно: пометить игрока и отправить сигнал на сервер, а не падать сразу. Мгновенная реакция подсказывает автору чита, какая проверка сработала.
Где спотыкаются
Предлагают шифровать каждое поле AES. Ключ лежит в той же памяти, что и данные, а горячие значения, которые читаются каждый кадр, начнут тормозить игру.
Строят всю защиту на клиенте в сетевой игре. Сервер, который верит присланному «у меня 10 000 золота», ломается простой подменой запроса, без всякого редактора памяти.
Обещают защиту, которую нельзя обойти. Честный ответ такой: цель в том, чтобы взлом стоил дороже выгоды от него, а в онлайне ключевые решения принимает сервер.