Как заблокировать скомпилированные классы Java, чтобы предотвратить декомпиляцию?

StackOverflow https://stackoverflow.com/questions/49379

  •  09-06-2019
  •  | 
  •  

Вопрос

Как мне заблокировать скомпилированные классы Java, чтобы предотвратить декомпиляцию?

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

Многие люди предлагают obfuscator, но они просто переименовывают классы, методы и поля с труднопроизносимыми последовательностями символов, но как насчет чувствительных постоянных значений?

Например, вы разработали компонент шифрования и дешифрования на основе метода шифрования на основе пароля.Теперь в этом случае любой среднестатистический пользователь Java может использовать ДЖАД чтобы декомпилировать файл класса и легко получить значение пароля (определенное как постоянное), а также соль и в свою очередь может расшифровывать данные, написав небольшую независимую программу!

Или такие чувствительные компоненты должны быть встроены в машинный код (например, VC ++) и вызывать их через JNI?

Это было полезно?

Решение

Некоторые из более продвинутых обфускаторов байт-кода Java делают гораздо больше, чем просто искажение имени класса. Зеликс КлассМастер, например, также может скремблировать поток вашего кода таким образом, что за ним действительно трудно уследить, и работает как отличный оптимизатор кода...

Кроме того, многие обфускаторы также способны зашифровывать ваши строковые константы и удалять неиспользуемый код.

Другим возможным решением (не обязательно исключающим запутывание) является использование зашифрованные файлы JAR и пользовательский загрузчик классов, который выполняет расшифровку (предпочтительно с использованием собственной библиотеки времени выполнения).

В-третьих (и, возможно, предлагающих самую надежную защиту), заключается в использовании встроенных компиляторов, таких как ССАГПЗ или Эксельсиор ДЖЕТ, например, которые компилируют ваш Java-код непосредственно в собственный двоичный файл для конкретной платформы.

В любом случае вы должны помнить, что, как говорится в эстонской пословице, "Замки - для животных".Это означает, что каждый бит кода доступен (загружен в память) во время выполнения и при наличии достаточных навыков, решимости и мотивации люди могут и будут декомпилировать, расшифровывать и взламывать ваш код...Ваша задача состоит просто в том, чтобы сделать процесс как можно более неудобным и при этом сохранить его работоспособным...

Другие советы

Пока у них есть доступ как к зашифрованным данным, так и к программному обеспечению, которое их расшифровывает, вы в принципе не сможете сделать это полностью безопасным.Способы решения этой проблемы, которые были решены ранее, заключаются в использовании некоторой формы внешнего черного ящика для обработки шифрования / дешифрования, например, ключей, удаленных серверов аутентификации и т.д.Но даже тогда, учитывая, что пользователь имеет полный доступ к своей собственной системе, это только усложняет ситуацию, а не делает невозможным - если только вы не можете привязать свой продукт напрямую к функциональности, хранящейся в "черном ящике", как, скажем, серверы онлайн-игр.

Отказ от ответственности:Я не специалист по безопасности.

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

Возможно, асимметричные клавиши могли бы сработать:

  • разверните зашифрованную лицензию с открытым ключом для расшифровки
  • позвольте клиенту создать новую лицензию и отправить ее вам для шифрования
  • отправьте новую лицензию обратно клиенту.

Я не уверен, но я верю, что клиент действительно может зашифровать лицензионный ключ с помощью открытого ключа, который вы ему дали.Затем вы можете расшифровать его с помощью своего закрытого ключа и также повторно зашифровать.

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

Независимо от того, что вы делаете, это может быть "декомпилировано".Черт возьми, вы можете просто разобрать его.Или посмотрите на дамп памяти, чтобы найти свои константы.Видите ли, компьютер должен знать их, поэтому ваш код тоже должен это знать.

Что с этим делать?

Старайтесь не отправлять ключ в качестве жестко закодированной константы в вашем коде:Сохраните это как настройку для каждого пользователя.Возложите на пользователя ответственность за хранение этого ключа.

@jatanp:или, что еще лучше, они могут декомпилировать, удалять лицензионный код и перекомпилировать.Что касается Java, я действительно не думаю, что существует правильное, защищенное от взлома решение этой проблемы.Даже злой маленький ключ не смог бы предотвратить это с помощью Java.

Мои собственные бизнес-менеджеры беспокоятся по этому поводу, а я слишком много думаю.Но опять же, мы продаем наше приложение крупным корпорациям, которые, как правило, соблюдают лицензионные условия - как правило, это безопасная среда благодаря счетчикам компонентов и юристам.Сам процесс декомпиляции может быть незаконным, если ваша лицензия написана правильно.

Итак, я должен спросить, не так ли в самом деле вам нужна надежная защита, подобную той, которую вы ищете для своего приложения?Как выглядит ваша клиентская база?(Корпорации?Или массы геймеров-подростков, где это было бы более серьезной проблемой?)

Если вы ищете решение для лицензирования, вы можете ознакомиться с API TrueLicense.Он основан на использовании асимметричных клавиш.Однако это не означает, что ваше приложение не может быть взломано.Каждое приложение можно взломать, приложив достаточно усилий.Что действительно важно, так это то, что Стью ответил, выясняя, насколько сильная защита вам нужна.

