Есть ли примеры кода, который трудно декомпилировать?
Иногда при декомпиляции Java-кода декомпилятору не удается правильно декомпилировать его, и в результате вы получаете небольшие кусочки байт-кода в выходных данных.
Каковы слабые стороны декомпиляторов? Есть ли примеры исходного кода Java, который компилируется в сложный для декомпиляции байт-код?
Обновить:
Обратите внимание, что я знаю, что использование этой информации не является безопасным способом скрытия секретов в коде, и что декомпиляторы могут быть улучшены в будущем.
Тем не менее, я все еще заинтересован в том, чтобы выяснить, какой тип кода лисирует сегодня для декомпиляторов.
6 ответов
Любой байт-код Java, прошедший через обфускатор, будет иметь "нелепый" вывод из декомпилятора. Кроме того, когда у вас есть другие языки, такие как Scala, которые компилируются в байт-код JVM, нет правила, что байт-код можно легко представить обратно в Java, и, скорее всего, нет.
Со временем декомпиляторы должны идти в ногу с новыми языковыми функциями и создаваемым ими байт-кодом, поэтому вполне вероятно, что новые языковые функции не могут быть легко изменены теми инструментами, которые вы используете.
Изменить: В качестве примера в.NET, следующий код:
lock (this)
{
DoSomething();
}
компилируется в это:
Monitor.Enter(this);
try
{
DoSomething();
}
catch
{
Monitor.Exit(this);
}
Декомпилятор должен знать, что C# (в отличие от любого другого языка.NET) имеет специальный синтаксис, предназначенный именно для этих двух вызовов. В противном случае вы получите неожиданные (подробные) результаты.
Драйверы JDBC типа 4 для DB2 Connect являются классическими. Все называется одно- или двухбуквенными именами, нерелевантным кодом, который в итоге не имеет никакого эффекта, и многим другим. Однажды я попытался взглянуть, чтобы отладить особо неприятную проблему, и в основном сдался. Я надеюсь (но отнюдь не уверен), что это было передано через обфускатор, а не код, который на самом деле выглядит так.
Еще одна любимая уловка (хотя я не помню продукт) - переименовать все объекты, которые будут построены из набора. {'0','O','l','1'}
что сделало чтение очень трудным.
Предполагая, что вы можете декомпилировать обратно к разумному стилю исходного кода (вы не всегда можете это сделать), "сложным" "обратным инжинирингом" являются алгоритмы, которые работают в незнакомых проблемных областях. Если вы не понимаете быстрых преобразований Фурье, не имеет большого значения, сможете ли вы вернуть код, который реализует FFT Butterfly. (Если эта фраза вам незнакома, я уже выиграл, если я ее закодирую. Если она вам знакома, вы довольно хороший инженер и, вероятно, не заинтересованы в коде обратного инжиниринга). [Ваш пробег с северокорейцами может отличаться.]
Исключения часто трудно декомпилировать. Однако любой код, который был запутан или написан на другом языке, трудно декомпилировать.
Кстати: с чего бы вам это знать?
Java хранит много информации в байт-коде (например, много имен). Так что относительно легко декомпилировать. Трудно декомпилировать байт-код, в основном, генерируется трудно читаемым исходным кодом (так что на самом деле это не вариант). Если вы действительно хотите запутать свой код, используйте обфускатор, который переименовывает все методы и переменные в неузнаваемые вещи.
Java-байт-код не соответствует напрямую Java-конструкциям, поэтому декомпиляция подразумевает, что вы знаете, что определенная последовательность Java-байт-кода соответствует конструкции Java-кода.
Платформа Soot для декомпиляции Java-байтового кода содержит много информации по этому вопросу, но их веб-страница сейчас недоступна для меня.