السلام عليكم

ان شاء الله هذا يعتبر موضوعى الاول فى مجتمع iSecur1ty سوف أتكلم عن موضوع شيق ولاحظت أنه لا يشغل أحد فى الوطن العربى الا قله قليله من أبنائيه لذلك قررت التحدث عن ما يسمى Buffer OverFlow.

كثير من المبرمجين يقعون فى بعض الاخطاء مثل مبرمج ال php يحدث وان يقع فى خطأ ما يسمى بال SQL injection فيؤدى ذلك الى حدوث خسائر كبيره وهذا مثال بسيط للأخطاء البرمجيه من هنا نتحدث عن موضوعنا وهوا أيضا خطأ برمجى من قبل مبرمج ليس من الضرورى أن يكون غير ماهر ولكن كثير من المبرمجيين يقع فى هذه الاخطاء ولولا ذلك ما كان exploit-db موجودا.

لفهم الموضوع جيدا لابد من النزول الى بعض التفاصيل من ضمن هذه التفاصيل كان لابد التعرف على ال Stack و كيفيه عمله.

تعريف ال Stack:

هو جزء متصل من الذاكره يستخدم غالبا بواسطه ما نسميه بال functions لكى يتم حفظ arguments الخاصه بها وأيضا لعمل ما يسمى dynamically allocate space for local variables.

التعامل مع ال Stack:

للتعامل مع ال stack نتعامل معه بأمريين هما (push, pop). يستخدم الامر push: لتخزين شئ معين فيه كما يستخدم الامر pop: للحصول على قيمه منه .

طريقه عمل ال Stack:

يعمل بطريقه تسمى  (LIFO)  وهوا ما يعنى ب Last input First output أى ما يخزن فيه الاخير يتم سحبه الأول و هذا شكل تصورى له.

 

stackLIFO

 

من أجل هذه العمليه كان لابد من تنظيم الامر فوجد ما يسمى بالمخزن أو ما يسمى ب Register خاص بال stack يسمى ESP وهو

stack pointer يشير الى قمه ال stack يتغير بعد كل عمليه تحدث فيه.

كيفيه عمل ال stack مع ال functions:

عندما يتم أستدعاء ال function يتم عمل عمليه push لل arguments الخاصه بها فى ال stack بعدها تتم نفس العمليه أيضا لما يسمى ب IP وهوا أختصار ل instruction pointer وهوا عباره عن عنوان يتم تسجيله من أجل أذا ما انتهت ال function من عملها يتم العوده الى هذا العنوان و تكمله سير البرنامج يخزن أيضا ما يسمى بالقيمه القديمه لل EBP و ال local variables الخاصه بال function.

تعرفنا على العلاقه القويه بين ال function و stack و عرفنا كيفيه أعطاء ال function ال arguments من خلال ال stack.

تعريف على Stack Buffer Overflows:

واحد من أشهر أنواع ال vulnerabilities الموجوده يستغل فى حاله ما أذا كانت ال function تأخذ قيم من المستخدم وتقوم بوضع هذه القيمه فى متغير ما أو مكان معين فى الذاكره وهوا ما يطلق عليه فى البرمجه buffer أما ال overflow يأتى من أن هذه ال function لا تقوم بعمليه فحص لحجم هذا المدخل ومقارنته بحجم ال buffer المخصص لها.

مثال بسيط:

buffer_1

شرح البرنامج:

هذا البرنامج كل ما عليه ان يأخذ معطى من المستخدم ثم طبعه على الشاشه مره أخرى وهذا يتم من خلال أثنين من ال functions الخاصه بالسى وهما gets, puts .
تقوم gets بأخذ مدخل من المستخدم و وضعه فى buffer معين يتم تحديده لها. أما عن puts تأخذ buffer وتقوم بطباعته على الشاشه.

ومن هنا تتحقق شروط ال buffer overflow وهي وجود function تتعامل مع ال stack وتأخذ arguments تأتى من المستخدم وهذه ال function لا تقوم بفحص للحجم.

نجد أيضا أنه يوجد عدد 2 function فى البرنامج واحده تستخدم من قيل ال main والاخرى لا يتم أستخدامها .

نقوم الان ب عمل compile للبرنامج كما هوا موضح:

gdb

هنا و أنا بقوم بهذه العمليه يوجد فى نظام تشغيل linux ما يسمى ب Address Space Randomization وهو يعطى عنوان عشوائى للبرنامج عند تنفيذه ولكن هنا قمنا بالسيطره على هذا السيناريو للشرح حتى أذا قمنا بتشغيل البرنامج مره أخرى بكون بنفس العناويين كما نقوم بألغاء الحمايه الداخليه لل stack وأيضا نفعل خاصيه الinternal debuger من أجل فحص البرنامج جزء جزء وهذه بعض الصور من البرنامج حين يعمل: حيث أقوم بعمل test لل buffer overflow

