هناك أشياء في العالم نأخذها كأمر مسلم به ، على الرغم من أنها روائع حقيقية. أحد هذه الأشياء هو أدوات Linux مثل ls و ps. على الرغم من أنهم عادة ما يُنظر إليهم على أنهم بسيطون ، إلا أن هذا بعيد عن النظر إلى الداخل. وكذلك تنسيق ELF القابل للتنفيذ والربط. تنسيق ملف يُستخدم بشكل عام ، لكن القليل منهم يفهمه. سيساعدك هذا الدليل السريع على الفهم.

بعد قراءة هذا الدليل ، سوف تتعلم:
- لماذا هناك حاجة إلى تنسيق ELF وما أنواع الملفات المستخدمة
- هيكل ملف ELF وتفاصيل التنسيق
- كيفية قراءة وتحليل المحتويات الثنائية لملف ELF
- ما الأدوات المستخدمة لتحليل الملفات الثنائية؟
ما هو ملف ELF؟
ELF تعني التنسيق القابل للتنفيذ والربط ، وتحدد بنية الملفات الثنائية والمكتبات والملفات الأساسية. تسمح مواصفات التنسيق لنظام التشغيل بتفسير إرشادات الجهاز الموجودة في الملف بشكل صحيح. عادةً ما يكون ملف ELF هو ملف الإخراج الخاص بمترجم أو رابط وله تنسيق ثنائي. باستخدام الأدوات المناسبة ، يمكن تحليلها ودراستها.
لماذا دراسة ELF بالتفصيل؟
قبل الغوص في التفاصيل الفنية ، لن يكون من الخطأ تفسير سبب فهم تنسيق تنسيق ELF. أولاً ، يسمح لك بدراسة التشغيل الداخلي لنظام التشغيل. عندما يحدث خطأ ما ، ستساعدك هذه المعرفة على فهم أفضل لما حدث بالضبط ولأي سبب. أيضا ، يمكن أن تكون القدرة على فحص ملفات ELF ذات قيمة للعثور على ثغرات الأمان واكتشاف الملفات المشبوهة. وأخيرا ، لفهم أفضل لعملية التنمية. حتى إذا قمت بالبرمجة بلغة عالية المستوى مثل Go ، فستظل تعرف بشكل أفضل ما يجري وراء الكواليس.
فلماذا دراسة ELF؟
- لفهم عام لنظام التشغيل
- لتطوير البرمجيات
- الطب الشرعي الرقمي والاستجابة للحوادث (DFIR)
- أبحاث البرامج الضارة (التحليل الثنائي)
من المصدر إلى العملية
أيا كان نظام التشغيل الذي نستخدمه ، فمن الضروري ترجمة وظائف شفرة المصدر بطريقة أو بأخرى إلى لغة وحدة المعالجة المركزية - رمز الجهاز. يمكن أن تكون الوظائف هي الأكثر أساسية ، على سبيل المثال ، فتح ملف على القرص أو عرض شيء ما على الشاشة. بدلاً من استخدام لغة وحدة المعالجة المركزية مباشرةً ، نستخدم لغة برمجة تحتوي على ميزات قياسية. المترجم ثم يترجم هذه الدالات إلى رمز كائن. ثم يتم ربط رمز الكائن هذا في البرنامج الكامل ، باستخدام رابط. والنتيجة هي ملف ثنائي يمكن تنفيذه على نظام أساسي محدد ونوع معين من وحدة المعالجة المركزية.
قبل أن تبدأ
هذا المنشور يحتوي على العديد من الفرق. من الأفضل تشغيلها على جهاز اختبار. انسخ الثنائيات الموجودة قبل تشغيل هذه الأوامر عليها. سنكتب أيضًا برنامج C صغير يمكنك تجميعه. في النهاية ، الممارسة هي أفضل طريقة لتعلم شيء ما.
تشريح ملف ELF
هناك اعتقاد خاطئ بأن ملفات ELF مخصصة فقط للملفات الثنائية أو القابلة للتنفيذ. قلنا بالفعل أنه يمكن استخدامها لأجزاء من الملفات القابلة للتنفيذ (رمز الكائن). مثال آخر هو ملفات المكتبة ومقالب أساسية (ملفات أساسية وملفات a.out). يتم استخدام مواصفات ELF أيضًا على Linux لوحدات kernel و kernel.

