
تطبيق برهان المفهوم لخادع مكدس الاستدعاء الديناميكي بالكامل
تنفيذ PoC لمزيف مكدس استدعاءات ديناميكي بالكامل
SilentMoonwalk هو تنفيذ PoC لمزيف مكدس استدعاءات ديناميكي بالكامل، يطبق تقنية لإزالة المستدعي الأصلي من مكدس الاستدعاءات، باستخدام ROP لإلغاء تزامن فك الترجيع مع تدفق التحكم.
هذا الـ PoC هو نتيجة بحث مشترك حول موضوع تزوير مكدس الاستدعاءات. مؤلفو البحث هم:
أود التأكيد على أن هذا العمل كان مستحيلاً لولا عمل Waldo-IRC و Trickster0، حيث ساهم كلاهما في المراحل المبكرة من الـ PoC، وفي البحث وراء الـ PoC.
يُظهر هذا المستودع تنفيذ PoC لتزوير مكدس الاستدعاءات عند استدعاء واجهات برمجة تطبيقات ويندوز عشوائية.
كانت هذه المحاولة مستوحاة من سلسلة التغريدات هذه و سلسلة التغريدات هذه، حيث أظهر وأشار السينسي namazso إلى توسيع نهج فك الترجيع للمكدس باستخدام سلسلة ROP لإلغاء تزامن فك الترجيع عن تدفق التحكم الحقيقي واستعادة المكدس الأصلي بعد ذلك.
يحاول هذا الـ PoC القيام بشيء مشابه لما سبق، ويستخدم مكدس إلغاء التزامن لإخفاء مكدس الاستدعاءات الأصلي تمامًا، مع إزالة قاعدة صورة EXE منه. عند العودة، يتم استدعاء أداة ROP لاستعادة المكدس الأصلي. في الكود، تتكرر هذه العملية 10 مرات في حلقة، باستخدام إطارات مختلفة في كل تكرار، لإثبات الاستقرار.
يدعم الأداة حاليًا وضعين، حيث أن أحدهما هو في الواقع تصحيح خاطئ لإطار pop RBP غير عامل تم تحديده، والذي يعمل عن طريق تحويل RSP الحالي وإضافة إطارين وهميين إلى مكدس الاستدعاءات. نظرًا لأنه يعمل باستخدام إطارات اصطناعية، أشير إلى هذا الوضع باسم "SYNTHETIC".
عند اختيار الإطار الذي يفك الترجيع عن طريق إخراج سجل RBP من المكدس، قد تحدد الأداة إطارًا غير مناسب، مما يؤدي إلى مكدس استدعاءات مقطوع فجأة، كما هو ملاحظ أدناه.

الحل السخيف للمشكلة سيكون إنشاء إطارين وهميين وربطهما مرة أخرى بمكدس الاستدعاءات المقطوع. سيؤدي هذا إلى إنشاء نوع من مكدس استدعاءات يبدو شرعيًا، حتى بدون إطار مناسب يفك الترجيع باستدعاء POP RBP، ولكن:
يمكن ملاحظة نتيجة التزوير الاصطناعي في الصورة أدناه:

الشكل 1: ويندوز 10 - مكدس استدعاءات يبدو شرعيًا وغير قابل لفك الترجيع حيث تمت إزالة وحدة EXE بالكامل (استدعاء دالة بدون معاملات getchar)
ملاحظة: وضع التشغيل هذا معطل افتراضيًا. لتمكين هذا الوضع، قم بتغيير CALLSTACK_TYPE إلى 1
هذا الوضع هو الحل الصحيح للمشكلة المذكورة أعلاه، حيث يتم استبدال الإطار غير المناسب ببساطة بآخر مناسب.

الشكل 2: ويندوز 10 - مكدس استدعاءات شرعي وقابل لفك الترجيع حيث تمت إزالة وحدة EXE بالكامل (استدعاء دالة بأربع معاملات MessageBoxA)
في المستودع، يمكنك أيضًا العثور على أداة صغيرة لفحص وظائف وقت التشغيل، والتي قد تكون مفيدة لتحليل إدخالات وظائف وقت التشغيل.
UnwindInspector.exe -h
Unwind Inspector v0.100000
Mandatory args:
-m <module>: Target DLL
-f <function>: Target Function
-a <function-address>: Target Function Address
مثال للإخراج:
UnwindInspector.exe -m kernelbase -a 0x7FFAAE12182C
[*] Using function address 0x7ffaae12182c
Runtime Function (0x000000000000182C, 0x00000000000019ED)
Unwind Info Address: 0x000000000026AA88
Version: 0
Ver + Flags: 00000000
SizeOfProlog: 0x1f
CountOfCodes: 0xc
FrameRegister: 0x0
FrameOffset: 0x0
UnwindCodes:
[00h] Frame: 0x741f - 0x04 - UWOP_SAVE_NONVOL (RDI, 0x001f)
[01h] Frame: 0x0015 - 0x00 - UWOP_PUSH_NONVOL (RAX, 0x0015)
[02h] Frame: 0x641f - 0x04 - UWOP_SAVE_NONVOL (RSI, 0x001f)
[03h] Frame: 0x0014 - 0x00 - UWOP_PUSH_NONVOL (RAX, 0x0014)
[04h] Frame: 0x341f - 0x04 - UWOP_SAVE_NONVOL (RBX, 0x001f)
[05h] Frame: 0x0012 - 0x00 - UWOP_PUSH_NONVOL (RAX, 0x0012)
[06h] Frame: 0xb21f - 0x02 - UWOP_ALLOC_SMALL (R11, 0x001f)
[07h] Frame: 0xf018 - 0x00 - UWOP_PUSH_NONVOL (R15, 0x0018)
[08h] Frame: 0xe016 - 0x00 - UWOP_PUSH_NONVOL (R14, 0x0016)
[09h] Frame: 0xd014 - 0x00 - UWOP_PUSH_NONVOL (R13, 0x0014)
[0ah] Frame: 0xc012 - 0x00 - UWOP_PUSH_NONVOL (R12, 0x0012)
[0bh] Frame: 0x5010 - 0x00 - UWOP_PUSH_NONVOL (RBP, 0x0010)
لبناء الـ POC وملاحظة سلوك مشابه لذلك الموجود في الصورة، تأكد من:
/GS-)/Od)/GL)/Os، /Ot)/Oi)يجدر ذكر الأعمال السابقة في هذا الموضوع، والتي بنت أساس هذا العمل.
شكر كبير لـ waldo-irc و trickster0، اللذان تعاونا معي في هذا البحث. أنا مدين لهم بكل شيء.
كل الفضل في الفكرة وراء هذا يعود لـ namaszo، الذي أعتبره شخصيًا عبقريًا. كما قام بمراجعة هذا الـ PoC قبل الإصدار، فشكر كبير له.