NadahWeb
Home
Compliance Services
PCI DSS ComplianceSOC 1 & SOC 2HIPAA ComplianceGDPR ComplianceISO 27001
Security Assessment
Vulnerability Assessment and Penetration Testing (VAPT)Infrastructure & Cloud SecurityRed Team
AI Security & GovernanceCloud Implementation & OptimizationSIEM & Endpoint SecurityDevelopment & BlockchainMarketingStrategic OutsourcingTraining and Education Programs
About UsBlogContact Us
Back to Intelligence
Offensive Security 12 min read

Offensive Rust: EDR Evasion via Direct System Calls

Modern Endpoint Detection and Response (EDR) solutions aggressively hook user-mode APIs. This technical deep dive explores how advanced threat actors use Rust to execute direct syscalls, bypassing NTDLL hooks entirely.

NW
NadahWeb Threat Intelligence
September 8, 2026

Bypassing EDRs

For years, the standard approach to malware development and red team tooling relied heavily on the Windows API. You want to allocate memory for your shellcode? You call VirtualAllocEx. You want to create a thread? CreateRemoteThread.

The problem is that modern Endpoint Detection and Response (EDR) solutions know exactly what you are doing.

EDRs achieve this visibility through User-Mode API Hooking. When a process loads, the EDR injects its own DLL into the process space. It overwrites the first few instructions of critical functions inside ntdll.dll (like NtAllocateVirtualMemory) with a JMP instruction. This redirect forces the execution flow into the EDR’s inspection engine before the system call ever reaches the Windows kernel.

If you use standard Windows APIs in 2026 for offensive operations, you are going to get caught. Period.

To bypass this, advanced threat actors have shifted to using Direct System Calls. By bypassing ntdll.dll entirely and manually moving the System Service Number (SSN) into the EAX register before invoking the syscall instruction, the EDR's user-mode hooks are completely blinded.

Here is how we implement this concept using Rust.

The Architecture of a Syscall

In a normal execution flow, calling VirtualAlloc looks like this: Application -> kernel32.dll -> ntdll.dll -> [EDR HOOK] -> Kernel Mode (Ring 0)

By using direct syscalls, we change the flow to: Application -> [Direct Assembly Syscall] -> Kernel Mode (Ring 0)

Every native Windows function corresponds to a specific System Service Number (SSN) in the kernel. For example, on Windows 10/11, the SSN for NtAllocateVirtualMemory is typically 0x18 (though this changes depending on the exact Windows build).

Implementing the Syscall in Rust

Rust has become the language of choice for modern offensive tooling due to its memory safety, powerful macro system, and seamless ability to drop into inline assembly.

To execute a direct syscall in Rust, we use the core::arch::asm! macro. Here is a simplified implementation of a direct syscall to NtAllocateVirtualMemory:

#![feature(asm)]

use std::ffi::c_void;
use std::ptr::null_mut;

// The System Service Number for NtAllocateVirtualMemory (Windows 11)
const NT_ALLOCATE_VIRTUAL_MEMORY_SSN: u32 = 0x18;

// Define the NTSTATUS return type
type NtStatus = i32;

unsafe fn direct_syscall_allocate(
    process_handle: isize,
    base_address: *mut *mut c_void,
    zero_bits: usize,
    region_size: *mut usize,
    allocation_type: u32,
    protect: u32,
) -> NtStatus {
    let status: NtStatus;

    core::arch::asm!(
        "mov r10, rcx",
        "mov eax, {ssn}",
        "syscall",
        ssn = const NT_ALLOCATE_VIRTUAL_MEMORY_SSN,
        inout("rcx") process_handle => _,
        inout("rdx") base_address => _,
        inout("r8") zero_bits => _,
        inout("r9") region_size => _,
        // Arguments 5 and 6 are passed on the stack
        // in x64 calling convention, but for simplicity 
        // this example abstracts the stack setup.
        lateout("eax") status,
        options(nostack)
    );

    status
}

Why does this work?

  1. No ntdll.dll interaction: The code never calls the hooked ntdll.dll functions.
  2. Raw execution: We manually load the SSN (0x18) into the eax register.
  3. Hardware boundary: The syscall instruction triggers a hardware interrupt, seamlessly crossing the boundary from user-mode (Ring 3) into the kernel (Ring 0).

The Catch: Dynamic System Service Numbers

The code above has a massive flaw: Hardcoded SSNs.

Microsoft frequently changes the SSNs between Windows versions, service packs, and even minor updates. If you hardcode 0x18 and deploy your payload to a Windows 10 machine where the SSN is 0x16, your tool will crash instantly, triggering an alert.

To build production-grade offensive tools (or to defend against them), you must implement Dynamic SSN Resolution. This involves manually reading the ntdll.dll file from disk (before the EDR has a chance to hook it in memory), parsing the PE headers, and extracting the clean SSNs dynamically at runtime. Techniques like "Hell's Gate" or "Halo's Gate" are famous implementations of this concept.

Defending Against Direct Syscalls

If EDRs are blinded in user-mode, how do blue teams defend against this? The battleground is shifting to Kernel-Mode Telemetry.

Modern EDRs rely heavily on Event Tracing for Windows (ETW), specifically the ETW Threat Intelligence provider, and kernel callbacks (ObRegisterCallbacks). While an attacker can hide how they allocated the memory by bypassing user-mode hooks, the kernel still records that the memory was allocated.

Need advanced red teaming to test your EDR configuration? Engage NadahWeb's offensive security team.

Rust Malware Development EDR Evasion Syscalls Red Teaming

Need expert help with Offensive Security?

Engage NadahWeb’s elite security team. Free 30-minute strategic consultation.

Engage Team
NadahWeb

Providing advanced cybersecurity solutions to protect your digital assets from evolving threats.

Certifications

  • PCI DSS
  • SOC 1 & SOC 2
  • HIPAA
  • GDPR
  • ISO/IEC 27001

Services

  • Compliance Services
  • Security Assessment
  • AI Security & Governance
  • SIEM & Endpoint Security
  • Development & Blockchain
  • Marketing
  • Strategic Outsourcing
  • Training & Education
  • Cloud Implementation

Company

  • About Us
  • Careers
  • Blog
  • Pricing
  • Contact

Contact Us

  • contact@nadahweb.com
  • +91 9286314474

© 2026 NadahWeb. All rights reserved.

Privacy PolicyTerms of Service