1 पॉइंट द्वारा GN⁺ 2024-08-24 | 1 टिप्पणियां | WhatsApp पर शेयर करें
  • यह Ghidra extension किसी प्रोग्राम के हिस्से को object file के रूप में export करता है, और exported file में symbols और relocation table जैसे वैध metadata शामिल होते हैं, ताकि toolchain में उसे फिर से process किया जा सके
  • इसके मुख्य उपयोग advanced binary patching, software porting, file format conversion, library creation, और decompilation projects में प्रोग्राम को कई object files में बांटकर फिर से implement करने के काम हैं
  • समर्थित combinations COFF x86/x86_64, ELF x86/x86_64/MIPS, OMF x86 हैं; COFF MIPS, OMF x86_64, और OMF MIPS समर्थित नहीं हैं
  • यूज़र Ghidra Listing में extract करने के लिए address range चुनता है, Relocation table synthesizer analyzer चलाता है, और फिर File > Export Program… से relocatable object file exporter को invoke करता है
  • relocation table synthesis Ghidra database accuracy पर निर्भर है, इसलिए गलत या missing जानकारी होने पर relocations टूट सकती हैं या छूट सकती हैं; export से ठीक पहले analyzer को फिर से चलाना सुरक्षित है

यह extension क्या करता है

  • Object file exporter extension for Ghidra एक Ghidra extension है, जो प्रोग्राम के किसी हिस्से को object file के रूप में export करने देता है
  • बनी हुई object file में symbols, relocation table जैसे वैध metadata शामिल होते हैं
  • इसी metadata की वजह से exported object file को toolchain में सीधे reuse करके आगे process किया जा सकता है

उपयोग के उदाहरण

  • Advanced binary patching
    • original हिस्से और modified हिस्से को हाथ से मिलाने के बजाय linker का इस्तेमाल करके उन्हें साथ में fit कराया जा सकता है
  • Software ports
    • प्रोग्राम से system-independent code को अलग करके बाकी हिस्से को replace किया जा सकता है
  • प्रोग्राम या object file को एक file format से दूसरे file format में convert किया जा सकता है
  • प्रोग्राम के हिस्से extract करना और library creation
    • प्रोग्राम के कुछ हिस्से extract करके किसी दूसरे context में reuse किए जा सकते हैं
  • decompilation projects में प्रोग्राम को कई object files में बांटा जा सकता है और उन्हें Ship of Theseus तरीके से फिर से implement किया जा सकता है

समर्थित architectures और object file formats

  • support matrix इस प्रकार है
    • COFF: x86, x86_64 समर्थित / MIPS समर्थित नहीं
    • ELF: x86, x86_64, MIPS समर्थित
    • OMF: x86 समर्थित / x86_64, MIPS समर्थित नहीं

build और installation

  • CLI build प्रक्रिया
    • repository को clone करें
    • GHIDRA_INSTALL_DIR environment variable को Ghidra installation directory पर set करें
    • gradle buildExtension चलाएं
    • बना हुआ Ghidra extension archive dist/ directory में बनेगा
  • GitHub Maven repository से package download करने के लिए authentication जरूरी है
    • read:packages permission वाला GitHub classic token बनाएं और ${GRADLE_USER_HOME}/gradle.properties में githubToken=ghp_xxx जोड़ें
    • या gradle installStandaloneDeps चलाकर submodule की vendored dependency को build और install करें
  • installation प्रक्रिया
    • releases page से extension download करें या local build करें
    • Ghidra में File > Install Extensions… से extension install करें
    • CodeBrowser window में File > Configure > Experimental से RelocationTableSynthesizedPlugin plugin enable करें

उपयोग flow और सावधानियां

  • basic usage प्रक्रिया
    • Listing view में extract करने के लिए address set चुनें
    • one-shot mode में दिए गए Relocation table synthesizer analyzer को चलाएं
    • File > Export Program… से relocatable object file exporter invoke करें
  • reconstructed relocations को Window > Relocation table (synthesized) में देखा जा सकता है
  • detailed evaluation report को Analysis > Auto Analyze... dialog में Relocation table synthesizer analyzer के Evaluation report policy option को set करके enable किया जा सकता है
  • extension इस्तेमाल करने से पहले पूरे प्रोग्राम को पहले से पूरा reverse engineer करना जरूरी नहीं है
  • successful delinking आम तौर पर export किए जाने वाले हिस्से और external references के metadata पर काफी निर्भर करता है
    • relocation locations के रूप में इस्तेमाल होने वाले functions और pointers
    • relocation targets के रूप में इस्तेमाल होने वाले symbol footprint
    • दोनों के बीच references
  • Relocation table synthesizer analyzer Ghidra database की accuracy पर निर्भर करता है
    • inaccurate या missing जानकारी analysis के दौरान broken relocations या missing relocations का कारण बन सकती है
  • object file exporter Relocation table synthesizer analysis results पर निर्भर करता है
    • संदेह हो तो object file export करने से ठीक पहले analyzer चलाकर सुनिश्चित करें कि relocation table up-to-date है

