2008-09-08 6 views
79

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

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

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

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

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

+4

Каков ваш прецедент? – user359996 2010-12-15 01:14:45

+0

Даже дизассемблированный родной код вполне доступен для некоторых людей, вам, вероятно, придется использовать некоторые обфускатор или ручная сборка, чтобы сделать его неочевидным (общий C++ компилируется с оптимизацией достаточно читаемый). Независимо код работает на устройстве пользователя, может быть перехвачен. Хотя требования к стоимости/квалификации такого перехвата могут быть довольно высокими, например, нарушение в смарт-карту "ta mper-proof "чип-код не является тривиальным, он доступен только с использованием верхнего оборудования и навыков. С Java-классами ... Я бы не стал сильно беспокоиться, вы, вероятно, зашифруете их достаточно, чтобы отключить скриптов, а не больше. – Ped7g 2016-09-22 10:43:53

ответ

83

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

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

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

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

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

11

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

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

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

13

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

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

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

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

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

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

+0

:) Мне понравилась ваша идея. – jatanp 2008-09-08 10:00:22

+1

Я использовал эту технику раньше, и она отлично работает. Однако с точки зрения атаки первым подходом было бы просто изменить код, который выполняет проверку лицензии и удалить его. Есть вещи, которые вы можете сделать, чтобы сделать этот вектор атаки более сложным, но если вы дадите атакующему управление аппаратным обеспечением, вы обречены на провал с подходящим мотивированным и квалифицированным злоумышленником. На практике цель состоит в том, чтобы держать в основном честных людей, честных. – 2010-06-24 12:04:27

6

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

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

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

+0

На самом деле, есть собственно рубить-доказательство решение, кстати выглядит как ключ: http://www.excelsior-usa.com/blog/excelsior-jet/java-bytecode-encryption-revisited/ – 2011-05-23 10:27:23

17

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

3

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

3

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

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

1

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

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

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

0

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

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

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

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

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

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

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

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