Domanda:
Come funziona BinDiff?
perror
2013-04-02 14:35:57 UTC
view on stackexchange narkive permalink

Vorrei sapere quali sono i principi di base (e forse alcune cose sulle ottimizzazioni e l'euristica) del software BinDiff. Qualcuno ha una spiegazione simpatica e pedagogica?

@Nirlzr: Non vedo come possa migliorare qualcosa cambiare i tag 'bindiff' in 'tool-bindiff' ... Ma, potrei solo avere una mente contorta, quindi dimmi di più a riguardo ...
Forse dovresti esprimere la tua voce in http://meta.reverseengineering.stackexchange.com/questions/322/bindiff-verses-bin-diffing-tags
@kennytm: Ah, mi sono perso questo ... Buona cattura, grazie.
Due risposte:
#1
+16
newgre
2013-04-03 02:01:48 UTC
view on stackexchange narkive permalink

In generale, BinDiff nella sua versione corrente al momento della stesura di questo documento (4.x) funziona facendo corrispondere gli attributi a livello di funzione. Fondamentalmente, la corrispondenza è divisa in due fasi: vengono generate le prime corrispondenze iniziali che vengono poi raffinate nella fase di drill down.

Partite iniziali

Innanzitutto BinDiff associa una firma basata sul i seguenti attributi a ciascuna funzione:

  • il numero di blocchi di base
  • il numero di bordi tra quei blocchi
  • il numero di chiamate alle sottofunzioni

Questo passaggio ci fornisce una serie di firme per ogni binario che a loro volta vengono utilizzate per generare l'insieme di corrispondenze iniziali. A seguito di una relazione uno-a-uno, BinDiff seleziona queste corrispondenze iniziali in base alle caratteristiche di cui sopra.

Il passaggio successivo cerca di trovare corrispondenze sul grafico delle chiamate di ciascun binario: per una corrispondenza verificata, l'insieme di vengono esaminate le funzioni chiamate dalla funzione abbinata per trovare più corrispondenze. Questo processo viene ripetuto finché vengono trovate nuove corrispondenze.

Drill Down

In pratica, non tutte le funzioni saranno abbinate dalla relazione uno a uno indotta dalla corrispondenza iniziale strategia, quindi dopo che gli abbinamenti iniziali sono stati determinati abbiamo ancora un elenco di funzioni non abbinate. L'idea della fase di drill down è di avere più strategie di abbinamento di funzioni diverse che vengono applicate fino a quando non viene trovata una corrispondenza. L'ordine di applicazione di queste strategie è importante: BinDiff prova prima quelle strategie per le quali assume la massima confidenza. Solo se non è stato possibile trovare alcuna corrispondenza, si procede con la strategia successiva. Questo viene ripetuto fino a quando BinDiff esaurisce le strategie o finché tutte le funzioni non vengono abbinate. Gli esempi includono l'indice MD, la corrispondenza basata sui nomi delle funzioni (ad esempio importazioni), i bordi del callgraph, l'indice MD, ecc.

Documento dell'indice MD

Confronto basato su grafici di oggetti eseguibili

Confronto strutturale di oggetti eseguibili

(Dichiarazione di non responsabilità: lavoro @ team zynamics / google, spero di non aver sbagliato nulla, altrimenti soeren mi farà arrabbiare ;-))

Quindi ci stai ancora lavorando? O è solo il progetto ogni venerdì?
Non ci sto lavorando e non l'ho mai fatto, ma BinDiff non è stato cancellato, se è questo che intendevi !?
Zynamics, la società dietro BinDiff, è stata acquisita da Google. Puoi inviare messaggi ad alcuni dipendenti che siedono su reddit di reverse engineering.
#2
+7
fasmotol
2013-04-02 15:47:17 UTC
view on stackexchange narkive permalink

Posso dire solo un paio di parole sulla costruzione di grafici di flusso di controllo, anche se la mia risposta non è sicuramente quella completa.

BinDiff utilizza un tipo statico di rilevamento dei flussi di esecuzione, suppongo perché l'esecuzione del codice non è sempre possibile (ad esempio per i driver dell'anello 0) o ragionevole (malware). In realtà, il file dato è disassemblato, quindi dovrebbe essere diviso in blocchi di base (questi sono pezzi di codice che hanno un modo di esecuzione diretto, sebbene questa definizione sia giusta in quel caso). È chiaro (considerando l'architettura x86, ad esempio) che istruzioni come jxx cambiano il flusso di controllo di un programma. Quindi i blocchi di base sono solitamente terminati da loro. Questo stesso processo di suddivisione del codice in blocchi non è un compito complicato, la parte più impegnativa è determinare la destinazione del salto.

Ad esempio qualcosa del genere:

  ... jz eax  

Quindi non possiamo (facilmente) capire con l'analisi statica automatizzata dove è puntata questa chiamata. I casi banali possono essere "emulati", ma in generale quel lavoro è molto duro e frustrante. L'altra opzione è tracciare il programma per vedere quali percorsi esegue il codice (che può essere fatto manualmente). Quando questi blocchi vengono trovati, l'unica cosa rimasta è costruire un grafico leggibile dall'uomo.

Comunque c'è un mucchio di modi in cui il flusso di esecuzione può essere modificato (eccezioni, hot patch da un altro thread, eventi dipendenti dal sistema, ecc.).

L '[articolo originale] (http://www.zynamics.com/downloads/bindiffsstic05-1.pdf) sull'algoritmo dell'omomorfismo del grafo è un buon inizio. Più recentemente, sono stati proposti alcuni [strumenti] (https://github.com/MartialB/BinSlayer) (vedi questo [documento] (http://dl.acm.org/citation.cfm?id=2430557) e questo [poster] (http://royalsociety.org/uploadedFiles/Royal_Society_Content/grants/labs-to-riches/2012/Andy%20king.pdf)). Ma questo [thread di Reddit] (http://www.reddit.com/r/ReverseEngineering/comments/16bc9t/binslayer_fast_comparison_of_binary_executables/) suggerisce che sono stati apportati alcuni miglioramenti a BinDiff.


Questa domanda e risposta è stata tradotta automaticamente dalla lingua inglese. Il contenuto originale è disponibile su stackexchange, che ringraziamo per la licenza cc by-sa 3.0 con cui è distribuito.
Loading...