
إضافة تصور تغطية الكود الثنائي لـ Ghidra
Dragon Dance هو إضافة لـ Ghidra تتيح تصور ومعالجة بيانات تغطية الشفرة الثنائية. يمكن استيراد بيانات التغطية من مصادر تغطية متعددة. حاليًا، تدعم الإضافة أدوات Dynamorio و Intel Pin لتنصيب الشفرة الثنائية. Dynamorio لديه وحدة جمع تغطية خاصة به تسمى "drcov". لا توفر Intel Pin وحدة جمع تغطية مدمجة. للتعامل مع غياب الوحدة، كان علي كتابة وحدة جمع تغطية خاصة بي لـ Intel Pin. لذا كتبت وحدة جمع تغطية لـ Intel Pin باسم ddph (مساعد Dragon Dance Pin). يمكنك استخدامها. يمكنك الاطلاع على مصدر ddph من هذا الرابط. إذا كنت لا ترغب في التجميع بنفسك، يمكنك استخدام الملفات الثنائية المجمعة التي قدمتها لأنظمة Windows و macOS و Linux.

يمكن لـ Dragon Dance استيراد واستخدام بيانات تغطية متعددة في نفس الجلسة. (كما أنها تدعم الجلسات المتعددة ولكن حاليًا غير قابلة للاستخدام من خلال الواجهة الرسومية). ويمكنك التبديل بينها أو تطبيق عمليات التقاطع والاختلاف والتمييز والجمع مع بعضها البعض بسرعة.
يتيح لك Dragon Dance عرض كثافة التعليمات المنفذة. وبالتالي يمكنك الحصول على فكرة عن التعليمات التي يتم تنفيذها بشكل متكرر. كما يمكنك عرض تصور التغطية على نافذة رسم الدالة.

يدعم Dragon Dance أيضًا نظام البرمجة النصية الخاص به.

