Buffer Overflow Part 2

السلام عليكم ورحمة الله وبركاته

نستكمل في هذه المقالة الحديث عن الـ Buffer

عرضنا في المقالة السابقة مثال على القراءة خارج نطاق الـ Buffer

سنستعرض في هذه المقالة -إن شاء الله- مثال آخر حول عملية الكتابة خارج نطاق الـ Buffer

بسم الله لنبدأ

مثال : الكتابة خارج نطاق الـ Buffer

المثال من نفس كتابنا السابق، كتاب The Shellcoder’s Handbook ( للمهتمين : المثال يبدأ من الصفحة رقم 13 )

لدينا الكود الآتي

1:  int main () {
2:      int array[5];
3:      int i;
4:      for (i = 0; i <= 255; i++ )
5:      {
6:         array[i] = 10;
7:      }
8:  }

2 : قمنا بتعريف متغير من نوع array ، ويفترض أن تكون سعة هذه الـ array هو 5 عناصر

3 : عرّفنا متغير آخر ، وهو العدّاد ( counter ) الذي سنستخدمه في الـ for loop

4 - 7 : في داخل الـ for loop قمنا بتخزين القيمة 10 في عناصر الـ array ، لكن المشكلة في هذا الكود أننا خرجنا خارج نطاق الـ array

لاحظ أن الـ for loop ستستمر بتنفيذ العملية array[i] = 10; حتى ينتفي الشرط i <= 255 ، وكما نعرف سابقًا ، الـ array لا تسع إلّا 5 عناصر

فالكود أعلاه بكل بساطة يقوم بالكتابة خارج نطاق الـ array ( الـ buffer )

طيّب، لنقم الآن بعمل Compile للكود ونرى ما سيحدث

1

مثل المرّة السابقة، نلاحظ أن الـ Compiler لم يقم بطباعة أي خطأ ، لننتقل الآن لتنفيذ البرنامج

1

في هذا المثال نلاحظ أننا حصلنا على رسالة الخطأ Segmentation fault ( في مثال القراءة خارج نطاق الـ Buffer من المقالة السابقة لم نواجه مشكلة في تنفيذ البرنامج )

وهي رسالة خطأ عامة تحتمل أسباب كثيرة ، أحد الأسباب الشائعة لهذه الرسالة هو عندما يحاول البرنامج الوصول لعنوان في الذاكرة غير مسموح الوصول له

أو عندما يحاول البرنامج الوصول لعنوان ذاكرة خاطئ في الأساس ، وأحد أسباب هذه الرسالة كذلك عندما يقوم البرنامج بالإشارة ( Dereferencing ) لـ pointer يحمل قيمة NULL

طيّب لنعود لبرنامجنا ونحاول البحث أكثر حول سبب هذا الخطأ ، سنستخدم gdb لهذه المُهمة ونقوم بفحص ملف الـ core dump ( الملف هذا يحمل نسخة من الذاكرة الخاصة بالعملية Process، تحديدًا في الوقت الذي توقّفت فيه العملية عن العمل )

1

 الآن نجد تفاصيل أكبر عن الخطأ، مثل أن البرنامج توقف عن العمل مع رسالة الخطأ signal 11 ،

بعد بحث سريع عن هذا الخطأ ، نجد أنه مرتبط بنفس الرسالة السابقة Segmentation fault ، ونجد كذلك في هذا المرجع تفصيل أكبر عن هذا الخطأ

Signal 11, or officially know as “segmentation fault”, means that the program accessed a memory location that was not assigned.

إذًا، يبدو أن البرنامج كان يحاول الوصول لعنوان ذاكرة لم يتم تعريفه ، بالتالي توقّف البرنامج عن العمل

وإن استكملنا فحص السطر الثاني من رسالة الخطأ الكاملة ، سنجد تحديدًا قيمة العنوان الذي كان البرنامج يحاول الوصول إليه

#0  0x0000000a in ?? ()

القيمة #0 تُشير للـ Stack Frame التي حدث فيها الخطأ، أو توقف عندها البرنامج

والقيمة 0x0000000a تُشير للعنوان الذي لم يتمكّن البرنامج من الوصول له

الآن ، لنحاول فهم هذا العنوان ، كما نعرف قيمة هذا العنوان هي في التمثيل Hexadecimal ، لو قمنا بتحويل هذه القيمة الى الـ Decimal سنحصل على القيمة الآتية :

1

أصبح الخطأ الآن واضح بالنسبة لنا، فالبرنامج كان يحاول الوصول للعنوان الذي قيمته 10 لكنه توقّف عن العمل، إمّا بسبب أن البرنامج لا يملك صلاحية الوصول لهذا العنوان، أو أن هذا العنوان غير موجود في الذاكرة من الأساس

أعتقد أن الأغلبية عرفوا الآن من أين أتت قيمة العنوان 10 ، لكن لنقم بطرح هذا السؤال :

من أين أتَت قيمة العنوان 10 ؟ وهل هي قيمة من نفس الذاكرة ؟ أم هو عنوان قمنا بالتلاعب به ( كتابته بأنفسنا ) ؟

لو عُدنا للكود الخاص بالبرنامج وتفحّصنا السطور  4 - 7 سنجد أن البرنامج كان يقوم بكتابة القيمة 10 في عناصر الـ array وكذلك أيضًا بكتابة القيمة 10 خارج نطاق الـ array

إذًا، كأنّنا عندما قمنا بالكتابة خارج نطاق الـ Buffer إستطعنا -بطريقة ما- التأثير على سير عمل البرنامج ( program flow ) ؟

الاجابة على هذا السؤال -ضمن هذا المثال- هي نعم

ومن هذه النقطة تبدأ تبرز في ذهننا العديد من الأسئلة المهمة مثل :

كيف إستطعنا التأثير على سير البرنامج ؟

وماهو الشيء الذي قمنا تحديدًا بتغيير قيمته، بالتالي مكّننا من التأثير على تسلسل البرنامج ؟

وكيف يبدو شكل الـ Buffer في الذاكرة ؟ وأين مكانه من الذاكرة ؟ ما الذي يسبقه ؟ وما الذي يليه ؟

كل هذه الأسئلة -وغيرها- سنناقشها في مقالات لاحقة بحول الله و قوّته ، أمّا في هذه المقالة ، نكتفي بهذا القدر من التفاصيل

ℹ️ [ملاحظة] هذه المقالة تمّت كتابتها خلال دراسة هذه المواضيع، فكل ما تم ذكره هنا قد يحتمل الخطأ، لكن بالإمكان العودة إلى المراجع التي إستندت عليها هذه المقالة