Thursday, 21 May 2026

Windows APIs, Syscalls, EDR Telemetry, and Modern Post-Exploitation Tradecraft

Introduction

This document summarizes high-level concepts related to Windows internals, API layers, syscall techniques, EDR telemetry, Beacon Object Files (BOFs), and behavioral detection logic observed in modern enterprise environments.


1. Windows Architecture Overview

Windows applications generally operate in user mode and interact with the operating system through several abstraction layers before transitioning into kernel mode.

Typical execution flow:

Application
    -> Win32 API
        -> ntdll.dll
            -> syscall boundary
                -> Windows kernel

The Windows kernel (ntoskrnl.exe) is responsible for:

·       Process scheduling

·       Memory management

·       Security enforcement

·       Driver interaction

·       Filesystems

·       Hardware abstraction


2. Win32 APIs vs Native APIs

Most applications use high-level Win32 APIs such as:

·       CreateProcess

·       VirtualAlloc

·       WriteProcessMemory

·       CreateRemoteThread

These functions are commonly exported through:

·       kernel32.dll

·       advapi32.dll

·       user32.dll

Below the Win32 layer is the Native API layer inside ntdll.dll.

Examples include:

·       NtAllocateVirtualMemory

·       NtWriteVirtualMemory

·       NtCreateThreadEx

These functions exist closer to the syscall boundary and eventually transition execution into kernel mode.


3. System Calls

A syscall transitions execution from user mode to kernel mode.

On modern Windows x64 systems this typically occurs through the CPU syscall instruction.

Traditional flow:

Application
 -> Win32 API
    -> Native API
       -> syscall
          -> kernel


4. Direct vs Indirect Syscalls

Direct Syscalls

Direct syscall techniques invoke syscall instructions from custom code.

This may involve constructing syscall stubs dynamically and bypassing higher-level API wrappers.

Indirect Syscalls

Indirect syscall techniques generally route execution through existing syscall stubs already present inside ntdll.dll.

The goal is often to blend more naturally with legitimate operating system behavior.

These approaches emerged because many EDR products historically focused heavily on user-mode API monitoring and hook-based telemetry.


5. .NET, VBA, and Native C/C++

.NET

.NET applications operate under the Common Language Runtime (CLR) and access Windows functionality through:

·       P/Invoke

·       D/Invoke

·       Interop

·       Reflection

VBA

VBA macros are high-level scripting environments commonly used inside Microsoft Office.

Because VBA has limited low-level capability, it has historically been used as:

·       a launcher,

·       orchestration layer,

·       or delivery mechanism

for native payloads written in C or C++.

Native C/C++

Native C/C++ code provides:

·       direct memory manipulation,

·       assembly integration,

·       low-level API access,

·       and greater control over execution behavior.


6. Beacon Object Files (BOFs)

BOFs are lightweight object modules commonly associated with modern adversary emulation frameworks.

Unlike DLLs:

·       BOFs are not full PE files,

·       are not loaded through the standard Windows loader,

·       and are typically executed directly in memory by an existing Beacon runtime.

BOFs can reduce certain forms of telemetry by avoiding:

·       additional process creation,

·       disk artifacts,

·       and standard PE loading behavior.


7. EDR Telemetry and Behavioral Detection

Modern EDR platforms perform significantly more than simple API-hook monitoring.

Common telemetry sources include:

·       Process lineage analysis

·       LOLBin monitoring

·       Memory behavior inspection

·       ETW telemetry

·       Thread start analysis

·       AMSI integration

·       Kernel callbacks

·       Behavioral correlation

As a result, detection frequently occurs because of the overall behavioral chain rather than a single suspicious API.


8. Why Initial Access Chains Become Noisy

Typical Legacy attacker TTP's could resemble

PowerShell
 -> download DLL
    -> write DLL to Temp
       -> rundll32.exe
          -> DLL export execution
             -> remote process injection

This execution chain is highly visible because it combines multiple high-signal behaviors:

·       Script interpreter execution

·       Hidden window execution

·       Network download activity

·       DLL execution from temporary directories

·       LOLBin usage (rundll32.exe)

·       Remote process injection behavior

Modern EDR products often correlate all of these signals into a single behavioral narrative.


9. The Shift from API Detection to Behavioral Analytics

Historically, defensive tooling focused heavily on detecting calls such as:

·       CreateRemoteThread

·       VirtualAllocEx

·       WriteProcessMemory

Modern EDR philosophy has evolved toward detecting suspicious operational patterns and execution context.

Examples include:

·       Office spawning interpreters

·       Chained LOLBins

·       Unbacked executable memory

·       Shellcode-like memory regions

·       Suspicious parent/child process relationships

·       Abnormal network-capable in-memory execution


10. Key Takeaways

  1. Syscalls and Native APIs reduce certain forms of user-mode visibility but do not eliminate telemetry.
  2. Modern EDR products increasingly rely on behavioral correlation rather than simple API hooking.
  3. Initial access chains often generate more detections than the post-exploitation tooling itself.
  4. BOFs and in-memory modules may reduce operational noise compared to traditional loaders, but they are still observable through multiple telemetry sources.
  5. Mature adversary emulation focuses on the entire attack chain, including:

·       execution provenance,

·       process lineage,

·       memory semantics,

·       behavioral shaping,

