Гайд MinecratOnly: Анализ защиты. Читы.

Начинающий
Статус
Оффлайн
Регистрация
28 Май 2022
Сообщения
24
Реакции[?]
33
Поинты[?]
0
Итак, задача: зайти на сервер с читами.

Анализ защиты.

С ходу можно сказать, что у проекта комплексная защита. Потому что, во-первых, при запуске проверяется наличие своей java. Если ее нет, она скачивается. После чего именно через скаченную java запускается сам лаунчер. Если попробовать с помощью батника запустить лаунчер через другую java, игра в последующем не запуститься. Однако, если тем же батником запустить лаунчер от скачаной java, то все запуститься. Во-вторых, сразу подключаем анализатор сетевого трафика (любой) и видим первый запрос от auth.minecraftonly.ru делается на
  1. Пожалуйста, авторизуйтесь для просмотра ссылки.
    ,
что в ответе дает нам launcher:03c13275cd98368231ea40c43e484508.

Рассчитаем MD5 лаунчера, который имеет расширение .jar. Сравнивая полученное значением с ответом запроса, понимаем, что лаунчер проверяет свою целостность.

Понятное дело, что, если мы внесем какие-либо изменения в файлы клиента, лаунчер их просто перекачает. Поэтому, для начала, нужно отключить все защиты в самом лаунчере.

Открываем jar файл в каком-нибудь java-decompiler (рекомендую Recaf -
Пожалуйста, авторизуйтесь для просмотра ссылки.
). Видим:
Снимок экрана 2022-05-29 в 22.12.27.png

Без обфускации никуда. В принципе, методом долгих тыков можно что-нибудь да понять, но все же лучше не мучиться и деобфуцировать. По внешнему виду можно разглядеть характерные черты Allatori. Можно написать свою простую функцию расшифровки строк и переименования классов и функций, но, чтобы не гадать берем готовый деобфускатор (рекомендую Deobfuscator -
Пожалуйста, авторизуйтесь для просмотра ссылки.
), анализируем и снимаем обфускацию. Кто не хочет разбираться –
Пожалуйста, авторизуйтесь для просмотра ссылки.
Снимок экрана 2022-05-29 в 22.15.49.png

Так уже понятнее и приятнее разбираться. Особо ленивым можно еще накинуть и трассировку, чтобы сразу понять что и в каких функциях происходит, но я приведу аналитический способ.

Идем по сетевому трафику:

2.
Пожалуйста, авторизуйтесь для просмотра ссылки.
- часть авторизации в личном кабинете;​
3.
Пожалуйста, авторизуйтесь для просмотра ссылки.
- как я понял, сбор железа и проверка на бан;​
4.
Пожалуйста, авторизуйтесь для просмотра ссылки.
- получение данных для авторизации непосредственно для входа на сервер;​
5.
Пожалуйста, авторизуйтесь для просмотра ссылки.
– проверка наличия и целостности библиотек клиента;​
6.
Пожалуйста, авторизуйтесь для просмотра ссылки.
- проверка наличия и целостности каких-то дополнительных библиотек (позже узнаем каких).​
Вырезаем проверку целостности лаунчера.

По ключевому слову “getVersion” (из ссылки) находим класс, в котором выполняется запрос на получение хеша лаунчера. Немного понимаем код и находим строки, которые отвечают за проверку.
К сожалению, больше нельзя прикреплять скрины
Пожалуйста, авторизуйтесь для просмотра ссылки.
  • Тупой способ: удалить расчет, который возвращает строку хэша и на ее место вставить явную строку хэша.
  • Более умный способ: удалить расчет, который возвращает строку хэша и на ее место вставить тот же запрос, который используется для получения эталонного хэша с сервера. Далее прописать точно такой же обработчик, который убирает “launcher:”.
  • Еще более умнее: эта функция возвращает bool = true. Прописать статичный возврат true.
  • Самый жоский: посvотреть, что вызывает эту функцию и вырезать.
Чем хороши 2-4 способы? Тем что при обновлении эталонного хэша на сервере не придется его каждый раз менять в лаунчере.

Рекомендую патчить оригинальный лаунчер, а не деобфуцированный. Сопоставляем их, кликаем по методу ПКМ – Edit with assembler и правим по своему усмотрению.

Первая проверка целостности лаунчера вырезана.