يتيح لك طريقة مرنة للتعامل مع بيانات التغطية. يمكنك تحميلها، حذفها، عرضها، إجراء عمليات التقاطع، الاختلاف، التمييز، الجمع عليها. سيحتوي القسم التالي على نظام البرمجة النصية وواجهة API. اضغط على مفاتيح Alt + Enter لتنفيذ البرنامج النصي.
الدوال المضمنة هي تنفيذ لعمليات التغطية الداخلية لتوفير واجهة لنظام البرمجة النصية. يمكن لدالة مضمنة إرجاع متغير كائن تغطية أو لا شيء. قد تحتوي الدوال المضمنة على أسماء مستعارة. تقبل وسيطًا مضمنًا كمعامل. يمكن أن تكون المعاملات ذات طول متغير.
الوسيط المضمن هو مرجع يحمل أنواعًا مختلفة من القيم. يتم تمرير الوسائط المضمنة من اليسار إلى اليمين. يمكن للوسيط المضمن حمل أنواع القيم التالية:
المتغيرات مسؤولة عن حمل كائن التغطية فقط. يمكن تحميلها بواسطة الدوال المضمنة. يمكن تمريرها كمعامل (وسيط مضمن) إلى الدوال المضمنة.
هناك نوعان من كائن التغطية. كائن تغطية فيزيائي و كائن تغطية منطقي
كائن التغطية الفيزيائي يشير إلى كائن تغطية تم تحميله مباشرة من ملف التغطية. وهي مرئية في جدول التغطية الموجود في الواجهة الرسومية. وبالتالي يمكنك التفاعل معها عبر عمليات الواجهة الرسومية.
كائن التغطية المنطقي يشير إلى كائن تغطية تمت معالجته في دالة مضمنة وإرجاعه كنتيجة. ليست مرئية في الواجهة الرسومية لكن يمكن أن تعيش في متغير حتى يتم تدميرها.
يتم الحفاظ على كائن التغطية بواسطة كائن المتغير تلقائيًا لكلا نوعي كائن التغطية. على سبيل المثال؛``` cov1 = load("firstcoverage.out") cov2 = load("secondcov.out")
cov1 = diff(cov1,cov2)
في هذا المثال، cov1 و cov2 متغيران. وكلا المتغيرين لهما physical coverage object. الدالة المدمجة diff تأخذ كلا المتغيرين وتضع القيمة المرتجعة في المتغير cov1. عملية الكتابة هذه ستضع result coverage object في المتغير، لكنها لا تحذف coverage object لأنه physical coverage object. ستظل بيانات التغطية هذه موجودة في الجلسة وأيضًا في GUI table.
دعنا نفكر في المثال السابق بهذه الطريقة؛```
cov1 = load("first.out")
cov2 = load("second.out")
cov3 = load("third.out")
rvar = sum(cov1,cov2,cov3)
rvar = diff(rvar, cov2)
في هذا المثال، ثلاثة متغيرات تغطية فيزيائية تدخل في عملية sum، وترجع عملية sum كائن نتيجة تغطية منطقية. ثم تأخذ عملية diff متغيرًا منطقيًا وآخر فيزيائيًا وتستبدل المتغير المسمى rvar.
في هذه الحالة، سيتم تعيين النتيجة إلى rvar وسيتم تدمير قيمة التغطية السابقة على الفور. لأن هذا كان كائنًا منطقيًا ويجب حذفه لمنع تسرب الكائن. إذا كنت تريد تدمير متغير يحتوي على كائن تغطية فيزيائي، عليك استدعاء الدالة المضمنة discard للقيام بذلك. سيتم تفصيل جميع الدوال المضمنة أدناه.
يمكنك كتابة سكريبتات معقدة باستخدام استدعاءات متداخلة للدوال المضمنة، يمكنك كتابة شيء مثل:
cres = diff(intersect(a, load("another.log"), c, d), sum(e,f) )
ليس عليك كتابة المنطق سطرًا بسطر.
قد تتغير وثائق API التالية وسلوكياتها حتى الوصول إلى الإصدار النهائي.
clear()
| الخاصية | الوصف |
|---|---|
| قيمة الإرجاع | لا شيء |
| الحد الأدنى لعدد المعاملات | 0 |
| الحد الأقصى لعدد المعاملات |
cwd( String : workingDirectory )
| الخاصية |
|---|
diff( Variable : var1, var2, ..... varN )
| الخاصية | الوصف |
|---|---|
| قيمة الإرجاع | متغير |
| الحد الأدنى لعدد المعاملات | 2 |
| الحد الأقصى لعدد المعاملات | غير محدود |
discard( Variable : var1, var2, ..... varN )
| الخاصية | الوصف |
|---|---|
| قيمة الإرجاع | لا شيء |
| الحد الأدنى لعدد المعاملات |
distinct( Variable : var1, var2, ..... varN )
| الخاصية | الوصف |
|---|---|
| قيمة الإرجاع | متغير |
| الحد الأدنى لعدد المعاملات | 2 |
| الحد الأقصى لعدد المعاملات |
goto( Integer : offset )
| الخاصية | الوصف |
|---|---|
| قيمة الإرجاع | لا شيء |
| الحد الأدنى لعدد المعاملات | 1 |
import( String : filePathOrCoverageName )
intersect( Variable : var1, var2, ..... varN )
| الخاصية | الوصف |
|---|---|
| قيمة الإرجاع | متغير |
| الحد الأدنى لعدد المعاملات | 2 |
| الحد الأقصى لعدد المعاملات |
show( Variable : var )
| الخاصية | الوصف |
|---|---|
| قيمة الإرجاع | لا شيء |
| الحد الأدنى لعدد المعاملات | 1 |
sum( Variable : var1, var2, ..... varN )
| الخاصية | الوصف |
|---|---|
| قيمة الإرجاع | متغير |
| الحد الأدنى لعدد المعاملات | 1 |
| الحد الأقصى لعدد المعاملات |
الإصلاحات
يمكن لـ Dragon Dance محاولة إصلاح موقف تم تحليله بشكل خاطئ في Ghidra أثناء استيراد ملف بيانات التغطية. في بعض الملفات الثنائية، لا يقوم Ghidra بفك ترجمة تعليمات دالة بسبب توليد كود غير متوقع من قبل المترجم. يتحقق Dragon Dance من سلامة الصورة المحملة وبيانات التغطية. إذا كانت صالحة لبعضها البعض وكان العنوان ينتمي إلى قسم قابل للتنفيذ ولكن هناك نقص في فك ترجمة التعليمات، يطلب البرنامج المساعد الإصلاح. ثم يحاول الإصلاح عن طريق فك ترجمة القسم الخام.

