Декомпилятор

редактировать

A декомпилятор - это компьютерная программа, которая принимает исполняемый файл в качестве входных данных, и пытается создать исходный файл высокого уровня, который можно перекомпилировать успешно. Следовательно, он противоположен компилятору , который берет исходный файл и создает исполняемый файл. Декомпиляторы обычно не могут полностью восстановить исходный исходный код и поэтому часто создают запутанный код. Тем не менее, декомпиляторы остаются важным инструментом обратного проектирования компьютерного программного обеспечения .

Содержание
  • 1 Введение
  • 2 Дизайн
    • 2.1 Загрузчик
    • 2.2 Дизассемблирование
    • 2.3 Идиомы
    • 2.4 Анализ программ
    • 2.5 Анализ потока данных
    • 2.6 Анализ типов
    • 2.7 Структурирование
    • 2.8 Генерация кода
  • 3 Легальность
  • 4 Инструменты
  • 5 См. Также
  • 6 Ссылки
  • 7 Внешние ссылки
Введение

Термин «декомпилятор» чаще всего применяется к программе, переводящей исполняемые программы (вывод из компилятор ) в исходный код на (относительно) языке высокого уровня, который при компиляции создаст исполняемый файл, поведение которого будет таким же, как у исходной исполняемой программы. Для сравнения: дизассемблер переводит исполняемую программу на язык ассемблера (и ассемблер может быть использован для сборки ее обратно в исполняемую программу).

Декомпиляция - это действие с использованием декомпилятора, хотя этот термин также может относиться к выходным данным декомпилятора. Его можно использовать для восстановления утерянного исходного кода, а также в некоторых случаях полезно для компьютерной безопасности, взаимодействия и исправления ошибок. Успех декомпиляции зависит от количества информации, содержащейся в декомпилируемом коде, и сложности анализа, выполняемого над ним. Форматы байт-кода, используемые многими виртуальными машинами (такими как Java Virtual Machine или .NET Framework Common Language Runtime ), часто включают обширные метаданные и высокоуровневые функции, которые делают декомпиляцию вполне осуществимой. Наличие отладочных данных может позволить воспроизвести исходные имена переменных и структур и даже номера строк. Машинный язык без таких метаданных или отладочных данных декомпилировать гораздо труднее.

Некоторые компиляторы и инструменты посткомпиляции создают запутанный код (то есть они пытаются создать вывод, который очень трудно декомпилировать или декомпилируется до запутанного вывода). Это сделано, чтобы затруднить обратное проектирование исполняемого файла.

Хотя декомпиляторы обычно используются для (воссоздания) исходного кода из двоичных исполняемых файлов, существуют также декомпиляторы для преобразования определенных файлов двоичных данных в читаемые и редактируемые источники.

Дизайн

Декомпиляторы можно рассматривать как состоящие из серии этапов, каждая из которых вносит свой вклад в определенные аспекты общего процесса декомпиляции.

Загрузчик

На первом этапе декомпиляции загружается и анализируется входной машинный код или промежуточный язык формат двоичного файла программы. Он должен уметь обнаруживать основные факты о программе ввода, такие как архитектура (Pentium, PowerPC и т. Д.) И точка входа. Во многих случаях он должен быть в состоянии найти эквивалент функции mainпрограммы C, которая является началом кода, написанного пользователем. Это исключает код инициализации среды выполнения, который по возможности не следует декомпилировать. Если доступны, также загружаются таблицы символов и данные отладки. Внешний интерфейс может идентифицировать используемые библиотеки, даже если они связаны с кодом, это предоставит библиотечные интерфейсы. Если он может определить используемый компилятор или компиляторы, он может предоставить полезную информацию для определения идиом кода.

Дизассемблирование

Следующим логическим этапом является разборка команд машинного кода в машинно-независимое промежуточное представление ( ИК). Например, машинная инструкция Pentium

mov eax, [ebx + 0x04]

может быть преобразована в IR

eax: = m [ebx + 4];

Идиомы

