مرحبا مرة أخرى! سنبدأ غدا فصولا في مجموعة جديدة في دورة
"الهندسة العكسية" . تقليديًا ، نشارك معك ترجمة مواد مفيدة حول الموضوع. دعنا نذهب!
من المهم بالنسبة لبعض المهاجمين أن يكون الاستغلال موثوقًا للغاية. يجب أن يؤدي دائمًا إلى تنفيذ التعليمات البرمجية عند تشغيله على نظام به نظام أساسي أساسي وإصدار من Flash. لإنشائه ، يمكنك استخدام الأخطاء عالية الجودة بشكل خاص. توضح هذه المقالة استخدام أحد هذه الأخطاء ، بالإضافة إلى العوامل التي تجعله مناسبًا بشكل خاص لعملية موثوقة.
علةCVE-2015-3077 - مشكلة تشويش الكتابة في أدوات تصفية Adobe Flash
Button و
MovieClip ، والتي تتيح لك الخلط بين أي
نوع من المرشحات وأي
نوع آخر. لقد أبلغت عن ذلك في أوائل ديسمبر 2015 ، وفي مايو تم إصلاحه. يحدث الخطأ لأن وحدة التكسير يمكنها الكتابة فوق المنشئ المستخدم لتهيئة كائن التصفية. ويرد أدناه رمز عينة استنساخ المشكلة:

هذا الرمز مربك نوعًا ما بسبب استخدام المشغل [] ، وهو أمر ضروري للتجميع في Flash CS. فيما يلي الشفرة المكافئة منطقياً (وهي ليست حقيقة تجمعها):

يعين هذا الرمز حقل تصفية الكائن: Button أو MovieClip إلى BlurFilter ، والذي يتم تخزينه بعد ذلك مباشرةً في Flash. ثم يتم الكتابة على مُنشئ BlurFilter بواسطة مُنشئ ConvolutionFilter. بعد ذلك ، يتم استدعاء getter ويتم إنشاء كائن ActionScript لتخزين BlurFilter الأصلي. ومع ذلك ، تم بالفعل الكتابة على المنشئ ، لذلك يسمى ConvolutionFilter. ينتج عن هذا كائن من النوع ConvolutionFilter ، مدعوم بإرجاع BlueFilter الأصلي.
في النهاية ، يمكن الوصول إلى حقول ConvolutionFilter (القراءة والكتابة) كما لو كانت تنتمي إلى BlurFilter. وبالمثل لأي نوع آخر من التصفية. هذا يفتح مجموعة واسعة من التلاعب مفيدة للاستغلال.
يوضح الرسم البياني أدناه موقع الكائنات الأصلية في الذاكرة التي يمكن أن يتم الخلط بينها وبين استخدام مشكلة عدم الحصانة هذه في Linux 64 بت.

في حالتين ، تكون المؤشرات قابلة للمقارنة بأعداد صحيحة وأرقام الفاصلة العائمة التي يمكن معالجتها. هذا يعني أنه يمكن قراءة المؤشرات وكتابتها مباشرة. بالإضافة إلى ذلك ، نظرًا لأن حقول الكائنات مرتبة وترتيب حسب الحجم وفقًا لتعريف الفئة ، فهي دائمًا في أماكن يمكن التنبؤ بها ، حتى لا تفشل الكتابة والقراءة. هذه الخصائص مهمة لضمان موثوقية الاستغلال.
استغلالنظرًا لأن استغلال هذه المشكلة يتطلب تشغيل تشويش الكتابة مرارًا وتكرارًا ، فقد بدأت بإنشاء وظيفة أداة مساعدة
لارتباك النوع ،
FilterConfuse.confuse . كما أنه يرتب الأمور: يُرجع مُنشئي عامل تصفية ActionScript مرة أخرى إلى حالته الطبيعية لاستدعاء وظيفة ضعيفة بشكل متكرر دون التأثير على سلوك ActionScript خارج الوظيفة نفسها.
كانت الخطوة الأولى هي تجاوز ASLR عن طريق تحديد عنوان جدول الوظائف الافتراضية (لفترة وجيزة vtable). الطريقة المثلى لذلك هي الخلط بين كائن ما و vtable مع كائن يوجد فيه عنصر متداخل مع vtable التي يمكن معالجتها. لكن vtable لجميع كائنات التصفية لها نفس الإزاحة. بدلاً من ذلك ، استخدمت
كائن BitmapData في DisplacementMapFilter لتحديد عنوان vtable.
لتحديد الموقع في ذاكرة الصورة النقطية للكائن ، أربكت DisplacementMapFilter مع BevelFilter. جعل هذا مؤشر BitmapData المخزن في DisplacementMapFilter محاذاة مع خصائص اللون
BevelFilter (
shadowColor و
shadowAlpha و
highlightColor و
highlightAlpha ). يتم دعم هذه الخصائص بواسطة عددين صحيحين 32 بت (كما هو موضح بالألوان ولون hc أعلى وأسفل) ، وخصائص اللون تصل إلى 24 بت من كل عدد صحيح ، بينما تصل خصائص ألفا إلى البتات 8 العليا. إذا قمت بقراءة هذه الخصائص ودمجها باستخدام حساب بت ، يمكنك استخراج عنوان BitmapData الفوري للكائن.

