2012-06-20 17 views
10

Ho bisogno di trovare la modalità exe/dll è stata costruita guardando le sue intestazioni. [modifica] Usare C++ solo senza strumenti esterni. [/ edit]Come verificare se un eseguibile o una DLL è compilato in modalità di rilascio o debug (C++)

C'è una vecchia discussione su come determinare la DLL è stata costruita in modalità Rilascio o Debug. http://forums.codeguru.com/archive/index.php/t-485996.html

Ma sfortunatamente non ho trovato nessuna risposta chiara.

+0

Cosa manca esattamente da quella discussione o cosa vorresti avere chiarito? Non c'è una risposta chiara a questo, perché non c'è modo di saperlo senza analizzare la DLL da vicino. – RedX

+0

Cosa consideri come modalità di rilascio o di debug? Il tuo exe/dll include una risorsa versione? – harper

+0

Non è garantito al 100% che la versione sia inclusa. – ChatCloud

risposta

6

Ho bisogno di trovare la modalità exe/dll è stata costruita guardando le sue intestazioni.

Se per "headers" intendi sezioni in PE o risorse (header non vi dirà nulla, e programmi non sono di solito spedito con i loro header di sviluppo!), Questo è tipo di possibile, entro certi limiti, e in modo inaffidabile. Altrimenti, questo è uno sforzo del tutto impossibile a meno che tu non abbia scritto tu stesso il programma.

Generalmente, è difficile fare una cosa del genere in modo affidabile, tanto più che "debug build" è una semplificazione di Microsoft Visual Studio che non esiste come tale nella maggior parte dei compilatori. Ad esempio, con GCC è perfettamente possibile avere una build ottimizzata che tuttavia contiene simboli di debug. È anche possibile attivare e disattivare le ottimizzazioni con #pragma (e modificare il livello di ottimizzazione e persino la macchina di destinazione!) E quindi avere funzioni ottimizzate (o gruppi di funzioni) in una build non ottimizzata e viceversa.

La presenza di simboli di debug è la tua ipotesi migliore per un programma che non hai scritto. Non è possibile (non realisticamente, in un modo semplice e automatico, comunque) di distinguere da un binario generato se è stato ottimizzato o meno.

Le sezioni .debug$S e .debug$T contengono rispettivamente simboli di debug e tipi di debug. Ci sono altre sezioni che iniziano con .debug, ma sono deprecate. Un programma che è stato costruito in "modalità di debug" e che non è stato in seguito rimosso avrà alcune o tutte queste sezioni.
Usando C++ senza strumenti esterni, vorrai saltare lo stub DOS "MZ" e l'intestazione PE. Dopo questo vengono le intestazioni di sezione, che puoi analizzare. È possibile scaricare la documentazione completa del formato file here.
Molto probabilmente, leggere il file e fare una corrispondenza di stringa per .debug sarà altrettanto valido.

Analogamente, è possibile guardare VERSIONINFO o il file manifest (consentono inoltre di specificare se un programma è una build di debug), ma questi non sono obbligatori. Puoi scrivere praticamente tutto ciò che vuoi in questi. Pertanto, sono anche meno affidabili rispetto alla ricerca di simboli di debug.

Un altro suggerimento, di nuovo inaffidabile, sarebbe quello di verificare quali versioni delle librerie di sistema fossero collegate a un programma. Se è la versione di debug, è probabile che fosse una build di debug. Tuttavia, si potrebbe fare una build di release e comunque collegarsi con le librerie di debug, nulla può impedirvi di farlo.

L'ipotesi migliore successivo sarebbe l'assenza di chiamate alla funzione CRT assert (che si potrebbe fare con una semplice partita di stringa), dal momento che la assert macro (da cui è normalmente chiamato) è interamente spogliato in una build con NDEBUG definito. Nessun uso di quel simbolo, nessuna stringa presente nel file binario.
Un programma che non ha eventuali asserzioni sarebbero identificati erroneamente come "versione di rilascio" indipendentemente dalla sua effettiva costruzione ed è interamente possibile ridefinire la macro assert per fare qualcosa di completamente diverso (ad esempio printf a testo e continua). Infine, non si sa se alcune librerie di terze parti statiche con cui si collega (che ovviamente ha già superato il preprocessore) contengano chiamate a assert di cui non si conosce la conoscenza.

