دراسة خبيثة

صورة

لقد صادفت ملف مستندات ضار مؤخرًا تم إرساله مع رسائل البريد الإلكتروني التصيدية. قررت أن هذا سبب وجيه لممارسة الهندسة العكسية وكتابة شيء جديد على هبر. تحت القطة - مثال على تحليل قطارة الماكرو الخبيثة وليس أقل من دلس الخبيثة.

دقيق


Sha256 من الملف - abb052d9b0660f90bcf5fc394db0e16d6edd29f41224f8053ed90a4b8ef1b519 . في ملف المستند نفسه ، توجد في الصفحة الأولى صورة توضح أن هذا الملف محمي وتشرح كيفية تمكين وحدات الماكرو ؛ هناك جدولين كبيرين بأرقام في الملف. تتم كتابة الأرقام في شكل عشري ، وأطولها مكون من عشرة أرقام ، وهناك أرقام موجبة وسالبة.

عندما تسمح الضحية بتنفيذ وحدات الماكرو (هناك من قاموا بتمكينها افتراضيًا؟) ، يتم إطلاق سلسلة من الإجراءات ، والتي تؤدي في النهاية وظيفة المحدثة b_network، الذي يغير الدليل الحالي إلى دليل مؤقت وينشئ الملف "icutils.dll" فيه ، حيث يكتب الأرقام من الجدول الأول على التوالي كعدد صحيح 32 بت مع علامة. والنتيجة هي دلل الصحيح. يتم استيراد وظيفة النسخ من dll :

Declare PtrSafe Function clone Lib "icutils.dll" _
(ByVal Saved As String, ByVal Time As Integer) As Boolean

ويبدأ بمعلمتين:

R1 = Module1.clone("Cream", 0)

إذا أعادت استدعاء الاستنساخ خطأ ، فسيتم استبدال ملف icutils.dll بالبيانات من الجدول الثاني ويتم استدعاء النسخ مرة أخرى بنفس المعلمات.

في المستقبل ، سأقول أن dll الأول هو 64 بت ولن يعمل على أنظمة 32 بت. وبالتالي ، يختار الماكرو بنية الشفرة الثنائية الصحيحة.

من المثير للاهتمام أن وظيفة updatedb_network تحتوي على جزء من الكود ليس له غرض وظيفي:

Sub updatedb_network()
...
Dim query_to_change As Variant
    Set query_to_change = CurrentDb.QueryDefs("query_name")
    
    query_to_change.SQL = "SELECT * FROM Table ORDER BY ID Asc"
    query_to_change.SQL = "SELECT Field1, Field2 FROM Table ORDER BY ID Asc"
    query_to_change.SQL = "SELECT Field1, Field2 FROM Table WHERE Field LIKE Fashion"
    query_to_change.SQL = "SELECT Field1, Field2 FROM Table WHERE Field LIKE '" & something & "'"
...
End Sub

ربما يكون هنا لإعطاء مظهر عمل مفيد لأولئك الذين يتنقلون بسرعة في التعليمات البرمجية ، ويرون بعض الأسطر في SQL ويعتقدون أن كل شيء على ما يرام؟ لا اعرف. أيضًا ، تحتوي معظم الوظائف والمتغيرات على أسماء عشوائية أو غير حقيقية (مثل updatedb_network ، والتي لا تتفاعل مع قاعدة البيانات أو الشبكة). على الرغم من وجود ، على سبيل المثال ، وظيفة dump_payload ، التي تقوم بتخزين 4 بايت في icutil.dll. ولكن على أي حال ، يجب أن يحذر وجود وظيفة Document_Open على الفور ، ولا يمكن لمؤلفي البرامج الضارة إعادة تسميتها بشكل تعسفي (على الرغم من أنه يمكنهم استخدام وظيفة أخرى يتم تشغيلها تلقائيًا بدلاً من ذلك).

لذا ، فإن وظائف الماكرو أكثر أو أقل وضوحًا ، فقد حان الوقت لتفريغ dll والمتابعة إلى تحليلها.

