Дисклеймер. Сказанное ниже является личным мнением автора. Сам по себе автор является мастером спорта международного класса по продавливанию дивана и ничего полезного в своей жизни он, разумеется, не сделал. Сказанное не претендует на звание истины в последней инстанции, а автор готов признавать свои ошибки и публично приносить извинения, если заденет чьи-то чувства прекрасного своей графоманией с шизофреническими наклонностями.
Ранее в статье Как не стоит делать: безопасность ивентов и клиентских скриптов я указывал на возможность дампа любых клиентских ресурсов, в том числе скрипты, контент браузера и dlcpack'и. Мнимая безопасность, которую создали разработчики RageMP создает иллюзию, которая играет плохую шутку с разработчиками серверов. Но есть и те, кто позаботился о безопасности своих скриптов, иногда даже в ущерб игрокам. В данной теме будет разобрана безопасность на примере Majestic и Smotra RAGE, так как принципы обеспечения безопасности клиентских ресурсов у них отличаются, а в следующей проведем разбор GTA 5 RP.
Перед началом отмечу, что дампы (а тем более их деобфусцированные или расшифрованные версии) я не предоставляю.
Начнем с Majestic. Ребята пошли по простому пути и решили обфусцировать с помощью javascript-obfuscator все, что возможно в ущерб и так не очень хорошей производительности.
Возьмем случайно место из дампа:
Выглядит страшно, но, как мы знаем, у страха только глаза велики. Если прочитать код, можно понять, что он не видоизменился относительно исходного после обфускации. Циклы сохранены, последовательность выполнения тоже. При кратком анализе можно сделать вывод, что единственная потеря - это название переменных и строки. Клиенту не особо-то и нужны корректные названия переменных, а вот строки - жизненно необходимы. Если посмотреть в начало файла, мы имеем целый массив со множеством строк:
После объявления массива сразу следуют функции его "исправления": массив изначально перемешан и в нем присутствует проверка целостности. В случае, если какая-то строка изменена, код зависнет в бесконечном цикле исправления массива.
В принципе, алгоритм предельно прост и ясен. Надо написать небольшой скриптик, который раскладывает часть объектов (так как позиция в массиве передавалась не числом, а читалась из свойства объекта), а также написать функцию, которая удаляет неиспользуемые переменные, потому что функция получения исходной строки создается на всех уровнях scope'ов, что вызывает небольшие трудности при чтении:
Потеряли названия переменных, потому подумаем над восстановлением хотя бы части их названий. По структуре дампа явно видно, что дамп собран webpack'ом или подобным сборщиком: есть реализация импортов, экспортов, shadow-переменных и прочей магии сборщиков. Можно предположить, что экспорт и импорт происходит посредством передачи функций в аргументы, потому допишем скриптик, добавив переименование функций и переменных в стиль вебпака, раскладывание предикейтов (!0, !1), а также переведем числа из hex в десятичные:
Итог по Majestic: подобный вид обфускации бесполезен. Единственная потеря в результате деобфускации - названия переменных. Несмотря на это, деобфусцированный дамп все также легок в чтении и не доставляет никаких проблем узнать названия функций, вызовов, аргументов функций. Несмотря на легкость в получении читабельного кода, подобная техника обфускации создает большие проблемы с производительностью:
В обфусцированном виде для вызова функции необходимо сделать 6 обращений к свойству объекта (которые, кстати, не оптимизируются v8, так как Ignition не умеет предугадывать результаты исполнения функции во время компиляции в байт-код), 3 обращения к массиву, против оригинального кода, который только 3 раза обращается к свойствам объекта и попадает под оптимизацию. Примерно то же самое происходит и в браузерной части Majestic, с одной оговоркой: там все еще хуже, так как используется Vue, который под обфускацией показывает совсем плачевную производительность.
Перейдем к SmotraRAGE: парни выбрали интересное решение и просто зашифровали скрипты своим алгоритмом с использованием pako и base64. Структура клиентских файлов примерно следующая: index.js, где выполняется расшифровка и подключение скриптов и основная папка "core", содержащая весь код. Любой файл из core встречает нас примерно следующим содержимым и пафосной надписью с информацией о том, кто создал защиту:
Чтобы расшифровать скрипты, нам необходимо реализовать свою функцию расшифровки. Подробности её реализации я не буду рассказывать, так как считаю подобное не этичным. Отмечу лишь одно: реализация заняла меньше времени, чем восстановление структуры файлов после дампа.
Итог по SmotraRAGE: подобная реализация защиты с точки зрения владельцев серверов намного лучше, нежели чем вариант обфускации Majestic, банально из-за одной вещи: производительность. Сохранен оригинальный вид кода, он не обфусцирован, а это значит, что игроки не страдают из-за маниакального желания "защитить" код.
Выводы из урока: не пытайтесь защитить код способами, что я показал ранее. Majestic страдает серьезным снижением производительности из-за обфускатора, который не справляется со своей задачей. А в случае SmotraRAGE это, ну я бы сказал, бесполезно. В обоих случаях все еще работает правило "не доверять клиенту".
P. S. Если "правообладатели" захотят связаться со мной - https://t.me/msmk_cn
Ранее в статье Как не стоит делать: безопасность ивентов и клиентских скриптов я указывал на возможность дампа любых клиентских ресурсов, в том числе скрипты, контент браузера и dlcpack'и. Мнимая безопасность, которую создали разработчики RageMP создает иллюзию, которая играет плохую шутку с разработчиками серверов. Но есть и те, кто позаботился о безопасности своих скриптов, иногда даже в ущерб игрокам. В данной теме будет разобрана безопасность на примере Majestic и Smotra RAGE, так как принципы обеспечения безопасности клиентских ресурсов у них отличаются, а в следующей проведем разбор GTA 5 RP.
Перед началом отмечу, что дампы (а тем более их деобфусцированные или расшифрованные версии) я не предоставляю.
Начнем с Majestic. Ребята пошли по простому пути и решили обфусцировать с помощью javascript-obfuscator все, что возможно в ущерб и так не очень хорошей производительности.
Возьмем случайно место из дампа:
Выглядит страшно, но, как мы знаем, у страха только глаза велики. Если прочитать код, можно понять, что он не видоизменился относительно исходного после обфускации. Циклы сохранены, последовательность выполнения тоже. При кратком анализе можно сделать вывод, что единственная потеря - это название переменных и строки. Клиенту не особо-то и нужны корректные названия переменных, а вот строки - жизненно необходимы. Если посмотреть в начало файла, мы имеем целый массив со множеством строк:
После объявления массива сразу следуют функции его "исправления": массив изначально перемешан и в нем присутствует проверка целостности. В случае, если какая-то строка изменена, код зависнет в бесконечном цикле исправления массива.
В принципе, алгоритм предельно прост и ясен. Надо написать небольшой скриптик, который раскладывает часть объектов (так как позиция в массиве передавалась не числом, а читалась из свойства объекта), а также написать функцию, которая удаляет неиспользуемые переменные, потому что функция получения исходной строки создается на всех уровнях scope'ов, что вызывает небольшие трудности при чтении:
Потеряли названия переменных, потому подумаем над восстановлением хотя бы части их названий. По структуре дампа явно видно, что дамп собран webpack'ом или подобным сборщиком: есть реализация импортов, экспортов, shadow-переменных и прочей магии сборщиков. Можно предположить, что экспорт и импорт происходит посредством передачи функций в аргументы, потому допишем скриптик, добавив переименование функций и переменных в стиль вебпака, раскладывание предикейтов (!0, !1), а также переведем числа из hex в десятичные:
Итог по Majestic: подобный вид обфускации бесполезен. Единственная потеря в результате деобфускации - названия переменных. Несмотря на это, деобфусцированный дамп все также легок в чтении и не доставляет никаких проблем узнать названия функций, вызовов, аргументов функций. Несмотря на легкость в получении читабельного кода, подобная техника обфускации создает большие проблемы с производительностью:
JavaScript:
// оригинальный вид
mp.players.local.setHealth(100)
// vs обфусцированный псевдо-код
let array = [
'players',
'setHealth'
'local',
];
function getOriginalString(offset) {
// здесь большой кусок кода, который исполняется один раз при запуске (проверка целостности)
return array[offset];
}
(() => {
let properties = {
0: 0,
1: 2,
2: 1
};
mp[getOriginalString(properties[0])][getOriginalString(properties[2])][getOriginalString(properties[1])](0x64);
}());
Перейдем к SmotraRAGE: парни выбрали интересное решение и просто зашифровали скрипты своим алгоритмом с использованием pako и base64. Структура клиентских файлов примерно следующая: index.js, где выполняется расшифровка и подключение скриптов и основная папка "core", содержащая весь код. Любой файл из core встречает нас примерно следующим содержимым и пафосной надписью с информацией о том, кто создал защиту:
Чтобы расшифровать скрипты, нам необходимо реализовать свою функцию расшифровки. Подробности её реализации я не буду рассказывать, так как считаю подобное не этичным. Отмечу лишь одно: реализация заняла меньше времени, чем восстановление структуры файлов после дампа.
Итог по SmotraRAGE: подобная реализация защиты с точки зрения владельцев серверов намного лучше, нежели чем вариант обфускации Majestic, банально из-за одной вещи: производительность. Сохранен оригинальный вид кода, он не обфусцирован, а это значит, что игроки не страдают из-за маниакального желания "защитить" код.
Выводы из урока: не пытайтесь защитить код способами, что я показал ранее. Majestic страдает серьезным снижением производительности из-за обфускатора, который не справляется со своей задачей. А в случае SmotraRAGE это, ну я бы сказал, бесполезно. В обоих случаях все еще работает правило "не доверять клиенту".
P. S. Если "правообладатели" захотят связаться со мной - https://t.me/msmk_cn
Вложения
Последнее редактирование: