SysWhispers2 - AV/EDR Evasion Via Direct System Calls


[![](https://1.bp.blogspot.com/-2huQwb9tNh4/X_u1-J9Tg7I/AAAAAAAAU-g/zaW0M51ztJ8p6zLoFx4yJYBaOb45jN9bgCNcBGAsYHQ/w640-h464/SysWhispers2.png)](<https://1.bp.blogspot.com/-2huQwb9tNh4/X_u1-J9Tg7I/AAAAAAAAU-g/zaW0M51ztJ8p6zLoFx4yJYBaOb45jN9bgCNcBGAsYHQ/s722/SysWhispers2.png>) SysWhispers helps with evasion by generating header/ASM files implants can use to make direct system calls. All core syscalls are supported and example generated files available in the `example-output/` folder. **Difference Between [SysWhispers](<https://www.kitploit.com/search/label/SysWhispers> "SysWhispers" ) 1 and 2** The usage is almost identical to [SysWhispers1](<https://github.com/jthuraisamy/SysWhispers> "SysWhispers1" ) but you don't have to specify which versions of Windows to support. Most of the changes are under the hood. It no longer relies on [@j00ru](<https://twitter.com/j00ru> "@j00ru" )'s [syscall tables](<https://github.com/j00ru/windows-syscalls> "syscall tables" ), and instead uses the "[sorting by system call address](<https://www.mdsec.co.uk/2020/12/bypassing-user-mode-hooks-and-direct-invocation-of-system-calls-for-red-teams/> "sorting by system call address" )" technique popularized by [@modexpblog](<https://twitter.com/modexpblog> "@modexpblog" ). This significantly reduces the size of the syscall stubs. The specific implementation in SysWhispers2 is a variation of @modexpblog's code. One difference is that the function name hashes are randomized on each generation. [@ElephantSe4l](<https://twitter.com/ElephantSe4l> "@ElephantSe4l" ), who had [published](<https://www.crummie5.club/freshycalls/> "published" ) this technique earlier, has another [implementation](<https://github.com/crummie5/FreshyCalls> "implementation" ) based in C++17 which is also worth checking out. The original SysWhispers repository is still up but may be deprecated in the future. **Introduction** Various security products place hooks in user-mode API functions which allow them to redirect execution flow to their engines and detect for suspicious behaviour. The functions in `ntdll.dll` that make the syscalls consist of just a few assembly instructions, so re-implementing them in your own implant can bypass the triggering of those security product hooks. This technique was popularized by [@Cn33liz](<https://twitter.com/Cneelis> "@Cn33liz" ) and his [blog post](<https://outflank.nl/blog/2019/06/19/red-team-tactics-combining-direct-system-calls-and-srdi-to-bypass-av-edr/> "blog post" ) has more technical details worth reading. SysWhispers provides [red teamers](<https://www.kitploit.com/search/label/Red%20Teamers> "red teamers" ) the ability to generate header/ASM pairs for any system call in the core kernel image (`ntoskrnl.exe`). The headers will also include the necessary type definitions. **Installation** > git clone https://github.com/jthuraisamy/SysWhispers2.git > cd SysWhispers2 > py .\syswhispers.py --help **Usage and Examples** **Command Lines** # 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 **Script Output** PS C:\Projects\SysWhispers2> py .\syswhispers.py --preset common --out-file syscalls_common . ,--. ,-. . . ,-. . , , |-. o ,-. ,-. ,-. ,-. ,-. / `-. | | `-. |/|/ | | | `-. | | |-' | `-. ,-' `-' `-| `-' ' ' ' ' ' `-' |-' `-' ' `-' `--- /| | @Jackson_T `-' ' @modexpblog, 2021 SysWhispers2: Why call the kernel when you can whisper? Common functions selected. Complete! Files written to: syscalls_common.h syscalls_common.c syscalls_common_stubs.asm **Before-and-After Example of Classic `CreateRemoteThread` DLL Injection** 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); } **Common Functions** Using the `--preset common` switch will create a header/ASM pair with the following functions: * NtCreateProcess (CreateProcess) * NtCreateThreadEx (CreateRemoteThread) * NtOpenProcess (OpenProcess) * NtOpenThread (OpenThread) * NtSuspendProcess * NtSuspendThread (SuspendThread) * NtResumeProcess * NtResumeThread (ResumeThread) * NtGetContextThread (GetThreadContext) * NtSetContextThread (SetThreadContext) * NtClose (CloseHandle) * NtReadVirtualMemory (ReadProcessMemory) * NtWriteVirtualMemory (WriteProcessMemory) * NtAllocateVirtualMemory (VirtualAllocEx) * NtProtectVirtualMemory (VirtualProtectEx) * NtFreeVirtualMemory (VirtualFreeEx) * NtQuerySystemInformation (GetSystemInfo) * NtQueryDirectoryFile * NtQueryInformationFile * NtQueryInformationProcess * NtQueryInformationThread * NtCreateSection (CreateFileMapping) * NtOpenSection * NtMapViewOfSection * NtUnmapViewOfSection * NtAdjustPrivilegesToken (AdjustTokenPrivileges) * NtDeviceIoControlFile (DeviceIoControl) * NtQueueApcThread (QueueUserAPC) * NtWaitForMultipleObjects (WaitForMultipleObjectsEx) **Importing into Visual Studio** 1. Copy the generated H/C/ASM files into the project folder. 2. In Visual Studio, go to _Project_ → _Build Customizations..._ and enable MASM. 3. In the _Solution Explorer_, add the .h and .c/.asm files to the project as header and source files, respectively. 4. Go to the properties of the ASM file, and set the _Item Type_ to _Microsoft Macro Assembler_. 5. Ensure that the project platform is set to x64. 32-bit projects are not supported at this time. **Caveats and Limitations** * Only 64-bit Windows is supported at this time. * System calls from the graphical subsystem (`win32k.sys`) are not supported. * Tested on Visual Studio 2019 (v142) with [Windows 10](<https://www.kitploit.com/search/label/Windows%2010> "Windows 10" ) SDK. **Troubleshooting** * Type redefinitions errors: a project may not compile if typedefs in `syscalls.h` have already been defined. * Ensure that only required functions are included (i.e. `--preset all` is rarely necessary). * If a typedef is already defined in another used header, then it could be removed from `syscalls.h`. **Credits** Developed by [@Jackson_T](<https://twitter.com/Jackson_T> "@Jackson_T" ) and [@modexpblog](<https://twitter.com/modexpblog> "@modexpblog" ), but builds upon the work of many others: * [@FoxHex0ne](<https://twitter.com/FoxHex0ne> "@FoxHex0ne" ) for cataloguing many function prototypes and typedefs in a machine-readable format. * [@PetrBenes](<https://twitter.com/PetrBenes> "@PetrBenes" ), [NTInternals.net team](<https://undocumented.ntinternals.net/> "NTInternals.net team" ), and [MSDN](<https://docs.microsoft.com/en-us/windows/> "MSDN" ) for additional prototypes and typedefs. * [@Cn33liz](<https://twitter.com/Cneelis> "@Cn33liz" ) for the initial [Dumpert](<https://github.com/outflanknl/Dumpert> "Dumpert" ) POC implementation. **Related Articles and Projects** * [@modexpblog](<https://twitter.com/modexpblog> "@modexpblog" ): [Bypassing User-Mode Hooks and Direct Invocation of System Calls for Red Teams](<https://www.mdsec.co.uk/2020/12/bypassing-user-mode-hooks-and-direct-invocation-of-system-calls-for-red-teams/> "Bypassing User-Mode Hooks and Direct Invocation of System Calls for Red Teams" ) * [@hodg87](<https://twitter.com/hodg87> "@hodg87" ): [Malware Mitigation when Direct System Calls are Used](<https://www.cyberbit.com/blog/endpoint-security/malware-mitigation-when-direct-system-calls-are-used/> "Malware Mitigation when Direct System Calls are Used" ) * [@Cn33liz](<https://twitter.com/Cneelis> "@Cn33liz" ): [Combining Direct System Calls and sRDI to bypass AV/EDR](<https://outflank.nl/blog/2019/06/19/red-team-tactics-combining-direct-system-calls-and-srdi-to-bypass-av-edr/> "Combining Direct System Calls and sRDI to bypass AV/EDR" ) ([Code](<https://github.com/outflanknl/Dumpert> "Code" )) * [@0x00dtm](<https://twitter.com/0x00dtm> "@0x00dtm" ): [Userland API Monitoring and Code Injection Detection](<https://0x00sec.org/t/userland-api-monitoring-and-code-injection-detection/5565> "Userland API Monitoring and Code Injection Detection" ) * [@0x00dtm](<https://twitter.com/0x00dtm> "@0x00dtm" ): [Defeating Userland Hooks (ft. Bitdefender)](<https://0x00sec.org/t/defeating-userland-hooks-ft-bitdefender/12496> "Defeating Userland Hooks \(ft. Bitdefender\)" ) ([Code](<https://github.com/NtRaiseHardError/Antimalware-Research/tree/master/Generic/Userland%20Hooking/AntiHook> "Code" )) * [@mrgretzky](<https://twitter.com/mrgretzky> "@mrgretzky" ): [Defeating Antivirus Real-time ](<https://breakdev.org/defeating-antivirus-real-time-protection-from-the-inside/> "Defeating Antivirus Real-time" )[Protection](<https://www.kitploit.com/search/label/Protection> "Protection" ) From The Inside * [@SpecialHoang](<https://twitter.com/SpecialHoang> "@SpecialHoang" ): [Bypass EDR’s memory protection, introduction to hooking](<https://medium.com/@fsx30/bypass-edrs-memory-protection-introduction-to-hooking-2efb21acffd6> "Bypass EDR’s memory protection, introduction to hooking" ) ([Code](<https://github.com/hoangprod/AndrewSpecial/tree/master> "Code" )) * [@xpn](<https://twitter.com/_xpn_> "@xpn" ) and [@domchell](<https://twitter.com/domchell> "@domchell" ): [Silencing Cylance: A Case Study in Modern EDRs](<https://www.mdsec.co.uk/2019/03/silencing-cylance-a-case-study-in-modern-edrs/> "Silencing Cylance: A Case Study in Modern EDRs" ) * [@mrjefftang](<https://twitter.com/mrjefftang> "@mrjefftang" ): [Universal Unhooking: Blinding Security Software](<https://threatvector.cylance.com/en_us/home/universal-unhooking-blinding-security-software.html> "Universal Unhooking: Blinding Security Software" ) ([Code](<https://github.com/CylanceVulnResearch/ReflectiveDLLRefresher> "Code" )) * [@spotheplanet](<https://twitter.com/spotheplanet> "@spotheplanet" ): [Full DLL Unhooking with C++](<https://ired.team/offensive-security/defense-evasion/how-to-unhook-a-dll-using-c++> "Full DLL Unhooking with C++" ) * [@hasherezade](<https://twitter.com/hasherezade> "@hasherezade" ): [Floki Bot and the stealthy dropper](<https://blog.malwarebytes.com/threat-analysis/2016/11/floki-bot-and-the-stealthy-dropper/> "Floki Bot and the stealthy dropper" ) * [@hodg87](<https://twitter.com/hodg87> "@hodg87" ): [Latest Trickbot Variant has New Tricks Up Its Sleeve](<https://www.cyberbit.com/blog/endpoint-security/latest-trickbot-variant-has-new-tricks-up-its-sleeve/> "Latest Trickbot Variant has New Tricks Up Its Sleeve" ) **References to SysWhispers** * [@JFaust_](<https://twitter.com/JFaust_> "@JFaust_" ): Process Injection [Part 1](<https://sevrosecurity.com/2020/04/08/process-injection-part-1-createremotethread/> "Part 1" ), [Part 2](<https://sevrosecurity.com/2020/04/13/process-injection-part-2-queueuserapc/> "Part 2" ), and [Alaris loader](<https://sevrosecurity.com/2020/10/14/alaris-a-protective-loader/> "Alaris loader" ) project ([Code](<https://github.com/cribdragg3r/Alaris> "Code" )) * [@0xPat](<https://www.twitter.com/0xPat> "@0xPat" ): [Malware Development Part 2](<https://0xpat.github.io/Malware_development_part_2/> "Malware Development Part 2" ) * [@brsn76945860](<https://twitter.com/brsn76945860> "@brsn76945860" ): [Implementing Syscalls In The ](<https://br-sn.github.io/Implementing-Syscalls-In-The-CobaltStrike-Artifact-Kit/> "Implementing Syscalls In The" )[CobaltStrike](<https://www.kitploit.com/search/label/CobaltStrike> "CobaltStrike" ) Artifact Kit * [@Cn33liz](<https://twitter.com/Cneelis> "@Cn33liz" ) and [@_DaWouw](<https://twitter.com/_DaWouw> "@_DaWouw" ): [Direct Syscalls in Beacon Object Files](<https://outflank.nl/blog/2020/12/26/direct-syscalls-in-beacon-object-files/> "Direct Syscalls in Beacon Object Files" ) ([Code](<https://github.com/outflanknl/InlineWhispers> "Code" )) **[Download SysWhispers2](<https://github.com/jthuraisamy/SysWhispers2> "Download SysWhispers2" )**