Возвращаемся к сети:

2 и 3 пункты сетевого трафика нам в принципе не интересны.
4 – явно, что-то важное, но вернемся позже.
5 – по-любому нужно отключить, если мы хотим добавить свои файлы в mods или в mincraft.jar.
6 – пока не трогаем.

Вырезаем проверку целостности клиента

Точно также, по ключевому слову “updates.php” ищем место, где происходит проверка. Здесь помним про разделение: есть целостность и есть наличие. Анализируем код и вырезаем проверки.

Теперь можно экспортировать наш патченный лаунчер и запускать его. Особо нетерпеливым можно закинуть в клиент сторонние файлы (читы) (не рекомендую использовать известные чит паки, лучше написать свой), чтобы убедиться, что все работает (имеется ввиду обход защиты). А можно просто попробовать запуститься, что и сделаем (помним про запуск от java, которую скачал загрузчик, так как от этой проверки мы не отвязывали). Доходим до авторизации на сервере, и авторизация не проходит.
Пожалуйста, авторизуйтесь для просмотра ссылки.

Всплывает еще одна защита – клиентская. Авторизация на сервере тоже часть сетевого трафика, поэтому возвращаемся к нему:

7.
Пожалуйста, авторизуйтесь для просмотра ссылки.
– запрос на авторизацию на сервер.​
Пример ответа: 6977a83d351bf31acef0c5b5ba7560ba;​
8.
Пожалуйста, авторизуйтесь для просмотра ссылки.
– составная ссылка, по которой мало что можно сказать на первый взгляд.​

Попробуем еще раз авторизироваться и посмотреть на трафик. Видим, что значения совершенно другие и больше напоминаю какие-то хэши, какую-либо зависимость выявлять бесполезно.

Анализируем дальше.

Очевидно, что это не стандартная моджонговская система авторизации. Поэтому лезем в minecraft.jar и ищем там “join.php”, находим класс YggdrasilMinecraftSessionService. Здесь строк, отвечающие за авторизацию немного, но они довольно информативные. Идет ссылка на некий класс ProtectLoader, который в свою очередь содержит некоторые пустые функции, которые будут висеть в памяти, а также ссылки на библиотеки с общим целым названием client.
Пожалуйста, авторизуйтесь для просмотра ссылки.
Пожалуйста, авторизуйтесь для просмотра ссылки.

Он находится в корне .minecraftonly. Рядом с ним еще один – protect. Оба с расширением dll и невероятно большим размером для динамической библиотеки такой игры, как minecraft. Это не может не настораживать.

Вспоминаем нашу сетевую трассу, а именно 6 пункт. Ответом на данный запрос являются 2 хэша, разделенные двоеточием. Рассчитываем MD5 для обоих файлов. Видим совпадение. Следовательно мы доказали то, что эти файлы отвечают за защиту как минимум авторизации и является довольно важными (хотя такой вывод можно было сделать просто из названия:relaxed:).

Вырезаем проверку целостности библиотек защиты.

Для чего? Чтобы можно было их модифицировать.

Возвращаемся в лаунчер. По ключевому слову “getlibver.php” ищем класс и метод, где осуществляется проверка. Сопоставляем – патчим – экспортируем лаунчер.

Теперь приступаем к анализу самих dll. Для начального исследования нам будет достаточно программы Process Hacker. Запускаем игру, после прогрузки открываем Process Hacker – Открываем наш процесс java.exe – Modules – Ищем библиотеку client.dll – Exports:
  • Agent_OnLoad – часть JNI - интерфейс, позволяющий из Java вызывать нативные функции;
  • Java_net_minecraft_ProtectLoader_checkProcess – что-то там с процессами делает, возможно проверяет на запрещенные;
  • Java_net_minecraft_ProtectLoader_loadClassData, Java_net_minecraft_ProtectLoader_protect и Java_ru_minecraftonly_ProtectLoader_loadClassData представляют наибольший интерес;
  • Две последние не интересны
