Jak zauważył już Oli w swojej odpowiedzi, nie można uzyskać bardzo oryginalnego kodu źródłowego pliku wykonywalnego.
Podczas kompilacji kodu źródłowego (kompilacja ma charakter typowy dla szerszej akceptacji, stąd cały proces, który „przekształca” kod źródłowy w plik wykonywalny), wiele informacji zostaje utraconych.
Na przykład preprocesor C wykona (między innymi):
- Interpretuj, wykonuj i usuwaj dyrektywy preprocesora (
#
instrukcje)
- Usuń komentarze
- Usuń niepotrzebne białe znaki
Z drugiej strony to, co nie zostało utracone podczas kompilacji kodu źródłowego, jest technicznie odwracalne do funkcjonalnie równoważnego kodu źródłowego.
To dlatego, że:
- Instrukcje binarne wykazują zgodność 1: 1 z instrukcjami montażu; asemblowanie kodu źródłowego asemblera jest po prostu konwersją instrukcji asemblera na instrukcje binarne oparte na tabeli korelencji; pojedyncza instrukcja binarna jest zawsze możliwa do zidentyfikowania i przywracania do pojedynczej instrukcji asemblacji ;
- Instrukcje montażu nie mają związku 1: 1 z instrukcjami C; kompilacja kodu źródłowego C zwykle nie jest zwykłą konwersją instrukcji C do instrukcji asemblera opartych na tabeli korelencji, w rzeczywistości często jest odwrotnie; zwykle instrukcja C jest konwertowana na wiele (często różniących się w zależności od kompilatora) instrukcji montażu; jednakże wzory wielu instrukcji asemblacji są zwykle identyfikowalne i odwracalne do pojedynczej instrukcji C ;
Istnieją narzędzia zwane dekompilatorami, których celem jest próba przywrócenia pliku wykonywalnego na funkcjonalnie równoważny kod źródłowy; jednak wynik jest zwykle czymś dalekim od bardzo oryginalnego kodu źródłowego (i zwykle również nie do skompilowania);
Rozważ ten program:
#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;
}
Kompilując go do pliku wykonywalnego i ponownie dekompilując do kodu źródłowego, jest to mniej więcej to, co zwykle otrzymujesz (w tym konkretnym przypadku użyłem gcc
/ Boomerang ):
// address: 0x80483fb
int main(int argc, char **argv, char **envp) {
printf("Literal strings will be recovered");
return 0;
}
Jak przewidziano:
- Brakuje dyrektyw preprocesora
- Brak komentarzy (oprócz tego
// address: 0x80483fb
, który został dodany przez dekompilator)
- Brakuje niepotrzebnych białych znaków (oprócz nowych linii i tabel, które zostały dodane przez dekompilator)
To także całkiem niezły wynik; nierzadko umieszcza się w kodzie instrukcje montażu w wierszu:
asm("assembly_instruction");
__asm__("assembly_instruction");
Najważniejsze jest (jak wskazano już w innych odpowiedziach): nie można uzyskać bardzo oryginalnego źródła pliku wykonywalnego *.
* Jednak w zależności od pliku wykonywalnego i na szczęście, to może być w stanie uzyskać coś za pomocą decompiler.
strings
program filtrujący może być bardzo przydatny w identyfikowaniu konkretnego programu binarnego, ponieważ drukuje wszystkie osadzone ciągi tekstowe dłuższe niż określona długość w plik binarny i przeglądanie wiadomości w programie czasami mówi wiele o tym, co to jest i co robi.