
गिड्रा के लिए बाइनरी कोड कवरेज विज़ुअलाइज़र प्लगइन
Dragon Dance Ghidra के लिए एक प्लगइन है जो बाइनरी कोड कवरेज डेटा को विज़ुअलाइज़ और मैनिपुलेट करने में सहायता करता है। कवरेज डेटा को कई कवरेज स्रोतों से आयात किया जा सकता है। फिलहाल प्लगइन Dynamorio और Intel Pin बाइनरी इंस्ट्रुमेंटेशन टूल्स को सपोर्ट करता है। Dynamorio का अपना कवरेज संग्रह मॉड्यूल है जिसे "drcov" कहा जाता है। Intel Pin में बिल्ट-इन कवरेज संग्रह मॉड्यूल नहीं है। मॉड्यूल की कमी से निपटने के लिए मुझे Intel Pin के लिए अपना स्वयं का कवरेज संग्रह मॉड्यूल लिखना पड़ा। इसलिए मैंने Intel Pin के लिए ddph (Dragon Dance Pin Helper) नाम का एक कवरेज संग्रह मॉड्यूल लिखा। तो आप इसका उपयोग कर सकते हैं। आप ddph का स्रोत इस लिंक से देख सकते हैं। यदि आप स्वयं संकलन करने में आलसी हैं, तो आप Windows, macOS और Linux के लिए मेरे द्वारा प्रदान की गई संकलित बाइनरी का उपयोग कर सकते हैं।

Dragon Dance एक ही सत्र में एकाधिक कवरेज डेटा को आयात और उपयोग कर सकता है। (साथ ही यह मल्टी-सेशन को सपोर्ट करता है लेकिन फिलहाल यह GUI द्वारा उपयोग योग्य नहीं है)। और आप उनके बीच स्विच कर सकते हैं या एक दूसरे के साथ इंटरसेक्शन, डिफरेंस, डिस्टिंक्ट या सम ऑपरेशन लागू कर सकते हैं।
Dragon Dance आपको निष्पादित निर्देशों की तीव्रता देखने की अनुमति देता है। ताकि आपको इस बात का संकेत मिल सके कि कौन से निर्देश कितनी बार निष्पादित हुए। साथ ही आप फंक्शन ग्राफ विंडो पर कवरेज विज़ुअलाइज़ेशन भी देख सकते हैं।

Dragon Dance अपनी स्वयं की स्क्रिप्टिंग प्रणाली का भी समर्थन करता है।