هيكل
بسبب القابلية للتوسعة لملفات ELF ، قد تختلف البنية لملفات مختلفة. يتكون ملف ELF من:
- رأس ELF
- معطيات
باستخدام الأمر readelf ، يمكننا أن ننظر إلى بنية الملف ، وسوف ننظر إلى شيء من هذا القبيل:

رأس ELF
كما ترون في لقطة الشاشة ، يبدأ رأس ELF بـ "رقم سحري". يعطي هذا "الرقم السحري" معلومات حول الملف. تحدد البايتات الأربع الأولى أن هذا ملف ELF (45 = E ، 4c = L ، 46 = F ، مسبوقة بـ 7f).
رأس ELF مطلوب. هناك حاجة حتى يتم تفسير البيانات بشكل صحيح أثناء الربط والتنفيذ. لفهم أفضل للعملية الداخلية لملف ELF ، من المفيد معرفة الغرض من هذه المعلومات.
فئة
بعد التصريح عن نوع ELF ، يتبع حقل الفصل الدراسي. تعني هذه القيمة البنية التي تم تصميم الملف من أجلها. يمكن أن يكون 01 (بنية 32 بت) أو 02 (64 بت). هنا نرى 02 ، والتي تتم ترجمتها بواسطة الأمر readelf كملف ELF64 ، أي بمعنى آخر ، يستخدم هذا الملف بنية 64 بت. هذا ليس مستغربا ، تم تثبيت معالج حديث في سيارتي.
معطيات
بعد ذلك ، يأتي حقل "البيانات" ، الذي يحتوي على خيارين: 01 - LSB (بت الأقل أهمية) ، والمعروف أيضًا باسم endian القليل ، أو 02 - MSB (بت الأكثر أهمية ، end-big). تساعد هذه القيم في تفسير بقية الكائنات في الملف. هذا أمر مهم لأن أنواع مختلفة من المعالجات التعامل مع هياكل البيانات بشكل مختلف. في حالتنا ، يتم استخدام LSB ، لأن المعالج لديه بنية AMD64.
يصبح تأثير LSB مرئيًا عند استخدام الأداة المساعدة hexdump على ملف ثنائي. دعونا نرى رأس ELF ل / bin / ps.
$ hexdump -n 16 /bin/ps 0000000 457f 464c 0102 0001 0000 0000 0000 0000 0000010
نرى أن أزواج القيم مختلفة ، بسبب تفسير ترتيب البيانات.
نص
ثم يتبع قيمة سحرية أخرى "01" ، وهي رقم الإصدار. الإصدار 01 فقط متاح حاليًا ، لذلك لا يعني هذا الرقم أي شيء مثير للاهتمام.
نظام التشغيل / أبي
لكل نظام تشغيل طريقته الخاصة في استدعاء الوظائف ، ولديه الكثير من القواسم المشتركة ، ولكن بالإضافة إلى ذلك ، لكل نظام اختلافات بسيطة. يتم تحديد ترتيب استدعاء الوظيفة من خلال واجهة التطبيق الثنائية (ABI). تصف حقول OS / ABI ABI المستخدم والإصدار الخاص به. في حالتنا ، القيمة هي 00 ، مما يعني أنه لا يتم استخدام امتدادات محددة. في الإخراج ، يظهر هذا على أنه النظام الخامس.
نسخة ABI
إذا لزم الأمر ، يمكن الإشارة إلى إصدار ABI.
آلة
يشير العنوان أيضًا إلى نوع الجهاز المتوقع (AMD64).
نوع
يشير حقل الكتابة إلى نوع الملف. فيما يلي بعض أنواع الملفات الشائعة.
CORE (القيمة 4)
DYN (ملف كائن مشترك) ، مكتبة (القيمة 3)
EXEC (ملف قابل للتنفيذ) ، ملف قابل للتنفيذ (القيمة 2)
REL (ملف Relocatable) ، ملف قبل الارتباط (القيمة 1)
انظر العنوان الكامل
على الرغم من أنه يمكن عرض بعض الحقول من خلال القراءة ، إلا أن هناك المزيد بالفعل. على سبيل المثال ، يمكنك معرفة المعالج الذي يوجد به الملف. استخدم hexdump لرؤية رأس ELF الكامل وجميع القيم.
7f 45 4c 46 02 01 01 00 00 00 00 00 00 00 00 00 |.ELF............| 02 00 3e 00 01 00 00 00 a8 2b 40 00 00 00 00 00 |..>......+@.....| 40 00 00 00 00 00 00 00 30 65 01 00 00 00 00 00 |@.......0e......| 00 00 00 00 40 00 38 00 09 00 40 00 1c 00 1b 00 |....@.8...@.....|
(إخراج hexdump -C -n 64 / bin / ps)
يحدد الحقل المميز نوع الجهاز. القيمة 3e هي العلامة العشرية 62 ، والتي تتوافق مع AMD64. للحصول على فكرة عن جميع أنواع الملفات ، راجع ملف الرأس
هذا .
على الرغم من أنه يمكنك القيام بكل هذا في ملف تفريغ سداسي عشري ، إلا أنه من المنطقي استخدام الأداة التي تعمل من أجلك. قد تكون الأداة المساعدة dumpelf مفيدة. يُظهر الإخراج المنسق المطابق لرأس ELF. سيكون من الجيد دراسة الحقول المستخدمة ، وما هي قيمها المعتادة.
الآن ، حيث أوضحنا معنى هذه الحقول ، حان الوقت للنظر في السحر الحقيقي وراءها والانتقال إلى العناوين التالية!
ملف البيانات
بالإضافة إلى الرأس ، تتكون ملفات ELF من ثلاثة أجزاء.
- رؤوس البرنامج أو القطاعات
- قسم أو عناوين القسم
- معطيات
قبل أن نغوص في هذه الرؤوس ، سيكون من المفيد معرفة أن ملف ELF له نوعان مختلفان. تم تصميم واحد منهم للرابط ويسمح بتنفيذ التعليمات البرمجية (شرائح). والآخر للأوامر والبيانات (المقاطع). اعتمادًا على الغرض ، يتم استخدام نوع الرأس المناسب. لنبدأ برأس البرنامج الموجود في الملفات القابلة للتنفيذ ELF.
عناوين البرنامج
يتكون ملف ELF من مقاطع صفرية أو أكثر ، ويصف كيفية إنشاء عملية ، صورة ذاكرة لتنفيذ وقت التشغيل. عندما ترى kernel هذه القطع ، فإنها تضعها في مساحة العنوان الافتراضية باستخدام استدعاء نظام mmap (2). بمعنى آخر ، يحول التعليمات المعدة مسبقًا إلى صورة في الذاكرة. إذا كان ملف ELF ثنائيًا عاديًا ، فإنه يتطلب رؤوس البرنامج هذه ، وإلا فلن يعمل. يتم استخدام هذه الرؤوس ، جنبا إلى جنب مع هياكل البيانات المقابلة ، لتشكيل العملية. بالنسبة للمكتبات المشتركة ، تكون العملية متشابهة.