بعد ذلك ، تحتاج إلى قراءة vtable من أعلى الكائن BitmapData. لهذا ، استخدمت خاصية
المصفوفة للكائن ConvolutionFilter. يتم تخزينه كمؤشر إلى صفيف من أرقام الفاصلة العائمة ، والتي يتم بموجبها تخصيص الذاكرة عند تعيين الخاصية ، ويتم إرجاع صفيف ActionScript يحتوي على هذه الأرقام عند استلام الخاصية. عن طريق تعيين مؤشر المصفوفة إلى كائن BitmapData ، يمكنك قراءة محتويات هذا الكائن من الذاكرة كصفيف من أرقام الفاصلة العائمة.
لتعيين المؤشر ، أربكت كائن ConvolutionFilter بالكائن DisplacementMapFilter (وليس نفس DisplacementMapFilter المستخدم أعلاه!) وقم بتعيين موقع BitmapData للكائن أعلاه في خاصية
mapPoint . خاصية mapPoint هي نقطة ذات إحداثيات عدد صحيح x و y (p_x و p_y في الشكل أدناه) التي تتوافق مع مؤشر المصفوفة في ConvolutionFilter ، مما جعل من السهل تعيين هذه القيمة. بعد ذلك ، أصبح من الممكن قراءة vtable من كائن BitmapData باستخدام مصفوفة مصفوفة من كائن ConvolutionFilter (تجدر الإشارة إلى أنه لهذا الكائن كان يجب الخلط بينه وبين DisplacementBitmapFilter ، ومن ثم الخلط بينه وبين ConvolutionFilter).

في هذه المرحلة ، يصبح الحفاظ على موثوقية الاستغلال أكثر صعوبة بسبب استخدام أرقام الفاصلة العائمة. تتم قراءة القيم vtable_low و vtable_high من مصفوفة ConvolutionFilter كأرقام الفاصلة العائمة ، لأن هذا هو نوع صفيف. ولكن لسوء الحظ ، ليست كل قيمة مؤشر صالحة هي رقم نقطة عائم صالح. هذا يعني أن قراءة القيمة ستُرجع NaN ، أو ما هو أسوأ ، قيمة عددية غير صحيحة تمامًا.
من الناحية المثالية ، لحل هذه المشكلة ، تحتاج إلى الوصول إلى vtable_low و vtable_high من خلال getter ، مما يفسرها على أنها أعداد صحيحة ، ولكن هذا ليس لأن عناصر المرشح عادةً ما تطفو بسبب وظائفها.
لحسن الحظ ، فإن الجهاز الظاهري AS2 كسول بما يكفي لتفسير أرقام الفاصلة العائمة - إنه يحول فقط قيمة إلى تعويم عندما يتم إجراء عملية عليها في ActionScript. عادةً لا تتطلب العمليات الأصلية التفسير ، باستثناء العمليات الخاصة مثل الحساب. هذا يعني أنه عند نسخ رقم الفاصلة العائمة من مصفوفة مصفوفة إلى vtable_low أو vtable_high ، فإنه سيحتفظ بقيمته في الذاكرة ، حتى لو كان غير صالح للعائم ، في حين أن المتغير الذي تم نسخه فيه لا يستخدم في ActionScript أو لتنفيذ العمليات الحسابية في الأم كود. وبالتالي ، إذا تم خلط قيمة المتغير على الفور مع نوع آخر يدعم النطاق الكامل لقيم 32 بت ، على سبيل المثال int ، فإنه يضمن أن تكون هي نفسها القيمة الأصلية في ذاكرة مصفوفة المصفوفة. لذلك ، من أجل تجنب عدم الموثوقية في الاستغلال ، من المهم إجراء تشويش الكتابة قبل معالجة العوامات في ActionScript.
للقيام بذلك ، كتبت فئة تحويل ،
FloatConverter ، باستخدام تشويش النوع في عوامل التصفية لتنفيذ عدد صحيح إلى تعويم ووظائف تعويم إلى عدد صحيح. يخلط بين خاصية ColorMatrixFilter
المصفوفة (لا تخلط بينه وبين خاصية المصفوفة ConvolutionFilter) ، وهي عبارة عن مجموعة من العوامات المضمنة ، مع خصائص GlowFilter و
alpha التي تصل إلى وحدات البايت int المختلفة.

