نقدم Stadeo – مجموعة من البرامج النصية التي يمكن أن تساعد زملاء الباحثين في مجال التهديد وعكس المهندسين على تفكيك شفرة Stantinko والبرامج الضارة الأخرى
Stadeo عبارة عن مجموعة من الأدوات التي تم تطويرها بشكل أساسي لتسهيل تحليل Stantinko ، وهي عبارة عن روبوتات تقوم بخداع النقرات وحقن الإعلانات والاحتيال على الشبكات الاجتماعية وهجمات سرقة كلمات المرور والتشفير.
تم عرض Stadeo لأول مرة في Black Hat USA 2020 وتم نشره لاحقًا للاستخدام المجاني.
النصوص المكتوبة بالكامل بلغة Python تتعامل مع تقنيات Stantinko الفريدة للتحكم في التدفق وتسطيح التدفق (CFF) والتشويش على السلسلة الموضحة في منشورنا في مارس 2020. بالإضافة إلى ذلك ، يمكن استخدامها لأغراض أخرى: على سبيل المثال ، قمنا بالفعل بتوسيع نهجنا لدعم فك تشفير CFF الموجود في Emotet – حصان طروادة يسرق بيانات الاعتماد المصرفية ويقوم بتنزيل حمولات إضافية مثل برامج الفدية.
تستخدم أساليب تبسيطنا IDA ، وهي أداة قياسية في الصناعة ، و Miasm – إطار عمل مفتوح المصدر يوفر لنا تحليلات مختلفة لتدفق البيانات ، ومحرك تنفيذ رمزي ، ومحرك تنفيذ رمزي ديناميكي ، ووسائل لإعادة تجميع الوظائف المعدلة.
يمكنك العثور على Stadeo على https://github.com/eset/stadeo.
المحتويات
أمثلة الاستخدام
للعمل مع Stadeo ، نحتاج أولاً إلى إعداد خادم RPyC (Remote Python Call) داخل IDA ، والذي يتيح لنا الوصول إلى واجهة برمجة تطبيقات IDA من مترجم Python التعسفي. يمكنك استخدام هذا البرنامج النصي لفتح خادم RPyC في IDA.
في جميع الأمثلة أدناه ، قمنا بإعداد خادم RPyC يستمع على 10.1.40.164:4455 (4455 هو المنفذ الافتراضي) ، ثم نتواصل مع الخادم من وحدة تحكم Python.
سنستخدم فصلين من فئات Stadeo:
- استراتيجيات CFF لتلطيف CFF
- StringRevealer لتبسيط السلسلة
يمكن تهيئة كلا الفئتين لكل من هندسة 32 بت و 64 بت.
تبسيط وظيفة واحدة
SHA-1 للعينة: 791ad58d9bb66ea08465aad4ea968656c81d0b8e
يقوم الكود أدناه بتفكيك الوظيفة في 0x1800158B0 مع المعلمة في R9 تعيين التسجيل ل 0x567C ويكتب نسخته المبهمة إلى ملف 0x18008D000 عنوان.
ال R9 المعلمة هي متغير تحكم لدمج حلقة CFF (متغير دمج) ويجب تحديدها باستخدام تعبيرات Miasm ، والتي تم توثيقها هنا ؛ لاحظ أن على المرء أن يستخدم RSP_init / ESP_init بدلا من RSP / ESP للإشارة إلى معلمات المكدس. على سبيل المثال ، سوف نستخدم ExprMem (ExprId (“ESP_init” ، 32) ExprInt (4و 32) ، 32) لاستهداف معلمة المكدس الأولى في بنية 32 بت.
من stadeo.cff.cff_strategies استيراد CFFStrategies من miasm.expression.expression استيراد ExprId، ExprInt cs = CFFStrategies (64) cs.solve_loop (0x1800158B0، 0x18008D000، سياق = {ExprId (“R9″، 64): ExprInt (64) } ، ip = ’10 .1.40.164 ‘)
من عند ملعب.CFF.إستراتيجيات cff استيراد استراتيجيات CFF من عند هياج.التعبير.التعبير استيراد ExprIdو ExprInt CS = استراتيجيات CFF(64) CS.حل_حلقة(0x1800158B0و 0x18008D000و سياق الكلام={ExprId(“R9”و 64): ExprInt(0x567cو 64)}و IP=“10 .1.40.164 “) |
معالجة الوظائف التي يمكن الوصول إليها
SHA-1 للعينة: e0087a763929dee998deebbcfa707273380f05ca
يتعرف الكود التالي فقط على الوظائف المبهمة التي يمكن الوصول إليها من 0x1002DC50 ويبحث عن مرشحين لدمج المتغيرات. تبدأ الوظائف المعترف بها والمعروفة بنجاح في 0x10098000.
من stadeo.cff.cff_strategies import CFFStrategies strat = CFFStrategies (32) res = strat.process_merging (0x1002DC50، 0x10098000، ip = “10.1.40.164”)
من عند ملعب.CFF.إستراتيجيات cff استيراد استراتيجيات CFF سترات = استراتيجيات CFF(32) الدقة = سترات.عملية_دمج(0x1002DC50و 0x10098000و IP=“10.1.40.164”) |
الإخراج الجزئي:
تخطي 0x1002dc50 مع val بلا: 0xbadf00d
رسم الخرائط: 0x1001ffc0 -> 0x10098000 مع val @ 32[ESP_init + 0x8]: 0x6cef
تخطي 0x100010f0 مع val بلا: 0xbadf00d
رسم الخرائط: 0x1000f0c0 -> 0x100982b7 مع val @ 32[ESP_init + 0x8]: 0x2012
رسم الخرائط: 0x1003f410 -> 0x10098c8a مع val @ 32[ESP_init + 0x4]: 0x21a4
رسم الخرائط: 0x1003f410 -> 0x10098f3d مع val @ 32[ESP_init + 0x4]: 0x772a
تخطي 0x1004ee79 (مكتبة func)
…
تم تفكيك الوظائف المعينة بشكل صحيح ولم يتم اعتبار الوظائف التي تم تخطيها على أنها غامضة. شكل ملف رسم الخرائط الأسطر في الإخراج هي:
التعيين:٪ obfuscated_function_address٪ ->٪ deobfuscated_function_address٪ with val٪ merging_variable٪:٪ merging_variable_value٪
القيمة الافتراضية لـ merging_variable_value يكون 0x0BADF00D. ال تخطي تتبع الخطوط نفس النمط ، لكن لا يوجد وظيفة_وظيفة_عنوان_التباس. يتم فقط تخطي وظائف المكتبة التي تعترف بها المؤسسة الدولية للتنمية دون مزيد من المعالجة.
معالجة جميع الوظائف
SHA-1 للعينة: e575f01d3df0b38fc9dc7549e6e762936b9cc3c3
نحن نستخدم الكود التالي فقط للتعامل مع CFF الموجود في Emotet ، والذي يتوافق تطبيق CFF الخاص به مع وصف التسوية الشائعة للتحكم في التدفق هنا.
نحن نفضل هذا النهج لأن الطريقة CFFStrategies.process_all () لا يحاول التعرف على متغيرات الدمج غير الموجودة في Emotet ويبحث فقط عن حلقة CFF واحدة لكل وظيفة ؛ ومن ثم فهو أكثر كفاءة.
تتم كتابة الوظائف المعترف بها والمعروفة بنجاح بالتسلسل من 0x0040B000. تنسيق الإخراج هو نفسه كما في ملف عملية_دمج الطريقة المستخدمة في معالجة الوظائف التي يمكن الوصول إليها على سبيل المثال ، ولكن بطبيعة الحال لن يكون هناك أي متغيرات دمج.
من stadeo.cff.cff_strategies import CFFStrategies strat = CFFStrategies (32) res = strat.process_all (0x0040b000، ip = “10.1.40.164”)
من عند ستديو.CFF.إستراتيجيات cff استيراد استراتيجيات CFF سترات = استراتيجيات CFF(32) الدقة = سترات.عملية_كل(0x0040b000و IP=“10.1.40.164”) |
الإخراج الجزئي:
رسم الخرائط: 0x00401020 -> 0x0040b000 مع val بلا: 0xbadf00d
تخطي 0x00401670 مع val بلا: 0xbadf00d
رسم الخرائط: 0x00401730 -> 0x0040b656 مع val بلا: 0xbadf00d
…
إعادة توجيه المراجع إلى دوال مبهمة
لا يقوم Stadeo تلقائيًا بتحديث المراجع إلى الوظائف بعد تبسيطها. في المثال أدناه ، نوضح كيفية تصحيح استدعاء دالة في الشكل 1 من ملف تبسيط وظيفة واحدة مثال. يظهر المرجع المصحح في الشكل 4.
نستخدم الكود التالي لتصحيح المكالمات ، والتي تكون المعلمة الرابعة لها 0x567C، للدالة المبهمة في 0x1800158B0 مع واحد مبهم في 0x18008D000. لاحظ أنه يتعين على المرء التأكد من أن المؤسسة الدولية للتنمية قد تعرفت على معلمات الوظيفة بشكل صحيح وربما إصلاحها.
من stadeo.utils.xref_patcher استيراد patch_xrefs patch_xrefs (0x1800158B0، 0x18008D000، {3: 0x567c}، ip = ’10 .1.40.164 ‘)
من عند ملعب.المرافق.xref_patcher استيراد patch_xrefs patch_xrefs(0x1800158B0و 0x18008D000و {3: 0x567c}و IP=“10 .1.40.164 “) |
الكشف عن سلاسل مبهمة في دالة
الوظيفة StringRevealer.process_funcs () يكشف السلاسل المبهمة في الوظيفة المحددة ويعيد خريطة السلاسل غير المفككة وعناوينها.
لاحظ أن التحكم في تدفق الوظيفة الهدف يجب أن يكون قد تم تفكيكه بالفعل.
في المثال أدناه ، قمنا بتفكيك سلاسل الدالة في 0x100982B7، هو مبين في الشكل 5. الوظيفة نفسها كانت مفككة في السابق معالجة الوظائف التي يمكن الوصول إليها مثال.
من stadeo.string.string_revealer استيراد StringRevealer sr = StringRevealer (32) strings = sr.process_funcs ([0x100982B7]، ip = “10.1.40.164”)
من عند ملعب.خيط.سلسلة_رابط استيراد StringRevealer ريال سعودى = StringRevealer(32) سلاسل = ريال سعودى.العملية_الممتعة([0x100982B7]و IP=“10.1.40.164”) |
محتوى متغير السلاسل بعد التنفيذ هو:
{0x100982B7: {‘SeLockMemoryPrivilege’}}
{0x100982B7: {“SeLockMemoryPrivilege”}} |
نأمل أن تجد أدوات Stadeo وهذا الشرح لاستخدامها مفيدًا. إذا كان لديك أي استفسارات ، تواصل معنا عبر البريد الإلكتروني[at]eset.com أو افتح مشكلة على https://github.com/eset/stadeo.