Тип преобразования кода, используемый в исполняемых файлах Linux


13

Я хочу спросить, какой тип кодировки используется для создания исполняемых файлов linux, например шестнадцатеричный, двоичный или что-то еще. как он конвертируется? Есть ли способ вернуть исходный код из этого исполняемого файла?

Вот немного кода, который у меня есть:

ELF���������>�����%|�����@�������������������@�8��@���������������������@�������@�����7<�����7<������� ������������������f�����f���������������������� ������[�UPX!L
h�h�8����������?�E�h=��ڊ̓�N�    4���9ISloB�q�w�]ȉ.��,ς��Q䝦����#e��-�N����/�b,���d<��'��-E��6E�s�/�U���ly�V�Y2]"a��S�.�hU�|�S�J�I�2���X}
�G0�;���5d�$���.)

что это значит?


Хотя это не поможет вам получить что-либо обратно, стоит отметить, что программа stringsфильтра может быть очень полезна для определения того, чем занимается конкретная двоичная программа, потому что она будет печатать все встроенные текстовые строки длиннее указанной длины в Бинарный файл и просмотр сообщений в программе иногда многое говорит о том, что это такое и что делает.
Джо

Возможно / частичное дублирование? stackoverflow.com/questions/193896/whats-a-good-c-decompiler
Ариэльф

Ответы:


29

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

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

objdump -d helloworld | less

Но это также будет включать в себя множество глупостей компилятора. Например, если вы скомпилируете самое простоеhelloworld.cpp с помощью G ++, а затем objdumpэто, в итоге вы получите 226 строк (208 лишенных) yuck. Вы могли бы написать «привет мир» всего за 15 строк сборки , скомпилировать его и все objdumpэто, но это все еще расцветает в 166 строк (обрезано).

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

Вы не можете повернуть скомпилированный код обратно в оригинальный исходный код.

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

Чтобы дать вам представление о масштабе проблемы, вся идея программного обеспечения для обратного проектирования имеет свой собственный сайт Stack Exchange .


Можете ли вы сказать мне, как я могу перепроектировать его и вернуть максимальное количество кода, потому что я потерял источник
redchief

7
Смотрите мое недавнее редактирование. Там нет возврата к первоисточнику. Если вы будете много учиться и тратить много времени, вы сможете переписать исходный код на основе дизассемблированного ассемблерного кода, но в большинстве случаев будет дешевле (если ваше время бесполезно) и проще просто переписать его с нуля.
Оли

1
Чтобы вернуть максимальный объем кода, нужно восстановить самую последнюю резервную копию. Это также, кстати, единственный способ надежно вернуть что-то похожее на исходный код.
CVn

1
Совсем не соглашаясь с последним абзацем, только примечание: некоторые декомпиляторы IME отлично справляются с восстановлением точной структуры кода (кроме, как вы сказали, комментариев, форматирования, имен символов ...). Если вы не написали программу в первую очередь, восстановленный исходный код все еще может быть непонятным, однако я думаю, что это отличный вариант для восстановления (хотя бы частично) утерянного исходного кода / неизвестного исходного кода (по крайней мере, его частей). на самом деле понятно, в зависимости от конкретного кода и от того, удачливы ли вы тоже)
kos

1
Это то, что все эти EULA в мире проприетарного программного обеспечения говорят, что вы не можете делать - обратное проектирование / разборка. Они включают такие пункты, как это, потому что это возможно, но, конечно, не просто! Но, как говорит @ MichaelKjörling, единственный хороший способ вернуть вещи - это создать несколько уровней резервного копирования для чего угодно.
Джо

7

У меня недостаточно очков репутации для комментария, так что это ответ:

Нет, невозможно конвертировать его «обратно». Вы упомянули упаковщик upx, вы когда-нибудь читали руководство по upx?

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

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


3

Это, вероятно, бинарный файл (ELF-файл), как хорошо описано здесь:

https://en.wikipedia.org/wiki/Executable_and_Linkable_Format

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


3

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

Во время компиляции исходного кода (компиляция, предназначенная как в его типичном более широком восприятии, следовательно, как весь процесс, который «преобразовывает» исходный код в исполняемый файл), теряется много информации.

Например, препроцессор C будет делать следующее (среди прочего):

  • Интерпретировать, выполнять и удалять директивы препроцессора ( #операторы)
  • Удалить комментарии
  • Удалить ненужные пробелы

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

Это потому что:

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

Существуют инструменты, называемые декомпиляторами, целью которых является попытка вернуть исполняемый файл в функционально эквивалентный исходный код; однако, результат, как правило, далек от оригинального исходного кода (и, как правило, также не компилируется);

Рассмотрим эту программу:

#include <stdio.h>

#define MESSAGE "Literal strings will be recovered" // This preprocessor directive won't be recovered

/*

This comment and the comment above won't be recovered

*/

int main(int argc, char* argv[]) {
    printf(MESSAGE);
    return 0;
}

Скомпилировав его в исполняемый файл и снова декомпилировав в исходный код, это более или менее то, что вы обычно получаете обратно (в данном конкретном случае я использовал gcc/ Boomerang ):

// address: 0x80483fb
int main(int argc, char **argv, char **envp) {
    printf("Literal strings will be recovered");
    return 0;
}

Как и предсказывалось:

  • Директивы препроцессора отсутствуют
  • Комментарии отсутствуют (кроме того // address: 0x80483fb, что было добавлено декомпилятором)
  • Отсутствует ненужный пробел (кроме новых строк и таблиц, которые были добавлены декомпилятором)

Это тоже довольно хороший результат; нередко получить встроенные инструкции по сборке в коде:

asm("assembly_instruction");
__asm__("assembly_instruction");

Суть в том (как уже отмечалось в других ответах): вы не можете получить очень оригинальный источник исполняемого файла *.

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


2

Исполняемые файлы обычно бинарные, если вы говорите о скомпилированных программах. Вы можете найти больше информации, используя file path/to/executable. Вы можете отобразить двоичные исполняемые файлы в шестнадцатеричном формате, используя, например, hexdump -C path/to/executable | less(что бы вы ни делали). Если вы хотите «преобразовать его обратно в исходную форму», вам придется использовать соответствующий декомпилятор, см. Этот пост, например , хотя это даст вам совершенно нечитаемый код, а не оригинал, из которого он был скомпилирован. Если это не скомпилированный двоичный файл, это будет своего рода исполняемый скрипт, который должен быть легко читаем в любом текстовом редакторе. То, что вы показали нам здесь, это, вероятно, скомпилированный исполняемый файл. ELF означает «Исполняемый и связывающий формат», который является распространенным двоичным форматом в системах Linux / Unix. Там'strings path/to/executable, если это то, что вам нужно.


Я пытался перепроектировать его с помощью упаковщика upx, но он не работал, а также с постом, который вы предложили. Поэтому, пожалуйста, скажите мне, если есть другой способ.
рыжий

Очень жаль, но я не могу сказать вам ничего больше, чем написано в отличном посте @ Oli.
Гинз
Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.