Почему приложения / апплеты Java могут быть декомпилированы?

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

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

Насколько я понимаю, Java-приложения развертывают JIT-компиляцию, поэтому они компилируются только перед тем, как их использовать в целях эффективности, верно? Я хотел бы знать причину,

Спасибо!

1 ответ

Решение

В любом случае, мой вопрос заключается в следующем: почему приложение Java может быть декомпилировано?

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

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

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

В случае такого языка, как C, компилятор генерирует машинные инструкции для CPU. Они могут быть легко декомпилированы в язык ассемблера, поскольку инструкции ассемблера довольно точно соответствуют 1:1 машинным инструкциям. Достаточно сложный декомпилятор может выдавать C как вывод, хотя, вероятно, не C, который будет естественным для записи. Что еще более важно, декомпилированный вывод будет в основном использовать сгенерированные декомпилятором имена для функций и переменных, если только скомпилированный код C не имеет отладочных символов, и в этом случае декомпилятор может использовать их.

Язык, подобный Java, не отличается существенно по концепции. Хотя байт-код Java или Dalvik предназначен для ВМ, а не для ЦП, базовый подход тот же. Обфускация помогает гарантировать, что в результирующем байт-коде существует минимальное количество читаемых человеком символов, чтобы уменьшить удобочитаемость любых декомпилированных результатов. Кроме того, отображение байт-кода VM на операторы языка имеет тенденцию быть гораздо ближе, чем отображение машинного кода на операторы C, что облегчает написание декомпилятора, который возвращает вас к синтаксису Java (например, smali/baksmali).

Именно степень сложности интерпретации декомпилированного машинного кода приводит к рекомендациям по переносу логики управления лицензиями в собственный код, например, через NDK. Однако это не означает, что результаты компилятора C не могут быть декомпилированы вообще.

Другие вопросы по тегам