
Plugin per la visualizzazione della copertura del codice binario per Ghidra
Dragon Dance è un plugin per Ghidra per visualizzare e manipolare i dati di copertura del codice binario. I dati di copertura possono essere importati da più fonti di copertura. Per ora il plugin supporta gli strumenti di strumentazione binaria Dynamorio e Intel Pin. Dynamorio ha un proprio modulo di raccolta della copertura chiamato "drcov". Intel Pin non fornisce un modulo di raccolta della copertura integrato. Per gestire la mancanza del modulo, ho dovuto scrivere il mio modulo di raccolta della copertura per Intel Pin. Quindi ho scritto un modulo di raccolta della copertura per Intel Pin chiamato ddph (Dragon Dance Pin Helper). Quindi puoi usarlo. Puoi vedere il codice sorgente di ddph da questo link. Se sei pigro per compilare da solo, puoi usare i binari compilati che ho fornito per Windows, macOS e Linux.

Dragon Dance può importare e utilizzare più dati di copertura nella stessa sessione. (Supporta anche multi-sessione ma per ora non è utilizzabile tramite GUI). E puoi passare da uno all'altro o applicare rapidamente operazioni di intersezione, differenza, distinzione o somma tra di loro.
Dragon Dance ti permette di visualizzare l'intensità delle istruzioni eseguite. Così puoi avere un'indicazione su quali istruzioni vengono eseguite con quale frequenza. Puoi anche visualizzare la copertura sulla finestra del grafico delle funzioni.

Dragon Dance supporta anche un proprio sistema di scripting.

Ti offre un modo flessibile di giocare con i dati di copertura. Puoi eseguire operazioni di caricamento, eliminazione, visualizzazione, intersezione, differenza, distinzione e somma su di essi. La sezione seguente conterrà il sistema di scripting e l'API. Premi i tasti Alt + Invio per eseguire lo script.
Le funzioni integrate sono implementazioni delle operazioni interne di copertura per fornire un'interfaccia al sistema di scripting. Una funzione integrata può restituire una variabile oggetto di copertura o nulla. Le funzioni integrate possono avere alias. Accettano un argomento integrato come parametro. I parametri possono essere di lunghezza variabile.
L'argomento integrato è un riferimento per contenere diversi tipi di valore. Gli argomenti integrati vengono passati in ordine da sinistra a destra. L'argomento integrato può contenere i seguenti tipi di valore:
Le variabili sono responsabili di contenere solo l'oggetto di copertura. Possono essere caricate dalle funzioni integrate. Possono essere passate come parametro (Argomento integrato) alle funzioni integrate.
Esistono due tipi di oggetto di copertura.
Oggetto di copertura fisico e Oggetto di copertura logico
Oggetto di copertura fisico punta a un oggetto di copertura caricato direttamente dal file di copertura. Sono visibili nella tabella di copertura che si trova sulla GUI. Quindi puoi interagire con essi tramite le operazioni della GUI.
Oggetto di copertura logico punta a un oggetto di copertura che è stato elaborato in una funzione integrata e restituito da essa come risultato. Non sono visibili sulla GUI ma possono vivere in una variabile finché non vengono distrutti.
L'oggetto di copertura viene mantenuto automaticamente dall'oggetto Variabile per entrambi i tipi di oggetto di copertura. Per esempio;``` cov1 = load("firstcoverage.out") cov2 = load("secondcov.out")
cov1 = diff(cov1,cov2)
In questo esempio cov1 e cov2 sono variabili. Ed entrambe le variabili hanno un oggetto di copertura fisico. Il built-in diff prende entrambe le variabili e imposta il valore di ritorno sulla variabile cov1. Tale operazione di sovrascrittura imposterà l'oggetto di copertura risultante sulla variabile, ma non elimina l'oggetto di copertura perché si tratta di un oggetto di copertura fisico. Quei dati di copertura rimarranno nella sessione e anche nella tabella GUI. Pensiamo all'esempio precedente in questo modo;```
cov1 = load("first.out")
cov2 = load("second.out")
cov3 = load("third.out")
rvar = sum(cov1,cov2,cov3)
rvar = diff(rvar, cov2)
In questo esempio, tre variabili di copertura fisica entrano in un'operazione di somma e l'operazione di somma restituisce un oggetto di copertura come risultato logico. Quindi l'operazione diff prende una variabile logica e una fisica e sovrascrive la variabile chiamata rvar.
In questo caso, il risultato sarà impostato su rvar e il suo valore di copertura precedente viene immediatamente distrutto. Poiché questo era un oggetto logico, dovrebbe essere eliminato per evitare perdite di oggetti. Se vuoi distruggere una variabile che contiene un oggetto di copertura fisica, devi chiamare il built-in discard. Tutti i built-in saranno dettagliati di seguito.
Puoi scrivere script complessi usando chiamate nidificate ai built-in, puoi scrivere qualcosa del tipo:
cres = diff(intersect(a, load("another.log"), c, d), sum(e,f) )
Non devi scrivere la logica riga per riga.
Le seguenti documentazioni delle API e i loro comportamenti potrebbero cambiare fino al raggiungimento della versione finale.
clear()
| Proprietà | Descrizione |
|---|---|
| Valore di ritorno | Nessuno |
| Conteggio minimo parametri | 0 |
| Conteggio massimo parametri | 0 |
| Descrizione | Questo built-in cancella la copertura visualizzata e imposta la copertura attiva a null. |
| Alias | Nessuno |
cwd( Stringa : directoryDiLavoro )
| Proprietà | Descrizione |
|---|---|
| Valore di ritorno | Nessuno |
| Conteggio minimo parametri | 1 |
| Conteggio massimo parametri | 1 |
| Descrizione | Imposta la directory di lavoro corrente con il percorso dato. Tutte le chiamate di importazione senza percorso assoluto dopo cwd cercheranno i file di copertura nella directory di lavoro attiva. |
| Alias | Nessuno |
diff( Variabile : var1, var2, ..... varN )