البرمجة

مفاهيم متقدمة في ملفات ELF

مفاهيم متقدمة متعلقة بصيغة ملفات ELF القابلة للتنفيذ

تُعدّ صيغة ملفات ELF (Executable and Linkable Format) من أكثر صيغ الملفات القابلة للتنفيذ شيوعاً على أنظمة يونكس وLinux الحديثة. صُممت هذه البنية لتكون مرنة ومحمولة، وتدعم مختلف المعالجات المعمارية، وتُستخدم ليس فقط للملفات القابلة للتنفيذ، بل أيضًا للملفات القابلة للربط الديناميكي والمكتبات المشتركة وملفات النواة.

لتحقيق فهم عميق ومتقدم حول صيغة ELF، من الضروري تحليل بنيتها الداخلية وتفاعلها مع النواة، آليات التحميل، معالجة الرموز (symbols)، وموضوعات متعلقة بالأمان مثل تقنيات الحماية من الاستغلال والهندسة العكسية.


الهيكل الداخلي لملف ELF

يتكون ملف ELF من ثلاثة أجزاء أساسية:

  1. رأس الملف ELF Header

  2. جدول ترويسات المقاطع Program Header Table

  3. جدول ترويسات الأقسام Section Header Table

1. رأس الملف ELF Header

يحتوي على معلومات عامة حول الملف مثل:

  • معرف الملف (magic number)

  • نوع الملف (تنفيذي، مكتبة مشتركة، ملف rel، إلخ)

  • المعمارية المستهدفة (x86, x86_64, ARM, RISC-V)

  • نقطة الدخول إلى البرنامج (Entry Point)

  • إزاحة جدول رؤوس البرنامج

  • إزاحة جدول رؤوس الأقسام

  • حجم كل من هذه الجداول وعدد مدخلاتها

2. جدول رؤوس البرنامج (Program Header Table)

هذا الجدول يحتوي على معلومات حول كيفية تحميل البرنامج في الذاكرة. كل مدخل في هذا الجدول يُمثّل جزءًا من الملف يجب تحميله أو تفسيره بطريقة معينة.

أنواع المداخل:

  • PT_LOAD: يُمثل جزءًا يجب تحميله في الذاكرة.

  • PT_DYNAMIC: يحتوي على معلومات الربط الديناميكي.

  • PT_INTERP: يُحدد المسار إلى محمل الربط الديناميكي (ld.so).

  • PT_NOTE: يحتوي على معلومات حول ABI أو تصحيح الأخطاء.

  • PT_TLS: يمثل معلومات حول تخزين TLS.

3. جدول رؤوس الأقسام (Section Header Table)

يُستخدم بشكل أساسي خلال مرحلة الربط وليس خلال تنفيذ البرنامج. يضم هذا الجدول أقسام مثل:

  • .text: كود البرنامج

  • .data: البيانات القابلة للتعديل

  • .bss: البيانات المُهيّأة إلى صفر

  • .symtab / .dynsym: جداول الرموز

  • .strtab / .dynstr: جداول السلاسل النصية للرموز

  • .rel/.rela: جداول إعادة التوطين (Relocation)


الربط الديناميكي ودور الـ PLT و GOT

عند تنفيذ برنامج يستخدم مكتبات ديناميكية، لا يتم تحميل جميع عناوين الدوال في البداية، بل تُستخدم آلية تُعرف بـ “الربط الكسول” (Lazy Binding) لتحقيق الأداء الأفضل.

Global Offset Table (GOT)

هي بنية بيانات تحتوي على عناوين الدوال والرموز الديناميكية. في البداية، يتم ملء مدخلات GOT بعناوين توجيهية إلى نقطة في الـ PLT.

Procedure Linkage Table (PLT)

تحتوي على تعليمات تُوجه نداءات الدوال الخارجية إلى المدخل المناسب في GOT. إذا لم يكن العنوان محملاً بعد، يتجه التنفيذ إلى محمل الربط ld-linux.so لملء العنوان في GOT.

تعمل PLT وGOT معًا لتوفير آلية فعالة لتأجيل ربط الرموز حتى لحظة الاستدعاء الأول، مما يقلل من زمن تحميل البرنامج.


إعادة التوطين (Relocation)

عندما يُربط برنامج بشكل ديناميكي، يجب تعديل بعض العناوين داخل الكود والبيانات لتتناسب مع العنوان الذي تُحمّل فيه هذه الكيانات في الذاكرة. هناك نوعان رئيسيان من معلومات إعادة التوطين:

  • Rel: تحتوي فقط على الإزاحة والنوع، وتُستخدم مع قيم في الذاكرة صفرية.

  • Rela: تحتوي على الإزاحة والنوع والقيمة المضافة (Addend)، وهي أكثر شيوعًا في الأنظمة التي تستخدم تنسيق ELF64.

عملية إعادة التوطين تتم خلال الربط أو التحميل، ويقوم بها محمل النظام أو linker مثل ld-linux.so.