في الإصدارات المستقبلية من البرنامج المساعد، قد يحتوي على المزيد من الإصلاحات أو الحلول البديلة للصورة.
التثبيت سهل للغاية.
قم بتشغيل Ghidra.
انقر على قائمة "File" ثم اختر "Install Extensions.."
انقر على أيقونة علامة الجمع الخضراء من أعلى يمين النافذة
اختر حزمة البرنامج المساعد بصيغة zip واختر Ok.
اختر dragondance من القائمة
انقر على Ok وأعد تشغيل Ghidra
أثناء التحميل الأول لملف ثنائي إلى Ghidra بعد تثبيت البرنامج المساعد، يجب أن يسألك Ghidra عما إذا كنت تريد تكوين البرنامج المساعد المثبت حديثًا أم لا.
إذا نقرت على زر Yes، يجب أن يظهر البرنامج المساعد DragonDance على الفور.
إذا نقرت على زر No، عليك تفعيله يدويًا بنفسك.
لتفعيله يدويًا،
انقر على قائمة "File" ثم اختر Configure من نافذة التفكيك (CodeBrowser)
انقر على أيقونة القابس الصغيرة من أعلى يمين نافذة Configure Tool.
ابحث عن عنصر DragonDance من قائمة البرامج المساعدة وقم بتمكين خانة الاختيار الخاصة به ثم انقر على Ok
يجب أن تظهر نافذة Dragon Dance.
بعد التفعيل، يجب أن تكون قادرًا على رؤية عنصر Dragon Dance في قائمة Window.
كما وصفت سابقًا، يمكن لـ 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 مخصصة. لحسن الحظ، قمت بصنع وحدتي الخاصة لجمع التغطية من 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. يلتقط المستوى العالي التعليمات بأكملها واحدة تلو الأخرى ويبني كتل تنفيذ ما قبل المعالجة. سيعطيك هذا مخرجات تغطية أكثر كثافة ولكنه أبطأ من المستوى المخفّض. يستخدم المستوى المخفّض كتل التتبع الخاصة بـ pin، لذا فهو أسرع بكثير من المستوى العالي. لكن هذا لن يسبب اختلافات كبيرة على مستوى مختلف من مخرجات التغطية. إذا كنت لا ترغب في القيام بأشياء محددة، فكر في استخدام المستوى المخفّض. (الافتراضي: reduced)
لمستخدمي macOS: بدءًا من macOS 10.11 (OS X El Capitan)، يأتي نظام التشغيل مع طبقة أمان تُسمى System Integrity Protection SIP. وهذا يمنع عمليات وضع المستخدم التي تحاول القيام بالحقن أو التعديل على عملية أخرى حتى إذا كنت تعمل بصلاحيات الجذر.
لتجاوز هذا المنع، يجب عليك تعطيله. للقيام بذلك، اتبع الخطوات التالية.
أعد تشغيل macOS
أثناء عملية الإقلاع، اضغط مع الاستمرار على مفتاحي Command + R.
سينتقل نظام التشغيل في النهاية إلى وضع الاسترداد
افتح الطرفية من قسم الأدوات المساعدة
اكتب csrutil status ثم اضغط على Enter. يجب أن ترى أن SIP مفعل.
اكتب csrutil disable واضغط على Enter.
اكتب csrutil status مرة أخرى للتأكد من تعطيله أم لا. ثم أعد تشغيل نظام التشغيل ودعه يقلع بشكل طبيعي. الآن أنت جاهز لاستخدام أدوات التنقيط الثنائية.



