دورة في Portable Executable

هذه الدورة منقولة عن دورة السيد Iczelion.

بنية ملفات PE:

في عالم Windows المختصر PE يعبر عن Portable Executable أو ملف تنفيذي محمول. في عالم Windows كل الملفات التنفيذية و مكاتب الربط الديناميكي DLL و ملفات وحدات الأجهزة SYS (ما عدا صيغ VxD, و DLL ذات 16 بت) تستخدم صيغة PE, حتى أنّ وحدات الأجهزة على مستوى نواة NT تستخدم هذه الصيغة.

تعتمد هذه الصيغة بالأساس على صيغة COFF (Common Object File Format) الخاصة بأنظمة Unix.

ماذا تعني “ملفات تنفيذية محمولة”؟

سميت هذه الصيغة بالمحمولة بسبب قدرتها على العمل على مختلف منصات Win32, حيث يقوم المحمل Loader في كل منصة Win32 بقرائتها و تحميلها بحسب المعالج الذي يستخدمه Windows حتى لو لم يكن Intel. لكن هذا لا يعني أنّه يمكننا تشغيل أي PE على أي CPU بدون اجراء بعض التعديلات.

ما الذي يفيدنا من دراسة صيغة PE؟

بما أنّ صيغة PE هي الصيغة العامة المستخدمة في أنظمة Windows, نكون بدراستنا لها و استيعابها قد تمكنا من الحصول على معلومات قيمة حول بنية Windows الداخلية و آلية عمله.

الشكل التالي يبين بطريقة مختصرة البنية العامة للملفات ذات صيغة PE:


كما نرى, ملفات PE مقسمة إلى عدة أقسام بعضها أساسي لايمكن تغييره أو اجتنابه , و البعض الآخر اختياري يمكن العمل عليه. كل ملفات PE دون استثناء (من ضمنها DLL ذات 32 بت) يجب أن تبدأ بترويسة نظام DOS البسيطة DOS MZ header.

لا يوجد فائدة لهذا القسم في Windows, إلا أنّه موجود للتوافق مع أنظمة DOS, فهو يمكّن DOS من إدراك أنّ الملف الذي يتعامل معه ملف تنفيذي فيقوم بنقل التنفيذ للقسم التالي أو ما يسمى DOS Stub و الذي هو عبارة عن برنامج EXE صحيح يعمل في حال عدم تعرف النظام على بنية PE, كما في الأنظمة القديمة مثلاً. يمكن لهذا البرنامج أن يقوم بعدة أعمال كأي برنامج عادي, لكن في العادة تكون وظيفته الشائعة في أغلب البرامج هي عرض رسالة تفيد بأن البرنامج غير قابل للتنفيذ على نظام DOS, حيث يقوم باستخدام الخدمة 9 من المقاطعة INT 21h حتى يقوم بطباعة العبارة التالية:


“This Program cannot run in DOS mode”.

يأتي بعد قسم DOS stub قسم ترويسة PEPE Header هي عبارة عن بنية PE تسمى IMAGE_NT_HEADERS. هذه البنية تحوي على العديد من الحقول الأساسية التي يستخدمها PE loader. و سنتعرف عليها أكثر مع تقدمنا في هذه الدورة أكثر. ففي حال تم تنفيذ البرنامج على نظام يفهم بنية PE, سيقوم محمّل PE بالتعرف على مكان إزاحة البداية الخاصة بترويسة PE من ترويسة DOS MZ. و هكذا يتجاوز قسم DOS stub بالقفز مباشرة إلى PE header.

كما ذكرنا بأنّ ملفات PE مقسّمة إلى عدة كتلة تسمى أقسام

sections . و القسم هو عبارة عن كتلة (مجموعة) من البيانات و صفات عامة مثل code/data, read/write, و غيرها…

يمكنك تشبيه ملف PE بالأقراص المنطقية, حيث تكون ترويسة PE هي قطاع الإقلاع, و الأقسام هي الملفات على القرص. و هذه الملفات تحوي على خصائص مختلفة مثل للقراءة فقط, نظام, مخفي, أرشيف, و غيرها.

يجب أن نوضح من هذه النقطة أنّ تجميع البيانات في القسم يتم عن طريق الصفات العامّة common attributes, و ليس على أساس منطقي.

من غير المهم كيف يتم استخدام code/data, إذا كان code/data في ملف PE يملك نفس الصفات, يمكن جمعهما في نفس القسم. لكن لا يجب علينا أن نفكّر بالأقسام على أنّها “code” أو “data” أو أي تمثيل منطقي آخر: فالأقسام يمكن أن تحوي على code و data في نفس المكان بشريطة أن تملك نفس الصفات العامة. فإذا كنت تملك كتلة من البيانات التي تود أن تكون للقراءة فقط, يمكنك وضعها في قسم معلّم على أنّه للقراءة فقط read-only. و عندما يقوم محمل PE بحجز الذاكرة و ربطها بالأقسام, يقوم بتفحّص صفات كل الأقسام و يعطي كتل الذاكرة المحجوزة لتلك الأقسام الصفات الموافقة لها و المحددة في بنية PE بالملف.

إذا فكرنا ببنية ملف PE كالقرص المنطقي, ترويسة PE كقطاع الإقلاع و الأقسام كملفات, لن نتمكن من التعامل مع الملفات لأننا لا نعرف أين هي, فنحن حتى الآن لم نتعرف على المكافئ للأدلة Directories في ملفات PE. لنعد مرة ثانية إلى بنية ملفات PE, فبعد ترويسة PE مباشرة يأتي section table, و الذي هو عبارة مصفوفة من السجلات. كل بنية تحوي معلومات حول كل قسم في ملف PE كالصفات, إزاحة الملف file offset , الإزاحة الإفتراضية virtual offset. فإذا وُجِد 5 أقسام في ملف PE , سيوجد 5 أعضاء في مصفوفة السجلات تماماً. و بناءً على هذا يمكننا مقارنة section table بالدليل الجدز root directory في القرص المنطقي. و كل عضو في المصفوفة مكافئ لأحد الأدلة في الدليل الجذز.

هذا كل شيء حول البنية الأساسية لصيغة ملفات PE , و سنقوم بتلخيص الخطوات الرئيسية في تحميل ملف PE إلى الذاكرة:

  1. عندما يتم تشغيل ملف PE, يقوم محمل PE بتفحص ترويسة DOS MZ للحصول على إزاحة ترويسة PE, فإن وُجدَت يتم القفز مباشرة إلى مكان ترويسة PE.
  2. يقوم محمل PE بفحص ترويسة PE للتأكد من صلاحيتها, فإذا كانت صالحة, يتقدم إلى نهاية ترويسة PE.
  3. يوجد مباشرة بعد ترويسة PE جدول الأقسام section table. يقوم محمل PE بقراءة المعلومات حول الأقسام و يقوم بربط هذه الأقسام في الذاكرة باستخدام file mapping. و يعطي كل قسم صفاته كما هو محدد في جدول الأقسام.
  4. بعد اكتمال ربط ملف PE بالذاكرة, يهتم محمل PE بالجزء المنطقي من ملف PE, على سبيل المثال بجدول الاستيراد import table.

علماً أنّ الخطوات السابقة تم تبسيطها جداً. لمزيد من المعلومات يمكنك مراجعة MSDN أو وصف LUEVEL SMEYER حول ملفات PE فهي مفصلة بشكل كبير, و يجب اتباعها كمرجع.

Advertisements