Как заблокировать скомпилированные классы Java, чтобы предотвратить декомпиляцию?
Я знаю, что это должна быть очень хорошо обсуждаемая тема в Интернете, но я не мог прийти к какому-либо выводу, направив их.
Многие люди предлагают обфускатор, но они просто переименовывают классы, методы и поля с помощью сложных для запоминания последовательностей символов, но как насчет чувствительных значений констант?
Например, вы разработали компонент шифрования и дешифрования, основанный на методе шифрования на основе пароля. Теперь в этом случае любой средний Java-человек может использовать JAD для декомпиляции файла класса и легко получить значение пароля (определенное как константа), а также соль и, в свою очередь, может расшифровать данные, написав небольшую независимую программу!
Или такие чувствительные компоненты должны быть встроены в собственный код (например, VC ++) и вызывать их через JNI ?
источник
Ответы:
Некоторые из более продвинутых обфускаторов байт-кода Java делают гораздо больше, чем просто изменение имени класса. Zelix KlassMaster , например, также может скремблировать поток кода таким образом, чтобы за ним было действительно трудно следить, и работает как отличный оптимизатор кода ...
Также многие из обфускаторов также могут шифровать ваши строковые константы и удалять неиспользуемый код.
Другое возможное решение (не обязательно исключающее обфускацию) - использовать зашифрованные файлы JAR и специальный загрузчик классов, который выполняет расшифровку (предпочтительно с использованием собственной библиотеки времени выполнения).
В-третьих (и, возможно, предлагая наиболее надежную защиту), является использование встроенных опережающих компиляторов, таких как, например, GCC или Excelsior JET , которые компилируют ваш Java-код непосредственно в собственный двоичный файл платформы.
В любом случае следует помнить, что по-эстонски говорится: «Замки - для животных». Это означает, что каждый бит кода доступен (загружен в память) во время выполнения и при наличии достаточных навыков, решимости и мотивации люди могут и будут декомпилировать, расшифровывать и взламывать ваш код ... Ваша задача просто сделать процесс настолько неудобным, насколько вы можете и по-прежнему поддерживать работу ...
источник
Пока у них есть доступ как к зашифрованным данным, так и к программному обеспечению, которое их расшифровывает, вы практически не можете сделать это полностью безопасным. Способы, которыми это было решено ранее, - это использование какой-либо формы внешнего черного ящика для обработки шифрования / дешифрования, например ключей, удаленных серверов аутентификации и т. Д. Но даже тогда, учитывая, что пользователь имеет полный доступ к своей собственной системе, это только делает вещи сложно, но возможно - если вы не можете напрямую привязать свой продукт к функциям, хранящимся в «черном ящике», как, скажем, игровые серверы онлайн.
источник
Отказ от ответственности: я не эксперт по безопасности.
Это звучит как плохая идея: вы позволяете кому-то шифровать данные с помощью «скрытого» ключа, который вы ему даете. Я не думаю, что это можно сделать безопасным.
Возможно, асимметричные клавиши могут работать:
Я не уверен, но я считаю, что клиент действительно может зашифровать лицензионный ключ с помощью открытого ключа, который вы ему дали. Затем вы можете расшифровать его своим закрытым ключом, а также повторно зашифровать.
Вы можете сохранить отдельную пару открытого / закрытого ключей для каждого клиента, чтобы убедиться, что вы действительно получаете данные от нужного клиента - теперь вы несете ответственность за ключи ...
источник
Что бы вы ни делали, его можно «декомпилировать». Черт возьми, его можно просто разобрать. Или посмотрите на дамп памяти, чтобы найти свои константы. Видите ли, компьютер должен их знать, значит, ваш код тоже должен это знать.
Что с этим делать?
Старайтесь не поставлять ключ как жестко заданную константу в своем коде: сохраните его как настройку для каждого пользователя. Возложите на пользователя ответственность за присмотр за этим ключом.
источник
@jatanp: или, что еще лучше, они могут декомпилировать, удалить код лицензирования и перекомпилировать. Я не думаю, что с Java есть правильное и надежное решение этой проблемы. Даже маленький злой ключ не смог бы предотвратить это с Java.
Мои собственные бизнес-менеджеры беспокоятся об этом, и я слишком много думаю. Но с другой стороны, мы продаем наше приложение крупным корпорациям, которые, как правило, соблюдают условия лицензирования - как правило, безопасная среда благодаря счетчикам и юристам. Сам акт декомпиляции может быть незаконным, если ваша лицензия написана правильно.
Итак, я должен спросить, действительно ли вам нужна усиленная защита, как вы ищете для своего приложения? Как выглядит ваша клиентская база? (Корпорации? Или подростковые массы игроков, где это будет более серьезной проблемой?)
источник
Если вы ищете решение для лицензирования, вы можете воспользоваться TrueLicense API . Он основан на использовании асимметричных клавиш. Однако это не означает, что ваше приложение невозможно взломать. Каждое приложение можно взломать, приложив достаточно усилий. Что действительно важно, как ответил Стю , это выяснить, насколько сильная защита вам нужна.
источник
Я не думаю, что существует какой-либо эффективный офлайн-метод борьбы с пиратством. Индустрия видеоигр пыталась обнаружить это много раз, и их программы всегда были взломаны. Единственное решение состоит в том, что программа должна быть запущена в интерактивном режиме и подключена к вашим серверам, чтобы вы могли проверить лицензионный ключ, и чтобы лицензиат имел только одно активное соединение за раз. Так устроены World of Warcraft или Diablo . Даже несмотря на то, что существуют частные серверы, разработанные для них, чтобы обойти безопасность.
Сказав это, я не верю, что средние / крупные корпорации используют нелегально скопированное программное обеспечение, потому что стоимость лицензии для них минимальна (возможно, я не знаю, сколько вы собираетесь взимать за свою программу) по сравнению с стоимость пробной версии.
источник
Вы можете без опасений использовать шифрование с помощью байтового кода.
Дело в том, что процитированная выше статья «Взлом шифрования байтового кода Java» содержит логическую ошибку. Основная претензия статьи - перед запуском все классы должны быть расшифрованы и переданы в
ClassLoader.defineClass(...)
метод . Но это не так.Упущенное здесь допущение заключается в том, что они работают в аутентичной или стандартной среде выполнения Java . Ничто не может заставить защищенное Java-приложение не только запускать эти классы, но даже расшифровывать и передавать их
ClassLoader
. Другими словами, если вы используете стандартную JRE, вы не можете перехватитьdefineClass(...)
метод, потому что стандартная java не имеет API для этой цели, и если вы используете модифицированную JRE с исправленнымClassLoader
или любым другим «хакерским трюком», вы не можете этого сделать, потому что защищенный java-приложение вообще не будет работать, а значит вам нечего будет перехватывать. И совершенно не имеет значения, какой «поиск патчей» используется или какой прием используют хакеры. Эти технические детали - совсем другая история.источник
В: Если я зашифрую свои файлы .class и использую собственный загрузчик классов для их загрузки и дешифрования на лету, предотвратит ли это декомпиляцию?
О: Проблема предотвращения декомпиляции байт-кода Java почти так же стара, как и сам язык. Несмотря на ряд доступных на рынке инструментов обфускации, начинающие программисты на Java продолжают придумывать новые и умные способы защиты своей интеллектуальной собственности. В этом выпуске Java Q&A я развенчиваю некоторые мифы вокруг идеи, часто пересказываемой на дискуссионных форумах.
Чрезвычайная легкость, с которой файлы Java .class могут быть преобразованы в исходные коды Java, которые очень похожи на исходные, во многом связана с целями разработки байт-кода Java и компромиссами. Помимо прочего, байтовый код Java был разработан для обеспечения компактности, независимости от платформы, сетевой мобильности и простоты анализа интерпретаторами байтового кода и динамическими компиляторами JIT (точно в срок) / HotSpot. Возможно, скомпилированные файлы .class настолько ясно выражают намерения программиста, что их легче анализировать, чем исходный исходный код.
Можно сделать несколько вещей, если не полностью предотвратить декомпиляцию, по крайней мере, сделать ее более сложной. Например, в качестве шага после компиляции вы можете массировать данные .class, чтобы сделать байтовый код труднее читать при декомпиляции или сложнее декомпилировать в действительный код Java (или и то, и другое). Такие методы, как выполнение экстремальной перегрузки имени метода, хорошо подходят для первого, а манипулирование потоком управления для создания структур управления, которые невозможно представить с помощью синтаксиса Java, хорошо работают для последнего. Более успешные коммерческие обфускаторы используют сочетание этих и других техник.
К сожалению, оба подхода фактически должны изменить код, который будет запускать JVM, и многие пользователи опасаются (справедливо), что это преобразование может добавить новые ошибки в их приложения. Кроме того, переименование метода и поля может привести к прекращению работы вызовов отражения. Изменение фактических имен классов и пакетов может нарушить работу некоторых других API Java (JNDI (Java Naming and Directory Interface), поставщиков URL и т. Д.). В дополнение к измененным именам, если связь между смещениями байтового кода класса и номерами строк исходного кода будет изменена, восстановление исходных трассировок стека исключений может стать трудным.
Затем есть возможность обфускации исходного исходного кода Java. Но по сути это вызывает аналогичный набор проблем. Шифровать, а не запутывать?
Возможно, сказанное выше заставило вас подумать: «А что, если вместо того, чтобы манипулировать байтовым кодом, я зашифрую все свои классы после компиляции и расшифрую их на лету внутри JVM (что можно сделать с помощью специального загрузчика классов)? Тогда JVM выполнит мои оригинальный байт-код, и все же нечего декомпилировать или реконструировать, верно? "
К сожалению, вы ошибаетесь как в том, что думаете, что вы были первым, кто придумал эту идею, так и в том, что она действительно работает. И причина не в надежности вашей схемы шифрования.
источник