Что такое декомпилятор, как он работает? - PullRequest
10 голосов
/ 25 мая 2010

Значит, действительно ли декомпилятор дает то, что дает источник скомпилированного / интерпретированного фрагмента кода? Потому что для меня это звучит невозможно. Как бы вы получили имена функций, переменных, классов и т. Д., Если он скомпилирован? Или я неправильно понимаю определение? Как это работает? И что является основным принципом создания?

Ответы [ 4 ]

10 голосов
/ 25 мая 2010

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

Создание декомпилятора - непростая задача. По сути, вам нужно взять приложение, которое вы декомпилируете (будь то исполняемый файл или какая-либо другая форма скомпилированного приложения), и проанализировать его в виде дерева, с которым вы можете работать в памяти. Затем вы проанализируете поток программы и попытаетесь найти шаблоны, которые могут указывать на то, что оператор if / переменная / функция / и т. Д. Использовался в определенном месте кода. На самом деле это всего лишь игра в догадки: вам нужно знать шаблоны, которые компилятор создает в скомпилированном коде, а затем искать эти шаблоны и заменять их эквивалентным понятным для человека исходным кодом.

Все это намного проще для программ более высокого уровня, таких как Java или .NET, где вам не нужно иметь дело с инструкциями по сборке, а такие вещи, как переменные, в основном заботятся о вас. Там вам не нужно угадывать столько, сколько просто переводить. Возможно, у вас нет точных имен переменных / методов, но вы, по крайней мере, можете довольно легко определить структуру программы.

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

1 голос
/ 25 мая 2010

Это работает, выводя «разумное» (основанное на некоторой эвристике) представление того, что находится в объектном коде. Степень сходства между тем, что он производит, и тем, что было изначально, имеет тенденцию сильно зависеть от того, сколько информации содержится в двоичном коде, с которого он начинается. Если вы начинаете с «чистого» двоичного файла, он обычно просто задает «разумные» имена для переменных, такие как i, j и k для индексов цикла и более длинные имена для большинство других.

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

1 голос
/ 25 мая 2010

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

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

0 голосов
/ 30 июля 2012

Это зависит от того, на каком языке вы декомпилируете. Если вы декомпилируете что-то вроде C или C ++, то единственная информация, предоставленная вам, - это имена функций и аргументы (в DLL). Если вы имеете дело с Java, то компилятор обычно вставляет номера строк, имена переменных, имена полей и методов и так далее. Если имен переменных нет, вы получите имена типа localInt1, localInt2, localException1. Или каким бы ни был компилятор. И это может сказать расстояние между строками, из-за номеров строк.

...