Идиоматические машинные кодовые последовательности - это последовательности кода, комбинированная семантика которых не сразу очевидна из индивидуальной семантики инструкций. Либо как часть фазы разборки, либо как часть более позднего анализа, эти идиоматические последовательности необходимо транслировать в известный эквивалентный IR. Например, ассемблерный код x86 :

cdq eax; edx установлен на расширение знака ≠ edi, edi + (tex) push xor eax, edx sub eax, edx

можно преобразовать в

eax: = abs (eax);

Некоторые идиоматические последовательности не зависят от машины; некоторые включают только одну инструкцию. Например, xor eax, eaxочищает регистр eax(устанавливает его в ноль). Это может быть реализовано с помощью правила машинно-независимого упрощения, такого как a = 0.

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

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

Анализ программ

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

mov eax, [ebx + 0x04] add eax, [ebx + 0x08] sub [ebx + 0x0C], eax

может привести к следующему IR после распространения выражения:

m [ebx + 12]: = m [ebx + 12] - (m [ebx + 4] + m [ebx + 8]);

Результирующее выражение больше похоже на язык высокого уровня, а также исключило использование машинного регистра eax. Более поздний анализ может удалить регистр ebx.

Анализ потока данных

Места, в которых определяется и используется содержимое регистров, должны отслеживаться с помощью анализа потока данных. Такой же анализ можно применить к местоположениям, которые используются для временных и локальных данных. Затем для каждого такого связанного набора определений значений и использования может быть сформировано другое имя. Возможно, что одно и то же местоположение локальной переменной использовалось более чем для одной переменной в разных частях исходной программы. Еще хуже то, что анализ потока данных может определить путь, по которому значение может перемещаться между двумя такими использованиями, даже если на самом деле это никогда не произойдет или не будет иметь значения в действительности. В плохих случаях это может привести к необходимости определять местоположение как объединение типов. Декомпилятор может позволить пользователю явно нарушить такие неестественные зависимости, что приведет к более ясному коду. Это, конечно, означает, что переменная потенциально может использоваться без инициализации, что указывает на проблему в исходной программе.

Анализ типов

Хороший декомпилятор машинного кода выполнит анализ типов. Здесь способ использования регистров или ячеек памяти приводит к ограничениям на возможный тип местоположения. Например, инструкции иподразумевают, что операнд является целым числом; программы не используют такую ​​операцию со значениями с плавающей запятой (за исключением кода специальной библиотеки) или с указателями . Инструкция addприводит к трем ограничениям, поскольку операнды могут быть как целыми, так и одним целым числом и одним указателем (с целыми числами и указателями соответственно; третье ограничение возникает из-за порядка двух операндов, когда типы различны).

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

Пример из предыдущего раздела может привести к следующему высокоуровневому коду:

struct T1 * ebx; struct T1 {int v0004; int v0008; int v000C; }; ebx->v000C - = ebx->v0004 + ebx->v0008;

Структурирование

Предпоследняя фаза декомпиляции включает структурирование IR в конструкции более высокого уровня, такие как whileциклы и if / then / elseусловные операторы. Например, машинный код

xor eax, eax l0002: или ebx, ebx jge l0003 add eax, [ebx] mov ebx, [ebx + 0x4] jmp l0002 l0003: mov [0x10040000], eax

может быть переведено на:

eax = 0; while (ebx < 0) { eax += ebx->v0000; ebx = ebx->v0004;} v10040000 = eax;

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

Генерация кода

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

Непосредственно перед генерацией кода может быть желательно разрешить интерактивное редактирование IR, возможно, используя некоторую форму графического пользовательский интерфейс. Это позволит пользователю вводить комментарии и неуниверсальные имена переменных и функций. Однако их почти так же легко вводить при редактировании после декомпиляции. Пользователь может захотеть изменить структурные аспекты, такие как преобразование цикл whileдо цикла for. Их труднее изменить с помощью простого текстового редактора, хотя инструменты рефакторинга исходного кода могут помочь в этом процессе. Пользователю может потребоваться ввести информацию, которую не удалось идентифицировать на этапе анализа типа, например преобразование выражения памяти в выражение массива или структуры. Наконец, может потребоваться исправить неправильный IR или внести изменения, чтобы выходной код был более читабельным.

Законность

