كيف يمكنني شرح سلوك استغلال رمز الصدفة التالي؟
-
29-09-2019 - |
سؤال
هذا هو رمز قذيفة لاستغلال ثغرة الأمن المخزن المؤقت. يضبط setuid(0)
ويولد قذيفة باستخدام execve()
. فيما يلي الطريقة التي فسرتها:
xor %ebx,%ebx ; Xoring to make ebx value 0
lea 0x17(%ebx),%eax ; adds 23 to 0 and loads effective addr to eax. for setuid()
int $0x80 ; interrupt
push %ebx ; push ebx
push $0x68732f6e ; push address // why this address only????
push $0x69622f2f ; push address // same question
mov %esp,%ebx
push %eax
push %ebx
mov %esp,%ecx
cltd ; mov execve sys call into al
mov $0xb,%al
int $0x80 ; interrupt
هل يمكن لأي شخص أن يشرح الخطوات بأكملها بوضوح؟
المحلول
int
هو الرمز opcode لإطلاق مقاطعة البرنامج. يتم ترقيم المقاطعات البرمجية (من 0 إلى 255) ويتم معالجتها بواسطة kernel. على أنظمة Linux ، المقاطعة 128 (0x80) هي نقطة الدخول التقليدية لمكالمات النظام. يتوقع kernel حجج استدعاء النظام في السجلات ؛ على وجه الخصوص ، يحدد ٪ eax سجل النظام الذي نتحدث عنه.
- اضبط ٪ EBX إلى 0
- حساب ٪ EBX+23 وتخزين النتيجة في ٪ eax (رمز opcy
lea
باعتبارها "تحميل عنوان فعال" ولكن ليس الوصول إلى الذاكرة ؛ هذه مجرد طريقة ملتوية لإجراء إضافة). - استدعاء النظام. ٪ EAX يحتوي على 23 ، مما يعني أن مكالمة النظام هي
setuid
. تستخدم مكالمة النظام هذه وسيطة واحدة (الهدف UID) ، والتي يمكن العثور عليها في ٪ EBX ، والتي تحتوي بشكل مناسب على 0 في تلك المرحلة (تم تعيينها في التعليمات الأولى). ملاحظة: عند العائد ، تكون السجلات غير معدلة ، باستثناء ٪ EAX التي تحتوي على القيمة التي تم إرجاعها لمكالمة النظام ، عادة 0 (إذا كانت المكالمة نجاحًا). - دفع ٪ ebx على المكدس (الذي لا يزال 0).
- $ 0x68732f6e على المكدس.
- اضغط $ 0x69622F2F على المكدس. نظرًا لأن المكدس ينمو "لأسفل" وبما أن معالجات X86 يستخدمون ترميز Endian قليلاً ، فإن تأثير التعليمات من 4 إلى 6 هو أن ٪ ESP (مؤشر المكدس) يشير الآن إلى تسلسل اثني عشر بايت ، من القيم 2F 62 69 6E 2F 73 68 00 00 00 00 (في سداسي عشري). هذا هو ترميز سلسلة "// bin/sh" (مع صفر الإنهاء ، وثلاثة أصفار إضافية بعد ذلك).
- نقل ٪ esp إلى ٪ ebx. الآن يحتوي EBX على مؤشر إلى سلسلة "// bin/sh" التي تم بناؤها أعلاه.
- دفع ٪ eax على المكدس (٪ eax هو 0 في تلك المرحلة ، هو الحالة التي تم إرجاعها من
setuid
). - ادفع ٪ ebx على المكدس (مؤشر إلى "// bin/sh"). تعليمات 8 و 9 بناء على المكدس مجموعة من مؤشرين ، الأول هو المؤشر إلى "// bin/sh" والثاني مؤشر فارغ. هذا الصفيف هو ما
execve
ستستخدم استدعاء النظام كوسيطة ثانية. - نقل ٪ esp إلى ٪ ecx. الآن ٪ ECX يشير إلى المصفوفة التي تم بناؤها مع تعليمات 8 و 9.
- Sign-Extend ٪ EAX في ٪ edx: ٪ eax.
cltd
هل بناء جملة AT&T لما تسمى وثائق Intelcdq
. نظرًا لأن ٪ eax يكون صفرًا في هذه المرحلة ، فإن هذا يضع ٪ edx إلى صفر أيضًا. - حدد ٪ AL (أقل بايت مهم من ٪ EAX) إلى 11. بما أن ٪ EAX كان صفر ، فإن القيمة الكاملة للنسبة ٪ EAX هي الآن 11.
- استدعاء النظام. تحدد قيمة ٪ eax (11) استدعاء النظام باسم
execve
.execve
يتوقع ثلاث وسيطات ، في ٪ ebx (مؤشر إلى سلسلة لتسمية الملف لتنفيذها) ، ٪ ecx (مؤشر إلى مجموعة من المؤشرات إلى الأوتار ، وهي وسيطات البرنامج ، أول نسخة من اسم البرنامج ، يستخدمه البرنامج الذي تم استدعاؤه نفسه) و ٪ EDX (مؤشر إلى مجموعة من المؤشرات إلى الأوتار ، والتي هي متغيرات البيئة ؛ يتحمل Linux تلك القيمة لتكون لاغية ، لبيئة فارغة) ، على التوالي.
لذا فإن الكود يدعو أولاً setuid(0)
, ، ثم المكالمات execve("//bin/sh", x, 0)
أين x
يشير إلى مجموعة من مؤشرين ، أول واحد هو مؤشر إلى "// bin/sh" ، في حين أن الآخر فارغ.
هذا الرمز معقد تمامًا لأنه يريد تجنب الأصفار: عند تجميعها في رموز opcodes الثنائية ، يستخدم تسلسل التعليمات فقط بايت غير صفري. على سبيل المثال ، إذا كانت التعليمات الثانية عشرة movl $0xb,%eax
(تعيين ٪ EAX بالكامل إلى 11) ، ثم كان التمثيل الثنائي لهذا الرمز opcane يحتوي على ثلاثة بايت من القيمة 0. عدم وجود صفر يجعل هذا التسلسل قابلاً للاستخدام كمحتويات لسلسلة C التي تم إنهاءها الصفري. هذا يهدف إلى مهاجمة برامج العربات التي تجرها الدواب من خلال الفائض العازلة ، بالطبع.