دلل الأول


أول دلل (sha256 7427cc4b6b659b89552bf727aed332043f4551ca2ee2126cca75fbe1ab8bf114 ) 64 بت.

تحتوي قائمة الوظائف المستوردة على الوظائف CreateProcessW (بدء تشغيل البرنامج) و CreateRemoteThread (إنشاء مؤشر ترابط في عملية أخرى ) و VirtualAllocEx (تخصيص كتلة من الذاكرة في عملية أخرى ) و WriteProcessMemory (الكتابة إلى ذاكرة عملية أخرى ) ، والتي تقترح على الفور إدخال رمز في آخر معالجة. لنرى الآن ماذا تفعل بالضبط باستخدام IDA Free و Ghidra.
نقطة الدخول الرئيسية ترجع ببساطة 1 ، ولا تفعل أي شيء آخر. الوظيفة المصدرة الثانية هي استنساخ ، والتي يتم استدعاؤها بواسطة الماكرو وتحتوي على كود خبيث.
لا يبدو أن المعلمات التي يطلق عليها تؤثر على أي شيء. يقوم التطبيق بفك تشفير كتلتين من البيانات. أول كتلة بيانات 0x78 بالمحتويات التالية (تم فك تشفيرها بالفعل):

https://pastebin.com/raw/Jyujxy7z\x00\x00\x00\x00\x00\x00\x00\xf2i\xe0\x1d\x95h\xbc\x03\xe4#\xe0\x1d<\x04\xe0\x1d\xe6\x00\xde\x01\xa4\x17\xbc\x03x\x01\xe0\x1d\xe2\x16x\x07Qy\xbc\x03@Fx\x07Df\xbc\x03\x89a\xde\x01q\x11\xe0\x1d|Ix\x07D@\xbc\x03\x8a\x01\xde\x01^9\xde\x01\xf2i\xe0\x1d\x95h\xbc\x03\xe4#\xe0\x1d\xab

يبلغ طول كتلة البيانات الثانية 0x1D4C ويحتوي على رمز قابل للتنفيذ.

بالإضافة إلى ذلك ، تتم كتابة مؤشر إلى الوحدة النمطية kernel32 ونتائج الدالة GetTickCount () وعنوان الدالة ZwDelayExecution () من kernel32 إلى بنية بايت بايت 0x90 .

ثم يتم إنشاء العملية ( CreateProcessW ) “cmd.exe”. باستخدام VirtualAllocEx ، يتم تخصيص اثنين من المخازن المؤقتة: مع أذونات RW بطول 0x108 وأذونات RWX بطول 0x1D4C. ينسخ المخزن المؤقت RW كتلة البيانات أعلاه والبنية المذكورة بطول 0x90. يكتب الهيكل أيضًا مؤشرًا إلى كتلة البيانات التي تم فك تشفيرها (في مساحة العنوان للعملية الفرعية (cmd.exe)). في RWX ، يتم نسخ المخزن المؤقت ( WriteProcessMemory) فك البيانات المشفرة مع رمز.
ثم ، في عملية cmd.exe ، يتم إنشاء دفق ( CreateRemoteThread ) بنقطة إدخال في بداية المخزن المؤقت RWX ، يتم تمرير مؤشر إلى المخزن المؤقت RW كوسيطة. يكمل هذا وظيفة النسخ ، ويستمر الإجراء في عملية cmd.exe.

ومن المثير للاهتمام ، أن وظيفة النسخ تبدو وكأنها قطعة غير قابلة للتحقيق من التعليمات البرمجية التي تستورد ( LoadLibraryW ) مكتبة " WorkPolyhistor ".

تم حقن التعليمات البرمجية في cmd.exe


ينفذ الإجراءات التالية:

  • يجد عناوين الوظائف الضرورية من kernel32.dll (يتم الحصول على عنوانه من العملية الأصلية)
  • تحميل ntdll ، Ole32 ، مكتبات User32
  • يجد عناوين الوظائف اللازمة في هذه المكتبات.

