PMMP Packet Logger: Decode Unencrypted Packets Pre-Encryption

Answered using AI by Vibe Coding

Code Question:

Напиши код для плагина PocketMine-MP PM API 5.37.3 при заходе игрока на сервер в консоль отправляется декодированная информация пакетов, которые издаёт клиент игрока при подключении, расшифрованная в полном виде.

Code Solution:

В PocketMine-MP версии API 5.37.3 невозможно напрямую расшифровывать пакеты клиента, так как они защищены шифрованием (включается при начале LoginSuccess). Однако до установления шифрования можно перехватывать и логировать незашифрованные пакеты, такие как LoginPacket, ClientCacheStatusPacket, RequestChunkRadiusPacket и другие, которые клиент отправляет до включения шифрования.

Ниже приведён пример плагина, который перехватывает и декодирует (в разборном виде) все пакеты, отправленные клиентом до включения шифрования, и выводит их в консоль.


✅ Что делает этот плагин:

  • Ловит пакеты от игрока до включения шифрования.
  • Расшифровывает (декодирует) структуру пакета.
  • Печатает в консоль имя пакета и его поля.

📁 plugin.yml

name: PacketLogger
version: 1.0.0
api: 5.0.0
main: PacketLogger\Main
author: YourName

📁 src/PacketLogger/Main.php

<?php

declare(strict_types=1);

namespace PacketLogger;

use pocketmine\event\Listener;
use pocketmine\event\server\DataPacketReceiveEvent;
use pocketmine\network\mcpe\protocol\DataPacket;
use pocketmine\plugin\PluginBase;
use pocketmine\utils\TextFormat;

class Main extends PluginBase implements Listener {

    public function onEnable(): void {
        $this->getServer()->getPluginManager()->registerEvents($this, $this);
    }

    public function onDataPacketReceive(DataPacketReceiveEvent $event): void {
        $player = $event->getOrigin();
        $packet = $event->getPacket();

        // Логируем только если шифрование ещё не включено
        if (!$player->isEncrypted()) {
            $this->logPacket($packet);
        }
    }

    private function logPacket(DataPacket $packet): void {
        $class = $packet::class;
        $fields = [];

        // Используем Reflection для получения публичных свойств пакета
        $reflection = new \ReflectionClass($packet);
        foreach ($reflection->getProperties() as $property) {
            $property->setAccessible(true);
            $value = $property->getValue($packet);
            if (is_array($value)) {
                $value = json_encode($value, JSON_UNESCAPED_SLASHES | JSON_UNESCAPED_UNICODE);
            } elseif (is_object($value)) {
                $value = sprintf("[object %s]", $value::class);
            }
            $fields[$property->getName()] = $value;
        }

        $this->getLogger()->info(TextFormat::YELLOW . "Packet: " . TextFormat::AQUA . basename(str_replace("\\", "/", $class)));
        foreach ($fields as $key => $value) {
            $this->getLogger()->info(TextFormat::GRAY . "  $key: " . $value);
        }
    }
}

⚠️ Важно:

  • Этот код не расшифровывает зашифрованный трафик — это технически невозможно без взлома шифрования Minecraft.
  • Он логирует только незашифрованные пакеты, отправленные до момента включения шифрования.
  • После LoginSuccess и включения шифрования, пакеты будут зашифрованы и не декодируются этим способом.

Если тебе нужно логировать все пакеты, включая зашифрованные — это возможно только через манипуляции с сетевым стеком, например, через прокси-сервер (вроде WaterDogPE) или MITM-прокси, но это уже выходит за рамки PMMP-плагина.