
Декомпилятор, ассемблер и дизассемблер для Java
Krakatau предоставляет ассемблер и дизассемблер для байт-кода Java, что позволяет преобразовывать бинарные class-файлы в удобочитаемый текстовый формат, вносить изменения и преобразовывать обратно в class-файл, даже для обфусцированного кода. Вы также можете создавать собственные class-файлы с нуля, вручную записывая байт-код, а также изучать и сравнивать низкоуровневые детали Java-бинарных файлов. В отличие от javap, дизассемблер Krakatau может обрабатывать даже сильно обфусцированный код, а результат дизассемблирования может быть повторно собран в class-файл.
Krakatau также предоставляет декомпилятор для преобразования Java-бинарных файлов в читаемый исходный код. В отличие от других декомпиляторов, декомпилятор Krakatau был специально разработан для работы с обфусцированным кодом и легко справляется с приёмами, которые ломают другие декомпиляторы. Однако декомпилятор Krakatau не поддерживает некоторые возможности Java 8+, такие как лямбда-выражения, поэтому он лучше всего работает со старым кодом.
Синтаксис ассемблера Krakatau в основном является надмножеством синтаксиса Jasmin с некоторыми незначительными несовместимостями, но в отличие от Jasmin, Krakatau имеет полную поддержку спецификации байт-кода Java 19 и даже поддерживает некоторые недокументированные функции, встречающиеся в старых версиях JVM. Обзор синтаксиса ассемблера см. в руководстве или полной спецификации.
Сначала вам нужно установить Rust и Cargo. Затем клонируйте этот репозиторий и выполните cargo build --release. Это создаст бинарный файл в target/release/krak2, который можно вызывать напрямую, добавить в PATH, создать символическую ссылку и т. д.
Дизассемблер имеет два режима: по умолчанию и roundtrip. Режим по умолчанию оптимизирован для читаемости и лёгкости модификации результирующих файлов ассемблера. При повторной сборке выходные данные будут создавать class-файлы, эквивалентные по поведению исходным с точки зрения спецификации JVM, но не обязательно побитово идентичные (например, элементы пула констант могут быть переупорядочены). Режим roundtrip создаёт выходные данные, которые при повторной сборке дают class-файлы, побитово идентичные исходным, но это означает, что файлы ассемблера сохраняют информацию о низкоуровневом кодировании, что усложняет их чтение, например, точный порядок элементов пула констант. Рекомендуется использовать режим roundtrip при работе с кодом, который опирается на нестандартные атрибуты, например, CLDC-код или Scala-код.
Пример использования:
krak2 dis --out temp RecordTest.class
krak2 dis --out disassembled.zip --roundtrip r0lling-challenge.jar
Вы можете дизассемблировать как отдельный class-файл, так и целый jar-файл. Если имя входного файла заканчивается на .jar или .zip, он будет обработан как jar-файл, и каждый .class-файл внутри jar будет дизассемблирован.
Опция --out управляет местом вывода. Если значение --out является каталогом, вывод будет помещён в отдельные файлы внутри этого каталога. В противном случае, если значение --out заканчивается на .jar или .zip, вывод будет помещён в один zip-файл по указанному пути. Если значение --out заканчивается на .j, вывод будет записан в этот файл (обратите внимание: один .j файл может содержать несколько классов — все классы будут дизассемблированы и записаны в один и тот же файл один за другим). Если опция --out опущена, дизассемблированные классы будут выведены в стандартный поток вывода.
Для дизассемблирования в режиме roundtrip, как описано выше, передайте опцию --roundtrip (или сокращённо -r).
Ассемблер Krakatau позволяет записывать байт-код Java в удобном для человека текстовом формате и преобразовывать его в бинарные Java class-файлы.
krak2 asm --out temp Krakatau/tests/assembler/good/strictfp.j
Вы можете собрать как отдельный .j файл, так и целый jar. Если имя входного файла заканчивается на .jar или .zip, он будет обработан как zip-архив, и каждый .j файл внутри будет собран.
Опция --out управляет местом вывода. Если значение --out является каталогом, вывод будет помещён в отдельные файлы внутри этого каталога. В противном случае, если значение --out заканчивается на .jar или .zip, вывод будет помещён в один zip-файл по указанному пути. Если значение --out заканчивается на .class, единственный выходной class-файл будет записан в этот файл (если во входных данных несколько классов, в этом случае будет выдана ошибка).
Декомпилятор v2 всё ещё находится в разработке. Для декомпиляции в настоящее время необходимо использовать Krakatau v1.