Проверим нет ли в памяти protect.dll – не находим. Следовательно, она грузится в другом месте. Закроем игру и запустим лаунчер до момента запуска игры. Точно также проверяем процесс на наличие client.dll и protect.dll. В этот раз находим только protect.dll:
  • Java_net_minecraft_ProtectLoader_protectProcess@@YAXPEAUJNIEnv_@@PEAV_jobject@@@Z – пропускаем;
  • Java_net_minecraft_ProtectLoader_checkProcess – как и в первом случае работает с процессами;
  • Java_net_minecraft_ProtectLoader_getHWID – скорее всего проверяет на бан по железу;
  • Java_net_minecraft_ProtectLoader_loadClassData – второе совпадение данной функции.

Итак, client.dll и protect.dll, по сути, две библиотеки-близнеца, имеющие много общего кода. Сравнивая функции можно заметить одну очень интересную – loadClassData. Вероятнее всего она имеет тело расчета MD5 лаунчера и передает этот расчет дальше для генерации чего-то. Самая логичная мысль по этому поводу будет найти то самое место расчета и попробовать заменить его на эталонный.

Что дальше?

Дальше будем исследовать данные библиотеки. Кидаем ее в IDA PRO и видим неприятную вещь: оба файла имеют секции vmp0 и vmp1. Это свидетельство того, что на файл наложен протектор VMProtect. У него есть разные версии и снятие той или иной отличны друг от друга. Универсального способа снятия также нет. Версию же можно попробовать узнать через Detect It Easy: программа действительно определит VMProtect версии 1.70. Однако помните, что сигнатуры самой программы могут быть устаревшими, поэтому определенная версия может оказаться неверной (подозреваю, что это 3.X). Но то, что это VMProtect – 100%.

И прежде, чем исследовать библиотеку, необходимо снять протектор, так как он накладывает механизмы, при работе которых нормальная отладка становится невозможной.

Снятие протекторов – дело творческое и неопытному пользователю скорее непосильное. Описание снятия и объяснение каждого действия наверно выйдет по объему больше, чем эта статья. Поэтому пока что будем считать, что, если вы дошли до данного текста, вы являетесь опытным разработчиком. Процесс снятия протектора я возможно опишу в следующей статье. А пока советую посмотреть тематический канал OALabs -
Пожалуйста, авторизуйтесь для просмотра ссылки.
– там можно найти все по этой теме.

Но пару слов все же скажу.
Итак, при авторизации в игру мы получаем строку, например:
0:0:Goodie‎:176529760610557459767:68394201325234:7dacd507f58be5ddbaa0b870f205ad20:0dfc9bffe25d5d27eab45bff9e408f20:fe708dba9f64bb2b4e4b9867a075b5d8:0

Что есть что: 0:0:login:session:servertype:md5hash:authhash:md5_check:0

Если MD5 лаунчера (обязательно в апперкейсе!), с которого мы пытаемся авторизироваться, совпадает с эталонным на сервере, то у нас правильно рассчитывается md5_check из той же самой пришедшей нам строки как
  • md5_check = MD5_String(authhash + Base64(Byte(XOR(MD5_Launcher_UPPERCASE & 2xKEY_HASH)))),
где Base64 - стандарт кодирования двоичных данных при помощи только 64 символов ASCII,
XOR - исключающее «или» (сложение по модулю 2),
Byte - байтовое представление проксоренных строк,
2xKEY_HASH - ключ, зашитый в библиотеку, равный d912b848fd300125 и использующийся два раза подряд для уравнения длин строк для ксора.

То есть, допустим мы авторизируется с самого нового лаунчера, его MD5 хэш равен
  • 6e392c8dab43aad47517b9d015bfa090
что в верхнем регистре дает
  • 6E392C8DAB43AAD47517B9D015BFA090
Проксорим эту строку с двойным ключом
  • d912b848fd300125d912b848fd300125
таким образом, чтобы на выходе получилась байтовая строка:
  • 527c020b507b0c7c2726070371707601530c0005200170085751717671010b05
Теперь пихаем ее в байтовый Base64 и получаем
  • UnwCC1B7DHwnJgcDcXB2AVMMAAUgAXAIV1FxdnEBCwU=
Далее берем authhash и присоединяем то, что получили
  • 0dfc9bffe25d5d27eab45bff9e408f20UnwCC1B7DHwnJgcDcXB2AVMMAAUgAXAIV1FxdnEBCwU=
и считаем MD5 этой строки, что собственно нам и даст
  • fe708dba9f64bb2b4e4b9867a075b5d8
