
أداة لاستخراج معلومات RTTI من الملفات التنفيذية لدلفي، مكتوبة بلغة Python خالصة
تقوم هذه الأداة بفحص ملف تنفيذي بحثاً عن بيانات Delphi، بما في ذلك RTTI وجداول الدوال الافتراضية. وهي تُخرج ملف JSON يحتوي على معلومات حول الفئات والدوال المحددة، والتي يمكن استخدامها لتحليل إضافي، على سبيل المثال:
يتم توفير سكربت IDAPython يمكنه تحميل المخرجات إلى IDA.
كُتب هذا السكربت ليكمّل أدوات أخرى للهندسة العكسية لـ Delphi.
صدر كمصدر مفتوح بواسطة NCC Group Plc - http://www.nccgroup.com/
طُوّر بواسطة David Cannings (@edeca) [email protected]
http://www.github.com/nccgroup/pythia
يُطرح هذا المشروع بموجب رخصة AGPL. يرجى الاطلاع على LICENSE لمزيد من المعلومات.
التدفق العام هو:
جداول vftables الخاصة بـ Delphi موثقة جيداً. المعلومات الخاصة بأحدث إصدار متاحة من Embarcadero. تتوفر وثائق غير رسمية لـ Delphi 2005 (انظر هنا).
شفرة مصدر Free Pascal مفيدة أيضاً (مرآة Github).
العنصر الأول في vftable هو vmtSelfPtr، الذي يشير إلى بداية جدول الدوال الافتراضية. يفحص السكربت كل مقطع كود في ملف PE بحثاً عن أي موقع يشير إلى الأمام بمقدار +0x4C بايت. لاحظ أن مترجم Delphi يحاذي vftables إلى حدود 4 بايت (من أجل التحسين).
على سبيل المثال، يحتوي العنوان الافتراضي VA التالي 0x0046E1C8 على الإزاحة 0x0046E214، والتي تسبق الموقع الحالي بمقدار 0x4C. كما هو موضح في IDA:
.text:0046E1C8 ; Classes::TComponent *vftable_TDCP_misty1
.text:0046E1C8 14 E2 46 00 vftable_TDCP_misty1 dd offset off_46E214
يمكن أن ينتج عن هذا الأسلوب نتائج إيجابية خاطئة، لذلك يتم فحص الحقول الأخرى في vftable للتأكد من كونها قيماً معقولة. على سبيل المثال، يتم فحص vmtInstanceSize للتأكد من أنه ليس مفرطاً، ويتم التحقق من أن مؤشرات الدوال تقع في مقطع قابل للتنفيذ. أثناء الاختبار، كان معدل النتائج الإيجابية الخاطئة منخفضاً جداً، على الرغم من أسلوب البحث بالقوة الغاشمة.
يتم فحص كل دالة موجودة في vftable لمعرفة ما إذا كانت موروثة من الفئة الأم أو مُحمّلة بشكل زائد (overloaded). لا يدعم Delphi الوراثة المتعددة، لذلك يمكن تحقيق ذلك عن طريق فحص المؤشر في vftable الخاص بالأم مع نفس الإزاحة.
إذا كان كلا المؤشرين يشير إلى نفس الدالة، فهي موروثة. وإذا كان للفئة الفرعية مؤشر مختلف، فهي دالة مُحمّلة بشكل زائد.
المخرج الأساسي للأداة هو ملف JSON يمكن إدخاله في معالجات / أدوات لاحقة. ومع ذلك، يتم تضمين عدد قليل من تنسيقات المخرجات الأخرى.
استخدم الخيار --save-tree لإنشاء ملف مثل:
TObject (at 0x0040112c)
|-- Exception (at 0x004081f8)
| |-- EAbort (at 0x00408260)
| |-- EAbstractError (at 0x00408ad4)
| |-- EAssertionFailed (at 0x00408a74)
| |-- EBcdException (at 0x004bd110)
| | +-- EBcdOverflowException (at 0x004bd16c)
| |-- EBitsError (at 0x0041ab04)
| |-- EComponentError (at 0x0041abbc)
| |-- EConvertError (at 0x00408850)
| |-- EDCP_cipher (at 0x0046a0ac)
| | +-- EDCP_blockcipher (at 0x0046a29c)
| |-- EDCP_hash (at 0x00469f20)
.. إلخ ..
PACKAGEINFO أو DVCLAL) وضبط الفحص لتخطيطات vftable المختلفة.vmtTypeInfo في vftable).call [ecx+3Fh] مع أسلوب مثيل).TComparer<System.Bindings.EvalProtocol.TPair<System.IInterface,System.Pointer>> والتي يصعب فك شفرتها في IDA.يرجى إرسال أمثلة على البرامج الثنائية التي لا تعمل معها هذه الأداة، حتى يمكن تحسينها.