أولاً، قم بتنزيل 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
وأضف ما يلي لإضافة gradle إلى PATH في كل تسجيل دخول لاحق.```
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
Oğuz Kartal (@0ffffffffh)
| 0 |
| الوصف | تقوم هذه الدالة المضمنة بمسح التغطية التي يتم عرضها وتضبط التغطية النشطة على قيمة فارغة. |
| الأسماء المستعارة | لا شيء |
| الوصف |
|---|
| قيمة الإرجاع | لا شيء |
| الحد الأدنى لعدد المعاملات | 1 |
| الحد الأقصى لعدد المعاملات | 1 |
| الوصف | يضبط دليل العمل الحالي بالمسار المعطى. جميع استدعاءات الاستيراد بدون مسار مطلق بعد cwd سيتم البحث عن ملفات التغطية في دليل العمل النشط. |
| الأسماء المستعارة | لا شيء |
| الوصف | يطبق عملية الفرق على متغيرات ذات طول متغير. ويعيد متغير نتيجة التغطية. |
| الأسماء المستعارة | لا شيء |
| 1 |
| الحد الأقصى لعدد المعاملات | غير محدود |
| الوصف | يدمر المتغيرات سواء كانت فيزيائية أو منطقية. سيقوم أولاً بتدمير كائن التغطية ثم يلغي تسجيل اسم المتغير من قائمة المتغيرات. بعد هذا الاستدعاء، تصبح جميع المتغيرات المعطاة غير معرفة. |
| الأسماء المستعارة | del |
| غير محدود |
| الوصف | يطبق عملية التمايز (xor) على متغيرات ذات طول متغير. ويعيد متغير نتيجة التغطية. |
| الأسماء المستعارة | xor |
| الحد الأقصى لعدد المعاملات |
| 1 |
| الوصف | يحدد موقع اختيار العنوان الحالي بواسطة الإزاحة المعطاة. يتم حساب قيمة العنوان الحقيقي عن طريق إضافة قيمة الإزاحة إلى قيمة قاعدة الصورة. |
| الأسماء المستعارة | لا شيء |
| الخاصية | الوصف |
|---|
| قيمة الإرجاع | متغير |
| الحد الأدنى لعدد المعاملات | 1 |
| الحد الأقصى لعدد المعاملات | 1 |
| الوصف | يستورد بيانات التغطية من ملف التغطية الفيزيائي. يأخذ مسارًا نسبيًا أو مطلقًا. أو اسم تغطية تم تحميله فيزيائيًا سابقًا. إذا كان المسار المعطى مسارًا مطلقًا، يقوم الاستيراد بالتحميل مباشرة من المسار. وإلا فإنه يبحث في دليل العمل الحالي للتحميل. في كلتا الحالتين، سيتحقق الاستيراد مما إذا كانت بيانات التغطية قد تم تحميلها بالفعل باستخدام مسارها. إذا تم تحميلها بالفعل، فإنه يعيد متغير التغطية المخبأ. أو إذا كانت القيمة المعطاة اسم تغطية فيزيائية، فإنه يبحث في خريطة التغطية من جلسته ويعيد كائن التغطية إذا كان موجودًا. |
| الأسماء المستعارة | get, load |
| غير محدود |
| الوصف | يطبق عملية التقاطع على المتغيرات ذات الطول المتغير. ويعيد متغير نتيجة التغطية. |
| الأسماء المستعارة | and |
| الحد الأقصى لعدد المعاملات | 1 |
| الوصف | يعرض متغير التغطية المعطى. إذا كان هناك كائن تغطية يتم عرضه بشكل نشط وهو كائن منطقي، تقوم الدالة بتدمير كائن التغطية السابق فورًا وتظهر الكائن المعطى. |
| الأسماء المستعارة | لا شيء |
| غير محدود |
| الوصف | يطبق عملية الجمع على المتغيرات ذات الطول المتغير. ويعيد متغير نتيجة التغطية. |
| الأسماء المستعارة | or, union |