На большинство компьютерных программ распространяется авторское право. Хотя точный объем того, что покрывается авторским правом, отличается от региона к региону, закон об авторском праве обычно предоставляет автору (программисту (программистам) или работодателю) совокупность исключительных прав на программу. Эти права включают право делать копии, в том числе копии, сделанные в RAM компьютера (если создание такой копии не является необходимым для использования программы). Поскольку процесс декомпиляции включает в себя создание нескольких таких копий, это обычно запрещено без разрешения правообладателя. Однако, поскольку декомпиляция часто является необходимым шагом для достижения функциональной совместимости программного обеспечения, законы об авторском праве как в США, так и в Европе разрешают декомпиляцию в ограниченной степени.

В США защита авторских прав добросовестного использования была успешно задействована в случаях декомпиляции. Например, в деле Sega v. Accolade суд постановил, что Accolade может на законных основаниях участвовать в декомпиляции, чтобы обойти механизм блокировки программного обеспечения, используемый игровыми консолями Sega. Кроме того, Закон об авторском праве в цифровую эпоху (ПУБЛИЧНЫЙ ЗАКОН 105–304) имеет соответствующие исключения как для тестирования безопасности, так и для оценки в §1205 (i), а также для обратного проектирования в §1205 (f).

В Европе Директива по программному обеспечению 1991 г. прямо предусматривает право на декомпиляцию для обеспечения взаимодействия. В результате жарких споров между, с одной стороны, сторонниками протекционизма программного обеспечения, а с другой - учеными, а также независимыми разработчиками программного обеспечения, статья 6 разрешает декомпиляцию только при соблюдении ряда условий:

  • Во-первых, лицо или объект должен иметь лицензию на использование декомпилируемой программы.
  • Во-вторых, декомпиляция должна быть необходима для достижения взаимодействия с целевой программой или другими программами. Поэтому информация о совместимости не должна быть легко доступна, например, в руководствах или документации по API. Это важное ограничение. Необходимость должна быть доказана декомпилятором. Цель этого важного ограничения состоит в первую очередь в том, чтобы побудить разработчиков документировать и раскрывать информацию о совместимости своих продуктов.
  • В-третьих, процесс декомпиляции должен, если возможно, ограничиваться частями целевой программы, относящимися к к взаимодействию. Поскольку одной из целей декомпиляции является понимание структуры программы, это третье ограничение может оказаться трудным для выполнения. Опять же, бремя доказательства лежит на декомпиляторе.

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

В целом право на декомпиляцию, предусмотренное статьей 6 , кодифицирует то, что считается обычной практикой в ​​индустрии программного обеспечения. Известно, что некоторые европейские иски возникли из-за права на декомпиляцию. Это может быть истолковано как означающее одно из трех: 1) право на декомпиляцию не часто используется, и поэтому право на декомпиляцию могло быть ненужным, 2) право на декомпиляцию функционирует хорошо и обеспечивает достаточную юридическую уверенность, чтобы не вызывать юридических споров или 3) незаконная декомпиляция в значительной степени остается незамеченной. В недавнем отчете о реализации Директивы по программному обеспечению европейскими странами-членами Европейская комиссия, похоже, поддерживает вторую интерпретацию.

Инструменты

Декомпиляторы обычно нацелены на конкретную двоичный формат. Некоторые из них представляют собой собственные наборы инструкций (например, Intel x86, ARM, MIPS), другие представляют собой байт-код для виртуальных машин (Dalvik, файлы классов Java, WebAssembly, Ethereum).

Из-за потери информации во время компиляции, декомпиляция почти никогда не бывает идеальной, и не все декомпиляторы работают одинаково хорошо для данного двоичного формата. Существуют исследования, в которых сравнивается производительность различных декомпиляторов.

См. Также
Ссылки
Внешние ссылки
Искать декомпилятор в Викисловаре, бесплатный словарь.
В Викиучебнике есть книга по теме: Обратный инжиниринг
Последняя правка сделана 2021-05-17 10:56:08
Содержание доступно по лицензии CC BY-SA 3.0 (если не указано иное).
Обратная связь: support@alphapedia.ru
Соглашение
О проекте