Я не думаю, что существует какой-либо эффективный автономный метод борьбы с пиратством.Индустрия видеоигр много раз пыталась найти это, и их программы всегда были взломаны.Единственное решение заключается в том, что программа должна быть запущена онлайн, подключенная к вашим серверам, чтобы вы могли проверить ключ lincense, и чтобы одновременно было только одно активное подключение лицензиата.Вот как это делается World of Warcraft или Диабло работает.Даже в жестких условиях существуют частные серверы, разработанные специально для них, чтобы обойти систему безопасности.

Сказав это, я не верю, что средние / крупные корпорации используют нелегально скопированное программное обеспечение, потому что стоимость лицензии для них минимальна (возможно, я не знаю, сколько вы собираетесь взимать за свою программу) по сравнению со стоимостью пробной версии.

Вы можете без опасений использовать шифрование байт-кодом.

Дело в том, что цитируемая выше статья “Взлом шифрования байт-кода Java” содержит логическую ошибку.Основная претензия к статье заключается в следующем перед запуском все классы должны быть расшифрованы и переданы в ClassLoader.defineClass(...) способ.Но это неправда.

Допущение, упущенное здесь, таково при условии, что они выполняются в аутентичной или стандартной среде выполнения Java.Ничто не может обязать защищенное java-приложение не только запускать эти классы, но даже расшифровывать и передавать их ClassLoader.Другими словами, если вы находитесь в стандартном JRE, вы не можете перехватить defineClass(...) метод, потому что стандартная java не имеет API для этой цели, и если вы используете модифицированный JRE с исправленным ClassLoader или любой другой “хакерский трюк”, вы не сможете этого сделать, потому что защищенное java-приложение вообще не будет работать, и поэтому вам нечего будет перехватывать.И абсолютно не имеет значения, какой "поиск исправлений” используется или какой трюк используют хакеры.Эти технические детали - совсем другая история.

Q:Если я зашифрую свои файлы .class и использую пользовательский classloader для загрузки и расшифровки их "на лету", предотвратит ли это декомпиляцию?

A:Проблема предотвращения декомпиляции байт-кода Java почти так же стара, как и сам язык.Несмотря на широкий спектр инструментов обфускации, доступных на рынке, начинающие Java-программисты продолжают придумывать новые и хитроумные способы защиты своей интеллектуальной собственности.В этом выпуске Java Q & A я развею некоторые мифы вокруг идеи, часто обсуждаемой на дискуссионных форумах.

Чрезвычайная легкость, с которой файлы Java .class могут быть реконструированы в исходные тексты Java, которые очень похожи на оригиналы, во многом связана с целями разработки байт-кода Java и компромиссами.Помимо прочего, Java byte code был разработан с учетом компактности, независимости от платформы, мобильности сети и простоты анализа интерпретаторами байт-кода и динамическими компиляторами JIT (just-in-time) / HotSpot.Возможно, скомпилированные файлы .class настолько четко выражают намерения программиста, что их было бы легче проанализировать, чем исходный код.

Можно сделать несколько вещей, если не для того, чтобы полностью предотвратить декомпиляцию, то, по крайней мере, для того, чтобы усложнить ее.Например, на этапе после компиляции вы могли бы изменить данные .class, чтобы сделать байтовый код либо более трудным для чтения при декомпиляции, либо более трудным для декомпиляции в допустимый Java-код (или и то, и другое).Такие методы, как выполнение экстремальной перегрузки имени метода, хорошо работают для первого, а манипулирование потоком управления для создания управляющих структур, которые невозможно представить с помощью синтаксиса Java, хорошо работают для второго.Более успешные коммерческие обфускаторы используют сочетание этих и других методов.

К сожалению, оба подхода фактически должны изменять код, который будет выполняться JVM, и многие пользователи боятся (и это справедливо), что это преобразование может добавить новые ошибки в их приложения.Кроме того, переименование методов и полей может привести к тому, что вызовы отражения перестанут работать.Изменение фактических имен классов и пакетов может привести к нарушению работы нескольких других Java API (JNDI (Java Naming and Directory Interface Интерфейс именования Java и каталогов), поставщиков URL-адресов и т.д.).В дополнение к измененным именам, если изменить связь между смещениями байтового кода класса и номерами строк источника, восстановление исходных трассировок стека исключений может стать затруднительным.

Затем есть возможность запутать исходный код Java.Но по сути это вызывает аналогичный набор проблем.Шифровать, а не запутывать?

Возможно, вышесказанное заставило вас задуматься: "Ну, а что, если вместо манипулирования байт-кодом я зашифрую все свои классы после компиляции и расшифрую их "на лету" внутри JVM (что можно сделать с помощью пользовательского загрузчика классов)?Затем JVM выполняет мой исходный байтовый код, и все же нет ничего для декомпиляции или обратного проектирования, верно? "

К сожалению, вы ошибаетесь, как думая, что вам первому пришла в голову эта идея, так и думая, что она действительно работает.И причина не имеет ничего общего с надежностью вашей схемы шифрования.

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top