Як заблокувати складені класи Java, щоб запобігти декомпіляції?


96

Як заблокувати компільовані класи Java для запобігання декомпіляції?

Я знаю, що це повинна бути дуже добре обговорена тема в Інтернеті, але я не зміг прийти до жодного висновку після їх перегляду.

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

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

Або такі чутливі компоненти повинні бути вбудовані в нативний код (наприклад, VC ++) і викликати їх через JNI ?


Навіть розібраний нативний код деяким людям все-таки читається, вам, мабуть, доведеться використовувати якийсь обфускатор або ручну збірку, щоб зробити його не очевидним (звичайний C ++, складений з оптимізацією, є читабельним). Який би код не працював на пристрої користувача, його можна перехопити. Хоча вимоги до вартості та вміння такого перехоплення можуть бути досить високими, наприклад, вторгнення в чіп-код "захищених від несанкціонованого" коду мікросхем не є дрібницею, це можна виконати лише з верхнім обладнанням та вмінням. З класами Java ... Я б не сильно турбував, ви, ймовірно, можете їх зашифрувати достатньо, щоб відвернути дітей сценаріїв, не більше.
Ped7g

Відповіді:


96

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

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

Іншим можливим рішенням (не обов'язково виключаючи обфускування) є використання зашифрованих файлів JAR та спеціальний завантажувач класів, який виконує розшифровку (бажано, використовуючи нативну бібліотеку виконання).

По-третє (і, можливо, пропонують найсильніший захист) - використовувати дострокові компілятори достроково, наприклад, GCC або Excelsior JET , наприклад, які компілюють ваш код Java безпосередньо на натурному двійковому двійковому коді.

У будь-якому випадку ви повинні пам’ятати, що, як говориться на естонській мові, «Замки для тварин». Це означає, що кожен біт коду є доступним (завантажується в пам'ять) під час виконання та приділяється достатньою навичками, рішучістю та мотивацією, люди можуть і будуть декомпілювати, розшифровувати та зламати ваш код ... Ваше завдання просто зробити процес таким же некомфортним, як ви можете і продовжуєте працювати,


13
+1 для "Замки призначені для тварин". Я здогадуюсь, відповідним терміном тут були б діти-сценарії.
Сурма

Ви маєте на увазі GCJ, і він мертвий.
Маркіз

1
Шифрування файлів для банку Componio теж мертве. Замість цього використовуйте JarProtector .
J.Profi

16

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


13

Відмова: Я не є експертом з безпеки.

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

Можливо, асиметричні ключі можуть спрацювати:

  • розгорнути зашифровану ліцензію з відкритим ключем для дешифрування
  • нехай клієнт створить нову ліцензію та надішле її вам для шифрування
  • відправити нову ліцензію назад клієнту.

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

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


2
Я раніше застосовував цю техніку, і вона чудово працює. Однак, з точки зору атаки, першим підходом було б просто змінити код, який виконує перевірку ліцензії та видалити його. Ви можете зробити, щоб зробити цей вектор атаки складнішим, але якщо ви наділите зловмиснику керування обладнанням, вам судилося провалитися з відповідним мотивованим та кваліфікованим нападником. На практиці мета - просто тримати в основному чесних людей, чесних.
Джим Раш

12

Незалежно від того, що ви робите, це може бути "декомпільовано". Чорт, можна просто розібрати. Або подивіться на дамп пам'яті, щоб знайти свої константи. Розумієте, комп’ютер повинен їх знати, тож вам знадобиться і ваш код.

Що з цим робити?

Постарайтеся не надсилати ключ у якості констант з твердим кодом: Зберігайте його як налаштування для кожного користувача. Зробіть відповідальність за догляд за цим ключем.


6

@jatanp: або ще краще, вони можуть декомпілювати, видалити ліцензійний код та перекомпілювати. Що стосується Java, я не думаю, що для цієї проблеми є правильне, непрацездатне рішення. Навіть злий маленький ключик не міг би запобігти цьому з Java.

Мої власні бізнес-менеджери переживають з цього приводу, і я думаю, що занадто багато. Але знову ж таки, ми продаємо нашу заявку великим корпораціям, які прагнуть дотримуватися ліцензійних умов - як правило, безпечне середовище завдяки лічильникам та юристам. Сам акт декомпіляції може бути незаконним, якщо ваша ліцензія написана правильно.

Отже, я маю запитати, чи справді вам потрібен посилений захист, як ви шукаєте для свого застосування? Як виглядає ваша клієнтська база? (Корпорації? Або підлітковий геймерський масив, де це буде більше питання?)


Насправді, існує правильне рішення, яке не має зламів, що btw виглядає як ключ: excelsior-usa.com/blog/excelsior-jet/…
Дмитро Лесков

@DmitryLeskov, можливо, "стійкий до злому". Але це просто наскок швидкості для кожного, хто хоче за кодом. Зрештою, байт-код повинен працювати на хост-платформі в незашифрованому вигляді. Повна зупинка.
Стю Томпсон

Ви не читали публікацію, на яку я посилався. Байтовий код перетворюється в код процесора dongle і шифрується. Коли кінцевий користувач запускає захищену програму, цей зашифрований код передається в "ключ". Донгл розшифровує та запускає його на своєму процесорі.
Дмитро Лесков

2
Корпоративні геймери-підлітки.
odiszapc

3

Якщо ви шукаєте рішення щодо ліцензування, ви можете ознайомитися з API TrueLicense . Він заснований на використанні асиметричних ключів. Однак це не означає, що ваша програма не може бути зламана. Кожна програма може бути зламана з достатнім зусиллям. Що насправді важливо, як відповів Стю , з'ясовуючи, наскільки сильний захист вам потрібен.


2

Я не думаю, що існує ефективний метод антипіратства в режимі офлайн. Індустрія відеоігор намагалася виявити, що багато разів і їх програми завжди були зламані. Єдине рішення полягає в тому, що програму потрібно запускати в режимі он-лайн, підключеного до ваших серверів, щоб ви могли перевірити ключ lincense і щоб ліцензіат одночасно мав лише одне активне з'єднання. Ось як World of Warcraft або Diablo . Навіть жорсткі розроблені для них приватні сервери, щоб обійти безпеку.

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


2

Ви можете використовувати шифрування байт-коду без побоювання.

Справа в тому, що цитована вище стаття «Злом шифрування байт-коду Java» містить логічну помилку. Основна вимога статті полягає в тому, що перед запуском всі класи повинні бути розшифровані та передані ClassLoader.defineClass(...)методу . Але це неправда.

Припущення, пропущене тут, передбачає, що вони працюють в автентичному або стандартному середовищі виконання Java . Ніщо не може зобов’язати захищений додаток java не лише запускати ці класи, але навіть розшифровувати та передавати їх ClassLoader. Іншими словами, якщо ви перебуваєте у стандартному JRE, ви не можете перехопити defineClass(...)метод, оскільки стандартний Java не має API для цієї мети, і якщо ви використовуєте модифікований JRE з виправленими ClassLoaderабо будь-якими іншими "хакерськими трюками", ви не можете це зробити, оскільки захищені додаток java взагалі не працюватиме, і тому вам нічого не буде перехоплювати. І абсолютно не має значення, який "шукач патчів" використовується або який трюк використовується хакерами. Ці технічні деталі - це зовсім інша історія.


Як саме ви маєте намір виявити виправлений JVM? У будь-якому випадку, все це робить, щоб зробити речі дещо складнішими.
Сурма

Ви не можете просто знайти дзвінок для визначенняClass () у своєму запуску програм? Коли ви здійснюєте цей виклик, у будь-якому випадку вам доведеться подати масив розшифрованих байтів. Хіба це не інший момент, де первинне джерело могло просочитися?
Асцендент

4
Я не дуже згоден з цією відповіддю. Для мене це звучить як "Питання: Який найпростіший спосіб знайти Пі? Відповідь: Візьміть 2 * Пі і розділіть на два". Я не згоден з ідеєю, але ви могли б включити більше деталей? Наприклад, чи очікуєте ви, що основна програма буде написана в чистому Java? Чи включає він код, який шукає модифікації?
Патрік М

-1

Питання: Якщо я шифрую свої файли .class і використовую користувальницький завантажувач, щоб завантажити та розшифрувати їх під час руху, чи запобіжить це декомпіляція?

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

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

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

На жаль, обидва підходи повинні насправді змінити код, який буде запущений JVM, і багато користувачів бояться (справедливо), що це перетворення може додати нових помилок у їхні програми. Крім того, перейменування методу та поля може призвести до припинення роботи роздумних дзвінків. Зміна фактичних назв класів та пакетів може порушити декілька інших API Java (JNDI (інтерфейс імені Java і імені каталогів), провайдерів URL тощо). Крім змінених імен, якщо зв'язок між зміщенням байт-коду класу та номерами вихідних рядків буде змінено, відновлення вихідних слідів стека винятків може стати складним.

Тоді є можливість обмацувати вихідний вихідний код Java. Але принципово це викликає подібний набір проблем. Шифрувати, а не придушувати?

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

На жаль, ви помиляєтеся, як думаючи, що ви вперше придумали цю ідею, так і подумавши, що вона насправді працює. І причина не має нічого спільного з силою вашої схеми шифрування.

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.