Байткод Java тривиально декомпилируется через JD-GUI, CFR и Fernflower. Мы шифруем классы, кодируем строки и переименовываем поля — так, чтобы из вашего плагина больше нельзя было восстановить исходный код.
Слева — то, что видит декомпилятор в обычном JAR. Справа — то же место после nObfuscator.
public class Main extends JavaPlugin {
@Override
public void onEnable() {
getCommand("fly").setExecutor(new FlyCommand());
System.out.println("[FlyV2] Плагин запущен, лицензия OK");
}
private boolean checkLicense(String key) {
return key.equals("SECRET-KEY-12345"); // украдём ключ
}
}
/**
* Decompiled by CFR 0.152.
* Could not decompile this class.
* java.lang.RuntimeException: malformed StackMapTable
*/
public class u.q.z extends JavaPlugin {
public void a() {
x79.invoke("\u0001NOB\u00A2\u00FF\u00D1\uFFFD\uFFFD"
+ "\u00E3\u00B9\u00D4..."); // строка зашифрована
}
private byte[][] ▂▂▂▂▂▂
= new byte[][] { load("...") };
}
Четыре уровня, каждый из них убирает доступный декомпилятору кусок вашего кода.
Все LDC-константы шифруются прямо в байткоде: декомпилятор видит блоб и вызов дешифратора. Рантайм-дешифратор генерируется с нуля под каждую сборку.
Класс-дешифратор вставляется в JAR под случайным именем пакета, класса и метода. Одинаковых выходов у двух обфускаций не бывает.
Мусорные synthetic-поля с нечитаемыми именами и поддельные атрибуты, на которых спотыкаются JD-GUI, CFR и Fernflower.
Приватные поля и методы получают нечитаемые имена. Мостовые методы, лямбды и reflection-хуки (access$, lambda$) не трогаются.
SourceFile, LineNumberTable и LocalVariableTable удаляются. Stack-trace больше не указывает на ваши исходники.
Свой рерайтер байткода сохраняет plugin.yml, TableSwitch-ветки, exception-таблицы и StackMapTable — плагин продолжает работать.
Renaming-инструменты, такие как ProGuard и Allatori, делают код менее читабельным, но после декомпиляции всё равно видно логику. Мы убираем саму возможность её прочитать.
| Обычные инструменты | nObfuscator | |
|---|---|---|
| Основной метод | Только переименование и сжатие | Полиморфное кодирование строк в байткоде + переименование |
| После декомпиляции | Читаемая логика и строка команд | Строки превращаются в блобы + вызов случайного кодека |
| Рантайм-кодек | Библиотечный, детерминированный | Свой, генерируется под случайное имя каждую сборку |
| Отладочная информация | Может остаться | Удаляется (SourceFile, строки, локалы) |
| Спигот / Paper | Часто ломают plugin.yml | plugin.yml сохраняется, ветки/StackMap пересчитаны |
Три шага — от исходного JAR до защищённого файла, готового к деплою.
Затяните ваш .jar-файл в окно загрузки. Файл обрабатывается на сервере и удаляется сразу после.
Лёгкий — 50, средний — 150, сильный — 300 CREDITS. Списываются при запуске обработки.
Получите обфусцированный JAR с собственным рантайм-дешифратором. Готово — можно выкладывать на сервер.
файл удаляется с сервера сразу после обработки
Если не нашли ответ — откройте виджет поддержки.
Да. Наш рерайтер байткода пересчитывает ветки, tableswitch/lookupswitch, exception-таблицы и StackMapTable после вставок, поэтому plugin.yml, listeners и JVM-верификация остаются нетронутыми.
Да. Загружается весь JAR — обрабатываются все классы внутри, структура архива и plugin.yml сохраняются.
Он увидит вызовы к классу-дешифратору со случайным именем и блобы вида \u0001NOB... вместо строк. Мусорные synthetic-поля и фейковые атрибуты дополнительно путают популярные декомпиляторы.
При регистрации вы получаете 300 CREDITS бесплатно. Одна обфускация стоит: Лёгкий — 50, Средний — 150, Сильный — 300. Кредиты выдаёт администрация в ручном режиме.
На уровне «Лёгкий» и «Средний» — практически нет: переименовываются только приватные члены, паттерны рефлексии сохраняются. Уровень «Сильный» тестируйте перед релизом.
Файлы обрабатываются в песочнице и автоматически удаляются после скачивания результата. Никакого долгого хранения, никакого доступа третьих лиц.