Mod Menu Stealth Concealment

Modlist_Self_Hide Вредоносное ПО (Malware) HIGH +9 очков

🎮 Влияние на механику Minecraft

Загрузчики модов хранят списки активных модификаций во внутренних структурах ядра и предоставляют публичные интерфейсы (например, FabricLoader.getInstance().getAllMods()), через которые меню и утилиты опрашивают загруженные дополнения.

Modlist_Self_Hide нацелен на алгоритмы, получающие доступ к внутренним структурам загрузчика через рефлексию и удаляющие контейнер определенного мода из общего списка. После удаления контейнера модификация продолжает исполняться, но перестает отображаться в списках модов, меню настроек и при опросе через API загрузчика. Данный метод модификации списка загрузчика через рефлексию дополняет файловое сокрытие (ModMenu_Config_Hiding, оценка 9), при котором чит перезаписывает modmenu.json на диске для удаления из графического меню.

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

🔍 Анализируемые функции и API

FabricLoaderImpl / ModContainerImpl

Внутренние классы Fabric Loader, хранящие список загруженных модификаций.

Class.getDeclaredField / setAccessible

Методы рефлексии для получения доступа к приватным полям реестра модов.

List.removeIf

Метод коллекции для удаления контейнера целевого мода по предикату.

💻 Реализация в моде (Исходный код)

package com.example.stealth;

import java.lang.reflect.Field;
import java.util.List;
import net.fabricmc.loader.impl.FabricLoaderImpl;
import net.fabricmc.loader.impl.ModContainerImpl;

public class ModListPurger {
    public static void purgeFromLoader(String targetModId) {
        try {
            FabricLoaderImpl loader = FabricLoaderImpl.INSTANCE;
            Field modsField = FabricLoaderImpl.class.getDeclaredField("mods");
            modsField.setAccessible(true);

            @SuppressWarnings("unchecked")
            List<ModContainerImpl> mods = (List<ModContainerImpl>) modsField.get(loader);
            if (mods != null) {
                mods.removeIf(container -> container.getMetadata().getId().equals(targetModId));
            }
        } catch (Exception ignored) {
            // Игнорирование ошибок при отсутствии доступа
        }
    }
}

🛡️ Сигнатура байткода и статический детект

Детектор анализирует байткод классов применительно к загрузчикам Fabric и Quilt, требуя одновременного выполнения трех условий в классе:

  • Ссылка на внутренние классы реализации загрузчика Fabric: FabricLoaderImpl или ModContainerImpl.
  • Вызовы методов рефлексии: java/lang/Class.getDeclaredField или setAccessible.
  • Вызов метода удаления элементов коллекции: java/util/List.removeIf.

Такая комбинация выявляет попытки получить доступ к закрытому внутреннему списку модов загрузчика через рефлексию и удалить контейнер мода с помощью предиката. Главное ограничение обусловлено привязкой к вектору атаки: правило детектирует сокрытие через внутренности Fabric/Quilt в оперативной памяти; файловое сокрытие путем перезаписи конфигурации Mod Menu на диске выявляется отдельным правилом ModMenu_Config_Hiding (также с оценкой 9).