Как Оли уже указал в своем ответе, вы не можете получить очень оригинальный исходный код исполняемого файла.
Во время компиляции исходного кода (компиляция, предназначенная как в его типичном более широком восприятии, следовательно, как весь процесс, который «преобразовывает» исходный код в исполняемый файл), теряется много информации.
Например, препроцессор 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");
Суть в том (как уже отмечалось в других ответах): вы не можете получить очень оригинальный источник исполняемого файла *.
* Однако, в зависимости от исполняемого файла и вашей удачи, вы можете получить что-то, используя декомпилятор.
strings
фильтра может быть очень полезна для определения того, чем занимается конкретная двоичная программа, потому что она будет печатать все встроенные текстовые строки длиннее указанной длины в Бинарный файл и просмотр сообщений в программе иногда многое говорит о том, что это такое и что делает.