Есть ли примеры кода, который трудно декомпилировать?

Иногда при декомпиляции 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-байтового кода содержит много информации по этому вопросу, но их веб-страница сейчас недоступна для меня.

http://www.sable.mcgill.ca/soot/

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