Подтвердить что ты не робот

Как работает декомпиляция?

Я слышал, что термин "декомпиляция" использовался несколько раз раньше, и я начинаю очень любопытно, как это работает.

У меня очень общее представление о том, как это работает; обратное проектирование приложения, чтобы увидеть, какие функции он использует, но я не знаю много за этим.

Я также слышал термин "дизассемблер", в чем разница между дизассемблером и декомпилятором?

Итак, чтобы подытожить мой вопрос (ы): Что именно участвует в процессе декомпиляции? Как это обычно делается? Насколько сложны/легки процессы? может ли он создать точный код? И в чем разница между декомпилятором и дизассемблером?

4b9b3361

Ответ 1

Один из величайших декомпиляторов, который сейчас находится здесь, - это, безусловно, Hex-Rays Decompiler. Если вы хотите видеть, что он может выводить, посмотрите http://www.hex-rays.com/products/decompiler/compare_vs_disassembly.shtml.

Его автор, Илфак Гильфанов, произнес речь о внутренней работе своего декомпилятора при некотором конфликте, и вот белая статья: http://www.hex-rays.com/products/ida/support/ppt/decompilers_and_beyond_white_paper.pdf и презентация здесь: http://www.hex-rays.com/products/ida/support/ppt/decompilers_and_beyond.ppt Это описывает хороший обзор, в чем все трудности при создании декомпилятора и о том, как заставить все это работать.

Кроме того, есть некоторые довольно старые документы, например. классическая кандидатская диссертация Кристины Чифунтес: http://itee.uq.edu.au/~cristina/dcc.html#thesis

Что касается сложности, все "декомпиляционные" вещи зависят от языка и времени исполнения двоичного файла. Например, декомпиляция .NET и Java считается "выполненной", так как есть свободные декомпиляторы, которые имеют очень высокий коэффициент успеха (они создают исходный источник). Но это вызвано спецификой виртуальных машин, которые используют эти среды выполнения.

Что касается действительно скомпилированных языков, таких как C, С++, Obj-C, Delphi, Pascal,... задача усложняется. Прочтите приведенные выше документы для деталей.

В чем разница между дизассемблером и декомпилятором?

Когда у вас есть двоичная программа (исполняемый файл, библиотека DLL,...), она состоит из инструкций процессора. Язык этих инструкций называется сборкой (или сборщиком). В двоичном коде эти команды кодируются двоично, поэтому процессор может их напрямую выполнять. Дисассемблер принимает этот двоичный код и переводит его в текстовое представление. Этот перевод обычно 1 к 1, то есть одна команда показана как одна строка текста. Эта задача сложна, но проста, программа просто должна знать все разные инструкции и как они представлены в двоичном формате.

С другой стороны, декомпилятор выполняет гораздо более сложную задачу. Он принимает либо двоичный код, либо вывод дизассемблера (который в основном тот же, что и 1-к-1), и создает высокоуровневый код. Позвольте мне показать вам пример. Скажем, у нас есть эта функция C:

int twotimes(int a) {
    return a * 2;
}

Когда вы его компилируете, компилятор сначала генерирует и собирает файл для этой функции, он может выглядеть примерно так:

_twotimes:
    SHL EAX, 1
    RET

(первая строка - это просто метка, а не настоящая инструкция, SHL выполняет операцию сдвига влево, которая быстро умножается на два, RET означает, что функция выполнена). В двоичном результате результат выглядит следующим образом:

08 6A CF 45 37 1A

(Я сделал это, а не настоящие двоичные инструкции). Теперь вы знаете, что дизассемблер выводит вас из двоичной формы в форму сборки. Декомпилятор переводит вас в код C (или какой-либо другой язык более высокого уровня).

Ответ 2

Декомпиляция - это, по сути, обратная задача компиляции. То есть - взять объектный код (двоичный) и попытаться воссоздать исходный код из него.

Декомпиляция зависит от наличия в объектном коде артефактов, которые могут быть использованы для определения структуры исходного кода.

С C/С++ не так много осталось, чтобы помочь процессу декомпиляции, так что это очень сложно. Однако с Java и С# и другими языками, которые нацелены на виртуальные машины, его легче декомпилировать, потому что язык оставляет много дополнительных подсказок в объектном коде.

Ответ 3

Кстати, вы можете получить некоторую информацию о работе декомпилятора здесь введите ссылку здесь Существует онлайн-версия декомпилятора (для процессора PowerPC), которые получают код ассемблера в нотации IDA Pro. Но у сервиса есть опции "make промежуточное представление", который генерирует следующее:

  • Код ввода (текст)
  • Абстрактный синтаксис исходного кода (дерева)
  • График вызовов в форме BasicBlock (график)
  • Metainformations, который был восстановлен во время декомпиляции:
    • График вызовов в форме Framed BasicBlock (график)
    • DataFlow значений регистра (график)
    • DataFlow значений переменных (график)
    • DataFlow зависимостей выражения (график)
  • Диаграмма Насси-Шнейдермана (дерево + график)
  • Структурированная диаграмма Насси-Шнейдермана (дерево + график)
  • Оптимизированная диаграмма Насси-Шнейдермана (дерево + график)
  • Описание исходного кода как алгоритм (некоторые вроде декомпиляции)
  • некоторые другие...

Вы можете использовать эту службу для экспериментов и понимания декомпиляторов.

BTW. Дисассемблер: двоичный машинный код → текст ассемблера Декомпилятор: ассемблерный текст → версия источника на языке высокого уровня (c, С++, расширение c и т.д.)