من المثير للاهتمام أنه بالنسبة لمعظم الوظائف في التعليمات البرمجية ، لا يوجد اسم وظيفة ، ولكن فقط CRC32 نيابة عن (يتم البحث في جميع أسماء الوظائف من المكتبة المحملة حتى تكون هناك وظيفة مع CRC32 المطلوب نيابة عن). ربما تكون هذه حماية ضد الحصول على قائمة الوظائف المستوردة بواسطة أداة السلاسل ، على الرغم من أنه من الغريب أن الشفرة المخزنة في شكل مشفر لديها مثل هذه الحماية ، في حين أن dll نفسه يستورد الوظائف ببساطة بالاسم. في المجموع ، تم الكشف عن الوظائف التالية:

kernel32:

  • GetProcAddress
  • مكتبة تحميل
  • Globalalloc
  • GetTempPath
  • GetFileAttributesW
  • CreateProcessW
  • Globalfree
  • GlobalRealloc
  • ملف مكتوب
  • CreateFileW (تم العثور عليه بالاسم)
  • ملف مكتوب
  • إغلاق
  • Gettickcount
  • إقرا الملف
  • GetfileSize

ntdll:

  • RtlCreateUnicodeStringFromAsciiz
  • تنفيذ ZwDelay
  • عملية ZwTerminate
  • swprintf

أوله 32:

  • CoInitialize (تم العثور عليه بالاسم)
  • CoCreateInstance (تم العثور عليها بالاسم)

msvcrt:

  • راند
  • srand

بعد ذلك ، تحصل العملية باستخدام GetTempPath على المسار إلى الدليل المؤقت ، وتنشئ ملفًا باسم النموذج 26342235.dat ، حيث يكون اسم الملف هو السجل العشري لـ TickCount الذي تم تلقيه من العملية الرئيسية ويتكرر في كل محاولة جديدة (أي إذا لم يكن من الممكن تنزيل الحمولة في المحاولة الأولى ، ثم في المحاولة الثانية سيتم إنشاء ملف بالاسم 26342236.dat). بعد ذلك ، يتم تحميل مكتبة wininet وهناك مؤشرات على الوظائف التالية:

  • InternetCloseHandle (crc32: 0xe5191d24)
  • InternetGetConnectedState (crc32: 0xf2e5fc0c)
  • InternetOpenA (crc32: 0xda16a83d)
  • InternetOpenUrlA (crc32: 0x16505e0)
  • InternetReadFile (crc32: 0x6cc098f5)