امتيازات الأمان في ملفات ELF

Address Space Layout Randomization (ASLR)

إحدى آليات الحماية التي تُطبق على ملفات ELF. تقوم ASLR بإعادة ترتيب توزيع أقسام البرنامج (stack، heap، المكتبات الديناميكية، إلخ) في الذاكرة في كل تنفيذ. هذا يجعل استغلال الثغرات أصعب لأن المهاجم لا يمكنه التنبؤ بمواقع معينة في الذاكرة.

Stack Canaries

عبارة عن قيمة تُضاف بين متغيرات الدالة في المكدس وعنوان الإرجاع. في حال وجود تجاوز للمكدس (Stack Overflow)، تتغير هذه القيمة مما يسمح لكاشف الاستغلال بمقاطعة التنفيذ.

NX Bit (No Execute)

تُستخدم لمنع تنفيذ صفحات معينة من الذاكرة (مثل stack وheap). يتم تحديد ذلك في جدول رؤوس البرنامج باستخدام علم PF_X.

RELRO (Relocation Read-Only)

تُستخدم لجعل بعض أجزاء من جدول GOT غير قابلة للكتابة بعد الانتهاء من الربط الديناميكي، مما يمنع المهاجمين من إعادة توجيه الاستدعاءات.

الأنواع:

  • Partial RELRO: يطبّق فقط حماية جزئية على بعض أجزاء GOT.

  • Full RELRO: يُجمد كامل جدول GOT ويمنع تعديله أثناء التنفيذ.


الجدول التالي يوضح مقارنة بين أقسام ELF الرئيسية ووظائفها:

اسم القسم الوصف يُستخدم أثناء قابل للتنفيذ؟ قابل للكتابة؟
.text كود الآلة التنفيذي التشغيل نعم لا
.data بيانات قابلة للتعديل التشغيل لا نعم
.bss بيانات مُهيّأة للصفر التشغيل لا نعم
.rodata بيانات ثابتة غير قابلة للتعديل التشغيل لا لا
.symtab جدول الرموز الكامل الربط/التصحيح لا لا
.dynsym جدول الرموز الديناميكي التشغيل لا لا
.rel.text / .rela.text إعادة توطين للكود التشغيل/الربط لا لا
.plt جدول ربط إجراءات ديناميكي (PLT) التشغيل نعم لا
.got جدول تعويضات عامة (GOT) التشغيل لا نعم

أدوات تحليل ملفات ELF

العمل مع ملفات ELF يتطلب مجموعة من الأدوات الاحترافية:

  • readelf: لفحص بنية ملف ELF

  • objdump: لتفكيك الكود وتحليل الأقسام

  • nm: لعرض الرموز

  • ldd: لعرض تبعيات المكتبات الديناميكية

  • strace/ltrace: لتعقب الاستدعاءات النظامية والدوال

  • gdb: مصحح أخطاء قوي للتنفيذ والتحليل الديناميكي

مثال على استخدام readelf:

bash
readelf -h my_binary readelf -S my_binary readelf -l my_binary

الهندسة العكسية وتحليل الملفات الخبيثة

معرفة بنية ELF ضرورية أيضًا في مجال الأمن السيبراني، خصوصًا في تحليل البرمجيات الخبيثة. تُستخدم تقنيات مثل:

  • تحليل الـ .text لفهم كيفية عمل البرنامج.

  • مراجعة الـ .got و .plt لمعرفة نداءات النظام أو المكتبات.

  • استخراج الرموز من .dynsym.

  • تحديد تقنيات التشفير أو الحماية المستخدمة.


تطورات حديثة في صيغة ELF

مع تطور الأنظمة، تم إدخال تحسينات كثيرة على ملفات ELF، أبرزها:

  • دعم التنسيقات المتقدمة مثل DWARF للـ Debugging.

  • دعم معمارية RISC-V وARM64.

  • استخدام تقنيات ضغط الأقسام لتوفير المساحة.

  • دعم أقسام TLS لتوفير متغيرات خاصة بكل خيط تنفيذ.

  • دعم Lazy Binding المحسن باستخدام تقنية STT_GNU_IFUNC.


الخلاصة التقنية

فهم بنية ملفات ELF لا يقتصر على المبرمجين منخفضي المستوى، بل يمتد إلى مجالات تحليل الأداء، أمان البرمجيات، بناء الأنظمة، والحوسبة السحابية. من خلال استكشاف المكونات الداخلية مثل رؤوس البرامج والأقسام، ومعالجة الرموز والربط الديناميكي، يستطيع المهندس أو الباحث بناء أدوات فعالة لتحليل البرامج، كشف الثغرات، أو تحسين الحماية.

تُعد صيغة ELF مثالًا على عبقرية التصميم الذي يوازن بين الكفاءة، القابلية للتوسعة، ودعم التوافقية عبر مختلف المعماريات والمنصات.


المراجع: