Come Oli ha già sottolineato nella sua risposta, non è possibile ottenere il codice sorgente molto originale di un eseguibile.
Durante la compilazione di un codice sorgente (compilazione intesa come nella sua più ampia accettazione tipica, quindi come l'intero processo che "trasforma" un codice sorgente in un eseguibile), molte informazioni vengono perse.
Il preprocessore C, per esempio, farà quanto segue (tra le altre cose):
- Interpretazione, esecuzione e rimozione delle direttive (
#
dichiarazioni) del preprocessore
- Rimuovi commenti
- Rimuovi gli spazi bianchi non necessari
D'altra parte, ciò che non viene perso durante la compilazione del codice sorgente è tecnicamente riverificabile in un codice sorgente funzionalmente equivalente.
Questo è perché:
- Le istruzioni binarie hanno una corrispondenza 1: 1 con le istruzioni di assemblaggio; l'assemblaggio di un codice sorgente di assembly è solo una semplice conversione delle istruzioni di assemblaggio in istruzioni binarie basate su una tabella di corrispondenze; una singola istruzione binaria è sempre identificabile e riverificabile in una singola istruzione di assemblaggio ;
- Le istruzioni di montaggio non hanno una corrispondenza 1: 1 con le istruzioni C; la compilazione di un codice sorgente C di solito non è solo una semplice conversione delle istruzioni C in istruzioni di assemblaggio basate su una tabella di corrispondenze, in realtà è spesso il contrario; di solito un'istruzione C viene convertita in istruzioni di assemblaggio multiple (spesso diverse in base al compilatore); tuttavia, i modelli di più istruzioni di assemblaggio sono generalmente identificabili e riverificabili in una singola istruzione C ;
Esistono strumenti chiamati decompilatori il cui scopo è tentare di ripristinare un eseguibile in un codice sorgente funzionalmente equivalente; tuttavia il risultato è di solito qualcosa di lontano dal codice sorgente molto originale (e di solito anche non compilabile);
Considera questo programma:
#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;
}
Compilandolo in un eseguibile e decompilandolo nuovamente in un codice sorgente, questo è più o meno ciò che di solito si ottiene (in questo caso specifico ho usato gcc
/ Boomerang ):
// address: 0x80483fb
int main(int argc, char **argv, char **envp) {
printf("Literal strings will be recovered");
return 0;
}
Come previsto:
- Mancano le direttive del preprocessore
- Mancano commenti (a parte
// address: 0x80483fb
, che è stato aggiunto dal decompilatore)
- Spazio bianco non necessario mancante (a parte le nuove righe e tabulazioni, che sono state aggiunte dal decompilatore)
Anche questo è un risultato abbastanza buono; non è raro ottenere istruzioni di assemblaggio in linea nel codice:
asm("assembly_instruction");
__asm__("assembly_instruction");
La linea di fondo è (come già sottolineato nelle altre risposte): non è possibile ottenere la fonte molto originale di un eseguibile *.
* Tuttavia, a seconda dell'eseguibile e della fortuna, potresti essere in grado di ottenere qualcosa usando un decompilatore.
strings
programma di filtro può essere molto utile per identificare ciò che un determinato programma binario è o fa perché stampa tutte le stringhe di testo incorporate più lunghe di una lunghezza specificata in un file binario e guardare i messaggi in un programma a volte ti dice molto su cosa è e cosa fa.