यह आपको कवरेज डेटा के साथ खेलने का लचीला तरीका प्रदान करता है। आप उन पर लोड, डिलीट, शो, इंटरसेक्ट, डिफ, डिस्टिंक्ट, सम ऑपरेशन कर सकते हैं। निम्नलिखित अनुभाग में स्क्रिप्टिंग सिस्टम और API शामिल होंगे। स्क्रिप्ट निष्पादित करने के लिए Alt + Enter कुंजियाँ दबाएँ।
बिल्ट-इन फ़ंक्शन आंतरिक कवरेज ऑपरेशनों के कार्यान्वयन हैं जो स्क्रिप्टिंग सिस्टम को एक इंटरफ़ेस प्रदान करते हैं। बिल्ट-इन फ़ंक्शन कवरेज ऑब्जेक्ट वेरिएबल या कुछ भी वापस कर सकता है। बिल्ट-इन के उपनाम हो सकते हैं।
वे पैरामीटर के रूप में बिल्ट-इन Arg स्वीकार करते हैं। पैरामीटर परिवर्तनीय लंबाई के हो सकते हैं।
बिल्ट-इन Arg विभिन्न प्रकार के मान को धारण करने के लिए एक संदर्भ है। बिल्ट-इन Args बाएँ से दाएँ क्रम में पास किए जाते हैं। बिल्ट-इन Arg निम्नलिखित मान प्रकार धारण कर सकता है:
वेरिएबल केवल कवरेज ऑब्जेक्ट को धारण करने के लिए जिम्मेदार होते हैं। उन्हें बिल्ट-इन फ़ंक्शन द्वारा लोड किया जा सकता है। उन्हें बिल्ट-इन फ़ंक्शन में पैरामीटर (बिल्ट-इन Arg) के रूप में पास किया जा सकता है।
कवरेज ऑब्जेक्ट दो प्रकार के होते हैं।
भौतिक कवरेज ऑब्जेक्ट और तार्किक कवरेज ऑब्जेक्ट
भौतिक कवरेज ऑब्जेक्ट एक कवरेज ऑब्जेक्ट को इंगित करता है जो सीधे कवरेज फ़ाइल से लोड किया जाता है। वे GUI पर कवरेज तालिका में दिखाई देते हैं। इसलिए आप GUI संचालन के माध्यम से उनके साथ इंटरैक्ट कर सकते हैं।
तार्किक कवरेज ऑब्जेक्ट एक कवरेज ऑब्जेक्ट को इंगित करता है जिसे किसी बिल्ट-इन फ़ंक्शन में संसाधित किया गया है और परिणामस्वरूप उससे वापस किया गया है। वे GUI पर दिखाई नहीं देते हैं लेकिन वे एक वेरिएबल में तब तक रह सकते हैं जब तक कि वे नष्ट न हो जाएँ।
कवरेज ऑब्जेक्ट दोनों प्रकार के कवरेज ऑब्जेक्ट के लिए स्वचालित रूप से वेरिएबल ऑब्जेक्ट द्वारा बनाए रखा जाता है। उदाहरण के लिए;``` cov1 = load("firstcoverage.out") cov2 = load("secondcov.out")
cov1 = diff(cov1,cov2)
इस उदाहरण में cov1 और cov2 चर हैं। और दोनों चरों में भौतिक कवरेज ऑब्जेक्ट है। diff बिल्ट-इन दोनों चरों को लेता है और रिटर्न वैल्यू को cov1 चर में सेट करता है। वह ओवरराइट संचालन परिणाम कवरेज ऑब्जेक्ट को चर में सेट करेगा लेकिन कवरेज ऑब्जेक्ट को हटाता नहीं है क्योंकि वह एक भौतिक कवरेज ऑब्जेक्ट है। वह कवरेज डेटा सत्र और GUI तालिका में बना रहेगा।
पिछले उदाहरण को इस प्रकार सोचें;```
cov1 = load("first.out")
cov2 = load("second.out")
cov3 = load("third.out")
rvar = sum(cov1,cov2,cov3)
rvar = diff(rvar, cov2)
इस उदाहरण में तीन भौतिक कवरेज चर योग संक्रिया में जाते हैं और योग संक्रिया तार्किक परिणाम कवरेज वस्तु लौटाती है। फिर अंतर संक्रिया एक तार्किक और एक भौतिक चर लेती है और rvar नामक चर को अधिलेखित करती है।
इस स्थिति में, परिणाम rvar पर सेट हो जाएगा और इसका पिछला कवरेज मान तुरंत नष्ट हो जाएगा। क्योंकि यह एक तार्किक वस्तु थी और वस्तु रिसाव को रोकने के लिए इसे हटा दिया जाना चाहिए। यदि आप किसी ऐसे चर को नष्ट करना चाहते हैं जिसमें कोई भौतिक कवरेज वस्तु है, तो आपको ऐसा करने के लिए discard अंतर्निहित को कॉल करना होगा। सभी अंतर्निहित विधियों का विवरण नीचे दिया जाएगा।
आप नेस्टेड अंतर्निहित कॉल का उपयोग करके जटिल स्क्रिप्ट लिख सकते हैं, आप कुछ इस प्रकार लिख सकते हैं:
cres = diff(intersect(a, load("another.log"), c, d), sum(e,f) )
आपको तर्क को पंक्ति दर पंक्ति लिखने की आवश्यकता नहीं है।
निम्नलिखित API दस्तावेज़ीकरण और उनके व्यवहार अंतिम संस्करण तक पहुँचने तक बदल सकते हैं।
clear()
| गुण | विवरण |
|---|---|
| वापसी मान | कोई नहीं |
| न्यूनतम पैरामीटर गणना | 0 |
| अधिकतम पैरामीटर गणना | 0 |
cwd( स्ट्रिंग : कार्यशीलनिर्देशिका )
| गुण | विवरण |
|---|
diff( चर : var1, var2, ..... varN )
| गुण | विवरण |
|---|---|
| वापसी मान | चर |
| न्यूनतम पैरामीटर गणना | 2 |
| अधिकतम पैरामीटर गणना | असीमित |
discard( चर : var1, var2, ..... varN )
| गुण | विवरण |
|---|---|
| वापसी मान | कोई नहीं |
| न्यूनतम पैरामीटर गणना | 1 |
distinct( चर : var1, var2, ..... varN )
| गुण | विवरण |
|---|---|
| वापसी मान | चर |
| न्यूनतम पैरामीटर गणना | 2 |
| अधिकतम पैरामीटर गणना | असीमित |
goto( पूर्णांक : ऑफ़सेट )
| गुण | विवरण |
|---|---|
| वापसी मान | कोई नहीं |
| न्यूनतम पैरामीटर गणना | 1 |
| अधिकतम पैरामीटर गणना |
import( स्ट्रिंग : फ़ाइलपथया कवरेजनाम )
intersect( चर : var1, var2, ..... varN )
| गुण | विवरण |
|---|---|
| वापसी मान | चर |
| न्यूनतम पैरामीटर गणना | 2 |
| अधिकतम पैरामीटर गणना | असीमित |
show( चर : var )
| गुण | विवरण |
|---|---|
| वापसी मान | कोई नहीं |
| न्यूनतम पैरामीटर गणना | 1 |
sum( चर : var1, var2, ..... varN )
| गुण | विवरण |
|---|---|
| वापसी मान | चर |
| न्यूनतम पैरामीटर गणना | 1 |
| अधिकतम पैरामीटर गणना | असीमित |
सुधार
ड्रैगन डांस कवरेज डेटा फ़ाइल आयात करते समय घिड्रा में गलत विश्लेषण की स्थिति को ठीक करने का प्रयास कर सकता है। कुछ बाइनरी पर, कंपाइलर द्वारा अप्रत्याशित कोड जनरेशन के कारण घिड्रा किसी फ़ंक्शन के निर्देशों को डीकंपाइल नहीं करता है। ड्रैगन डांस लोड की गई छवि और कवरेज डेटा अखंडता की जाँच करता है। यदि वे एक-दूसरे के लिए मान्य हैं और पता एक निष्पादन योग्य अनुभाग से संबंधित है लेकिन निर्देश डीकंपाइलेशन की कमी है, तो प्लगइन ठीक करने के लिए कहता है। फिर यह कच्चे अनुभाग को डीकंपाइल करके ठीक करने का प्रयास करता है।

