
Plugin per Binary Ninja che sincronizza l'analisi in modo bidirezionale con un repository Ghidra Server, tramite un sottoprocesso bridge Java.
Un plugin Binary Ninja che si connette a un repository Ghidra Server e importa la sua analisi — simboli, nomi di funzione e commenti — direttamente in una binary view Binary Ninja aperta.
Ghidra e Binary Ninja hanno ciascuno i propri punti di forza. Questo plugin ti permette di usarli entrambi sullo stesso binario senza copiare manualmente nomi o commenti tra i due. Connettiti a un Ghidra Server in esecuzione, esplora i suoi repository e fai doppio clic su qualsiasi file di progetto per estrarre la sua analisi nella view BN attualmente aperta.
La sincronizzazione va in entrambe le direzioni.
| BN ← Ghidra (import) | BN → Ghidra (checkin) | |
|---|---|---|
| Simboli (etichette, nomi di funzione) | ✓ | ✓ |
| Commenti (EOL/PRE/POST/PLATE/REP) | ✓ | ✓ |
| Firme di funzione (tipo di ritorno, calling convention) | ✓ | ✓ |
| Parametri di funzione (rinomina, retype, aggiunta) | ✓ | ✓ |
| Tipi di dato (struct/union/enum/typedef + pointer/array) | ✓ | ✓ |
| Equate (nomi di costanti + riferimenti) | ✓ | ✓ |
| Segnalibri | ✓ | ✓ |
| Elementi di dato tipizzati | ✓ | ✓ |
| Flag di funzione (thunk, no-return, inline) | ✓ come tag BN | — |
| Variabili locali (storage-aware) | ✓ | parziale — mappatura dello storage dei registri non implementata |
Binary Ninja (C++ plugin)
│ TCP / newline-delimited JSON
▼
ghidra-bridge-*.jar (Java, runs as a subprocess)
│ Java RMI / SSL
▼
Ghidra Server (ghidraSvr, running on the network)
Il plugin avvia un sottoprocesso Java (il "bridge") al caricamento. Il bridge mantiene la connessione RMI al Ghidra Server e parla un semplice protocollo JSON verso il plugin tramite un socket TCP locale. Questo tiene tutto il codice Java/RMI fuori dal processo C++ e permette alla JVM di avviarsi in background mentre BN termina il caricamento.
La JVM del bridge inizializza anche il framework Application di Ghidra all'avvio, così il percorso di scrittura può usare le API di alto livello del program-model di Ghidra (ProgramDB, DataTypeManager, SymbolTable, FunctionManager) invece delle scritture grezze db.Table.putRecord() — vedi Checkin write path sotto.
| Path | Linguaggio | Ruolo |
|---|---|---|
plugin/ | C++ / Qt6 | Plugin sidebar di Binary Ninja |
bridge/ | Java 17 | Client RMI Ghidra + server bridge JSON |
Plugin (C++):
plugin.cpp — registra le impostazioni e il widget della sidebar; avvia subito la JVM del bridge al caricamentoGhidraConnection.cpp — singleton; gestisce il ciclo di vita del bridge e tutte le operazioni basate su RMIBridgeProcess.cpp — lancia il JAR del bridge come sottoprocesso con pipe stdout/stderr; legge la riga di handshake READY port=NBridgeClient.cpp — client TCP; invia richieste JSON, riceve risposte, smista eventi asincroniSyncEngine.cpp — applica un GhidraDbExport a una BinaryView (simboli, commenti, flag)ui/ProjectPanel.cpp — widget della sidebar: albero dei repo, dialog di connessione, log delle attivitàui/ConnectDialog.cpp — dialog host/porta/utente/passwordBridge (Java):
BridgeMain.java — parsing degli argomenti; inizializza UniversalIdGenerator e il framework Application di Ghidra; avvia il server TCP; stampa READY port=N su stdoutBridgeServer.java — accetta una connessione client TCP e le assegna una BridgeConnectionBridgeConnection.java — dispatcher delle richieste JSON; serializza le risposte delle API Ghidra in JSON; gestisce opCheckin (crea una nuova versione del programma sul server)GhidraSession.java — sessione RMI autenticata; incapsula RemoteRepositoryServerHandleEventStreamer.java — thread in background per ogni repo aperto; invia RepositoryChangeEvent al plugin come eventi JSON asincroniDatabaseExporter.java — percorso di lettura: estrae le tabelle di simboli/commenti/flag di funzione/tipi di dato/equate/segnalibri da un ManagedBufferFileHandle (il buffer DB remoto di Ghidra) tramite accesso grezzo a db.jarProgramApplier.java — percorso di scrittura: apre il file buffer come un vero ProgramDB e applica tutte le modifiche lato BN tramite le API di alto livello di Ghidra (vedi Checkin write path sotto)DatabaseImporter.java — helper legacy di scrittura grezza mantenuti solo come seam di test; la apply(...) di produzione delega a ProgramApplieropCheckin apre il file buffer gestito del programma in modalità scrittura, costruisce un ProgramDB sopra di esso e applica le modifiche lato BN tramite le API del program-model di Ghidra. Le scritture grezze db.Table.putRecord() sono evitate — erano la fonte di ogni bug di corruzione al checkin che abbiamo mai incontrato:
| Scrittura di tier errato | Modalità di fallimento |
|---|---|
setIntValue(col, longTypeId) sulla tabella Function Data | IntField.setLongValue tronca silenziosamente con l2i → StackPurge corrotto a ogni aggiornamento di firma |
setByteValue(col, isUnion) su V5V6 Composite Data Types | la colonna è BooleanField in Ghidra 12.x → IllegalFieldAccessException ("Illegal field access") |
setIntValue(col, 0) sulla colonna V2 Typedef Flags | la colonna è ShortField → stesso crash, schema diverso |
| Scrittura dell'header composite senza righe di component-settings | CompositeEditorModel.cloneAllComponentSettings lancia ArrayIndexOutOfBoundsException quando la struct viene aperta in Ghidra |
Scrittura di un simbolo PARAMETER con SYM_ADDR_COL = indirizzo RAM | Address is not a VariableAddress lanciato da FunctionDB.loadSymbolBasedVariables a qualsiasi accesso alla funzione |
Passaggio di un DBChangeSet null a DBHandle.save() | il server scrive un file change-data da 0 byte → il checkout successivo fallisce con EOFException in ProgramContentHandler.loadProgramChangeSet |
ProgramApplier non ha queste trappole perché passa attraverso DataTypeManager.addDataType, SymbolTable.createLabel, Listing.setComment, Function.setReturnType, ecc. — API che mantengono automaticamente gli invarianti delle tabelle interconnesse di Ghidra. Esegue anche un passaggio cleanupBadVariableSymbols all'inizio di ogni checkin per eliminare la corruzione lasciata nel database dalle versioni precedenti del bridge.
server-package/CleanupBadVariableSymbols.java è un GhidraScript standalone che esegue la stessa pulizia tramite analyzeHeadless — utile quando un file è troppo corrotto per essere aperto nella GUI di Ghidra.
./test.sh # macOS / Linux: tiers 0-3 (C++ unit + BN-headless + Java)
test.bat # Windows equivalent
test.bat --parity # cross-DB parity tier only (C++ BN tests + gradlew parityTest)
test.bat --e2e # live Ghidra-server E2E (starts a local ghidraSvr)
La suite è organizzata in cinque tier. I tier 2–4 esistono per dimostrare una proprietà: gli stessi dati compatibili finiscono per essere memorizzati sia nel .bndb sia nel program database di Ghidra (la matrice di compatibilità in cima a questo README).