وبهذه الطريقة يمكنك تنفيذ تحويل موثوق للطفو إلى int ، لكن لسوء الحظ ، هذا لا يعمل بشكل صحيح في الاتجاه المعاكس. للوصول إلى مصفوفة اللون في ColorMatrix في ActionScript ، يتم نسخ المصفوفة بأكملها ، حتى لو قمت بالوصول إلى أولها فقط. عند نسخ صفيف ، يتم تحويل كل عنصر إلى رقم ، والذي يتضمن استدعاء للمؤشرات (على سبيل المثال ، استدعاء valueOf لكائن). نظرًا لأن مصفوفة الألوان هي الأطول من فئة GlowFilter بأكملها ، فإنها تنهال عند الخلط بينها وبين GlowFilter. هذا يعني أنه قد يحدث تحويل قيم غير معروفة من هذه الكومة ، مما سيؤدي إلى تعطل إذا كانت تشير إلى مؤشرات غير صالحة عند التحويل إلى رقم. لذلك ، بالنسبة إلى int-to-float ، قمت بتنفيذ محول عائم باستخدام تشويش آخر ConvolutionFilter و DisplacementMapFilter ، وهو ممثل مباشر ولا يستدعي قيمًا غير معروفة من الكومة.

يعمل هذا على حل مشكلة الأعطال الناتجة عن الوصول إلى قيم غير مألوفة من الكومة ، ولكن للأسف ، هناك مشكلة موثوقية أخرى مرتبطة بالتعويم في هذا الاستغلال. ويرجع ذلك إلى تطبيق getter مصفوفة getter. جميع القيم الرقمية في ActionScript 2 هي من النوع Number ، وهو اتحاد عدد صحيح ومؤشر برقم مزدوج. يتم تخزين مصفوفة ConvolutionFilter الأصلية كصفيف من أرقام الفاصلة العائمة ، ولكن يتم نسخها إلى صفيف ActionScript للحفاظ على الوصول عندما يتم استدعاء getter matrix ، ويتم تحويل القيم إلى مضاعفة في العملية. بعد ذلك ، عند استدعاء محول التعويم ، يتم تحويلها مرة أخرى إلى أرقام الفاصلة العائمة.
يؤدي الاحتفاظ برقم الفاصلة العائمة إلى رقم مزدوج الدقة والعكس بالعكس عادةً إلى حفظ قيمته ، ولكن ليس إذا كانت القيمة العائمة هي SNaN. وفقًا لمواصفات النقطة العائمة ، هناك نوعان من NaNs: NaN الصامت (QNaN) والإشارة NaN (SNaN). عندما يظهر QNaN ، لا يحدث شيء ، لكن SNaN في بعض الحالات يطرح استثناء الفاصلة العائمة. في x86 ، ينتج عن التحويل المزدوج إلى تعويم دائمًا QNaN (حتى إذا جاء مضاعف من SNaN) لتجنب استثناءات غير متوقعة.
لذلك ، إذا كانت البتات الأدنى من المؤشر هي SNaN ، فسيتم تحويلها إلى QNaN ، مما يعني أنه سيتم تعيين البتة الأولى (بت البزارة العقيمة الأولى ، البتة 22) عندما لا ينبغي لها ذلك. يمكن تجنب هذه المشكلة عند قراءة vtable - يمكن قراءة البايت الثالث من المؤشر الذي يحتوي على البتة الأولى دون محاذاة لتأكيد القيمة الحالية. وبالتالي ، ستتم قراءة التعليمات البرمجية دون محاذاة (بعد قراءة vtable مرة أخرى مع زيادة مؤشر الصورة النقطية بواحد) وضبط قيمة int إذا تبين أن العائمة SNaN.
باستخدام محولات الطفو الموضحة أعلاه ، يمكن تحويل عنوان vtable إلى عدد صحيح. أنت الآن بحاجة إلى الحصول على الرمز للتنفيذ باستخدام هذا العنوان. تتمثل إحدى الطرق السهلة لتحريك مؤشر التعليمات في الكتابة فوق vtable للكائن (أو مؤشر لكائن به vtable). يمكن القيام بذلك عن طريق الخلط بين مصفوفة مصفوفة ConvolutionFilter و BitmapData لمؤشر DisplacementFilter.
نهاية الجزء الاول. سيتم نشر الجزء الثاني من الترجمة بعد ذلك بقليل ، ونحن الآن في انتظار تعليقاتكم وندعو الجميع إلى دورة
الهندسة العكسية لـ OTUS.