После этого начинается генерация хеша логина (loginhash), который потом используется в генерации ссылки авторизации на сервере. Если же MD5 лаунчера будет отличаться от эталонного на сервере, то сформируется неверный md5_check, что приведет к генерации неверного хеша логина, с которым на сервер не попасть.

Как генерируется loginhash?
В библиотеку зашит еще один ключ
  • XQkGBlYIDQ9fAldSVFUHBQIBAgNUXAcOVV1XVlYEUAY=
который переводится в байты функцией Base64_to_byte -
  • 5d09060656080d0f5f0257525455070502010203545c070e555d575656045006
и ксорится с 2xKEY_HASH, что на выходе дает ASCII строку
  • 907440979fdbdd50f8316d3639dff5b3
Полученная строка посимвольно мешается с authhash, что дает
  • 900d7f4c490b9f7f9ef2d5bdd5dd5207fe8a3b1465db3f6f399ed4f0f85fb230
Далее считается MD5 данной строки, что дает
  • 10d855b944abf57e1861dab363b34de8
и затем уже эта строка ксорится с 2xKEY_HASH, а полученное байтовое представление подается на вход функции byte_to_Base64, что дает
  • VQlVClcNVgFSUFJSVgQFUFUBBwMGWVYLUFdRAwRVVw0=
и именно эта строка дальше передается в игру.

Общее представление:
  • loginhash = byte_to_Base64(XOR(MD5_String(XOR(посимвольно(Base64_to_byte(KEY_Base64) & 2xKEY_HASH) & authhash)) & 2xKEY_HASH))
Далее loginhash участвует примерно в таких же расчетах только уже для генерации ссылки авторизации на сервере. И чтобы собственно дойти до этой самой генерации необходимо как и в первом случае чтобы правильно рассчитался md5hash и совпал с тем, что пришел с сервера. А рассчитывается он
  • md5hash = MD5_String(посимвольно(MD5_minecraft.jar + XOR(Base64_to_byte(KEY_Base64) & 2xKEY_HASH) + authhash)),
где KEY_Base64 - еще один зашитый ключ, равен XQ8HVANcBVsAVFYEVlMFV1ENAQBRCgEOVlcDUwMEUFY=

Здесь если MD5_minecraft.jar будет неверным, то сгенерируется неверная ссылка.

В случае успешной проверки происходит обратное преобразование строки
  • VQlVClcNVgFSUFJSVgQFUFUBBwMGWVYLUFdRAwRVVw0= - loginhash
к виду
  • 10d855b944abf57e1861dab363b34de8
путем ксора с 2xKEY_HASH, которое передается в mineceaft.jar. При авторизации на сервер нам приходит еще один ключ (ret), который соединяется с предыдущей строкой. Рассчитывается MD5
  • final_auth_link = MD5_String(ret + XOR(loginhash & 2xKEY_HASH))
На этом все. final_auth_link играет решающую роль во всем этом и делает авторизацию возможной.

К этому моменту мы имеем:
  • лаунчер, в котором отключены все защиты;
  • client.dll и protect.dll без протектора.
Так как protect.dll идет в цепочке загрузке первее, то начнем с нее. Грузим ее в IDA PRO и ставим брик на начало функции Java_net_minecraft_ProtectLoader_loadClassData, запускаем лаунчер и доходим до момента, когда остается нажать только “Войти в игру”. В IDA аттачимся к процессу java. Если IDA будет выкидывать исключения, настраиваем обработку на пропуск (не передавать их Java). Вообще, возможно, не с первого раза получится запустить, да и вообще подобрать обработку исключений. Потом нажимаем F9. В лаунчере нажимаем кнопку “Войти в игру” и на моменте “Выполняется загрузка библиотек” сработает наш брик.

Если IDA спросит о том, что обнаружена библиотека с таким же названием, просто нажимаем на “Some”. Теперь отлаживаем: можно, конечно, идти по ассемблеру, но гораздо понятнее будет если нажать Tab либо F5 и идти по декомпилированному коду (F8) по ходу смотря, что записывается в переменные: по ходу отладки вы заметите, что в некоторые переменные попадают значения из того самого ответа на 4-й запрос. Отсюда вывод: сервер генерирует начальные хэши, по которым потом строится ссылка авторизации 8. Идем дальше по отладчику и встречаем переменную, в которую попадает путь до лаунчера, а потом этот лаунчер подается в функцию расчета MD5 и, наконец, этот MD5 участвует в генерации уже других хэшей, из которых складывается ссылка авторизации на сервер…

