Direct Syscalls
NOTE: As of May 2023, direct syscalls may not be sufficient enough to bypass EDR as more vendors are adding callbacks to their solutions. These callbacks determine where the return statements are happening in memory, if the memory address is outside of ntdll.dll this is a clear IOC.
We should replace direct syscalls with indirect syscalls.
Introduction
Direct syscalls work by reading the syscall number from the functions assembly code. It's works by getting the assembly call to the SSN (System Security Number) by it's syscall stub offset.
Example - Direct Syscalls:
The important thing to notice is that we are using GetProcAddress to obtain a pointer to the memory address of the specific function we are looking for, we then caculate the offset based on the assembly stub.
NOTE: The important difference between this and using the NtAPI, where we are just using a function through it's declared prototype. When using the native API we are not diving into any of the assembly details or syscall numbers. IMPORTANT: Many legitimate applications use NtAPI functions directly, which is not an IOC imo. Direct syscalls, calling NtAPI functions from outside ntdll memory is always a clear IOC.
All syscalls return a NTSTATUS value that indicates the status (or error) code of the operation.
The majority of syscalls are not documented by Microsoft, therefore the syscall modules will reference the documentation shown below.
Disassembling ntdll.dll in IDA can also be beneficial.
The majority of the syscalls are exported from ntdll.dll. We can view them by opening ntdll.dll in IDA.
NOTE: Syscalls provide low-level access to the operating system, by calling these functions directly acts as a bypass to EDR hooks set in place at the higher level API functions. (VirtualAlloc, CreateProcess, CreateThread, etc.)
Syscall Service Number (SSN)
Every syscall has a Syscall Service Number (SSN). These numbers are what the kernel uses to distinguish syscalls from each other and are executed in the syscall stub (explained below). IMPORTANT: syscall service numbers are not static throughout all version of windows as they have changed over time. See the table below:
Syscall Stub
The syscall stub or syscall structure will look like the snippet shown below.
Syscall Stub Explained
mov r10, rcx
This moves the value of rcx
register into r10
register. NOTE: The rcx
register typically holds the first argument to a function or syscall.
mov eax, SSN
This moves the constant value SSN into the eax register. The eax register is used to specify syscall numbers, which determines which syscall the program should invoke.
syscall
The syscall instruction when executed triggers a switch from user mode to kernel mode, transfering control to the operating systems kernel. invokes the current syscall in the eax register.
IMPORTANT:
The kernel uses the values in registers like rax
, rdi
, rsi
, rdx
, r10
, and others to determine which syscall is being requested and to access the syscall's arguments.
rax
: Contains the syscall number (which was loaded with mov eax, SSN
in this case).
rdi
, rsi
, rdx
, r10
, r8
, r9
: These registers are used to pass arguments to the syscall.
rcx
holds the address of the application to be executed.rdx
holds the command-line arguments.r8
holds the security attributes.r9
holds the security attributes for the thread.
Test & Jne Instructions
Verifying SSN Number:
Syscalls In Memory
Each syscall number in memory is equal to the previous SSN + 1. For example: the first Syscall (mov eax, 0) is ZwAccessCheck and the second (mov eax,1) is NtWorkFactoryWorkReady so on so forth.
NOTE: Understanding that the syscalls have a relation to one another will come in handy for evasion purposes in upcoming syscall modules.
NTAPIs that arn't syscalls
NOTE: while some NtAPIs return NTSTATUS
, they are not necessarily syscalls.
If they don't have a SSN number or lack the mov r10, rcx
then they do not comply as a syscall.
Example of NtAPIS that are not syscalls:
LdrLoadDll
- This is used by theLoadLibrary
WinAPI to load an image to the calling process.SystemFunction032
andSystemFunction033
- These NtAPIs were introduced earlier and perform RC4 encryption/decryption operations.RtlCreateProcessParametersEx
- This is used by theCreateProcess
WinAPI to create arguments of a process.
Last updated