·       and operational discipline.


11. .NET Limitations vs Native C/C++ in Low-Level Windows Operations

Managed vs Unmanaged Execution

One of the most important distinctions between .NET languages and native C/C++ is the difference between managed and unmanaged execution.

.NET applications run under the Common Language Runtime (CLR). The CLR provides:

·       memory management,

·       garbage collection,

·       JIT compilation,

·       exception handling,

·       and runtime safety services.

This provides major development advantages but also introduces additional telemetry and operational visibility.

Typical .NET execution flow:

C# Code
 -> CLR
    -> P/Invoke or Interop
       -> Win32 API
          -> ntdll.dll
             -> syscall

By comparison, native C/C++ executes directly as unmanaged machine code:

Native C/C++
 -> Win32 or Native API
    -> syscall boundary


Why .NET Commonly Relies on Win32 APIs

.NET itself does not natively expose most low-level Windows internals.

As a result, low-level operations often require:

·       P/Invoke,

·       D/Invoke,

·       COM interop,

·       or unmanaged delegates.

Examples include:

·       memory allocation,

·       process creation,

·       thread creation,

·       token manipulation,

·       and low-level handle operations.

Historically, many .NET offensive frameworks heavily relied on:

·       kernel32.dll

·       advapi32.dll

·       user32.dll

through P/Invoke declarations.

This created highly visible execution patterns.


Additional Telemetry Introduced by .NET

Because .NET uses the CLR, it introduces additional telemetry layers beyond the Windows API layer itself.

Examples include:

·       CLR module loading

·       JIT compilation activity

·       AMSI inspection

·       ETW providers

·       managed assembly metadata

·       reflection activity

·       in-memory assembly loading

This means defenders may observe:

·       the .NET runtime itself,

·       suspicious assembly loading patterns,

·       or managed code behavior,

before low-level API activity even occurs.


Native C/C++ and Lower-Level Control

Native C/C++ provides significantly more direct control over:

·       memory layout,

·       execution flow,

·       calling conventions,

·       assembly integration,

·       and syscall-related behavior.

Because native code operates without the CLR:

·       fewer runtime artifacts exist,

·       execution paths are simpler,

·       and developers have finer control over Windows internals.

This is one reason advanced low-level tooling is commonly written in:

·       C

·       C++

·       Rust

·       Nim

rather than managed languages.


Win32 APIs and EDR Visibility

Historically, many EDR platforms focused heavily on monitoring high-level Win32 APIs.

Examples include:

·       VirtualAlloc

·       VirtualAllocEx

·       WriteProcessMemory

·       CreateRemoteThread

·       CreateProcess

These APIs became heavily associated with:

·       malware loaders,

·       injectors,

·       commodity malware,

·       and offensive tooling.

As a result, security products commonly instrumented:

·       kernel32.dll

·       kernelbase.dll

·       ntdll.dll

using user-mode hooks and telemetry collection.

This is one reason low-level native tooling evolved toward:

·       Native API usage,

·       dynamic import resolution,

·       syscall-oriented techniques,

·       and reduced dependency on standard Win32 wrappers.


Why BOFs Became Popular for Post-Exploitation

Beacon Object Files (BOFs) are lightweight in-memory task modules commonly written in C and used by modern adversary emulation frameworks.

Unlike traditional DLL-based tooling, BOFs are not full Portable Executable (PE) files loaded through the standard Windows loader.

Instead, they are object modules executed directly inside an existing agent or Beacon process.

This architectural model became popular because it can:

·       reduce process creation events,

·       reduce dependency on scripting interpreters,

·       avoid loading additional PE files,

·       reduce disk artifacts,

·       and perform highly focused in-memory operations.

BOFs are typically designed for short-lived operational tasks such as:

·       token operations,

·       process enumeration,

·       credential access simulation,

·       Active Directory enumeration,

·       privilege checks,

·       and memory interaction tasks.

Because BOFs execute within an already-running agent context, they can reduce the amount of observable execution-chain noise compared to launching separate external tooling.


Why BOFs Are Operationally Attractive

BOFs generally:

·       execute quickly,

·       have limited scope,

·       avoid spawning child processes,

·       and leverage an existing Beacon context.

This reduces:

·       process lineage noise,

·       interpreter telemetry,

·       additional PE loader visibility,

·       and some forms of execution-chain telemetry.

Because BOFs are written in native C:

·       they can interact directly with Windows internals,

·       use Native APIs,

·       and avoid many of the runtime artifacts associated with managed environments.


Important Modern Reality

It is important to understand that reduced telemetry does not mean invisibility.

Modern EDR platforms increasingly monitor:

·       memory semantics,

·       thread behavior,

·       ETW telemetry,

·       process relationships,

·       call stack integrity,

·       executable memory regions,

·       and behavioral correlations.

As a result, contemporary defensive monitoring focuses on the overall behavioral narrative rather than solely on whether a particular Win32 API was called.


Conclusion

Modern Windows security monitoring is no longer centered solely around individual API calls.

While syscall-oriented techniques may reduce visibility at certain user-mode monitoring layers, contemporary EDR products increasingly rely on broader behavioral analytics and telemetry correlation.

As a result, the overall execution chain, operational context, process lineage, and memory behavior frequently determine whether activity is considered suspicious

No comments:

Post a Comment