Мод-меню для RedM: как они загружаются и как заметить меню, не зная его названия
Что мод-меню делает на сервере RedM, три сигнала, которые выдают его без чёрных списков и известных названий, и чего не увидит ни один античит.
Мод-меню не объявляет о себе. Его нет ни в одном списке ресурсов, оно не выдаёт ошибок при старте, а использующий его игрок три четверти сессии ведёт себя нормально. Когда вы наконец замечаете его, обычно это потому, что другой игрок снял на видео нечто невозможное. В этой статье о мод-меню для RedM объясняется, где меню проникает внутрь, что оно даёт заплатившему за него и какие сигналы его выдают, при этом знать, как оно называется, не нужно.
Где меню проникает внутрь
Первая стадия - внешняя программа. Она запускается до игры или во время неё, открывает процесс и записывает собственный код в адресное пространство игры. С этого мгновения меню - уже не программа, стоящая рядом с игрой: оно внутри неё, с теми же правами над игрой, что у самой игры над собой. Оно может вызывать функции движка, читать ваш клиентский Lua, как только он оказался на машине, и возвращать управление, так что ничто заметно не останавливалось. Серьёзные загрузчики защищены (упакованные бинарники, игровые функции, найденные по отладочным символам) именно для того, чтобы этот шаг не оставлял читаемого следа.
Вторая стадия интереснее для нас, потому что она касается вашего сервера. Чтобы выполнять Lua с правами ресурса, а значит, иметь возможность вызывать ваши сетевые события, обращаться к вашим экспортам и сходить за ваш собственный код, меню перехватывает уже работающий ресурс. Оно закладывает свои значения в глобальное пространство этого ресурса, а затем его код просыпается там, как будто всегда там и был. Один реальный случай, который мы наблюдали: меню кладёт четыре переменные (идентификатор пользователя, токен, ключ) в глобальную таблицу легитимного ресурса ещё до того, как запускается его собственный слой обфускации. Эти четыре переменные - ручка его двери, и они же его поведенческая подпись.
Есть и третий путь, куда более шумный: запуск собственного ресурса. Для этого нужен доступ к серверу, а не к клиенту. Если меню работает как объявленный ресурс, ваша проблема не читер, а член персонала.
Оказавшись внутри, покупатель получает следующее:
Состояние персонажа: неуязвимость, бесконечные патроны, хождение сквозь стены, скорость. Это вызовы функций движка, бесплатные, когда ты уже внутри.
Спавн: педы, лошади, транспорт, объекты, пачками. Это видимая досада, та, о которой жалуется ваше сообщество.
Ваши сетевые события: меню читает ваши клиентские скрипты, извлекает названия серверных событий и воспроизводит их с любыми аргументами. Это для вас самое дорогое (деньги, предметы, роли), и в логах оно выглядит не как читерство, а как ваша собственная экономика.
Дамп: чтение и вывод ваших ресурсов. Меню не только пытается читерить, оно пытается скопировать ваш сервер.
Почему чёрный список названий бесполезен
Естественная реакция - вести список: известные названия меню, подозрительные названия ресурсов, названия событий, хеши файлов. Он ловит первую версию, на неделю. Потом автор переименовывает. Некоторые меню прямо рекламируют кнопку «сменить имя», другие выбирают случайное имя при каждом запуске, а значения, закладываемые в глобальное пространство, генерируются на лету. Чёрный список описывает не возможность, а написание, а написание в мире поменять дешевле всего.
Три сигнала, не зависящих от названия
1. Анонимный вызывающий. В RedM каждый вызов функции движка приходит из некоторого контекста. Когда вызывающий код принадлежит работающему ресурсу, движок знает, какому. Когда это инжектированный код, называть нечего: вызывающий неизвестен. Принцип умещается в одну фразу: подозрительна не вызываемая функция, а то, что ни один ресурс не признаёт этот вызов своим. Создать лошадь, поставить неуязвимость, стать невидимым: ролевой сервер делает все три весь день, но всегда из опознаваемого скрипта.
Один этот сигнал нанёс бы вред, поэтому мы его смягчаем: мы требуем отдельных наблюдений, прежде чем оповещение уйдёт, игнорируем окно допуска, пока игрок загружается (когда сам движок вызывает без контекста), а чёрный экран быстрого перемещения временно разоружает семейство «состояния». Значения остаются внутри компании: опубликованные, они станут щелью, в которую меню спрячется.
Не публикуется/Пороги срабатывания не публикуются: известное значение - это значение, под которое настраивают чит.
2. Запись в глобальное пространство другого ресурса. Это сам жест загрузки. Ресурс не пишет в глобальную таблицу другого ресурса: так ресурсы друг с другом не разговаривают, и ни у одного ролевого фреймворка нет причин так делать. Поэтому мы следим за этой записью. У нас она проглатывается: значение внешне принимается, затем возвращается испорченным с сохранением формы, так что загрузчик считает, что всё удалось, и рушится дальше по цепочке, а исходный токен попадает в материал дела. Этот токен не анонимен: это аккаунт, оплативший меню.
3. Массовое чтение файлов ресурсов. Дамп плохо прячется: он читает много и быстро, и читает то, что ни один скрипт в игре никогда не открывает. Мы измеряем всплеск, а не файл, и подкладываем файлы, которые незачем читать: легитимный скрипт их игнорирует, а дампер глотает вместе со всем остальным и называет себя. Предел ясен, и мы его озвучиваем: эта защита живёт внутри игры, поэтому она видит дампы, идущие через игру. Инструмент, копирующий ваш кэш с диска, вне процесса, она никогда не встретит. Единственный настоящий ответ на это договорной, а не технический.
Чего это семейство детекций не видит
Всё сказанное выше предполагает, что чит говорит с движком. Полностью внешний чит - нет: он читает память игры из другого процесса, иногда со второй машины, не вызывает ни одной функции, не пишет ни в одно состояние Lua и лишь рисует на вашем экране или двигает вашу мышь. Ни один из наших трёх сигналов не срабатывает, и ни один античит, работающий внутри игры, не вправе утверждать обратное. ESP только для чтения находится в том же положении: он ничего не меняет, а значит, нигде себе не противоречит.
Остаётся эффект: выстрел по траектории, которой не создаёт ни один человек, прицел, который прыгает и замирает, знание позиций, которых у игрока быть не должно. Вы уже детектируете не программу, а её след; это тема нашей статьи о silent aim. И потому что вопрос возвращается всегда: да, окончательное решение должно приниматься не на машине игрока, и это весь спор клиента с сервером.
Если хотите увидеть, как выглядит материал о загрузке меню (неизвестный вызывающий, восстановленный токен, метка времени), демо-панель открыта без регистрации, наш античит RedM показывает, где это семейство находится среди остальных, а общие принципы изложены в статье как работает античит RedM.