प्लगइन के भविष्य के संस्करणों में, इसमें छवि के लिए अधिक सुधार या वर्कअराउंड शामिल हो सकते हैं।
स्थापना काफी आसान है।
Ghidra प्रारंभ करें।
"File" मेनू पर क्लिक करें और फिर "Install Extensions.." चुनें।
विंडो के ऊपरी-दाएँ से हरा प्लस आइकन क्लिक करें
प्लगइन ज़िप पैकेज चुनें और Ok चुनें।
सूची से dragondance चुनें
Ok क्लिक करें और ghidra को पुनरारंभ करें
प्लगइन स्थापना के बाद पहली बार किसी बाइनरी को Ghidra में लोड करने के दौरान, Ghidra को आपसे पूछना चाहिए कि क्या आप नव स्थापित प्लगइन को कॉन्फ़िगर करना चाहते हैं।
यदि आप हाँ बटन क्लिक करते हैं, तो DragonDance प्लगइन तुरंत दिखाई देना चाहिए।
यदि आप नहीं बटन क्लिक करते हैं तो आपको इसे स्वयं मैन्युअल रूप से सक्रिय करना होगा।
मैन्युअल रूप से सक्रिय करने के लिए,
"File" मेनू पर क्लिक करें और फिर Disassembly विंडो (CodeBrowser) से Configure चुनें
Configure Tool विंडो के ऊपरी दाएँ कोने से छोटे प्लग आइकन पर क्लिक करें
प्लगइन सूची में DragonDance आइटम ढूँढें और इसका चेकबॉक्स सक्षम करें फिर Ok क्लिक करें
Dragon Dance विंडो दिखाई देनी चाहिए।
सक्रियण के बाद आपको Window मेनू में Dragon Dance आइटम देखने में सक्षम होना चाहिए।
जैसा कि मैंने पहले वर्णित किया है, Dragon Dance Dynamorio और Intel Pin से कवरेज डेटा आयात कर सकता है। (अभी के लिए)। वास्तव में ये सामान्य बाइनरी इंस्ट्रुमेंटेशन उपकरण हैं। कवरेज डेटा एकत्र करने के लिए आपको उनके साथ उपयुक्त मॉड्यूल का उपयोग करना होगा। Dynamorio का अपना कवरेज मॉड्यूल है जिसे drcov कहा जाता है। आप कवरेज एकत्र करने के लिए उस अंतर्निहित मॉड्यूल का उपयोग कर सकते हैं।
Dynamorio का उपयोग करना
आप निम्न कमांड का उपयोग करके Dynamorio से कवरेज डेटा एकत्र कर सकते हैं:
drrun -t drcov -logdir [COVERAGE_OUTPUT_DIRECTORY_PATH] -- [EXECUTABLE_PATH_TO_EXAMINE] [EXECUTABLE_ARGUMENTS]
आउटपुट दी गई निर्देशिका में drcov.[EXECUTABLE_NAME].[ID].proc.log प्रारूप में रखा जाएगा।
Intel Pin का उपयोग करना
जैसा कि मैंने पहले उल्लेख किया है, Intel Pin कोई अंतर्निहित कवरेज कलेक्टर मॉड्यूल प्रदान नहीं करता है। आपको एक कस्टम पिन मॉड्यूल का उपयोग करना होगा। सौभाग्य से मैंने Pin से कवरेज एकत्र करने के लिए अपना स्वयं का तैयार किया है। इसलिए यह हमें कुछ लाभ देता है। जरूरत पड़ने पर मैं इसे बढ़ा सकता हूं या इसमें अतिरिक्त सुविधाएं, विकल्प जोड़ सकता हूं।
जबकि बाद के संस्करण काम कर सकते हैं, केवल Intel PIN 3.7 समर्थित है। ये तुरंत Intel PIN पृष्ठ पर पेश नहीं किए जाते हैं, इसलिए यहां प्रत्यक्ष डाउनलोड लिंक हैं:
आप ddph के स्रोत तक यहाँ पहुँच सकते हैं। मैं Windows, macOS और Linux के लिए बाइनरी साझा करूँगा। या आप इसके बिल्ड शेल स्क्रिप्ट का उपयोग करके अपना स्वयं का बाइनरी बना सकते हैं।
Intel Pin से कवरेज डेटा एकत्र करने के लिए निम्न कमांड का उपयोग करें:
pin -t ddph.[so,dylib,dll] [ddph options] -- [EXECUTABLE_PATH_TO_EXAMINE] [EXECUTABLE_ARGUMENTS]
ddph में संग्रह के लिए कुछ विकल्प हैं।
-o: इस विकल्प के साथ आप कवरेज आउटपुट फ़ाइलनाम निर्दिष्ट कर सकते हैं। (डिफ़ॉल्ट: ddph.out)
-l: आप ऑपरेशन लॉग फ़ाइलनाम निर्दिष्ट कर सकते हैं। यदि आप इस विकल्प पर "no" पास करते हैं, तो ddph लॉगिंग ऑपरेशन नहीं करेगा। (डिफ़ॉल्ट: ddph.log)
-p: कैप्चर विवरण स्तर। यह विकल्प reduced या high हो सकता है। high स्तर पूरे निर्देशों को एक-एक करके कैप्चर करता है और पूर्व-प्रसंस्करण निष्पादन ब्लॉक बनाता है। यह आपको अधिक गहन कवरेज आउटपुट देगा लेकिन यह कम गति वाला होता है। reduced स्तर pin के ट्रेस ब्लॉक का उपयोग करता है इसलिए यह high स्तर की तुलना में बहुत तेज़ है। लेकिन इससे कवरेज आउटपुट के विभिन्न स्तरों पर बड़ा अंतर नहीं होगा। यदि आप विशिष्ट चीजें नहीं करना चाहते हैं, तो reduced स्तर का उपयोग करने पर विचार करें। (डिफ़ॉल्ट: reduced)
macOS उपयोगकर्ताओं के लिए: macOS 10.11 (OS X El Capitan) से शुरू करते हुए, OS एक सुरक्षा परत के साथ आता है जिसे सिस्टम इंटीग्रिटी प्रोटेक्शन SIP कहा जाता है। यह उपयोगकर्ता मोड प्रक्रियाओं को रोकता है जो किसी अन्य प्रक्रिया में इंजेक्शन या संशोधन करने का प्रयास करती हैं, भले ही आप रूट विशेषाधिकारों के तहत चल रहे हों।
इस रोकथाम को दूर करने के लिए, आपको इसे अक्षम करना होगा। ऐसा करने के लिए नीचे दिए गए चरणों का पालन करें।
macOS को पुनरारंभ करें
बूट प्रक्रिया के दौरान, Command + R कुंजियाँ दबाए रखें।
OS अंततः रिकवरी मोड में प्रवेश करता है
Utilities अनुभाग से एक टर्मिनल खोलें
csrutil status टाइप करें और एंटर दबाएँ। आपको देखना चाहिए कि SIP सक्षम है।
csrutil disable टाइप करें और एंटर दबाएँ।
यह सुनिश्चित करने के लिए फिर से csrutil status टाइप करें कि यह अक्षम है या नहीं। फिर OS को पुनरारंभ करें और इसे सामान्य रूप से बूट होने दें। अब आप बाइनरी इंस्ट्रुमेंटेशन टूल का उपयोग करने के लिए तैयार हैं।



