Защита java приложений от реинженеринга / Native Classloader / NLaunch

HomaPlus

Разработчик
Пользователь
Заблокирован
Сообщения
1 743
Решения
26
Веб-сайт
gitlab.com
NLaunch - Библиотека для безопасной загрузки классов в java из защищенного формата .lar

Как это работает?

Для java-приложения
1) Ты пишешь java приложение
2) Собираешь его в .jar - архив
3) Получаешь сертификат формата PEM (сделаю сам, или в скриптах сборки можно сгенерировать свой)
4) Запрашиваешь у меня перекомпиляцию нативных библиотек под твой сертификат
(при необходимости можно настроить получение сертификата извне)
(исходный код модулей криптографии дать на руки могу только при особых условиях сотрудничества)
5) Запускаешь скрипты сборки
6) Запускаешь nlaunch.jar, указав в -Dnlaunch.lars=!%путь-к-lar-пакету%
7) Все запускается
Для minecraft-сборки (или 1-го мода)
5) Запускаешь minecraft с полным(и) модом(и), через nlaunch.jar ,,в режиме агента,, и некоторое время
играешь и активно используешь различные функции мода (статический агент в разработке)
все что было использовано - во время работы агента - попадет в .lar часть мода
6) Запускаешь скрипты сборки, в параметрах указав главный класс(ы), (а так же те, которые не нужно включать в .lar)
7) Помещаешь получившийся (урезанный) .jar в папку модов, вместо оригинального и указываешь путь к получившейся .lar-части
8) Майнкрафт запускается

Почему именно так?
Загрузчик модов Minecraft, считывает байты из jar-архива, который откроет любой декомпилятор
Принцип работы NLaunch - ,,прямая,, загрузка классов сразу в jvm. Т.е из java получить данные не возможно. Единственный вариант
получить исходные данные классов - распотрошить машинный код модуля криптографии


Скорость работы
Небольшие оптимизации реализации NLaunch для Forge - компенсируют те 20ms, которые уйдут на расшифровку классов внутри оперативной памяти

Кому это подойдет?
Тому, кому есть что защищать на стороне конечного потребителя
Подойдет для защиты сборок с модами, конкретных модов, плагинов, и других java-приложений
(Например, вы автор плагинов, и вы не хотите, чтобы кто-то смотрел ваш код через декомпилятор)
Повторюсь: Nlaunch совместим с любыми java приложениями. Даже с сайтом на Spring, или сервером Spigot.


В комплекте с NLaunch предоставляю
1) Саму библиотеку (nlaunch.jar), исходники и систему сборки lar-архивов
2) Сборку модуля криптографии под windows/linux x64
3) Модифицированные библиотеки minecraft/forge для правильной интеграции
4) Техподдержку актуальной версии NLaunch


Связь
Желательно почта Te4hnoPublic@yandex.ru

На данный момент реализована и протестирована поддержка windows-x64 / linux-x64 + Minecraft Forge 1.12.X-2860
Поддержка других версий minecraft, дополнительная комплектация, цена, и прочие тонкости сотрудничества - обсуждаются лично
(просьба писать на почту, на личные сообщения форума могу не ответить. Для тех, кто готов предложить меньше 5к - просьба не засорять почту)
 
Последнее редактирование:
Например, вы автор плагинов, и вы не хотите, чтобы кто-то смотрел ваш код через декомпилятор
Так, а каким образом конечный потребитель запустит один-единственный плагин, который теперь в lar формате, если весь остальной сервер - нет?
 
Последнее редактирование:
Так, а каким образом конечный потребитель запустит один-единственный плагин, который теперь в lar формате, если весь остальной плагин - нет?
Достаточно подключить NLaunch к проекту любым способом, закинуть плагин в папку с плагинами и подключить lar-архив (Пункт 6, для Java-приложений),
Так же можно включить NLaunch в свой плагин, и загрузить lar-пакет вручную (через специальное, очень простое API, Комплектация, пункт 1).
После чего, все классы внутри lar, будут доступны для использования внутри JVM. (Т.е на них можно будет сослаться обычным импортом)

Nlaunch нисколько не влияет на логику работы приложения. Т.е - как были плагины в в папке с плагинами в формате .jar - так они и продолжат работать.

Так же (при желании) можно сконвертировать уже само ядро, или его части в .lar (Комплектация, пункт 1), и точно так же загрузить
 
Это как-то скажеться на производительности?
Скорость работы
Небольшие оптимизации реализации NLaunch для Forge - компенсируют те 20ms, которые уйдут на расшифровку классов внутри оперативной памяти
Лишь незначительно увеличит время запуска серверов. Nlaunch так же поддерживает потоковую загрузку .lar-пакетов

Сервера, которые используют моды, основанные на преобразовании бай-кода перед загрузкой (как например Forge и Fabric) будут иметь эквивалентную скорость запуска, за счет заранее выполненных преобразований агентом (Для МС-сборки, пункт 5)

