Mod Menu Stealth Concealment
Влияние на механику 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).