باستخدام InternetGetConnectedState ، يتحقق التطبيق من وجود شبكة ، إذا لم يكن كذلك ، يستدعي التطبيق الوظيفة على عنوان غير موجود ويتعطل (مثل هذه الحماية ضد تحديد العنوان الذي يتم الحصول على الحمولة منه باستخدام جهاز معزول عن الشبكة. هذه هي الحالة الوحيدة عندما ينتهي التطبيق بشكل غير طبيعي ، في بقية 3 محاولات تتم ، وبعد ذلك ينتهي cmd.exe باستخدام ZwTerminateProcess ). إذا كانت هناك شبكة ، باستخدام الوظائف التي تم العثور عليها ، يتم تنزيل الحمولة من عنوان URL الذي تم تمريره من العملية الرئيسية (https://pastebin.com/raw/Jyujxy7z) ويتم حفظه في الملف الذي تم إنشاؤه مسبقًا باستخدام ملحق .dat.

بعد ذلك ، تتم قراءة الحمولة من ملف .dat ، تم فك تشفيره (base64) ، تم فك تشفيره باستخدام XOR مع CRC32 من عنوان URL ، تحقق من أن أول 2 بايت من البيانات التي تم فك تشفيرها هي 'MZ' ، إذا كان الأمر كذلك ، يتم حفظ النتيجة في ملف بنفس الاسم ولكن امتداد. إملف تنفيذى

رمز فك تشفير بايثون
from binascii import crc32
from base64 import b64decode


def decrypt_payload(payload_b64: bytes, url: str):
    payload_bin = b64decode(payload_b64.decode())
    key = str(crc32(url.encode())).encode()
    decrypted = bytearray()
    for i, b in enumerate(payload_bin):
        decrypted.append(b ^ key[i % len(key)])
    return bytes(decrypted)

باستخدام الوظيفة CreateProcessW ، يتم تشغيل الملف المحفوظ. إذا سارت الأمور على ما يرام ، يتم إنهاء عملية cmd.exe باستخدام ZwTerminateProcess . إذا حدث خطأ ما (باستثناء عدم وجود شبكة) ، فسيتم تكرار كل شيء من جديد ، ويتم إجراء 3 محاولات كحد أقصى ، ويتم زيادة أسماء ملفات dat و exe بمقدار 1 في كل مرة.

دلل الثاني


دلل الثاني (sha256 006200fcd7cd1e71be6c2ee029c767e3a28f480613e077bf15fadb60a88fdfca ) 32 بت.

في ذلك ، يتم تنفيذ الوظائف الخبيثة الرئيسية في وظيفة النسخ . تقوم أيضًا بفك تشفير 2 من المخازن المؤقتة. يبلغ حجم المخزن المؤقت الأول 0x78 (120) بايت ، ويتم فك تشفير هذه البيانات وكتابتها (في شكل غير مشفر):

https://pastebin.com/raw/Jyujxy7z\x00\x00\x00\x00\x00\x00\x00\x1e(\xf0\x0e\xc5r\xc0;\x12)\xc0;Jr\xc0;Y4\xbc\x03/Mx\x07\x038\xde\x01\x9e\x05\xe0\x1d#\x08\xbc\x03\xeeU\xf0\x0e\x18{x\x078\x1a\xf0\x0e\xccg\xf0\x0eze\xde\x01\x89&\xe0\x1d\xf6\x1f\xe0\x1d

يمكن ملاحظة أنه في البداية هو نفس عنوان URL الموجود في إصدار x64.

يتم تخصيص مخزن مؤقت ثاني بحجم 0x4678 بايت بأذونات RWX. يتم فك تشفير الشفرة فيه ، وبعد ذلك يتم استدعاء دالة منه مع إزاحة 0x4639 من بداية المخزن المؤقت.

لم أحلل هذا الرمز بالتفصيل. يجد أيضًا وظائف على CRC32 ، ويطلق notepad.exe ، ويحقن الشفرة التي تقوم بتنزيل الحمولة من نفس عنوان URL على Pastebin.

حمولة مع Pastebin


حمولة غير مشفرة مع Pastebin هو ملف exe 32 بت (sha256 9509111de52db3d9a6c06aa2068e14e0128b31e9e45ada7a8936a35ddfaf155f ) لم أقم بفكه بالتفصيل حتى الآن بسبب ضيق الوقت.

استنتاج


بشكل عام ، أذهلتني البرمجيات الخبيثة بشكل سيئ إلى حد ما ، مع الكثير من الأخطاء (لا أسميها هنا عن قصد). كما لو كانوا يجلدون.
يجد دلل في وظائف الذاكرة التي لا تستخدم في أي مكان في وقت لاحق. ربما يتم إعادة كتابة هذا الرمز ، مثل الماكرو ، بانتظام من قبل مجرمي الإنترنت في كل مرة يبدأ فيها اكتشافه بواسطة مضادات الفيروسات ، ونتيجة لذلك تبقى هذه القطع الأثرية في الرمز.

من المثير للاهتمام أيضًا أنه في إصدار "dll" من dll الذي "تم إسقاطه" على قرص x64 ، لا يتم إخفاء أسماء الوظائف المستوردة "الخطيرة" (يمكنك على الأقل رؤيتها سلاسل) ، وفي التعليمات البرمجية التي تم فك تشفيرها في الذاكرة ولا تلائم القرص ، توجد على CRC32 من ليس فقط بالاسم.

تمت إزالة حمولة Pastebin بعد بضعة أيام.

PS KDPV مأخوذة من هنا

All Articles