
Binary Ninja प्लगइन जो एक Java bridge subprocess के माध्यम से Ghidra Server repository के साथ विश्लेषण को द्विदिशात्मक रूप से सिंक करता है।
एक Binary Ninja प्लगइन जो Ghidra Server रिपॉज़िटरी से कनेक्ट होता है और उसके विश्लेषण — प्रतीकों, फ़ंक्शन नामों, और टिप्पणियों — को सीधे एक खुले Binary Ninja बाइनरी व्यू में आयात करता है।
Ghidra और Binary Ninja दोनों की अपनी-अपनी खूबियाँ हैं। यह प्लगइन आपको एक ही बाइनरी पर दोनों का उपयोग करने देता है, बिना मैन्युअल रूप से नाम या टिप्पणियाँ एक-दूसरे में कॉपी किए। एक चल रहे Ghidra Server से कनेक्ट करें, उसकी रिपॉज़िटरीज़ ब्राउज़ करें, और किसी भी प्रोजेक्ट फ़ाइल पर डबल-क्लिक करके उसका विश्लेषण वर्तमान में खुले BN व्यू में खींच लें।
सिंक दोनों दिशाओं में होता है।
| BN ← Ghidra (आयात) | BN → Ghidra (चेकइन) | |
|---|---|---|
| प्रतीक (लेबल, फ़ंक्शन नाम) | ✓ | ✓ |
| टिप्पणियाँ (EOL/PRE/POST/PLATE/REP) | ✓ | ✓ |
| फ़ंक्शन सिग्नेचर (रिटर्न टाइप, कॉलिंग कन्वेंशन) | ✓ | ✓ |
| फ़ंक्शन पैरामीटर (नाम बदलें, टाइप बदलें, जोड़ें) | ✓ | ✓ |
| डेटा टाइप (struct/union/enum/typedef + pointer/array) | ✓ | ✓ |
| Equates (कॉन्स्टेंट नाम + संदर्भ) | ✓ | ✓ |
| बुकमार्क | ✓ | ✓ |
| टाइप्ड डेटा आइटम | ✓ | ✓ |
| फ़ंक्शन फ़्लैग (thunk, no-return, inline) | ✓ BN टैग के रूप में | — |
| लोकल वेरिएबल (स्टोरेज-अवेयर) | ✓ | आंशिक — रजिस्टर-स्टोरेज मैपिंग लागू नहीं है |
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)
प्लगइन लोड होने पर एक Java सबप्रोसेस (जिसे "bridge" कहा जाता है) शुरू करता है। ब्रिज Ghidra Server के साथ RMI कनेक्शन बनाए रखता है और एक लोकल TCP सॉकेट पर प्लगइन से सरल JSON प्रोटोकॉल में बात करता है। इससे सारा Java/RMI कोड C++ प्रोसेस से बाहर रहता है और JVM बैकग्राउंड में शुरू हो सकता है जबकि BN लोड होना पूरा करता है।
ब्रिज JVM स्टार्टअप पर Ghidra के Application फ़्रेमवर्क को भी इनिशियलाइज़ करता है ताकि राइट पाथ कच्चे db.Table.putRecord() राइट्स के बजाय Ghidra के हाई-लेवल प्रोग्राम-मॉडल APIs (ProgramDB, DataTypeManager, SymbolTable, FunctionManager) का उपयोग कर सके — नीचे Checkin write path देखें।
| पाथ | भाषा | भूमिका |
|---|---|---|
plugin/ | C++ / Qt6 | Binary Ninja साइडबार प्लगइन |
bridge/ | Java 17 | Ghidra RMI क्लाइंट + JSON ब्रिज सर्वर |
प्लगइन (C++):
plugin.cpp — सेटिंग्स और साइडबार विजेट रजिस्टर करता है; लोड पर ब्रिज JVM को तुरंत शुरू करता हैGhidraConnection.cpp — सिंगलटन; ब्रिज लाइफसाइकल और सभी RMI-आधारित ऑपरेशन्स प्रबंधित करता हैBridgeProcess.cpp — ब्रिज JAR को stdout/stderr पाइप्स के साथ सबप्रोसेस के रूप में लॉन्च करता है; READY port=N हैंडशेक लाइन पढ़ता हैBridgeClient.cpp — TCP क्लाइंट; JSON रिक्वेस्ट भेजता है, रिस्पॉन्स प्राप्त करता है, async इवेंट्स डिस्पैच करता हैSyncEngine.cpp — एक GhidraDbExport को BinaryView पर लागू करता है (प्रतीक, टिप्पणियाँ, फ़्लैग)ui/ProjectPanel.cpp — साइडबार विजेट: रेपो ट्री, कनेक्ट डायलॉग, एक्टिविटी लॉगui/ConnectDialog.cpp — होस्ट/पोर्ट/यूज़र/पासवर्ड डायलॉगब्रिज (Java):
BridgeMain.java — आर्गुमेंट पार्सिंग; UniversalIdGenerator और Ghidra Application फ़्रेमवर्क इनिशियलाइज़ करता है; TCP सर्वर शुरू करता है; stdout पर READY port=N प्रिंट करता हैBridgeServer.java — एक TCP क्लाइंट कनेक्शन स्वीकार करता है और उसे एक BridgeConnection सौंपता हैBridgeConnection.java — JSON रिक्वेस्ट डिस्पैचर; Ghidra API रिस्पॉन्स को JSON में सीरियलाइज़ करता है; opCheckin संभालता है (सर्वर पर एक नया प्रोग्राम वर्ज़न बनाता है)GhidraSession.java — ऑथेंटिकेटेड RMI सेशन; RemoteRepositoryServerHandle को रैप करता हैEventStreamer.java — प्रत्येक खुले रेपो के लिए बैकग्राउंड थ्रेड; RepositoryChangeEvents को async JSON इवेंट्स के रूप में प्लगइन को पुश करता हैDatabaseExporter.java — रीड पाथ: कच्चे db.jar एक्सेस के माध्यम से एक ManagedBufferFileHandle (Ghidra का रिमोट DB बफ़र) से symbol/comment/function-flag/data-type/equate/bookmark टेबल्स निकालता हैProgramApplier.java — राइट पाथ: बफ़र फ़ाइल को एक असली ProgramDB के रूप में खोलता है और Ghidra के हाई-लेवल APIs के माध्यम से सभी BN-साइड परिवर्तन लागू करता है (नीचे Checkin write path देखें)DatabaseImporter.java — लिगेसी रॉ-राइट हेल्पर्स केवल एक टेस्ट सीम के रूप में रखे गए हैं; प्रोडक्शन apply(...) ProgramApplier को डेलिगेट करता हैopCheckin प्रोग्राम की मैनेज्ड बफ़र फ़ाइल को राइट मोड में खोलता है, उसके ऊपर एक ProgramDB बनाता है, और Ghidra के प्रोग्राम-मॉडल APIs के माध्यम से BN-साइड परिवर्तन लागू करता है। कच्चे db.Table.putRecord() राइट्स से बचा जाता है — वे ही हर उस चेकइन-करप्शन बग का स्रोत थे जो हमने कभी देखा:
| गलत-टियर राइट | विफलता मोड |
|---|---|
Function Data टेबल पर setIntValue(col, longTypeId) | IntField.setLongValue चुपचाप l2i-ट्रंकेट करता है → हर सिग्नेचर अपडेट पर StackPurge करप्ट हो जाता है |
V5V6 Composite Data Types पर setByteValue(col, isUnion) | Ghidra 12.x में कॉलम BooleanField है → IllegalFieldAccessException ("Illegal field access") |
V2 Typedef Flags कॉलम पर setIntValue(col, 0) | कॉलम ShortField है → वही क्रैश, अलग स्कीमा |
| component-settings रो के बिना composite हेडर लिखना | Ghidra में struct खोलने पर CompositeEditorModel.cloneAllComponentSettings ArrayIndexOutOfBoundsException थ्रो करता है |
SYM_ADDR_COL = RAM एड्रेस के साथ PARAMETER प्रतीक लिखना | किसी भी फ़ंक्शन एक्सेस पर FunctionDB.loadSymbolBasedVariables द्वारा Address is not a VariableAddress थ्रो होता है |
DBHandle.save() को null DBChangeSet पास करना | सर्वर एक 0-बाइट change-data फ़ाइल लिखता है → अगला चेकआउट ProgramContentHandler.loadProgramChangeSet में EOFException के साथ विफल होता है |
ProgramApplier में ये जाल नहीं हैं क्योंकि यह DataTypeManager.addDataType, SymbolTable.createLabel, Listing.setComment, Function.setReturnType, आदि के माध्यम से रूट करता है — ऐसे APIs जो Ghidra के इंटरलॉकिंग-टेबल इनवेरिएंट्स को स्वचालित रूप से बनाए रखते हैं। यह हर चेकइन की शुरुआत में एक cleanupBadVariableSymbols पास भी चलाता है ताकि पुराने ब्रिज वर्ज़न द्वारा डेटाबेस में छोड़ी गई करप्शन को साफ़ किया जा सके।
server-package/CleanupBadVariableSymbols.java एक स्टैंडअलोन GhidraScript है जो analyzeHeadless के माध्यम से वही क्लीनअप चलाता है — तब उपयोगी होता है जब कोई फ़ाइल Ghidra GUI में खोलने के लिए बहुत करप्ट हो।
./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)
सूट पाँच टियर में व्यवस्थित है। टियर 2–4 एक ही गुण सिद्ध करने के लिए हैं: वही संगत डेटा अंततः .bndb और Ghidra प्रोग्राम डेटाबेस दोनों में संग्रहीत होता है (इस README के शीर्ष पर दी गई संगतता मैट्रिक्स)।
| टियर | क्या | कहाँ | गेट |
|---|---|---|---|
| 0 | शुद्ध यूनिट टेस्ट | plugin/test/*.cpp (binja-ghidra-tests), ब्रिज *Test.java | हमेशा |
| 1 | Ghidra-DB राउंड-ट्रिप | ब्रिज *RoundTripTest.java (एक असली ProgramDB के विरुद्ध ProgramApplier) | ghidra.home / GHIDRA_HOME चाहिए |
| 2 | BN BinaryView/.bndb राउंड-ट्रिप | plugin/test/bn/ (binja-ghidra-bn-tests; headless binaryninjacore) | headless-सक्षम BN लाइसेंस के बिना साफ़ तौर पर SKIP होता है (BN_LICENSE env का सम्मान किया जाता है) |
| 3 | क्रॉस-DB पैरिटी | CanonicalParityTest (C++ और Java) testdata/parity/fixtures/ में साझा गोल्डन्स के विरुद्ध | टियर 1+2 के साथ |
| 4 | लाइव-सर्वर E2E | ब्रिज LiveServerE2ETest — एक टेम्प डिर में असली ghidraSvr बूट करता है, analyzeHeadless के माध्यम से सीड करता है, RMI पर checkout → export → checkin → re-export चलाता है | test.bat --e2e (GHIDRA_E2E=1 सेट करता है) |