पहले, ghidra (नवीनतम संस्करण, वर्तमान में 9.1.2) और dragondance डाउनलोड करें``` $ wget https://ghidra-sre.org/ghidra_9.1.2_PUBLIC_20200212.zip $ wget https://github.com/0ffffffffh/dragondance/archive/master.zip $ unzip ghidra_9.1.2_PUBLIC_20200212.zip $ unzip master.zip
फिर gradle और jdk स्थापित करें```
$ sudo apt install openjdk-11-jdk
$ wget https://services.gradle.org/distributions/gradle-5.2.1-bin.zip
$ sudo unzip -d /opt/gradle gradle-5.2.1-bin.zip
नई प्रोफ़ाइल फ़ाइल बनाएं``` $ sudo vi /etc/profile.d/gradle.sh
और प्रत्येक बाद के लॉगिन में PATH में gradle जोड़ने के लिए निम्नलिखित जोड़ें।```
export GRADLE_HOME=/opt/gradle/gradle-5.2.1
export PATH=${GRADLE_HOME}/bin:${PATH}
इसे तुरंत करने के लिए, बिना लॉगआउट किए``` $ source /etc/profile.d/gradle.sh
अब हम dragondance बनाने के लिए आगे बढ़ सकते हैं```
$ cd dragondance-master/
$ gradle -PGHIDRA_INSTALL_DIR=/home/ubuntu/ghidra_9.1.2_PUBLIC
> Task :buildExtension
Created ghidra_9.1.2_PUBLIC_20200506_dragondance-master.zip in /home/ubuntu/dragondance-master/dist
BUILD SUCCESSFUL in 29s
5 actionable tasks: 5 executed
ubuntu@ubuntu:~/dragondance-master$
जहाँ आपको Ghidra को डाउनलोड करने के पथ को समायोजित करना पड़ सकता है। अब आप निर्मित एक्सटेंशन dragondance-master/dist में पा सकते हैं।
कमांड प्रॉम्प्ट शैली में पंक्ति दर पंक्ति स्क्रिप्ट निष्पादन।
संदर्भ परिवर्तन जागरूकता
फंक्शन (रूटीन) आधारित कवरेज विज़ुअलाइज़ेशन
निष्पादन प्रवाह जागरूकता
स्क्रिप्टिंग में और अधिक बिल्ट-इन
सत्र में नवीनतम परिवर्तनों को सहेजने और तेज़ी से लोड करने के लिए अपना स्वयं का कवरेज डेटाबेस प्रारूप।
स्यूडो कोड पेंटिंग। (Ghidra इसके लिए कोई API प्रदान नहीं करता है। इसलिए मुझे इसे प्राप्त करने का कोई तरीका या कामकाज खोजने के लिए Ghidra के स्रोत कोड का अध्ययन करना होगा।)
UI संवर्द्धन
Oğuz Kartal (@0ffffffffh)
| विवरण |
| यह अंतर्निहित दृश्यमान कवरेज को साफ करता है और सक्रिय कवरेज को शून्य पर सेट करता है। |
| उपनाम | कोई नहीं |
| वापसी मान | कोई नहीं |
| न्यूनतम पैरामीटर गणना | 1 |
| अधिकतम पैरामीटर गणना | 1 |
| विवरण | दिए गए पथ के साथ वर्तमान कार्यशील निर्देशिका सेट करता है। cwd के बाद बिना निरपेक्ष पथ वाले सभी आयात कॉल सक्रिय कार्यशील निर्देशिका में कवरेज फ़ाइलों की खोज करेंगे। |
| उपनाम | कोई नहीं |
| विवरण |
| दिए गए परिवर्तनीय लंबाई के चरों पर अंतर संक्रिया लागू करता है और परिणामी कवरेज चर लौटाता है। |
| उपनाम | कोई नहीं |
| अधिकतम पैरामीटर गणना |
| असीमित |
| विवरण | चरों को नष्ट करता है चाहे वे भौतिक हों या तार्किक। यह पहले कवरेज वस्तु को नष्ट करेगा और फिर चर नाम को चर सूची से हटा देगा। इस कॉल के बाद दिए गए सभी चर अपरिभाषित हो जाते हैं। |
| उपनाम | del |
| विवरण |
| दिए गए परिवर्तनीय लंबाई के चरों पर distinct (xor) संक्रिया लागू करता है और परिणामी कवरेज चर लौटाता है। |
| उपनाम | xor |
| 1 |
| विवरण | दिए गए ऑफ़सेट द्वारा वर्तमान पता चयन का पता लगाता है। वास्तविक पता मान की गणना छवि आधार मान में ऑफ़सेट मान जोड़कर की जाती है। |
| उपनाम | कोई नहीं |
| गुण | विवरण |
|---|
| वापसी मान | चर |
| न्यूनतम पैरामीटर गणना | 1 |
| अधिकतम पैरामीटर गणना | 1 |
| विवरण | भौतिक कवरेज फ़ाइल से कवरेज डेटा आयात करता है। सापेक्ष या निरपेक्ष पथ लेता है। या पहले भौतिक रूप से लोड किया गया कवरेज नाम। यदि दिया गया पथ निरपेक्ष है, तो आयात सीधे उस पथ से लोड होता है। अन्यथा यह लोड करने के लिए वर्तमान कार्यशील निर्देशिका के अंतर्गत देखता है। दोनों ही मामलों में, आयात जाँच करेगा कि कवरेज डेटा पहले से लोड है या नहीं, इसके पथ का उपयोग करके। यदि पहले से लोड है, तो यह कैश्ड कवरेज चर लौटाता है। या यदि दिया गया मान किसी भौतिक कवरेज का नाम है, तो यह अपने सत्र से कवरेज मैप देखता है और यदि मौजूद है तो कवरेज वस्तु लौटाता है। |
| उपनाम | get, load |
| विवरण |
| दिए गए परिवर्तनीय लंबाई के चरों पर प्रतिच्छेदन संक्रिया लागू करता है और परिणामी कवरेज चर लौटाता है। |
| उपनाम | and |
| अधिकतम पैरामीटर गणना | 1 |
| विवरण | दिए गए कवरेज चर को दृश्यमान करता है। यदि कोई सक्रिय रूप से दृश्यमान कवरेज वस्तु है और वह तार्किक है, तो फ़ंक्शन पिछली कवरेज वस्तु को तुरंत नष्ट कर देता है और दी गई वस्तु दिखाता है। |
| उपनाम | कोई नहीं |
| विवरण |
| दिए गए परिवर्तनीय लंबाई के चरों पर योग संक्रिया लागू करता है और परिणामी कवरेज चर लौटाता है। |
| उपनाम | or, union |