السلام عليكم ورحمة الله وبركاته.
هذه السلسلة ستغطي أساسيات لغة C المهمة لمجال الهندسة العكسية (Reverse Engineering). لن نتوسع في كل تفاصيل اللغة، بل في ما يهم من قراءة الـ disassembly وتحليل الـ binaries.
المراحل التي يمر بها كود لغة C
أولاً يكون لدينا الكود المصدر (Source Code) وهو الملف بامتداد .c وفيه الكود الذي كتبناه. هذا الكود يمر بأربع مراحل قبل أن ينفذ، ومن المهم جداً فهمها:
1. المعالجة المسبقة (Preprocessor)
في هذه المرحلة تتم عدة خطوات من أهمها:
- إزالة التعليقات.
- توسيع وحدات الماكرو (
#define). - توسيع الملفات المضمنة (
#include). - الترجمة الشرطية (
#ifdef,#ifndef,#endif) — وهي شائعة جداً في الشيفرات الحقيقية وستصادفها كثيراً أثناء التحليل.
يكون الملف الناتج بامتداد .i.
2. المترجم (Compiler)
تقوم هذه المرحلة بتحويل الكود إلى لغة التجميع (Assembly)، ويكون الملف بامتداد .s.
نقطة مهمة لمجال RE: في هذه المرحلة تحديداً تُطبَّق تحسينات المترجم (
O0/O1/O2/O3). هذه التحسينات تغيّر شكل الـ disassembly الناتج كلياً — فالكود المترجم بـO0يختلف جذرياً عن المترجم بـO2. من الضروري أن تعرف أي مستوى تحسين استُخدم عند تحليل أي ملف.
3. المجمع (Assembler)
بهذه المرحلة يقوم المجمع بتحويل كود لغة التجميع إلى لغة الآلة (صفار وواحدات)، ويكون الملف بامتداد .o.
ملاحظة مهمة: هذا الملف هو object file قابل للنقل (relocatable) — أي أن العناوين داخله ليست نهائية بعد، والاستدعاءات ما زالت غير محلولة. وهذا هو السبب في وجود المرحلة الرابعة.
4. الرابط (Linker)
هذه المرحلة تقوم بما يلي:
- دمج جميع ملفات
.oمعاً مع المكتبات. - ربط استدعاءات الوظائف بتعريفاتها.
- حلّ العناوين النهائية.
نهايةً يكون الملف قابل للتنفيذ.
ملاحظة حسب نظام التشغيل: على ويندوز يكون الناتج PE بامتداد
.exe، أما على لينكس فيكون ELF بدون امتداد (مثلa.out). هذا التمييز أساسي في الهندسة العكسية وسنفصّل فيه لاحقاً.
تمرين عملي
من المهم أن تتعلم كيف تُطبّق هذه الخطوات يدوياً وتشاهد الكود وهو يتغير من مرحلة لمرحلة. على لينكس باستخدام gcc:
gcc -E program.c -o program.i # 1. المعالجة المسبقة
gcc -S program.i -o program.s # 2. المترجم → Assembly
gcc -c program.s -o program.o # 3. المجمع → Object file
gcc program.o -o program # 4. الرابط → Executable
افحص محتوى كل ملف في كل مرحلة ولاحظ الفرق.
أداة مفيدة: Compiler Explorer (godbolt)
موقع godbolt.org يريك الـ assembly الناتج مباشرة أثناء كتابة الكود، مع إمكانية اختيار مستوى التحسين (O0/O2…). أداة لا غنى عنها لربط الكود المصدري بما يُنتجه المترجم.
لماذا يهم هذا في الهندسة العكسية؟
كل مرحلة من هذه المراحل تترك أثراً مفيداً للمحلل:
| المرحلة | الأثر الذي يهم المحلل |
|---|---|
| المعالجة المسبقة | رؤية الكود بعد توسيع الماكرو وفهم البناء الحقيقي. |
| المترجم | فهم تأثير التحسينات على شكل الـ assembly. |
| المجمع | قراءة لغة الآلة والأوبكود. |
| الرابط | فهم بنية الملف القابل للتنفيذ (PE/ELF) والاستدعاءات الخارجية (imports). |
باختصار: فهم هذه المراحل الأربع هو حجر الأساس لقراءة أي ثنائي، وهو ما سنبني عليه بقية السلسلة بإذن الله.