Mod Menu Configuration Stealth Concealment

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

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

Mod Menu — стандартный графический интерфейс просмотра модификаций для Fabric и Quilt, считывающий списки загруженных дополнений и пользовательские настройки для отображения меню в игре.

ModMenu_Config_Hiding выявляет модификации, которые скрытно перезаписывают файл <config>/modmenu.json на диске для удаления своего названия из списка. В исследованном образце (com.example.timer.TimerClientMod) код мода выполняется в точке входа onPreLaunch. До загрузки графического интерфейса метод hideFromModMenu() находит modmenu.json, парсит его через JsonParser.parseReader(), обходит массивы "hidden_mods" и "hiddenMods" и добавляет строку "timer". После этого метод создает необходимые директории и сохраняет обновленный JSON на диск через Files.newBufferedWriter() и GsonBuilder().toJson(root, writer).

Когда Mod Menu инициализирует интерфейс, он считывает обновленный файл и не показывает модификацию в списке модов. Чит продолжает исполняться с полными правами, но исключается из отображаемого в интерфейсе списка установленных дополнений.

Этот метод дополняет правило Modlist_Self_Hide (score 9): если Modlist_Self_Hide фиксирует удаление контейнера мода из списка загрузчика через рефлексию (FabricLoaderImpl.getMods().removeIf(...)), то ModMenu_Config_Hiding фиксирует модификацию конфигурационного файла Mod Menu на диске. В легитимном окружении файл modmenu.json редактируется самим Mod Menu (com.terraformersmc.modmenu) по запросу пользователя через меню настроек либо поставляется в готовых сборках. Программная правка чужого конфига сторонним модом на этапе preLaunch свидетельствует о намеренном сокрытии чита.

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

modmenu.json

Файл конфигурации Mod Menu, содержащий пользовательские настройки и списки скрытых модов.

hidden_mods / hiddenMods

Ключи JSON-массива, определяющие идентификаторы скрытых от отображения модификаций.

⚙️ Декомпилированный вид (Vineflower)

private static void hideFromModMenu() {
   try {
      Path path = FabricLoader.getInstance().getConfigDir().resolve("modmenu.json");
      JsonObject root;
      if (Files.exists(path)) {
         try (Reader reader = Files.newBufferedReader(path, StandardCharsets.UTF_8)) {
            root = JsonParser.parseReader(reader).getAsJsonObject();
         }
      } else {
         root = new JsonObject();
      }

      for (String key : new String[]{"hidden_mods", "hiddenMods"}) {
         JsonArray hidden;
         if (root.has(key) && root.get(key).isJsonArray()) {
            hidden = root.getAsJsonArray(key);
         } else {
            hidden = new JsonArray();
            root.add(key, hidden);
         }

         boolean present = false;

         for (JsonElement entry : hidden) {
            if (entry.isJsonPrimitive() && entry.getAsString().equals("timer")) {
               present = true;
               break;
            }
         }

         if (!present) {
            hidden.add("timer");
         }
      }

      Files.createDirectories(path.getParent());

      try (Writer writer = Files.newBufferedWriter(path, StandardCharsets.UTF_8)) {
         new GsonBuilder().setPrettyPrinting().create().toJson(root, writer);
      }
   } catch (Exception e) {
      TimerClientMod.LOGGER.warn("Failed to hide timer from Mod Menu", e);
   }
}

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

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

  • Имя файла конфигурации: modmenu.json.
  • Ключи массива скрытых модов: hidden_mods или hiddenMods.

Такая комбинация выявляет модификации, перезаписывающие файл конфигурации Mod Menu на диске для исключения собственного идентификатора из графического меню. Правило ориентировано на проверку дисковой конфигурации Mod Menu, дополняя отдельное правило Modlist_Self_Hide (оценка 9), нацеленное на очистку списка загрузчика в рантайме через рефлексию.