إيجاد الـ Bad Characters في الـ Shellcode
الكاتب: صبري صالح | يوم: 12 يناير, 2011 | التعليقات: 18 | القراءات: - عدد المشاهدات 26٬998
مقدمة
في مرحلة من مراحل كتابتنا لثغرة BufferOverflow فإننا قد نعاني من مشكلة مملة و نجد أن الـPayload يعطّل الـ Exploit بكامله مع أننا قد تأكدنا أن كل شئ يمشى بأفضل حال قبل وضع الـ Shellcode الحقيقي. السبب في ذلك هو وجود الـ Bad Characters أو الـ Restricted Characters.
ستكتشف تلك المشكلة عندما تضع نقطة وقوف Break Point في الـ Debugger ولكن عند تنفيذ الثغرة لن تصل إلى ذلك العنوان. أو أنك ستصل ولكن الـ Shellcode لن يعمل (بشرط تأكدك أن جميع الأجزاء الأخرى سليمة).
ما هي الـ Bad/Restricted Characters؟
هي Characters عادية من ضمن الـ Shellcode يتم عمل Decoding لها بشكل طبيعي ولكن لها معنى لا يقبله البرنامج المصاب كأن يكون هذا الـ Characters سيدخل في تسمية ملف مثلا و فلو فرضنا أن في الشل كود قيمة ستدخل في تسمية ملف ما و كانت القيمة “\x7D” و التي تعني “}” و من المعروف أننا لا نستطيع وضع هذا الحرف في إسم ملف فوقتها سيوقف هذا الحرف مجرى عملية الـ Decoding للـ Shellcode.
قد يبدر إلى أذهاننا بعض الأسئلة, منها..
س/ هل جميع البرامج المصابة سيكون بها Bad Characters Restriction ؟
ج/ لا
س/ هل يوجد Bad Characters أساسية يجيب أزيلها من أي Shellcode أقوم بعمله؟
ج/ نعم, هما: x00 و x0d
س/ هل كل البرامج لها نفس الـ Bad Characters أي أنني أستطيع أن أحذف كل ما تم اكتشافه سابقا في البرامج اللاحقة؟
ج/ لا, لكل برنامج Bad Characters مختلفة تختلف بطبيعة البرنامج و طريقة تنفيذه
س/ هل يمكن أن يحتوي البرنامج على أكثر من Bad Character واحد ؟
ج/ للأسف نعم
إيجاد الـ Bad Characters – الطريقة الأولى
في البداية, هذه الطريقة هي طريقة مملة و مرهقة جدا و إن كنت سأعطيها إسما فلا أجد أفضل من “طريقة السكتة الدماغية“ حيث يتوقف العقل عن التفكير تماما مع الحاجة إلى الكثير من العمل الممل إلا إذا كنت محظوظ و وجدت الحرف في أول سطر أو سطرين, وأمر الحظ بالذات غير متوفر بالنسبة لي شخصيا.
تعتمد هذه الطريقة على إنشاء جميع احتمالات الحروف من 0-255 عن طريق سكريبت يسمى generatecodes.pl.
في البداية تقوم بتنفيذ السكريبت مع إزالة الـBad Characters الشائعة x00 و x0d .
./generatecodes.pl 00,0d
"\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0a\x0b\x0c\x0e\x0f\x10"
"\x11\x12\x13\x14\x15\x16\x17\x18\x19\x1a\x1b\x1c\x1d\x1e\x1f"
"\x20\x21\x22\x23\x24\x25\x26\x27\x28\x29\x2a\x2b\x2c\x2d\x2e"
"\x2f\x30\x31\x32\x33\x34\x35\x36\x37\x38\x39\x3a\x3b\x3c\x3d"
"\x3e\x3f\x40\x41\x42\x43\x44\x45\x46\x47\x48\x49\x4a\x4b\x4c"
"\x4d\x4e\x4f\x50\x51\x52\x53\x54\x55\x56\x57\x58\x59\x5a\x5b"
"\x5c\x5d\x5e\x5f\x60\x61\x62\x63\x64\x65\x66\x67\x68\x69\x6a"
"\x6b\x6c\x6d\x6e\x6f\x70\x71\x72\x73\x74\x75\x76\x77\x78\x79"
"\x7a\x7b\x7c\x7d\x7e\x7f\x80\x81\x82\x83\x84\x85\x86\x87\x88"
"\x89\x8a\x8b\x8c\x8d\x8e\x8f\x90\x91\x92\x93\x94\x95\x96\x97"
"\x98\x99\x9a\x9b\x9c\x9d\x9e\x9f\xa0\xa1\xa2\xa3\xa4\xa5\xa6"
"\xa7\xa8\xa9\xaa\xab\xac\xad\xae\xaf\xb0\xb1\xb2\xb3\xb4\xb5"
"\xb6\xb7\xb8\xb9\xba\xbb\xbc\xbd\xbe\xbf\xc0\xc1\xc2\xc3\xc4"
"\xc5\xc6\xc7\xc8\xc9\xca\xcb\xcc\xcd\xce\xcf\xd0\xd1\xd2\xd3"
"\xd4\xd5\xd6\xd7\xd8\xd9\xda\xdb\xdc\xdd\xde\xdf\xe0\xe1\xe2"
"\xe3\xe4\xe5\xe6\xe7\xe8\xe9\xea\xeb\xec\xed\xee\xef\xf0\xf1"
"\xf2\xf3\xf4\xf5\xf6\xf7\xf8\xf9\xfa\xfb\xfc\xfd\xfe\xff"
الأن نأخذ أول سطر من المخرجات و نستبدل الـ Shellcode بهذا السطر و نضع الـ Break Point خاصتنا و من ثم ننفذ البرنامج. إذا وصلنا للعوان الصحيح فهذا يعني أن Bad Characters ليست من ضمن الحروف التي في السطر الأول.
مثال:
shellcode = ("\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0a\x0b\x0c\x0e\x0f\x10")
الأن نضيف السطر الثاني من المخرجات إلى السطر الأول و نضع الـ Break Point خاصتنا و من ثم ننفذ البرنامج. إذا وصلنا للعوان الصحيح فهذا يعني أن Bad Characters ليست من ضمن الحروف التي في السطر الثاني, و هكذا.
مثال:
shellcode = ("\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0a\x0b\x0c\x0e\x0f\x10"
"\x11\x12\x13\x14\x15\x16\x17\x18\x19\x1a\x1b\x1c\x1d\x1e\x1f")
عندما لا نصل للعنوان الصحيح, نقوم بقسم السطر الذي وصلنا عنده و حصل عنده خطأ في النتائج و نستبدل النصف الأول منه بـ “\x41” مثلا . ثم نجرب فإن حصل خطأ, فهذا يعني أن الـ Bad Character في النصف الأخر, وقتها نبدأ نغير حروف النصف الثاني من السطر الأخير إلى “\x41” و نجرب في كل مره حتى نصل أنه لا يوجد خطأ في النتائج و عندها سنعرف ال Bad Character
مثال:
"\x41\x41\x41\x41\x41\x41\x41\x41\x28\x29\x2a\x2b\x2c\x2d\x2e"
سنفترض أننا وجدنا و أنه “x0a” إذا سنقول بعمل الأتي
./generatecodes.pl 00,0d,0a
"\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0b\x0c\x0e\x0f\x10\x11"
"\x12\x13\x14\x15\x16\x17\x18\x19\x1a\x1b\x1c\x1d\x1e\x1f\x20"
"\x21\x22\x23\x24\x25\x26\x27\x28\x29\x2a\x2b\x2c\x2d\x2e\x2f"
"\x30\x31\x32\x33\x34\x35\x36\x37\x38\x39\x3a\x3b\x3c\x3d\x3e"
"\x3f\x40\x41\x42\x43\x44\x45\x46\x47\x48\x49\x4a\x4b\x4c\x4d"
"\x4e\x4f\x50\x51\x52\x53\x54\x55\x56\x57\x58\x59\x5a\x5b\x5c"
"\x5d\x5e\x5f\x60\x61\x62\x63\x64\x65\x66\x67\x68\x69\x6a\x6b"
"\x6c\x6d\x6e\x6f\x70\x71\x72\x73\x74\x75\x76\x77\x78\x79\x7a"
"\x7b\x7c\x7d\x7e\x7f\x80\x81\x82\x83\x84\x85\x86\x87\x88\x89"
"\x8a\x8b\x8c\x8d\x8e\x8f\x90\x91\x92\x93\x94\x95\x96\x97\x98"
"\x99\x9a\x9b\x9c\x9d\x9e\x9f\xa0\xa1\xa2\xa3\xa4\xa5\xa6\xa7"
"\xa8\xa9\xaa\xab\xac\xad\xae\xaf\xb0\xb1\xb2\xb3\xb4\xb5\xb6"
"\xb7\xb8\xb9\xba\xbb\xbc\xbd\xbe\xbf\xc0\xc1\xc2\xc3\xc4\xc5"
"\xc6\xc7\xc8\xc9\xca\xcb\xcc\xcd\xce\xcf\xd0\xd1\xd2\xd3\xd4"
"\xd5\xd6\xd7\xd8\xd9\xda\xdb\xdc\xdd\xde\xdf\xe0\xe1\xe2\xe3"
"\xe4\xe5\xe6\xe7\xe8\xe9\xea\xeb\xec\xed\xee\xef\xf0\xf1\xf2"
"\xf3\xf4\xf5\xf6\xf7\xf8\xf9\xfa\xfb\xfc\xfd\xfe\xff"
و نتأكد مرة أخرى, لو لظهر أي خطأ في مجرى سير البرنامج في الـ Debugger إذن كل شئ على ما يرام. و إن لم!!, فهذا يعني -ولا حول ولا قوه إلا بالله- أنه يوجد Bad Character أخر و يجب أن تكمل المسيرة حتى تجده.
إيجاد الـ Bad Characters – الطريقة الثانية – تحديث 19/2/2013
قام فريق Corelan بإيقاف تطوير الإضافة pvefindaddr واستبدلها بالإضافة الجديدة والأفضل mona.py مع استخدام الدالة compare
حمل الإضافة من هنا mona.py
كل ما عليك فعله هو وضع الإضافة في مجلد الـمنقح Immunity debugger في المسار التالي
C:\Program Files\Immunity Inc\Immunity Debugger\PyCommands
ثم ضع ملف الـ Shellcode في الـ C حيث يكون مساره
c:\shellcode.bin
ملاحظة: إذا كان الـShellcode بصيغة الـ Hex فيجب تحويله إلى Binary , الرجاء زيارة هذا الرابط
الأن ضع الـ Break point خاصتك ثم نفذ الـ exploit الذي يحتوي على الـ shellcode الحقيقي
بمجرد توقف البرنامج, نفذ الأمر التالي في Command bar في الـ Immunity Debugger
!mona compare c:\shellcode.bin
ستخرج لك نافذة تحتوي على العناوين التي تتواجد بها الـ Bad Characters مثل هذه
الأن اذهب إلى نافذة الـسجلات من
View >> Log أو اضغط ALT + L
ستجد التالي: (يرجى تكبير الصورة)
كما ترى في حالتي كانت الـ Bad Characters هي 5c و 2f
أيضا تستطيع أن تجد النتائج في ملف compare.txt على هذا المسار
“C:\Program Files\Immunity Inc\Immunity Debugger“
(هذا المسار يحتوي على معظم نتائج استخدام mona.py).
إيجاد الـ Bad Characters – الطريقة الثانية
في البداية أحب أن أرفع القبعة إلى Peter Van رئيس فريق Corelan و هو من أشهر و أقوى الأشخاص في شرح الـ Buffer Overflow ومبرمج للعديد من السكربتات المفيدة جدا في هذا المجال.
الطريقة الثانية هي عن طريق إضافة رائعة إسمها pvefindaddr مع استخدام الدالة compare
ملاحظة: لا تنسى إضافة pvefindaddr فلها استخدامات كثيرة و رائعة في الـ Buffer Overflow
كل ما عليك فعله هو وضع الإضافة في مجلد الـمنقح Immunity debugger في المسار التالي
C:\Program Files\Immunity Inc\Immunity Debugger\PyCommands
ثم ضع ملف الـ Shellcode في الـ C حيث يكون مساره
c:\shellcode.bin
ملاحظة: إذا كان الـShellcode بصيغة الـ Hex فيجب تحويله إلى Binary , الرجاء زيارة هذا الرابط
الأن ضع الـ Break point خاصتك ثم نفذ الـ exploit الذي يحتوي على الـ shellcode الحقيقي
بمجرد توقف البرنامج, نفذ الأمر التالي في Command bar في الـ Immunity Debugger
!pvefindaddr compare c:\shellcode.bin
ستخرج لك نافذة تحتوي على العناوين التي تتواجد بها الـ Bad Characters مثل هذه
الأن اذهب إلى نافذة الـسجلات من
View >> Log أو اضغط ALT + L
ستجد التالي: (يرجى تكبير الصورة)
كما ترى في حالتي كانت الـ Bad Characters هي 5c و 2f
أيضا تستطيع أن تجد النتائج في ملف compare.txt على هذا المسار
“C:\Program Files\Immunity Inc\Immunity Debugger“ (هذا المسار يحتوي على معظم نتائج استخدام pvefindaddr).
تحياتي واحترامي
المهندس صبري صالح. مهندس حماية شبكات و أنظمة و فحصها معالجة و تحليل الأحداث الأمنية و المسؤول عن تطبيق معايير الـ ISO 27001 , يعمل في بيئات متعددة المنصات. حاصل على عدة شهادات تقنية.
التعليقات:
اترك تعليقاً | عدد التعليقات: (18)
يارجل تسلم يمناك على هذا الموضوع …
يبدو صاير تدرس وتتعلم من وراي 🙂
ألف شكر يا صبري على هالموضوع ولا تحرمنا من إبداعاتك …
يوجد كنز مخفي بداخلك، سنخرجه من خلال Security4Arabs بإذن الله !
دمت بود …
بارك الله فيك أستاذ صبري ونفع الله بك على هذه المقالة الرائعة. ولكن فقط لمزيد من ال توضيح :
سأوضح لما هما غير مرغوبين . ( سببت لي مشاكل عندما قرأت عنها أول مرة ولم أكن
أفهم سببها , حتى بعد وقت طويل. لذا سأحاول توضيحها لمن لم يفهمها 🙂 )
ربما يجهل البعض لم هذه المحرّفات (Bad Characters) السبب أن الأولى “x00”
والتي تعني NULL في جدول الآسكي و تمثّل نهاية سلسلة نصّية . مثلاً في الأسمبلي إذا
أردت تعريف متغير نصّي اسمه “text” مثلاً :
text db “My name is Barakat”,0
يوضع الصفر ( في النظام الست عشري 0x00 ) . لإخبار بنهاية السلسلة النصيّة
لذا سيتم تجاهل مابعد !. لمزيد من الفهم , أنشئ ملف بالإمتداد c : ـ
#include
int main() {
printf(“My name is Barakat\n”);
return 0;
}
شغل هذا البرنامج المكتوب بالسي بعد( ترجمته) , ستجده طبع My name is Barakat
جرّب أن تفتحه بأي hex editor (في لينكس توجد الأداة hexedit متوفرة مع النظام )
إبحث عن النص السابق وإستبدل قيمة الحرف i (في النظام الست عشري 0x69 )
بـ x00 أو 00 (حرف x إشارة بأنها قيمة هكس فقط ). ماذا سيطبع ؟
ستجده يطبع My name فقط !
الآن ماذا لو كان هذا المحرّف في الشل كود ؟ سيتم تجاهل الباقي من الشل ولن ينفّذ “حتماُ تم تخريبة ” \ :
x0D أو 0xD, يمثل هذا المحرّف “r\” في جدول الآسكي. وتعمل عكس الـ NULL .
حيث يتم تجاهل ماقبلها (بينما في الأولى العكس “مابعدها”). جرب أن تستخدم المثال الأول
وتستبدل قيتمة حرف “i” بـ “x0D أو 0D”.
ستجد أنه طبع : s Barakat
لست متأكد من مشكلتها بصراحة مع الشل لأنني لا أعرف طريقة تنفيذة فالمفترض أن
ماسبق تنفيذه من الشل لايهم . الا اذا كانت هناك قفزة للخلف بعد هذا المحرّف. مما يعني
أنها قد لاتكون دائماً Bad Characters. ربما في بعض الشلات , وربما في مواضع
مثلاً لو كان لديك إثنان منها , قد يكون الأول Bad Characters والثاني لا !
وأبسط حل التخلص منها كلها فلا وجود للمزاجية p: .
ربما تكون هنا طريقة ثالثة ( لست متأكد ) وهي تشفير الشل بإستخدام الأداة ALPHA2 حيث تشفره بمحرّفات
لاتسبب مشاكل عادة وتنتج شل كود مشفر بالمحرفات 0-9 و A-Z قرأتها هنا :
http://skypher.com/wiki/index.php/Hacking/Shellcode/Alphanumeric/ALPHA2
أرجو الإطلاع عليها.
زادك الله علما أخي صبري والإخوة في مجتمع الحماية ووفقكم الله لكل خير .
أخي بركات بارك الله فيك على هذه الإضافة الرّائعة.
@Binary: حياك الله دكتور,, أبدا والله فقط أحببت أن أرفع معنوياتي بكتابة موضوع أما ما تم كتابته فهو من بعض ما عندكم. يكفي أن الموضوع أعجبك يأبو محمد
@بركاتـ: سلمت يداك حفظك الله و بالطبع استفدنا من إضافتك الرائعة
لكن أريد أن انوه أن استخدام الـ Encoders يزيد من حجم الـ Shellcode و هذا الشئ أحيانا يكون غير مسموح به حيث الحجم المسموح به يكون محدود و لهذا ابتعدت عن هذه الطريقة لأني عانيت من مسألة حجم الـShellcode في وقت كان حساس جدا.
مرة أخرى سلمت يداك أخوي بركات و كثر الله من أمثالك
صبري، إذا ومعنويّات هابطة وقدّمت هذا الإبداع، كيف وهي مرتفعة؟ 🙂
جزاك الله خيراً على هذا الموضوع (السلسلة) الرّائعة
@بشار: حياك الله أخوي ,,
إن شاء الله تتحسن الأمور في المستقبل القريب و نرجع بأي خبر جيد 🙂
بارك الله فيك يا مهندس
ماشاء الله تبارك الله, عقول جداً راقيه بمفهومها وبتوصيل تلك المعلومه بالطريقه الصحيحه,
بارك الله فيك أخي صبري.
موضوع يستحق القراءه أكثر من مّره.
السلام عليكم
الله يعطيك العافية ما قصرت على التوضيح
بالنسبة لأستخدم ال encoding وبعض الانواع تحتاج الى احد الريجسترات يكون يؤشر الى مكان مسموح فيه الكتابه …. فقط الalpha هو الي ما يحاتج ريجستر لكن تحتاج تقريبا الى دبل حجم الشل العادي
بالتوفيق
طيب انت متاكد ان carriage return دائما bad
x0d??
@واحد أقرأ الردود و ستفهم و تجد رد على سؤالك
اه انت قلت ان دائما بيبقى bad ممكن اعرف ليه ؟
@واحد: ال bad char يختلف من برنامج لآخر حسب كيفية تعامله مع البيانات لكن هناك بعض chars التي تكون bad في أغلب البرامج
و منها 00 0a 0d
لكن ممكن أن نجد برامج تقبل حتى null byte
بالمناسبة كيف الأحوال lnxg33k ؟ 😉
عنوان العوده مش شرط يكون bad char على الفكره
wxcxw@ كلامك فل ال null مش شرط يكون bad 🙂
افضل طريقه هى استخدام pvefindaddr او اى differ اخر
انا مش lnxg33k بس انا واحد بتكلم معاه فى #corelan
IRC
[…] مراجعة موضوع (قمت بتحديث الموضوع): إيجاد الـ Bad characters في الـ Shellcode إيجاد الـ Bad Characters في الـ […]
ولا عجب
الناس تركض خلف دروس البفر اوفرفلو، واخر رد في هذا المووضوع 2011!!!
ملاحظة بعد 4 سنوات
هذه bad char في معظم البرامج وانا دائما اتجنبها
x00
xff
x0a
x0d
x1a
بارك الله فيكم والله نورتونا بمعلوماتكم القيم
شكر اخ بركات واخ ThreatActor على الاضافات المميزة
زادكم الله علما ويحفظ والديكم
موضوع جدا مهم وقوي ونفتقر في العالم العربي عن مثل هذه المواضيع
ولكن عندي تعقيب على Bad Characters
انها غالباً تكوني
\x0d
ولكن الاجهزه الجديده win7 and 8 and 10
ماتكون x0d من ضمن Bad Characters
الاكيد يكون فقط \x00
وايضا على حسب البرنامج
في برنامج اشتغلت عليه
كان Bad Characters
\x00\x04\x37\x44\x62\xb8
وكان برنامج على win 7
وصحيح الموضوع قديم ولكن المعلومات قيمه
وايضا الاجهزه الجديده صارت تظهر شكل Bad Characters بشكل التالي
\x0b\x0b
نفترض انه السطر الاول بشكل هذا
x01\x02\x03\x04\x05\x06\x07\x08\x09\x0a\x0b\x0c\x0d\x0e\x0f
وكان Bad Characters موجود
راح يظهر بهذا الشكل
x01\x02\x03\x04\x05\x06\x07\x0b\x0b\x0a\x0b\x0c\x0d\x0e\x0f
نلاحظ تم اضافه ( x0b\x0b )
هنا Bad Characters فقط x08 في حال تم الحذف سوف يظهر بهذا الشكل
x01\x02\x03\x04\x05\x06\x07\x09\x0a\x0b\x0c\x0d\x0e\x0f
وشكرا لكم