رأس البرنامج في ملف ELF ثنائي
نرى 9 عناوين برنامج في هذا المثال. في البداية من الصعب فهم ما تعنيه. دعونا الغوص في التفاصيل.
GNU_EH_FRAME
هذا هو قائمة الانتظار فرزها المستخدمة من قبل برنامج التحويل البرمجي GCC. يخزن معالجات الاستثناء. إذا حدث خطأ ما ، يتم استخدامها لمعالجة الموقف بشكل صحيح.
GNU_STACK
يستخدم هذا الرأس لحفظ معلومات المكدس. ميزة مثيرة للاهتمام هي أن المكدس لا يجب أن يكون قابلاً للتنفيذ ، لأن هذا قد يستتبع ثغرات أمنية.
إذا كانت شريحة GNU_STACK مفقودة ، فسيتم استخدام المكدس القابل للتنفيذ. تُظهر الأدوات المساعدة Scanelf و execstack تفاصيل جهاز المكدس.
أوامر لعرض رأس البرنامج:
- نفايات (pax-utils)
- elfls -S / bin / ps
- eu-readelf –program-headers / bin / ps
أقسام ELF
رؤوس الأقسام
تحدد رؤوس الأقسام جميع أقسام الملف. كما سبق ذكره ، يتم استخدام هذه المعلومات للربط وإعادة التوطين.
تظهر الأقسام في ملف ELF بعد قيام برنامج التحويل البرمجي GNU C بتحويل رمز C إلى أداة تجميع ، ويقوم أداة تجميع GNU بإنشاء كائنات.
كما هو موضح في الشكل أعلاه ، يمكن أن يحتوي القطاع على 0 أو أكثر من الأقسام. هناك أربعة أقسام رئيسية للملفات القابلة للتنفيذ: .text و .data و .rodata و .bss. كل من هذه الأقسام بالتمهيد بأذونات مختلفة ، والتي يمكن عرضها مع readelf -S.
.text
يحتوي على رمز قابل للتنفيذ. سيتم تعبئتها في مقطع به حقوق قراءة وتنفيذ. يتم تنزيله مرة واحدة ، ولا يتغير محتواه. يمكن رؤية ذلك باستخدام الأداة المساعدة objdump.
12 .text 0000a3e9 0000000000402120 0000000000402120 00002120 2**4 CONTENTS, ALLOC, LOAD, READONLY, CODE
.data
تهيئة البيانات مع أذونات القراءة والكتابة.
.rodata
تهيئة البيانات بأذونات للقراءة فقط. (= أ).
.bss
بيانات غير مهيأة مع أذونات القراءة / الكتابة. (= WA)
[24] .data PROGBITS 00000000006172e0 000172e0 0000000000000100 0000000000000000 WA 0 0 8 [25] .bss NOBITS 00000000006173e0 000173e0 0000000000021110 0000000000000000 WA 0 0 32
أوامر لعرض الأقسام والعناوين.
- dumpelf
- elfls -p / bin / ps
- eu-readelf –section-headers / bin / ps
- readelf -S / bin / ps
- objdump -h / bin / ps
مجموعات القسم
يمكن تجميع بعض الأقسام كما لو كانت تشكل كلاً واحداً. روابط جديدة تدعم هذه الوظيفة. لكن في حين أن هذا ليس شائعًا.
على الرغم من أن هذا قد لا يبدو مثيرا للاهتمام ، إلا أن معرفة أدوات تحليل ملف ELF توفر فوائد كبيرة. لهذا السبب ، يتم تقديم نظرة عامة على هذه الأدوات والغرض منها في نهاية المقالة.
ثنائيات ثابتة وديناميكية
عند التعامل مع ثنائيات ELF ، سيكون من المفيد معرفة كيفية ربط هذين النوعين من الملفات. يمكن أن تكون ثابتة وديناميكية ، وهذا ينطبق على المكتبات التي يستخدمونها. إذا كان الثنائي "ديناميكي" ، فهذا يعني أنه يستخدم مكتبات خارجية تحتوي على بعض الوظائف الشائعة ، مثل فتح ملف أو إنشاء مأخذ توصيل شبكة. الثنائيات الثابتة ، على النقيض من ذلك ، تشمل جميع المكتبات اللازمة.
إذا كنت تريد التحقق مما إذا كان الملف ثابتًا أم ديناميكيًا ، فاستخدم الأمر file. سوف تظهر شيئًا كهذا:
$ file /bin/ps /bin/ps: ELF 64-bit LSB executable, x86-64, version 1 (SYSV), <b>dynamically linked (uses shared libs)</b>, for GNU/Linux 2.6.24, BuildID[sha1]=2053194ca4ee8754c695f5a7a7cff2fb8fdd297e, stripped
لتحديد المكتبات الخارجية التي يتم استخدامها ، استخدم ببساطة ldd على نفس الثنائية:
$ ldd /bin/ps linux-vdso.so.1 => (0x00007ffe5ef0d000) libprocps.so.3 => /lib/x86_64-linux-gnu/libprocps.so.3 (0x00007f8959711000) libc.so.6 => /lib/x86_64-linux-gnu/libc.so.6 (0x00007f895934c000) /lib64/ld-linux-x86-64.so.2 (0x00007f8959935000)
نصيحة: لمعرفة المزيد من التبعيات ، من الأفضل استخدام الأداة المساعدة lddtree.
أدوات التحليل الثنائية
إذا كنت ترغب في تحليل ملفات ELF ، فسيكون من المفيد بالتأكيد إلقاء نظرة أولى على الأدوات الموجودة. هناك مجموعة أدوات لتطوير عكس الثنائيات والرمز القابل للتنفيذ. إذا كنت جديدًا في تحليل ملفات ELF ، فابدأ بالتحليل الثابت. يتضمن التحليل الثابت أننا نفحص الملفات دون بدء تشغيلها. عندما تبدأ في فهم عملهم بشكل أفضل ، انتقل إلى التحليل الديناميكي. نفذ الأمثلة وانظر إلى سلوكهم الحقيقي.
الأدوات الشعبية
Radare2
تم إنشاء مجموعة الأدوات Radare2 بواسطة سيرجي ألفاريز. الرقم 2 يعني أن الكود قد تمت إعادة كتابته بالكامل مقارنة بالإصدار الأول. الآن يتم استخدامه من قبل العديد من الباحثين لدراسة تشغيل الكود.
حزم البرمجيات
تحتوي معظم أنظمة Linux على ثنائيات مثبتة. يمكن أن تساعدك الحزم الأخرى على رؤية المزيد من المعلومات. ستعمل مجموعة الأدوات الصحيحة على تبسيط عملك ، خاصة إذا كنت تقوم بتحليل ملفات ELF. لقد جمعت هنا قائمة من الحزم والأدوات المساعدة لتحليل ملفات ELF.
elfutils/ usr / bin / eu-addr2line
/ usr / bin / eu-ar - بديل لـ ar لإنشاء ملفات الأرشيف ومعالجتها
/ usr / bin / eu-elfcmp
/ usr / bin / eu-elflint - تحقق من الامتثال لمواصفات gABI و psABI
/ usr / bin / eu-findtextrel - ابحث عن عمليات نقل النص
/ usr / bin / eu-ld - يجمع بين ملفات الكائنات والأرشيف
/ usr / bin / eu-make-debug-archive
/ usr / bin / eu-nm - يعرض رموز الكائن والملفات القابلة للتنفيذ
/ usr / bin / eu-objdump - يعرض معلومات من ملف الكائن
/ usr / bin / eu-ranlib - ينشئ فهرسًا لملفات الأرشيف
/ usr / bin / eu-readelf - يعرض ملف ELF في شكل قابل للقراءة
/ usr / bin / eu-size - يُظهر حجم كل قسم (نص ، بيانات ، bss ، إلخ)
/ usr / bin / eu-stack - يُظهر مكدس العملية الحالية أو تفريغ kernel
/ usr / bin / eu-strings - يعرض سلاسل النص (مثل الأداة المساعدة للسلاسل)
/ usr / bin / eu-strip - يزيل جدول الأحرف من ملف ELF
/ usr / bin / eu-unstrip - يضيف الرموز ومعلومات تصحيح الأخطاء إلى الملف الثنائي
ملاحظة: حزمة elfutils ستكون بداية جيدة ، حيث تحتوي على معظم أدوات التحليل
elfkickers/ usr / bin / ebfc - مترجم لغة Brainfuck
/ usr / bin / elfls - يُظهر رؤوس البرنامج ورؤوس الأقسام ذات الأعلام
/ usr / bin / elftoc - يحول ثنائي إلى برنامج C
/ usr / bin / infect - أداة مساعدة لحقن قطارة بإنشاء ملف setuid في / tmp
/ usr / bin / objres - ينشئ كائنًا من بيانات منتظمة أو ثنائية
/ usr / bin / rebind - يغير الربط ورؤية الأحرف في ملفات ELF
/ usr / bin / sstrip - يزيل المكونات غير الضرورية من ملف ELF
ملاحظة: يركز مؤلف حزمة ELFKickers على معالجة ملفات ELF ، والتي تتيح لك الحصول على مزيد من المعلومات عند العمل مع ثنائيات ELF "الخاطئة"
باكس تيلس/ usr / bin / dumpelf - تفريغ بنية ELF الداخلية
/ usr / bin / lddtree - مثل ldd ، مع تحديد مستوى التبعيات المعروضة
/ usr / bin / pspax - يعرض معلومات ELF / PaX حول العمليات الجارية
/ usr / bin / scanelf - مجموعة واسعة من المعلومات ، بما في ذلك تفاصيل PaX
/ usr / bin / scanmacho - يعرض تفاصيل ثنائيات Mach-O (في Mac OS X)
/ usr / bin / symtree - يظهر شخصيات شجرة
ملاحظة: يمكن لبعض الأدوات المساعدة في هذه الحزمة مسح الدلائل بشكل متكرر ، وهي مثالية لتحليل محتويات الدليل بالكامل. وينصب التركيز على أدوات البحث PaX. بالإضافة إلى دعم ELF ، يمكنك استخراج المعلومات من ثنائيات Mach-O.
مثال الإخراج
scanelf -a /bin/ps TYPE PAX PERM ENDIAN STK/REL/PTL TEXTREL RPATH BIND FILE ET_EXEC PeMRxS 0755 LE RW- R-- RW- - - LAZY /bin/ps
prelink/ usr / bin / execstack - يمكنك عرض أو تغيير المعلومات حول ما إذا كان المكدس قابل للتنفيذ
/ usr / bin / prelink - تنقل المكالمات في ملفات ELF لتسريع العملية
أسئلة مكررة
ما هو أبي؟
ABI هو "واجهة التطبيق الثنائية" ويحدد واجهة منخفضة المستوى بين نظام التشغيل والرمز القابل للتنفيذ.
ما هو ELF؟
ELF هو تنسيق قابل للتنفيذ وربط. هذا أحد مواصفات التنسيق الذي يحدد كيفية كتابة التعليمات في التعليمات البرمجية القابلة للتنفيذ.
كيف يمكنني رؤية نوع الملف؟
استخدم أمر الملف للمرحلة الأولى من التحليل. هذا الأمر قادر على إظهار التفاصيل المستخرجة من الأرقام والعناوين "السحرية".
استنتاج
ملفات ELF للتنفيذ والربط. حسب الغرض ، فهي تحتوي على الأجزاء والأقسام اللازمة. تقوم نواة نظام التشغيل بفحص الشرائح وتعيينها في الذاكرة (باستخدام mmap). يتم عرض الأقسام بواسطة رابط يقوم بإنشاء ملف قابل للتنفيذ أو كائن مشترك.
تتميز ملفات ELF بمرونة عالية وتدعم أنواعًا مختلفة من وحدات المعالجة المركزية (CPU) ، وهياكل الماكينات ، وأنظمة التشغيل. كما أنه قابل للتمديد ، تم تصميم كل ملف بشكل مختلف ، اعتمادًا على الأجزاء المطلوبة. باستخدام الأدوات الصحيحة ، يمكنك معرفة الغرض من الملف وفحص محتويات الملفات الثنائية. يمكنك عرض الوظائف والخطوط الموجودة في الملف. بداية جيدة لأولئك الذين يبحثون عن البرامج الضارة ، أو لفهم لماذا تتصرف العملية (أو لا) بطريقة معينة.
موارد لمزيد من الدراسة
إذا كنت تريد معرفة المزيد عن ELF والهندسة العكسية ، يمكنك رؤية العمل الذي نقوم به في Linux Security Expert. كجزء من المنهج الدراسي ، لدينا
وحدة هندسية عكسية مع العمل العملي في المختبر.
لأولئك منكم الذين يحبون القراءة ، وثيقة جيدة وعميقة:
تنسيق ELF وورقة من تأليف براين ريتر ، المعروف أيضًا باسم ELFkickers. بالنسبة لأولئك الذين يحبون فهم المصدر ، انظر إلى
رأس ELF الموثق من Apple.
مجلس:
إذا كنت ترغب في التحسن في تحليل الملفات ، فابدأ استخدام
أدوات التحليل الشائعة المتوفرة حاليًا.