Так вот, точно такой же алгоритм работает на сервере. Там генерируется единственно возможная ссылка, по которой пройдет успешная авторизация и, если происходит переход по ссылки, отличной от сгенерированной на сервере – все ломается. Поэтому так важно то, чтобы в генерации участвовал оригинальный MD5 хэш лунчера.

Что касается подмены, то спектр достаточно широкий. Можно в тупую поменять хэш на правильный или подменить путь патченного лаунчера на путь до оригинала. Тут уже зависит от вашей фантазии.

Для client.dll ситуация похожая, только он считает MD5 хэш minecraft.jar и так же использует его в генерации конечной ссылки. Таким образом, если вы собираетесь внедрять свой код в minecraft.jar, придется патчить еще и client.dll.

Итак, общий вывод по dll’кам: их основная задача сгенерировать единственно правильную ссылку для авторизации на серверах. Первая – protect, генерирует нам loginhash и передает его в minecraft.jar. Делает она это в любом случае, правильность зависит от MD5 лаунчера. Из дополнительных функций данной dll – получение железа компьютера – функция getHWID и дальнейшая передача длинной строки в лаунчер для проверки на бан.
Вторая – client, генерирует уже саму ссылку на основе полученного loginhash и MD5 minecraft.jar.

После всех патчей пробуем зайти на сервер – авторизация проходит успешно, но клиент вылетает. Значит мы упустили еще одну клиентскую защиту. Еще раз лезем в minecraft.jar – класс ProtectLoader и анализируем функцию loadProtect. Видим, что идет вызов нативной функции checkProcess. Нам не интересно, что она делает, но исходя из названия – что-то мешающее нем, поэтому просто вырезаем ее вызов. Собираем и пробуем еще раз зайти.

Успех. Считаю поставленную задачу выполненной..

Сам хак - https://yougame.biz/threads/255276/

Снимок экрана 2022-05-22 в 19.04.45.png
 
Последнее редактирование:
Начинающий
Статус
Оффлайн
Регистрация
7 Мар 2018
Сообщения
28
Реакции[?]
6
Поинты[?]
0
Годно. Жаль, не могу ставить реакции.
Месяц назад, тоже копался в их лаунчере.
Кому надо, забирайте деобфусцированные и запускабельные исходники лаунчера, с оригинальными названиями классов (при обфускации не были удалены исходные названия).

Пожалуйста, авторизуйтесь для просмотра ссылки.
 
Начинающий
Статус
Оффлайн
Регистрация
4 Июн 2017
Сообщения
21
Реакции[?]
5
Поинты[?]
0
С одной стороны годно, а с другой стороны там нет защиты) В общем для новичков пойдет хотя они и с таким гайдом ничего не смогут в принципе
 
Начинающий
Статус
Оффлайн
Регистрация
27 Дек 2021
Сообщения
12
Реакции[?]
0
Поинты[?]
0
Годно. Жаль, не могу ставить реакции.
Месяц назад, тоже копался в их лаунчере.
Кому надо, забирайте деобфусцированные и запускабельные исходники лаунчера, с оригинальными названиями классов (при обфускации не были удалены исходные названия).

Пожалуйста, авторизуйтесь для просмотра ссылки.
И куда кидать эти папки в launcher.jar? Помоги
 
VirtualAllocEx
Пользователь
Статус
Оффлайн
Регистрация
30 Дек 2021
Сообщения
358
Реакции[?]
83
Поинты[?]
5K
К сожалению, больше нельзя прикреплять скрины
Можно. Кидаешь все скрины на имгур и после успешной закачки - копируешь прямую ссылку на скрин и вставляешь фото по ссылке. GOVARD Ravin когда сделаете бл нормальный залив скринов? Хотя бы как у зелёного форума, там всё через имгур проходит
 
Начинающий
Статус
Оффлайн
Регистрация
28 Май 2022
Сообщения
24
Реакции[?]
33
Поинты[?]
0
Добавил описание алгоритма расчета ссылки авторизации (не знаю почему раньше не добавил..)
 
Начинающий
Статус
Оффлайн
Регистрация
9 Авг 2022
Сообщения
9
Реакции[?]
0
Поинты[?]
0
Сверху Снизу