Как заблокировать скомпилированные классы Java, чтобы предотвратить декомпиляцию? - PullRequest
87 голосов
/ 08 сентября 2008

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

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

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

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

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

Ответы [ 9 ]

92 голосов
/ 08 сентября 2008

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

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

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

Третье (и, возможно, предложение самой надежной защиты) - это использование встроенных опережающих компиляторов, таких как, например, GCC или Excelsior JET , которые компилируют код Java непосредственно на платформу специфический нативный двоичный файл.

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

16 голосов
/ 08 сентября 2008

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

12 голосов
/ 08 сентября 2008

Отказ от ответственности: я не эксперт по безопасности.

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

Может быть, асимметричные ключи могут работать:

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

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

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

10 голосов
/ 08 сентября 2008

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

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

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

5 голосов
/ 08 сентября 2008

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

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

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

3 голосов
/ 08 сентября 2008

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

2 голосов
/ 07 марта 2012

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

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

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

2 голосов
/ 08 сентября 2008

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

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

0 голосов
/ 18 сентября 2015

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

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

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

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

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

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

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

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

...