testprogramm

هنا قمنا بتجربه البرنامج أكثر من مره مع زياده حجم المدخل الذى يؤخد بواسطه gets ويخزن فى buffer ولكن هذا المخزن حجمه 8-bytes وحجم المدخل زادت عن هذا الحجم ومع الزياده ظهر ما يسمى ب segmentation fault وهذه رساله خطأ تحدث فى حالات معينه منها عند محاوله الوصول لعنون غير صحيح فى الذاكره ولمعرفه ماذا حدث لابد من عمليه تسمى ال debuging تسخدم فى ذلك أدوات كثيره أشهرها gdb
ثم نأخد المدخل الذى ظهر عنده الخطأ وندخله من خلال ال gdb لفحص محتوى ال stack عند هذه الحاله ومعرفه سبب حدوث الخطأ.
هنا ما حدث انه أخذ ال 8-bytes الخاصيين بال local buffer ثم أخذ تخطى ال old value for BP ثم بدأ بالكتابه فوق ال Return address وهذا العنوان هوا قيمه الIP المسجل فى ال stack من أجل الذهاب له بعد الانتهاء من الfunction فعند الذهاب يأتى أن يأخذ العنوان يجده عنوان لا وجود له وهذا هوا السبب فى ظهور الخطأ.

عند فتح البرنامج بال gdb يظهر كما هوا موضح بالصوره:

startgdb

نقوم بعمل break point عند كل ال functions الموجوده عندى فى البرنامج ثم نقوم بعمل  run للبرنامج بعمل ما يسمى ب disassemble لل main function لملاحظه العنوايين  كما هوا موضح:

1
الان البرنامج يتوقق عند أول سطر فى ال function normall لتنفيذها مع الفحص next ومن هنا نقوم بفحص ال stack ونقارن العناويين لمعرفه ال return address المخزن فى ال satck. ماذا تتوقع ان ترى فى هذا العنوان؟! لابد أن ترى ال address الذى يذهب أليه البرنامج بعد الانتهاء من تنفيذ ال function normall وهوا 0x08048486 مع التدقيق فى بيانات ال stack سوف ترى هذا العنوان موجودا به.
2
عند الانتقال الى الأمر التالى بأمر next سوف نصل للهدف وهوا أخذ البرنامج المدخل الخاص بيا. البرنامج أظهر الخطأ عند ال byte رقم ١٢ سوف أعطى أول 8-bytes حرف A و ال 4-bytes التاليه حرف B أما ال 4-bytes الاخيره حرف C لكى يصبح المدخل هكذا AAAAAAAABBBBCCCC
نعيد فحص ال stack ثانيه بعد هذه العمليه نجد أن قيمه ال return address تغيرت و أصبحت قيمتها 0x43434343 حيث أن ال ٤٣ هيا قيمه ال capital C بالأسكى وهذا دليل على مقدرتى على تغيير هذا العنوان.

ال function hacked غير مستخدمه فى البرنامج أطلاقا ولكن أذا حصلنا على عنوان هذه ال function فى الذاكره يكون من السهل اعطاء العنوان لل return address وبدل ما يسرى البرنامج فى طريقه الصحيح والمفترض يأخذ طريق أخر وهوا تنفيذ هذه ال function الغير مستخدمه فى main function ولكن كيف يمكن الحصول على عنوان هذه ال function؟ الجواب عن طريق disassemble function كما هوا موضح:

3

أخذ أول عنوان فى العناويين الموجوده و هو بدايه تنفيذ ال hacked function وهو 0x0804844c يمكننا الان الخروج من ال gdb لقد قمنا بالغرض الكامل منه.

هقوم الان بتشغيل البرنامج من خلال أعطائه المدخلات من خلال أداه printf التى يمكنها أعطاء قيم hex من خلال \x ولكن سوف هعطى العنوان بطريقه عكسيه نظرا لطريقه عمل ال stack كما شرحتا من قبل :
4
كما رأينا تم تنفيذ ال hacked function من قبل البرنامج بمجرد أعطائها عنوان ال function ومن هذا المثال رأينا نبذه عن ال buffer overflow وكيفيه التعامل معه.

ليس قليلا ما ذكر ولكن الذى ذكر فى المثال لمجرد التوضيح وليس البرنامج السابق صغير فهو جزء من application كبير و مشهور مثلا. وبدلا من أعطاء البرنامج المدخلات من خلال نفس الجهاز ممكن أن يأخذ مدخلاته من خلال port وبدلا أيضا من أجبار البرنامج على تنفيذ ال function صغيره كما فى المثال من الممكن ان اجبرها على تنفيذ كود خبيث موضوع عند عنوان معين فى الذاكره وأجبر البرنامج على تنفيذه.
أتمنى أن يكون قد نال أعجابكم….