2010-05-25 15 views
10

Quindi un decompilatore è davvero una cosa che dà la fonte di un pezzo di codice compilato/interpretato? Perché a me sembra impossibile. Come otterresti i nomi delle funzioni, variabili, classi, ecc. Se è compilato. O sto interpretando male la definizione? Come funziona? E qual è il principio generale dietro a farne uno?Che cos'è un de-compiler come funziona?

risposta

10

Hai ragione riguardo alla tua definizione di decompilatore: richiede un'applicazione compilata e produce codice sorgente da abbinare. Tuttavia, lo non è nella maggior parte dei casi conosce il nome e la struttura di variabili/funzioni/classi - semplicemente indovina. Analizza il flusso del programma e cerca di trovare un modo per rappresentare quel flusso attraverso un certo linguaggio di programmazione, tipicamente C. Tuttavia, poiché il linguaggio di programmazione di scelta (C, in questo esempio) è spesso a un livello superiore rispetto allo stato del programma sottostante (un eseguibile binario), alcune parti del programma potrebbero essere impossibili da rappresentare con precisione; in questo caso, il decompilatore fallirebbe e avresti bisogno di usare un disassemblatore. Questo è il motivo per cui a molte persone piace confondere il loro codice: rende molto più difficile per i decompilatori aprirlo.

Costruire un decompilatore non è un compito semplice. Fondamentalmente, devi prendere l'applicazione che stai decompilando (sia esso un eseguibile o qualche altra forma di applicazione compilata) e analizzala in un qualche tipo di albero su cui puoi lavorare in memoria. Dovresti quindi analizzare il flusso del programma e provare a trovare i pattern che potrebbero suggerire che una dichiarazione/variabile/funzione if sia stata utilizzata in una determinata posizione nel codice. È tutto solo un gioco di indovinelli: dovresti conoscere i pattern che il compilatore compila nel codice compilato, quindi cercare quei pattern e sostituirli con codice sorgente equivalente leggibile dall'uomo.

Questo è tutto molto più semplice per programmi di livello superiore come Java o .NET, in cui non devi occuparti delle istruzioni di assemblaggio e cose come le variabili sono per lo più prese in considerazione per te. Lì, non devi indovinare tanto quanto tradurre direttamente. Potresti non avere nomi di variabili/metodi esatti, ma puoi almeno dedurre la struttura del programma abbastanza facilmente.

Disclaimer: Non ho mai scritto un decompilatore e quindi non conosco ogni dettaglio di ciò di cui sto parlando. Se sei veramente interessato a scrivere un decompilatore, dovresti ottenere un libro sull'argomento.

+0

Qual è il principio generale che sta dietro a farne uno? –

+0

In realtà, è possibile ottenere spesso i nomi delle variabili per Java e gli eseguibili senza chiavi gcc debug-ready. – paxdiablo

+0

@paxdiablo: Sì, è per questo che mi sono assicurato di includere "nella maggior parte dei casi" lì, perché ci sono alcuni casi in cui * puoi * effettivamente ottenere codice sorgente che sembra quasi identico all'originale. :) –

1

Un decompilatore prende sostanzialmente il codice macchina e lo riporta alla lingua in cui è stato formattato. Se non sbaglio, penso che il decompilatore debba sapere in quale lingua è stato compilato, altrimenti non lo farà lavoro.

Lo scopo principale del decompilatore è quello di tornare al codice sorgente; per esempio, una volta il mio file Java è stato danneggiato e l'unica cosa che potevo quindi riportarlo era usando un decompilatore (dato che il file di classe non era danneggiato).

1

Funziona deducendo una rappresentazione "ragionevole" (basata su alcune euristiche) di ciò che è nel codice oggetto. Il grado di somiglianza tra ciò che produce e ciò che era originariamente lì tende a dipendere pesantemente da quanta informazione è contenuta nel binario da cui inizia. Se si inizia fondamentalmente con un binario "puro", in genere si blocca solo creando nomi "ragionevoli" per le variabili, ad esempio utilizzando i, j e k per gli indici di loop e nomi più lunghi per la maggior parte degli altri.

D'altra parte, un linguaggio che supporta l'introspezione deve incorporare molte più informazioni sui nomi delle variabili, i tipi, ecc. Nell'eseguibile. In un caso come questo, la decompilazione può produrre qualcosa di molto più vicino all'originale, come in genere mantenendo i nomi originali per funzioni, variabili, ecc.In tal caso, il decompilatore può spesso produrre qualcosa di simile allo simile all'originale - possibilmente perdendo poco più della formattazione e dei commenti.

0

Dipende dal linguaggio che si sta decompilando. Se stai decompilando qualcosa come C o C++, le uniche informazioni fornite sono i nomi delle funzioni e gli argomenti (nelle DLL). Se si ha a che fare con java, il compilatore di solito inserisce numeri di riga, nomi di variabili, nomi di campi e metodi e così via. Se non ci sono nomi di variabili, otterresti nomi come localInt1, localInt2, localException1. O qualunque sia il compilatore. E può dire la spaziatura tra le righe, a causa dei numeri di riga.