Se si desidera verificare un programma che è stato scritto da soli, è possibile sfruttare il fatto che l'ottimizzatore rimuoverà completamente le cose che sono probabilmente irraggiungibili o non utilizzate. Potrebbero essere necessari 2-3 tentativi per farlo correttamente, ma in pratica dovrebbe essere semplice come definire una variabile (o una funzione esportata se il compilatore/linker non esporta simboli non utilizzati) e scrivere due o tre valori magici ad esso da un percorso del programma che non è raggiungibile. Un compilatore che ottimizza almeno collasserà le varie mosse ridondanti in una, o più probabilmente le eliminerà interamente.
È quindi possibile eseguire una ricerca di stringa binaria per i valori magici. Se non sono presenti, è una build ottimizzata.

+0

la maggior parte delle mie applicazioni compilate per debug (win32, vs2010) di me non contengono la stringa '.debug'. Un'alternativa sarebbe quella di verificare quale versione del runtime C++ viene utilizzata dall'applicazione. per esempio. alla ricerca di 'MSVCR80D.dll'' MSVCR90D.dll' 'MSVCR100D.dll' ... – smerlin

+0

@smerlin: Sì, questa è un'altra (anche se inaffidabile) cosa che si potrebbe cercare (come indicato sopra, fare riferimento al paragrafo 6) . La cosa è, davvero non puoi dirlo con certezza. – Damon

0

Quando si crea un progetto C++ in Visual Studio, vengono generate due configurazioni. I nomi di queste configurazioni sono Debug e Release. La configurazione di Debug include la generazione di informazioni di debug, meno ottimizzazione e supporto per Modifica & Continua.

Ma questo è solo un punto di partenza. È possibile creare configurazioni arbitrarie e persino aggiungere tutte le informazioni di debug alla configurazione Release. Quindi non esiste una build Debug o Release chiara.

È possibile provare a identificare se il simbolo del preprocessore _DEBUG è stato definito. Questo viene raramente modificato e viene utilizzato nella risorsa versione. Il bit 0 del campo FILEFLAGES di solito indica che i simboli _DEBUG sono stati definiti durante la compilazione della risorsa.

1

La domanda è molto buona e, come già affermato, non ci sono indicatori (ovvi) reali evidenti che indicano se un'immagine è stata sottoposta a debug o rilasciata.

Come explained qui e here, la presenza di una directory di debug NON è un indicatore se è stata creata o meno un'immagine nella modalità di rilascio. È molto comune che le immagini rilasciate siano costruite con il supporto per il debug. In effetti, quasi TUTTI i file di immagine del sistema operativo Windows sono costruiti con il supporto per il debug (in caso contrario, non ci sarebbe alcuna possibilità di collegare queste immagini rilasciate con i file di simboli dal Microsoft Symbols Server). Anche se queste immagini sono immagini di rilascio!

Anche la presenza della sezione .debug (in realtà, i nomi delle sezioni NON hanno un ruolo nella specifica PE, il nome di una sezione può essere modificato e impostato come si desidera - al Loader non interessa!) NON è un indicatore di immagine Release vs. Debug.

1

C'è un vecchio strumento di inversione chiamato LordPE. Ti permetterà di aprire due file e diffare le intestazioni. Ho compilato un programma "ciao mondo" in VS2008 in modalità di rilascio e debug e li ho confrontati. Come negli altri poster, non ho visto nulla che potesse servire da indicatore.

Ma quello che ho trovato come indicatore era il riempimento nella sezione .text del binario. Vi sono oltre cento byte con il valore 0xCC dopo l'ultimo byte di codice nella sezione .text nella versione Debug. Nella versione Release, non c'erano byte 0xCC. I byte 0xCC verranno visualizzati come int3 o punti di interruzione in un debugger.

Problemi correlati