سؤال

هذا هو رمز قذيفة لاستغلال ثغرة الأمن المخزن المؤقت. يضبط 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 سجل النظام الذي نتحدث عنه.

  1. اضبط ٪ EBX إلى 0
  2. حساب ٪ EBX+23 وتخزين النتيجة في ٪ eax (رمز opcy lea باعتبارها "تحميل عنوان فعال" ولكن ليس الوصول إلى الذاكرة ؛ هذه مجرد طريقة ملتوية لإجراء إضافة).
  3. استدعاء النظام. ٪ EAX يحتوي على 23 ، مما يعني أن مكالمة النظام هي setuid. تستخدم مكالمة النظام هذه وسيطة واحدة (الهدف UID) ، والتي يمكن العثور عليها في ٪ EBX ، والتي تحتوي بشكل مناسب على 0 في تلك المرحلة (تم تعيينها في التعليمات الأولى). ملاحظة: عند العائد ، تكون السجلات غير معدلة ، باستثناء ٪ EAX التي تحتوي على القيمة التي تم إرجاعها لمكالمة النظام ، عادة 0 (إذا كانت المكالمة نجاحًا).
  4. دفع ٪ ebx على المكدس (الذي لا يزال 0).
  5. $ 0x68732f6e على المكدس.
  6. اضغط $ 0x69622F2F على المكدس. نظرًا لأن المكدس ينمو "لأسفل" وبما أن معالجات X86 يستخدمون ترميز Endian قليلاً ، فإن تأثير التعليمات من 4 إلى 6 هو أن ٪ ESP (مؤشر المكدس) يشير الآن إلى تسلسل اثني عشر بايت ، من القيم 2F 62 69 6E 2F 73 68 00 00 00 00 (في سداسي عشري). هذا هو ترميز سلسلة "// bin/sh" (مع صفر الإنهاء ، وثلاثة أصفار إضافية بعد ذلك).
  7. نقل ٪ esp إلى ٪ ebx. الآن يحتوي EBX على مؤشر إلى سلسلة "// bin/sh" التي تم بناؤها أعلاه.
  8. دفع ٪ eax على المكدس (٪ eax هو 0 في تلك المرحلة ، هو الحالة التي تم إرجاعها من setuid).
  9. ادفع ٪ ebx على المكدس (مؤشر إلى "// bin/sh"). تعليمات 8 و 9 بناء على المكدس مجموعة من مؤشرين ، الأول هو المؤشر إلى "// bin/sh" والثاني مؤشر فارغ. هذا الصفيف هو ما execve ستستخدم استدعاء النظام كوسيطة ثانية.
  10. نقل ٪ esp إلى ٪ ecx. الآن ٪ ECX يشير إلى المصفوفة التي تم بناؤها مع تعليمات 8 و 9.
  11. Sign-Extend ٪ EAX في ٪ edx: ٪ eax. cltd هل بناء جملة AT&T لما تسمى وثائق Intel cdq. نظرًا لأن ٪ eax يكون صفرًا في هذه المرحلة ، فإن هذا يضع ٪ edx إلى صفر أيضًا.
  12. حدد ٪ AL (أقل بايت مهم من ٪ EAX) إلى 11. بما أن ٪ EAX كان صفر ، فإن القيمة الكاملة للنسبة ٪ EAX هي الآن 11.
  13. استدعاء النظام. تحدد قيمة ٪ 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 التي تم إنهاءها الصفري. هذا يهدف إلى مهاجمة برامج العربات التي تجرها الدواب من خلال الفائض العازلة ، بالطبع.

مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top