NLaunch загружает в jvm именно тот байткод, который ты скомпилировал, так что в рантайме производительность не изменится
Объединено

Выложил на гит демонстрационную версию приложения, защищенного Nlaunch

 
Последнее редактирование:
Выложил на гит демонстрационную версию приложения, защищенного Nlaunch

Покопался в ней немного. Заняло это примерно час, так что подумайте прежде чем покупать🙂

Библиотека упакована через UPX, написана с использованием Go, CGo. В ней присутствует:
  1. Проверка целостности: функция 0x63136440 проверяет GetProcAddress в java.dll на соответствие ожидаемому хешу.
  2. XOR stream cipher (0x63130EE0): побайтовый шифр с мутирующим сидом (seed = seed + plaintext_byte), для обфускации строк
  3. String shuffling (0x63130FC0): перемешивающий шифр для обфускации строковых констант
  4. Полная обфускация имён пакетов, функций, типов и переменных Go-кода с помощью garble
Алгоритм шифрования .lar файла - RSA-OAEP с асимметричными хеш-функциями:
Label hash: SHA-256 (для хеширования метки в OAEP)
MGF1 hash: SHA-512 (Mask Generation Function)
Ключ: RSA-4096 (512 байт на блок)
Label: пустая (nil)

Для файлов >512 байт данные разбиваются на блоки по 512 байт (0x200), каждый блок дешифруется RSA-OAEP независимо. Для данных >0x801 байт используется дополнительная XOR-маска поверх RSA-дешифрованных блоков (функция 0x63135160).

Ключевые функции библиотеки:
0x63130900 (zDdjEITjjQB.OsVPXQ.ReadKey) - Загрузка RSA ключа из обфусцированных данных
0x631309C0 (zDdjEITjjQB.(*OsVPXQ).Decrypt) - RSA-OAEP дешифровка одного блока (512 байт)
0x63130B60 (zDdjEITjjQB.V4KByKto0nMx) - SHA-256 хеширование (для метки)
0x63133420 (main.A7HHgNZsaM) - getSafe - дешифровка в byte[]
0x631334A0 (main.H5j6qwLsO) - loadSafe - дешифровка в Class<?>
0x63133F00 - Главная точка входа
0x63131120 - RSA PKCS#1 v1.5 / OAEP ядро (EME-OAEP декодирование)
0x63131800 - RSA CRT-оптмизированная экспонента
0x63130C40 - Инициализация XOR-ключа для обфускации RSA-ключа
0x63130EE0 - XOR stream cipher (побайтовая обфускация)
0x63130FC0 - Деобфускация строки (перемешивающий шифр)
0x63135160 - Мультиблочная RSA + XOR-дешифровка данных (>512 байт)


Ключевое соотношение названий обфусцированных пакетов к нормальным:
ixE7QIOhPq - crypto/x509
gSqbWWz - crypto/sha* (hash)
zDdjEITjjQB - Главный криптомодуль (OsVPXQ.Decrypt, ReadKey)
OHsH4wiN - archive/zip
VgFw5YoB - crypto/sha256
zxMrRfOHwjw - log
ds6vT1 - os
ydBPj7XsdPTG - io/ioutil или bufio
lXd_nObhF3 - math/big
fPzRVDNgcK - sort (internal)
AUqQN_PB - golang.org/x/sys/windows/registry


После расшифровки получаем META-INF/MANIFEST.MF и plus/hellonl/HelloNlaunch.class:

Java:
package plus.hellonl;

public class HelloNlaunch {
   private static String _codePass0A_ = "Home Homa Homa Plus";

   public static void main(String... args) {
      printLogo();
      seeUrl();
   }

   private static void printLogo() {
      String prefix = "----------------------------------------------------";
      print(prefix,
          "  _   _   _                                  _     \n"
        + " \\   __ _   _   _   _ __     ___  |__  \n"
        + "  \\ / _` '_ \\   / __'_ \\ \n"
        + " |\\  (_|_(__  |\n"
        + " |_\\_|_ \\__,_ \\__,_|_|_ \\___|_|_|\n"
        + "        PROTECT YOUR APP WITH NLAUNCH NOW              ",
          prefix);
   }

   private static void seeUrl() {
      try {
         Runtime rt = Runtime.getRuntime();
         String url = "https://vk.cc/crIL2s";
         rt.exec("rundll32 url.dll, FileProtocolHandler " + url);
      } catch (Exception e) {
         throw new RuntimeException(e);
      }
   }

   private static void print(Object... o) {
      for (Object l : o) {
         System.out.println(l);
      }
   }
}

Ключ шифрования:

-----BEGIN RSA PRIVATE KEY-----
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
-----END RSA PRIVATE KEY-----

Это всё было получено в результате статического анализа с помощью утилит (upx, xdd, binwalk, fernflower, ghidra, goresym), я не запускал эту программу. Хотя уверен, что перехватить загруженные классы из JVM было бы намного проще. А так, было интересно попробовать свои силы в этом. Всем удачи и мирного неба над головой!
 
Назад
Сверху Снизу