काम करने का तरीका

  • object file तीन हिस्सों से बनी होती है
    • relocatable section bytes
    • symbol table

      • relocation table
      • linker जब कई object files से executable बनाता है, तब वह जो काम करता है
      • sections को memory में place करता है
      • virtual address space में symbol addresses calculate करता है
      • final symbol addresses के आधार पर section bytes पर relocations apply करता है
      • आम तौर पर यह प्रक्रिया खत्म होने के बाद relocation table discard कर दी जाती है
      • अगर debugging symbols retain नहीं किए जाते, तो symbol table भी discard हो जाती है, और सिर्फ non-relocatable section bytes बचते हैं
      • यह extension सावधानीपूर्वक analysis से उस data को फिर से बना सकता है, जिससे प्रोग्राम को वापस object file में delink किया जा सकता है

1 टिप्पणियां

 
GN⁺ 2024-08-24
Hacker News की राय
  • इसे यहां देखकर अच्छा लगा। मुझे लगता है यह वाकई शानदार प्रोजेक्ट है, और मैंने MS COFF support जोड़ने में मदद की थी
    हालांकि मेरी शुरुआती PR पहले से मौजूद ELF support की तुलना में काफी अधूरी थी, इसलिए अगर कोई समस्या आती है तो शायद वह मेरी वजह से हो सकती है। फिर भी इसमें सुधार दिख रहा है
    मैंने अभी इसे किसी बड़े काम में इस्तेमाल नहीं किया है, लेकिन Visual Studio 2003 से compile की गई Hello World executable को delink करके Linux x86 पर GCC+glibc से फिर से link करना, और फिर MinGW+msvcrt से relink करना सबसे मजेदार था
    Hello World से बड़ा कुछ अभी मुश्किल है, और खासकर मैं Ghidra को अच्छी तरह नहीं जानता, इसलिए बड़ी binaries में delink करने की range चुनने का अच्छा तरीका भी अभी नहीं मिला है
    संयोग से आज ही इस tool का Nixpkgs derived package merge हुआ है, इसलिए NixOS unstable में इसे ghidra.withExtensions से install किया जा सकता है। location है ghidra-extensions.ghidra-delinker-extension
    बस कुछ दिन पहले नया version आया था, लेकिन मैंने PR rebase नहीं किया, इसलिए फिलहाल यह पुराना version है, और जल्द ही update डालने की कोशिश करूंगा

    • delink किए जाने वाले targets को track करने का एक तरीका program tree में folders और fragments का इस्तेमाल करना है
      उदाहरण के लिए, अगर आपके पास ऐसा Ghidra program है जिसने original executable बनाने वाली कई object files के नाम और ranges पता कर लिए हैं, तो उस folder या fragment पर right-click > Select Addresses करके उसे पूरा select किया जा सकता है
      relocation synthesis analyzer और export, दोनों को script किया जा सकता है या program के tree manager के जरिए automate किया जा सकता है, जिससे मनचाही range हाथ से select करने और analyzer व export को manually run करने की जरूरत कम हो जाती है
  • काफी दिलचस्प लग रहा है, और कुछ साल पहले छोड़े हुए game reverse engineering project को फिर से देखने का मन हो रहा है
    अच्छा होगा अगर एक complete example हो जो शुरू से आखिर तक दिखाए कि इसे कैसे इस्तेमाल करना है और इसके output का कैसे उपयोग करना है

  • यह जानना चाहता हूं कि executable के कौन-से sections export करने हैं, यह पता लगाने में कितना काम लगता है
    क्या 2008–2015 के आसपास के अपेक्षाकृत modern Win32 game को object file के रूप में export करके, कुछ घंटों में फिर से पूरी executable के रूप में compile/link करना realistic है?

    • जब तक आप किसी variable या function के बीच से नहीं काटते, काफी स्वतंत्र रूप से export कर सकते हैं, और original object file boundaries को अनिवार्य रूप से follow करने की जरूरत नहीं है
      क्या export करना है, यह अलग सवाल है और इसके लिए program की जानकारी चाहिए। debug symbols हों तो यह बहुत आसान हो जाता है, और उनके बिना भी, जब Ghidra database को export करने लायक सही बना लेते हैं, तो आम तौर पर अंदाजा लगने लगता है कि क्या कहां है
      submit किए गए post के user case में, उन्होंने जुलाई की शुरुआत में पहला issue डाला था, और अगस्त के मध्य तक उन्हें functionally equivalent तरीके से चलने वाली relinked executable मिल गई थी
      हालांकि उस समय COFF export में fix करने लायक काफी bugs थे और i386 analyzer में भी सुधार की जरूरत थी, इसलिए उम्मीद है कि अब किसी और को वही समस्याएं कम झेलनी पड़ेंगी
      कितना समय लगेगा, यह नहीं पता, लेकिन अगर debug symbols हैं और किस्मत वाकई अच्छी है, तो छोड़कर, इसमें कुछ घंटों से ज्यादा लगने की संभावना है। कोई experienced reverse engineer उस समय में कुछ चलने लायक बना सकता है, लेकिन वह पहली loading screen के बीच में crash भी हो सकता है, और यह ऐसा काम है जिसमें खत्म होने तक पता नहीं चलता कि कब खत्म होगा
  • शानदार लगता है। शायद किसी दिन यह existing programs को ज्यादा आसानी से तोड़कर अपनी जरूरत के हिसाब से इस्तेमाल करने में मदद कर सके
    Meta का LLM Compiler या LLM-based decompilation जैसी research है, और programs को parts में बांटना व कुछ parts को replace करना ऐसा interesting area हो सकता है जिसमें LLM explore कर सके और खुद improve कर सके, क्योंकि इसमें data काफी rich है
    learning के नजरिए से भी इसमें कई interesting tokens छिपे हैं, और उनसे बहुत कुछ किया जा सकता है

  • सच कहूँ तो यह जादू जैसा लगता है। समझना पड़ेगा कि यह कैसे संभव है

    • सरल शब्दों में, object file तीन हिस्सों से बनी होती है: relocatable section bytes, relocation table, और symbol table
      जब linker कई object files से executable बनाता है, तो वह sections को memory में रखता है, virtual address space में symbol addresses की गणना करता है, और फिर final symbol addresses के आधार पर section bytes पर relocations लागू करता है
      delink का तरीका यह है कि यह पता लगाया जाए कि वे relocations कहाँ लागू हुए थे, उन्हें उलटा जाए, और फिर से relocatable bytes हासिल किए जाएँ। उसके बाद उलटी की गई जानकारी के आधार पर relocation table और symbol table बनाकर पैक कर दें, तो object file मिल जाती है
      सच में कठिन हिस्सा relocation points ढूँढने वाला analysis है। ज़्यादातर काम Ghidra पर छोड़ा जाता है, लेकिन references को relocation points में बदलने का काम करना पड़ता है। x86 पर यह तुलनात्मक रूप से आसान है और MIPS पर यह डरावने सपने जैसा कठिन है। इसी के लिए ज़रूरी data इकट्ठा करने और object file को serialize करने तक का काम automate करने के लिए यह extension बनाया गया है
    • यह हर CPU architecture पर आसानी से नहीं होगा, लेकिन जितना दिखता है उतना बेतुका काम भी नहीं है। मूल रूप से object file और executable file या shared library में बहुत बड़ा फर्क नहीं होता
      Microsoft platforms को छोड़ दें तो कई बार असली file format भी वही होता है; उदाहरण के लिए ELF ऐसा ही है
      बड़ा फर्क relocation का है। object files में बारीक relocation information होती है, लेकिन executables में आम तौर पर नहीं होती। Windows के executable image में सिर्फ इतना minimal relocation होता है कि executable relocate होने पर किन code और data addresses को ठीक करना है; और image खुद केवल पूरे image base address के स्तर पर ही relocate हो सकती है
      इसके उलट object file में symbol-level relocation होता है। इस जानकारी को सही-सही दोबारा बनाने के लिए disassembly में symbols के बारे में काफी सटीक जानकारी जोड़नी पड़ती है
      एक और बड़ा फर्क यह है कि object file अभी linked नहीं होती। कोई भी symbol resolve नहीं हुआ होता। इसे ठीक करना उल्टा आसान है: delink के दौरान अगर कोई symbol मौजूदा range के बाहर है, तो आम तौर पर उसे unresolved symbol में बदल दें। बाद में relink करते समय कोई दूसरी object file या library वह symbol provide करेगी, तभी वह फिर से जुड़ पाएगा
      entry point न होने जैसे छोटे फर्क भी हैं, लेकिन उनका बहुत मतलब नहीं है
      इसलिए executable image या shared object से object file काटने की boundary व्यवहार में लगभग मनमानी है। मूल compilation के समय यह translation units में बँटी होगी, लेकिन link stage पर उन boundaries की बहुत परवाह नहीं की जाती। हाँ, अगर matching decompile चाहिए, तो object file boundary गलत होने पर काम बहुत कठिन हो सकता है, इसलिए संभव हो तो उसे पता कर लेना बेहतर है
      मैंने इस समस्या पर असल में काम किया है, लेकिन details में थोड़ा गलत हो सकता हूँ, इसलिए इसे reference की तरह ही देखें। object files पर blog post लिखने की कोशिश की थी, और पहले से कुछ अच्छे लेख भी मौजूद हैं
  • जिज्ञासा है कि यह process पूरी तरह safe है या नहीं। जानना चाहता हूँ कि success हमेशा guaranteed है या analysis conservative तरीके से चलता है
    उदाहरण के लिए, अगर ELF में कोई टुकड़ा, data या functionality missing हो, तो क्या delink fail हो जाता है?

    • जवाब देना जटिल है
      मेरा analyzer कम-से-कम जिस हिस्से को export करना है, उसके लिए सटीक Ghidra database पर निर्भर करता है। जिन कई समस्याओं को ठीक करना होता है, उन्हें log करने की मैंने काफी कोशिश की है, लेकिन जो मौजूद ही नहीं है उसे देखा नहीं जा सकता
      खास तौर पर missing references और कटे हुए variables detect नहीं होते, और अजीब undefined behavior तक ले जा सकते हैं
      इनमें से कुछ समस्याओं को track करने के तरीके हैं। अब तक मिला सबसे अच्छा तरीका है executable को किसी अलग base address पर relink करना और original program की address range को map न होने देना। तब छूटे हुए absolute relocation points पर segmentation fault होगा और आप debug कर पाएँगे। हालांकि यह तभी संभव है जब target में MMU हो
      कटे हुए variables को track करना खास तौर पर बहुत मुश्किल है, अगर उन पर शक न हो। क्योंकि corrupt होने वाली चीज़ कटे हुए variable के बाद की memory होती है। integer को pointer समझ लेने के cases भी track करना कठिन है। integer value target symbol के रखे गए address के हिसाब से बदलती रहती है, जिससे program behavior अनियमित हो जाता है; खासकर उन programs में जो address space के बहुत निचले हिस्से में load होते हैं, समस्या बड़ी होती है
      फिर भी अगर Ghidra database पर्याप्त सटीक है, और उसी object file format में दोबारा export किया जाए जो मूल रूप से इस्तेमाल हुआ था, फिर उसी platform और उसी toolchain का उपयोग किया जाए, तो megabytes के program code और data को सफलतापूर्वक delink किया जा सकता है। मेरा मानना है कि अगर linker ने कोई काम किया है, तो उसे उलटना भी संभव होना चाहिए
      इसके उलट, अगर आप original program के platform और toolchain से मेल न खाने वाला cross-delink शुरू करते हैं—जैसे Linux i386 ELF executable से COFF object file में delink करके उसे i386 Windows toolchain में इस्तेमाल करना—तो कहानी अलग हो जाती है। अगर export relocations को express कर सके, तो आपको चलने वाली relocatable object file मिल भी सकती है, लेकिन ABI mismatch से भी लड़ना पड़ेगा। संभव है, पर पहले project के तौर पर recommend नहीं करूँगा
      संक्षेप में, आप क्या कर रहे हैं और Ghidra database कितना सटीक है, इसके आधार पर यह “बस चल जाता है” से लेकर “Cthulhu से दया की भीख माँगने” तक जा सकता है
    • आपके सवाल के आशय के हिसाब से, यह पूरी तरह safe नहीं है, और हो भी नहीं सकता
      उदाहरण के लिए int getSpecialArrayElement(char *array, uint64 key) { i = computeOffset(key); return array[i]; } जैसे function के बारे में सोचें
      computeOffset मनमाने तौर पर complex हो सकता है, और अगर obfuscation चाहिए तो इसे जानबूझकर analysis के लिए कठिन बनाया जा सकता है। इस function को memory में किसी भी arbitrary जगह access करने से रोकने वाली कोई चीज़ नहीं है
      जब तक आप हर संभव input try नहीं करते, यह नहीं जान सकते कि यह linker द्वारा पहले से memory में defined किसी symbol को access कर रहा है या नहीं, और computeOffset में ऐसी कोशिश को रोकने वाले Turing trap भी हो सकते हैं
  • इसे एक ऐसे idea से जोड़ना दिलचस्प होगा जिसे पहले सिर्फ़ सोचा था, सच में बनाया नहीं था: debug information से header files जनरेट करना, और ज़रूरत पड़ने पर LLM से उन्हें साफ़-सुथरा करवाना

    • असल में ऐसी कुछ कोशिशें हुई हैं। Microsoft Program Database के लिए यह मौजूद है
      https://github.com/wbenny/pdbex
      LLM से साफ़-सुथरा करवाने वाले हिस्से पर, अभी reverse engineering में LLM models लागू करके बड़ी सफलता के बहुत उदाहरण नहीं दिखते। शायद यह वह क्षेत्र भी हो सकता है जहाँ LLM architecture की सीमाएँ सामने आती हैं
      मैं विशेषज्ञ नहीं हूँ, लेकिन अगर दांव लगाना हो तो कई reverse engineering use cases में diffusion models ज़्यादा दिलचस्प लगेंगे
      बिल्कुल वही चीज़ नहीं है, लेकिन Binary Ninja में Sidekick नाम का feature है जो LLM के ज़रिए disassembly को व्यवस्थित करने की कोशिश करता है। निजी तौर पर मुझे यह बहुत प्रभावशाली नहीं लगा, लेकिन किसी के लिए उपयोगी हो सकता है
    • pahole ELF DWARF information से compile किए जा सकने वाले C header files बना देता है
      यहाँ LLM ज़्यादा relevant नहीं लगता। Header file executable से export हुए सभी types को उनके original values के साथ सही तरह से रखती है और usable होती है, या फिर वह ग़लत/अधूरी होती है। LLM से कुछ और गढ़वाने से मदद नहीं मिलेगी
      Ghidra में भी data structures export करने की built-in सुविधा है, और DWARF structures से generate किया जा सकता है। Right-click -> Export to C header
    • कुछ साल पहले मैंने DWARF information से C API के लिए type-aware fuzzer automatic generate और inject करने वाला tool बनाया था: https://github.com/intel/fffc
      Header generation और बाद में type constraints के हिसाब से modify किए जा सकने वाले mutators बनाना भी उसी का हिस्सा था
      LLM वाला हिस्सा जोड़ें तो anonymous structs जैसी चीज़ों को नाम देना शायद संभव लगे, लेकिन यह अच्छा idea है या नहीं, पता नहीं। ज़्यादा दिलचस्प कोशिश यह हो सकती है कि documentation के उद्देश्य से known type constraints को LLM शब्दों में समझाकर summarize करे
    • थोड़ा अलग विषय है, लेकिन मैंने exported object file के लिए Ghidra database की contents के आधार पर debugging symbols generate करके debugging experience बेहतर करने के बारे में भी सोचा था
      अभी तक इसे implement न करने की वजह यह है कि अब तक इसके बिना काम चल गया। ऊपर से यह काफ़ी गहरी rabbit hole लगती है, और जिस rabbit hole में अभी हूँ वह पहले ही काफ़ी बड़ी है
  • यह सच में काफ़ी शानदार लगता है, और पहले सोचे गए game modding idea से भी जुड़ा है। Tenchu decompilation blog series भी अच्छी थी

    • किसी दिन इस project पर वापस लौटना होगा। लगातार बहुत ज़्यादा version tracking sessions करने के बाद break लेना पड़ा, और इसी बीच delinking side quest लगातार बेकाबू होकर बड़ा होता जा रहा है
  • अभी जो काम कर रहा हूँ उसमें इसका तुरंत कोई use नहीं है, लेकिन पहले यह किया होता तो यह tool सच में बहुत उपयोगी होता
    उम्मीद है जल्द ही इसे आज़माने का समय या मौका मिलेगा