You are currently viewing Indirect Syscall

Indirect Syscall

Hello Hackers! Its been a while since I write a blog post related to malware development, so with that in mind I am writing a blog on Indirect Syscall technique used in malware development. If you are expecting any new research or POC for bypassing the AV/EDR , then this is not a suitable blog for you. This project demonstrates how indirect syscalls work internally, step by step. And yes, help from various AI tools has been taken for understanding the concept.

 

Theoretical Concept

Normally when we call any Windows API like VirtualAlloc(), the API will gets triggered from kernel32.dll and then from there a middle-ware API for VirtualAlloc() from kernelbase.dll gets called and then NtAllocateVirtualMmeory() will gets called. This Native API will contain all the necessary assembly instructions in form of syscall stub (SSN, syscall, etc.) and enables the temporary transition from user mode (ring 0) to kernel mode (ring 0) after execution. Refer to below screenshot for more understanding. In Direct Syscall we se the SSN number to directly call the Windows API , for example the SSN number of the VirtualAlloc() is 0x18 for 64 bit windows system.

Although direct syscalls can successfully bypass user-mode hooks implemented by EDR solutions, they introduce distinct indicators of compromise that may still trigger detection mechanisms.

  • In the case of direct syscalls, the syscall instruction is executed from the memory region of the custom assembly stub itself, rather than from within ntdll.dll. This behavior is highly anomalous, as legitimate syscall execution on Windows is expected to originate exclusively from the ntdll.dll code section.
  • Additionally, the corresponding ret instruction is also executed inside the same custom assembly region. As a result, the control flow both originates from and returns to a non-ntdll memory region, creating an execution pattern that deviates from standard Windows syscall behavior and can be used as a reliable detection signal by EDR products.

Indirect syscall is a technique to:

    1. Avoid calling the high-level APIs direcctly
    2. Avoid executing syscall from your own module
    3. Execute the Syscall instruction from inside ntdll’s .text section , making it appear legitimate.

Overall Code Flow

  1. Map a clean copy of ntdll.dll from disk
  2. Extract syscall numbers (SSNs) from clean ntdll
  3. Locate a syscall; ret gadget in loaded ntdll
  4. Prepare global state (SSN + gadget address)
  5. Jump into ntdll to execute the syscall indirectly

The Code

Step 1 (ntdll Mapping):

Instead of relying on the in-memory ntdll.dll which may be modified or hooked by security software, the engine reads a clean copy of ntdll.dll from disk. This copy is used purely as a reference source to extract syscall metadata, not for execution.
The function is basically reading the local copy of the ntdll.dll and allocating the space in the memory using the HeapAlloc(), so that the buffer in the memory can be used to read the section and the headers of the PE file.

Step 2 (Extracting SSN)

The above function helps to extract the SSN from the clean copy of the ntdll file. It is parsing the section headers and finding the RVA to the export address table using  the DATA DIRECTORY . The export address table (EAT) resides at the 0th position of the Data Directory address (If you are unfamiliar with the Export Address Table  , then I will recommend to checkout my previous blog). Data Directory in a PE file is a structure which contain two field for every element , Virtual Address and Directory Size.

typedef struct _IMAGE_DATA_DIRECTORY {
    DWORD   VirtualAddress;
    DWORD   Size;
} IMAGE_DATA_DIRECTORY, *PIMAGE_DATA_DIRECTORY;

Once we get RVA of the export address table, we start parsing the functions from the export address table, once we found the the particular function, we will search for a few specific offset, 4C 8B D1 B8. The SSN is at the 4th place from the start of the offset. Lets dig into this more using the diagram below.

 

We can see that the  Syscall is happening using the Native API (NtAllocateVirtualMemory). First instruction is related to the MOV and it has the offset that we are searching and after that we can see that another MOV instruction is happening where some value is moving to the EAX and that particular value is the SSN.

So, the above code is just extracting the SSN for a particular API.

Step 3: (Finding return gadget)

 

If you are unfamiliar with the term return gadget , then don’t worry I still don’t know why the hell this was named like that.

In the context of indirect syscalls, a return gadget refers to an existing, legitimate instruction sequence that performs a system call and then returns execution back to user mode in a normal, expected way.

Above definition is copied from ChatGPT but I didn’t understand that as well.

So, basically we want to execute the syscall and return to the already loaded NTDLL.dll memory region instead of memory region of our malicious binary and that is what the above code is doing and for doing that we first need to find the return address of the loaded NTDLL modules region.

So for finding the return address of the loaded NTDLL memory region, we are need to find the .text section (.text section is the section where all your instructions resides.) and once we are in the .text section we need to find few instruction bytes (instruction bytes are hidden in the code, you need to do little exercise to find that) and once we find the opcodes to the return instruction , we are just storing that address in a global variable.

Step 4 : (Implementing syscall)

We have the SSN, return address and API schema and now we can just call the Windows API using the syscall. In the above codes, we can see that we are first calling custom VirtualAlloc() and we can see what it is doing in indirect_syscall.asm file. We are just moving the ssn number into eax and after that we are jumping to the returning back to the loaded NTDLL memory region.

 

Demo

Here is the demonstration of the full POC.

 

Hope you guys liked this post. Happy Hacking !!