Chapter 10

Chapter 10: Modern Techniques (2024-2025)

The offensive-defensive landscape in Windows security evolves at a relentless pace. Techniques that represented the cutting edge just two years ago have become baseline capabilities, while entirely new approaches emerge to address ever-more-sophisticated detection mechanisms. This chapter examines the current state of the art as of 2024-2025, exploring both the latest offensive techniques and the defensive measures they must contend with.

Understanding this evolution isn't merely academic. For offensive security professionals, staying current means the difference between successful engagements and immediate detection. For defenders, understanding emerging threats enables proactive hardening and detection development before techniques become widespread. This chapter bridges both perspectives, explaining not just what these techniques do, but why they emerged and what trade-offs they represent.


The Evolution of Evasion

To understand where we are, we must first understand how we got here. The progression of evasion techniques over the past five years follows a clear pattern: each defensive innovation spawns offensive counter-measures, which in turn drives new defensive capabilities.

                    TECHNIQUE EVOLUTION 2020-2025

    ┌─────────────────────────────────────────────────────────────────────┐
    │  2020-2021: The Direct Syscall Era                                  │
    │  ┌────────────────────────────────────────────────────────────────┐ │
    │  │  Problem: EDRs hooking ntdll.dll functions                     │ │
    │  │  Solution: Direct syscalls via SysWhispers                     │ │
    │  │  Detection Response: Stack tracing, syscall origin checking    │ │
    │  └────────────────────────────────────────────────────────────────┘ │
    ├─────────────────────────────────────────────────────────────────────┤
    │  2022-2023: The Indirect Syscall Era                                │
    │  ┌────────────────────────────────────────────────────────────────┐ │
    │  │  Problem: Stack traces showing syscall from unusual locations  │ │
    │  │  Solution: Indirect syscalls (Hell's Gate, Halo's Gate)        │ │
    │  │  Detection Response: ETW-TI, kernel callbacks, deeper analysis │ │
    │  └────────────────────────────────────────────────────────────────┘ │
    ├─────────────────────────────────────────────────────────────────────┤
    │  2024-2025: The Full Stack Masquerade Era                           │
    │  ┌────────────────────────────────────────────────────────────────┐ │
    │  │  Problem: Full call stack analysis, kernel telemetry           │ │
    │  │  Solutions:                                                    │ │
    │  │  ├── Synthetic stack frames with UNWIND_INFO accuracy         │ │
    │  │  ├── Thread pool callback execution                           │ │
    │  │  ├── Module stomping with signed DLLs                         │ │
    │  │  ├── BYOVD for kernel-level bypass                            │ │
    │  │  └── Hardware security consideration (CET, VBS)               │ │
    │  │  Detection Response: Hardware telemetry, ML models            │ │
    │  └────────────────────────────────────────────────────────────────┘ │
    └─────────────────────────────────────────────────────────────────────┘

This progression reveals an important truth: evasion techniques don't become obsolete—they become table stakes. Today's sophisticated implant must implement direct syscalls, indirect syscalls, stack spoofing, and sleep encryption as baseline capabilities, then layer additional techniques on top.


Advanced Syscall Techniques

We covered basic syscall evasion in earlier chapters, but the techniques have continued to evolve. Modern EDRs don't just hook ntdll.dll—they analyze syscall patterns, monitor instruction pointers, and correlate syscall activity with other telemetry. Countering these defenses requires more sophisticated approaches.

Syscall Gadget Randomization

One detection technique involves identifying which module contains the syscall instruction being used. If all syscalls originate from the same unusual location—or show consistent patterns—this becomes a detection signal. Syscall gadget randomization addresses this by using different modules for different syscalls.

                    SYSCALL GADGET DISTRIBUTION

    The syscall; ret instruction sequence (0F 05 C3) appears in many modules:

    ┌─────────────────────────────────────────────────────────────────────┐
    │  Module              │  Gadget Count  │  Detection Risk            │
    ├─────────────────────────────────────────────────────────────────────┤
    │  ntdll.dll           │  Many          │  Low (expected location)   │
    │  win32u.dll          │  Several       │  Low (syscall stub DLL)    │
    │  kernelbase.dll      │  Some          │  Medium                    │
    │  kernel32.dll        │  Some          │  Medium                    │
    │  combase.dll         │  Several       │  Medium                    │
    │  rpcrt4.dll          │  Some          │  Medium                    │
    │  user32.dll          │  Several       │  Medium                    │
    │  gdi32.dll           │  Several       │  Medium                    │
    └─────────────────────────────────────────────────────────────────────┘

    Strategy: Build a pool of gadgets across modules, randomly select for each syscall

The implementation involves scanning loaded modules for the syscall pattern, building a pool of valid gadgets, then selecting randomly (or pseudo-randomly based on the syscall being made) from this pool. Each syscall can originate from a different module, breaking pattern-based detection.

SSN Validation and Caching

System Service Numbers (SSNs) change between Windows versions and even between builds. Hardcoding SSNs, as early syscall implementations did, creates compatibility problems. Dynamic resolution addresses this, but the resolution itself can be detected.

Modern implementations cache resolved SSNs and validate them against multiple sources:

                    SSN RESOLUTION STRATEGIES

    Method 1: Parse ntdll.dll exports directly
    ├── Find function by hash
    ├── Read SSN from mov r10, rcx; mov eax, SSN pattern
    └── Validate: SSN should be < 0x500 for modern Windows

    Method 2: Exception directory walking
    ├── Enumerate all Zw* functions
    ├── Sort by address (SSN order)
    ├── SSN = position in sorted list
    └── Validate: Cross-reference with Method 1

    Method 3: Hell's Gate (hooked function recovery)
    ├── If function is hooked (JMP at start)
    ├── Search neighboring functions for valid SSN
    ├── Calculate target SSN from neighbor's SSN ± offset
    └── Validate: Multiple neighbors should agree

    Caching:
    ┌────────────────────────────────────────────────────────────────────┐
    │  Hash(NtAllocateVirtualMemory) → SSN: 0x18 → Validated: TRUE      │
    │  Hash(NtProtectVirtualMemory)  → SSN: 0x50 → Validated: TRUE      │
    │  Hash(NtWriteVirtualMemory)    → SSN: 0x3A → Validated: TRUE      │
    └────────────────────────────────────────────────────────────────────┘

Validation prevents attackers from using corrupted or intentionally manipulated SSNs that defenders might plant as honeypots. Multiple resolution methods provide cross-validation.


Thread Pool Execution

One of the most significant recent developments is the shift toward callback-based execution. Instead of directly calling suspicious functions, modern techniques queue callbacks through legitimate Windows mechanisms. The thread pool API provides particularly useful primitives.

Why Thread Pool Execution Matters

When code executes through a thread pool callback, the call stack looks entirely legitimate:

                    CALL STACK COMPARISON

    Direct Execution (Suspicious):
    ┌────────────────────────────────────────────────────────────────────┐
    │  NtAllocateVirtualMemory                                          │
    │  MyAllocationWrapper+0x42      ← Unbacked memory (suspicious)     │
    │  ShellcodeMain+0x187           ← Unbacked memory (suspicious)     │
    │  Unknown+0x0                   ← No valid return (suspicious)     │
    └────────────────────────────────────────────────────────────────────┘

    Thread Pool Execution (Legitimate-Looking):
    ┌────────────────────────────────────────────────────────────────────┐
    │  NtAllocateVirtualMemory                                          │
    │  TppWorkerThread+0x2B4         ← ntdll.dll (legitimate)           │
    │  RtlUserThreadStart+0x21       ← ntdll.dll (legitimate)           │
    └────────────────────────────────────────────────────────────────────┘

The thread pool worker thread handles the callback, and its call stack shows only legitimate system code. The shellcode's address doesn't appear in the stack trace at the point of the syscall.

Thread Pool Primitives

Windows provides several thread pool mechanisms, each with different characteristics:

                    THREAD POOL EXECUTION OPTIONS

    TpAllocWork / TpPostWork:
    ┌────────────────────────────────────────────────────────────────────┐
    │  Use case: Execute arbitrary function once                         │
    │  Timing: Immediate (queued to worker thread)                       │
    │  Cleanup: TpReleaseWork                                            │
    │  Stack appearance: TppWorkerThread → callback                      │
    └────────────────────────────────────────────────────────────────────┘

    TpAllocTimer / TpSetTimer:
    ┌────────────────────────────────────────────────────────────────────┐
    │  Use case: Delayed or periodic execution                           │
    │  Timing: After specified delay or at intervals                     │
    │  Cleanup: TpReleaseTimer                                           │
    │  Stack appearance: TppTimerQueueExpiration → callback              │
    └────────────────────────────────────────────────────────────────────┘

    TpAllocWait / TpSetWait:
    ┌────────────────────────────────────────────────────────────────────┐
    │  Use case: Execute when kernel object signals                      │
    │  Timing: Event-driven                                              │
    │  Cleanup: TpReleaseWait                                            │
    │  Stack appearance: TppWaitThread → callback                        │
    └────────────────────────────────────────────────────────────────────┘

    TpAllocIoCompletion:
    ┌────────────────────────────────────────────────────────────────────┐
    │  Use case: Execute on I/O completion                               │
    │  Timing: After async I/O completes                                 │
    │  Stack appearance: TppIoThread → callback                          │
    └────────────────────────────────────────────────────────────────────┘

Different callbacks suit different scenarios. Timer callbacks work well for delayed execution (like sleep encryption wake-up). Work callbacks handle immediate execution needs. Wait callbacks can trigger on external events.

Implementation Considerations

Using thread pool APIs effectively requires dynamic resolution to avoid IAT entries:

    Resolution Flow:

    1. Get ntdll.dll handle (GetModuleHandle or PEB walk)
    2. Resolve Tp* functions by hash:
       ├── TpAllocWork
       ├── TpPostWork
       ├── TpReleaseWork
       └── Other needed functions
    3. Cast to appropriate function pointer types
    4. Use for callback-based execution

    Callback Function Requirements:

    - Match expected signature for callback type
    - Handle provided context parameter
    - Execute payload code
    - Signal completion if needed (for synchronization)
    - Avoid blocking worker threads for extended periods

The main caveat is that callback functions execute in worker threads, not the main thread. State shared between the main thread and callback must be properly synchronized.


Bring Your Own Vulnerable Driver (BYOVD)

Kernel-level detection mechanisms like ETW-TI pose a fundamental challenge: they operate from a higher privilege level than user-mode implants. BYOVD addresses this by leveraging legitimate but vulnerable drivers to gain kernel write access, enabling direct patching of kernel structures.

The BYOVD Concept

Many legitimate, signed drivers contain vulnerabilities that allow arbitrary kernel memory read/write. Since these drivers are properly signed by their vendors (and often by Microsoft's Hardware Compatibility program), they load without triggering Driver Signature Enforcement. Once loaded, their vulnerabilities become tools.

                    BYOVD ATTACK FLOW

    ┌─────────────────────────────────────────────────────────────────────┐
    │  1. Locate vulnerable driver                                        │
    │     ├── Must be properly signed                                    │
    │     ├── Known exploitable vulnerability                            │
    │     └── Allows arbitrary kernel memory access                      │
    ├─────────────────────────────────────────────────────────────────────┤
    │  2. Load driver                                                     │
    │     ├── Copy to disk (can use innocuous name)                      │
    │     ├── Create service registry entries                            │
    │     └── Start service (driver loads)                               │
    ├─────────────────────────────────────────────────────────────────────┤
    │  3. Exploit vulnerability                                           │
    │     ├── Send IOCTL with exploit payload                            │
    │     ├── Gain arbitrary read/write primitive                        │
    │     └── Use primitive to modify kernel structures                  │
    ├─────────────────────────────────────────────────────────────────────┤
    │  4. Disable defenses                                                │
    │     ├── Patch ETW-TI functions (ret at start)                      │
    │     ├── Remove kernel callbacks (unlink from lists)                │
    │     ├── Disable DSE (clear g_CiOptions)                            │
    │     └── Other kernel-level modifications                           │
    └─────────────────────────────────────────────────────────────────────┘

Common BYOVD Targets

The security community maintains lists of vulnerable drivers. Some notable examples:

Driver Vendor Vulnerability Capability
dbutil_2_3.sys Dell Arbitrary memory R/W Full kernel access
ene.sys Various Physical memory mapping Full kernel access
gdrv.sys GIGABYTE Arbitrary memory R/W Full kernel access
RTCore64.sys MSI Physical memory mapping Full kernel access

Microsoft's Vulnerable Driver Blocklist attempts to prevent known-bad drivers from loading, but new vulnerabilities are regularly discovered, and blocklist updates lag behind.

ETW-TI Patching via BYOVD

One of the most impactful uses of BYOVD is patching ETW Threat Intelligence functions in the kernel. These functions generate telemetry for security tools; disabling them blinds those tools to certain activities.

                    ETW-TI KERNEL PATCHING

    Target Functions in ntoskrnl.exe:
    ┌────────────────────────────────────────────────────────────────────┐
    │  EtwTiLogReadWriteVm                                              │
    │  ├── Logs NtReadVirtualMemory / NtWriteVirtualMemory calls       │
    │  └── Patch: ret (0xC3) at function start                         │
    │                                                                    │
    │  EtwTiLogSetContextThread                                         │
    │  ├── Logs thread context manipulation                            │
    │  └── Patch: ret (0xC3) at function start                         │
    │                                                                    │
    │  EtwTiLogMapView                                                  │
    │  ├── Logs memory mapping operations                               │
    │  └── Patch: ret (0xC3) at function start                         │
    │                                                                    │
    │  EtwTiLogAllocExecVm                                              │
    │  ├── Logs executable memory allocation                            │
    │  └── Patch: ret (0xC3) at function start                         │
    └────────────────────────────────────────────────────────────────────┘

    Effect: EDR loses visibility into these operations at kernel level

The patch is simple—replacing the first byte with ret (0xC3) causes the function to return immediately without logging anything. With a kernel write primitive from BYOVD, this patch is straightforward to implement.

Driver Signature Enforcement Bypass

Beyond ETW-TI, BYOVD enables disabling Driver Signature Enforcement entirely, allowing unsigned kernel drivers to load:

    DSE Bypass via ci.dll!g_CiOptions:

    1. Locate ci.dll in kernel memory
    2. Find g_CiOptions variable (pattern scan)
    3. Write 0 to g_CiOptions
    4. Unsigned drivers can now load

    Alternative: Callback removal

    1. Find PsSetLoadImageNotifyRoutine callback list
    2. Walk list, find EDR callbacks
    3. Unlink EDR callbacks from list
    4. EDR no longer notified of driver loads

These techniques represent a significant escalation in the arms race—they don't just evade detection, they actively disable defensive mechanisms.


Module Stomping

Module stomping addresses a fundamental detection vector: unbacked executable memory. When shellcode runs from heap-allocated or directly mapped memory, that memory has no backing file on disk. EDRs can easily identify such regions as suspicious. Module stomping solves this by overwriting the code section of a legitimately loaded, signed DLL.

The Stomping Process

                    MODULE STOMPING WORKFLOW

    ┌─────────────────────────────────────────────────────────────────────┐
    │  1. Select target module                                            │
    │     ├── Microsoft-signed DLL                                       │
    │     ├── .text section larger than payload                          │
    │     ├── Not heavily used (to avoid crashes)                        │
    │     └── Already loaded or loadable                                 │
    ├─────────────────────────────────────────────────────────────────────┤
    │  2. Load module without initialization                              │
    │     └── LoadLibraryEx with DONT_RESOLVE_DLL_REFERENCES             │
    │         (Loads PE, maps sections, but doesn't run DllMain)         │
    ├─────────────────────────────────────────────────────────────────────┤
    │  3. Locate .text section                                            │
    │     ├── Parse PE headers                                           │
    │     ├── Find section with executable characteristics               │
    │     └── Verify size accommodates payload                           │
    ├─────────────────────────────────────────────────────────────────────┤
    │  4. Overwrite .text section                                         │
    │     ├── VirtualProtect to PAGE_READWRITE                           │
    │     ├── memcpy payload over original code                          │
    │     └── VirtualProtect to PAGE_EXECUTE_READ                        │
    ├─────────────────────────────────────────────────────────────────────┤
    │  5. Execute payload                                                 │
    │     └── Call into stomped region                                   │
    └─────────────────────────────────────────────────────────────────────┘

    Result: Payload runs from memory backed by signed DLL

Target Selection

Not every DLL is suitable for stomping. Good targets share certain characteristics:

    Ideal Stomping Targets:

    ✓ Large .text section
      └── Payload must fit; larger is better for flexibility

    ✓ Microsoft or reputable vendor signed
      └── Reduces suspicion, passes signature checks

    ✓ Not frequently called after stomping
      └── Original exports now contain payload, calling them crashes

    ✓ Common in processes
      └── Blends with normal process behavior

    ✓ Not integrity-checked by other modules
      └── Some DLLs are verified at runtime

    Common Targets:
    ┌────────────────────────────────────────────────────────────────────┐
    │  amsi.dll      - Often already patched for AMSI bypass            │
    │  version.dll   - Commonly side-loaded, large .text                │
    │  dbghelp.dll   - Debug helper, rarely used after load             │
    │  msvcp*.dll    - C++ runtime, large, not always needed            │
    │  urlmon.dll    - URL moniker, large .text section                 │
    └────────────────────────────────────────────────────────────────────┘

Detection Considerations

While module stomping provides backing for executable memory, it creates other artifacts:

  1. Memory hash mismatch: The in-memory .text section no longer matches the on-disk file
  2. Protection changes: The RW→RX transition is observable
  3. Execution from unexpected location: Calls should originate from original code, not stomped payload

Advanced EDRs can detect some of these patterns, but the technique remains effective against many products.


Control-Flow Enforcement Technology (CET)

Intel's Control-Flow Enforcement Technology and its adoption in Windows represent a fundamental shift in the defensive landscape. CET includes two main features: Shadow Stacks and Indirect Branch Tracking (IBT). Understanding CET is crucial for both offensive and defensive practitioners.

Shadow Stack

The shadow stack is a hardware-maintained copy of return addresses. Every call instruction pushes the return address to both the regular stack and the shadow stack. Every ret instruction compares the return address from the regular stack against the shadow stack—if they differ, an exception occurs.

                    SHADOW STACK OPERATION

    Normal Call/Return:

    CALL target
    ├── Push return address to stack         (RSP)
    ├── Push return address to shadow stack  (SSP)
    └── Jump to target

    RET
    ├── Pop return address from stack         (RSP)
    ├── Pop return address from shadow stack  (SSP)
    ├── Compare addresses
    │   ├── Match: Continue execution
    │   └── Mismatch: Raise #CP exception
    └── Jump to return address

    Impact on Attacks:

    ┌────────────────────────────────────────────────────────────────────┐
    │  ROP Chains:                                                       │
    │  ├── Require manipulating shadow stack                            │
    │  ├── Shadow stack in kernel-protected memory                      │
    │  └── Effectively blocked by CET                                   │
    │                                                                    │
    │  Stack Spoofing:                                                   │
    │  ├── Must also spoof shadow stack entries                         │
    │  ├── Requires kernel-level access to shadow stack                 │
    │  └── Significantly more complex                                   │
    │                                                                    │
    │  Direct/Indirect Syscalls:                                        │
    │  ├── No ROP involved                                              │
    │  ├── Call/ret pairs remain matched                                │
    │  └── Unaffected by shadow stack                                   │
    └────────────────────────────────────────────────────────────────────┘

Indirect Branch Tracking (IBT)

IBT ensures that indirect calls and jumps (those not directly to a fixed address) land on valid targets. Valid targets are marked by ENDBR64 (or ENDBR32) instructions at function entry points.

                    INDIRECT BRANCH TRACKING

    Indirect Call Flow:

    CALL RAX (indirect call)
    └── Jump to address in RAX

    At target address:
    ├── First instruction must be ENDBR64 (0xF3 0x0F 0x1E 0xFA)
    │   └── Valid target, continue execution
    └── First instruction is NOT ENDBR64
        └── Raise #CP exception

    Impact:

    ┌────────────────────────────────────────────────────────────────────┐
    │  JOP (Jump-Oriented Programming):                                  │
    │  ├── Gadgets must start with ENDBR                                │
    │  ├── Severely limits available gadgets                            │
    │  └── Most JOP attacks blocked                                     │
    │                                                                    │
    │  Callback Execution:                                               │
    │  ├── Callbacks naturally have ENDBR (function entries)            │
    │  ├── Thread pool, timer callbacks unaffected                      │
    │  └── Shellcode injection affected                                  │
    │                                                                    │
    │  Shellcode Execution:                                              │
    │  ├── Shellcode typically lacks ENDBR                              │
    │  ├── Can add ENDBR prologue to shellcode                          │
    │  └── Or execute via legitimate callback mechanism                  │
    └────────────────────────────────────────────────────────────────────┘

CET Adoption Status

As of 2024-2025, CET adoption is growing but not universal:

Component CET Support
Intel 11th+ Gen CPUs Hardware support
AMD Zen 3+ CPUs Hardware support
Windows 11 Shadow stack enabled
Windows 10 (recent) Optional enforcement
Chrome, Edge Shadow stack enabled
Most applications Not yet enforced

The transition period creates opportunities. Many systems and applications don't yet enforce CET, and techniques like thread pool execution and indirect syscalls work regardless of CET status.


AI and Machine Learning Considerations

Both offense and defense increasingly employ machine learning. EDRs use ML models to identify suspicious behavior patterns, while offensive tools explore ways to evade these models.

ML-Based Detection

Modern EDRs employ multiple ML approaches:

                    EDR ML DETECTION LAYERS

    Static Analysis:
    ┌────────────────────────────────────────────────────────────────────┐
    │  Features extracted:                                               │
    │  ├── PE structure anomalies                                       │
    │  ├── Import table characteristics                                 │
    │  ├── Section entropy and sizes                                    │
    │  ├── String patterns and frequencies                              │
    │  └── Code patterns and instruction sequences                      │
    │                                                                    │
    │  Model output: Malicious probability score                        │
    └────────────────────────────────────────────────────────────────────┘

    Behavioral Analysis:
    ┌────────────────────────────────────────────────────────────────────┐
    │  Features tracked:                                                 │
    │  ├── API call sequences                                           │
    │  ├── Memory allocation patterns                                   │
    │  ├── File and registry access                                     │
    │  ├── Network connection behavior                                  │
    │  └── Process relationship patterns                                │
    │                                                                    │
    │  Model output: Suspicious behavior score                          │
    └────────────────────────────────────────────────────────────────────┘

    Correlation:
    ┌────────────────────────────────────────────────────────────────────┐
    │  Multiple signals combined:                                        │
    │  ├── Static score + behavioral score + context                    │
    │  ├── Comparison with known-bad patterns                           │
    │  └── Anomaly detection against baseline                           │
    │                                                                    │
    │  Decision: Alert, block, or allow                                  │
    └────────────────────────────────────────────────────────────────────┘

Evading ML Detection

ML models are susceptible to adversarial techniques:

Feature Manipulation: Modify artifacts that ML models use as features without affecting functionality. This includes padding sections to affect entropy, adding benign imports, and including legitimate strings.

Behavioral Blending: Ensure malicious behavior resembles legitimate patterns. Avoid distinctive sequences, insert benign operations between suspicious ones, and randomize timing.

Adversarial Examples: Craft inputs specifically designed to fool particular models. This requires understanding the target model's decision boundaries.

    Behavioral Evasion Strategies:

    API Call Sequencing:
    ├── Don't call VirtualAlloc → VirtualProtect → WriteProcessMemory in sequence
    ├── Insert benign API calls (GetTickCount, GetCurrentThread) between sensitive calls
    └── Randomize order when operations are independent

    Timing Patterns:
    ├── Vary delays between operations
    ├── Avoid consistent sleep intervals
    └── Add jitter to all timing

    Memory Patterns:
    ├── Use varying allocation sizes
    ├── Avoid predictable allocation patterns
    └── Normalize entropy of allocated regions

    String Obfuscation:
    ├── Runtime string construction
    ├── Encrypted storage with runtime decryption
    └── Stack string construction

Defense Evolution: Kernel Telemetry

Defenders haven't stood still. The evolution of kernel-level telemetry provides increasingly comprehensive visibility into system behavior.

Modern Telemetry Sources

                    KERNEL TELEMETRY LANDSCAPE (2024-2025)

    ETW Threat Intelligence (ETW-TI):
    ┌────────────────────────────────────────────────────────────────────┐
    │  Provides: Syscall-level visibility for security-sensitive ops    │
    │  Coverage:                                                         │
    │  ├── Process/Thread creation and termination                      │
    │  ├── Virtual memory operations (especially cross-process)         │
    │  ├── Handle operations (duplication, inheritance)                 │
    │  ├── Module loading                                               │
    │  └── Memory protection changes                                    │
    │  Evasion: BYOVD kernel patching                                   │
    └────────────────────────────────────────────────────────────────────┘

    Kernel Callbacks:
    ┌────────────────────────────────────────────────────────────────────┐
    │  PsSetCreateProcessNotifyRoutine                                  │
    │  └── Notified of all process creation/termination                 │
    │                                                                    │
    │  PsSetCreateThreadNotifyRoutine                                   │
    │  └── Notified of all thread creation                              │
    │                                                                    │
    │  PsSetLoadImageNotifyRoutine                                      │
    │  └── Notified of all image (DLL/EXE) loads                        │
    │                                                                    │
    │  ObRegisterCallbacks                                               │
    │  └── Notified of handle operations (with filtering)               │
    │                                                                    │
    │  CmRegisterCallback                                                │
    │  └── Notified of registry operations                              │
    │                                                                    │
    │  Evasion: BYOVD callback removal (unlink from lists)              │
    └────────────────────────────────────────────────────────────────────┘

    Minifilter Drivers:
    ┌────────────────────────────────────────────────────────────────────┐
    │  File system minifilter                                            │
    │  └── All file operations visible                                   │
    │                                                                    │
    │  Network filter drivers                                            │
    │  └── Network connection visibility                                 │
    │                                                                    │
    │  Evasion: Minifilter detachment (risky, may cause BSOD)           │
    └────────────────────────────────────────────────────────────────────┘

    Hardware Telemetry:
    ┌────────────────────────────────────────────────────────────────────┐
    │  Intel Processor Trace (PT)                                        │
    │  └── Hardware-level execution tracing                              │
    │                                                                    │
    │  Intel Last Branch Record (LBR)                                    │
    │  └── Recent branch history for each thread                         │
    │                                                                    │
    │  Performance Monitoring Counters                                   │
    │  └── Anomaly detection via performance patterns                    │
    │                                                                    │
    │  Evasion: Very difficult - hardware-based, not software hooks     │
    └────────────────────────────────────────────────────────────────────┘

Hardware Telemetry Challenges

Hardware-based detection presents the most difficult evasion challenge. Intel PT, for example, traces every branch taken by the processor—there's no user-mode hook to bypass, no kernel function to patch. The trace happens at the silicon level.

Current research explores:

These technologies aren't yet widely deployed in EDR products but represent the likely future of detection.


Emerging Techniques and Research Areas

The security research community continues pushing boundaries in both directions. Several emerging areas merit attention.

Active Research Topics

    2024-2025 Research Frontiers:

    Offensive:
    ┌────────────────────────────────────────────────────────────────────┐
    │  Hypervisor Attacks                                                │
    │  ├── VBS/HVCI bypass research                                     │
    │  ├── Credential Guard attacks                                     │
    │  └── Hypervisor breakout attempts                                 │
    │                                                                    │
    │  CET Bypass                                                        │
    │  ├── Shadow stack manipulation techniques                         │
    │  ├── IBT gadget discovery                                         │
    │  └── Exception-based bypass methods                               │
    │                                                                    │
    │  Hardware Telemetry Evasion                                        │
    │  ├── PT trace pollution                                           │
    │  ├── LBR manipulation                                             │
    │  └── Performance counter confusion                                │
    │                                                                    │
    │  ML Adversarial Attacks                                            │
    │  ├── EDR model reverse engineering                                │
    │  ├── Adversarial payload generation                               │
    │  └── Behavioral mimicry                                           │
    └────────────────────────────────────────────────────────────────────┘

    Defensive:
    ┌────────────────────────────────────────────────────────────────────┐
    │  Hardware-Assisted Detection                                       │
    │  ├── PT-based monitoring                                          │
    │  ├── LBR-based call stack validation                              │
    │  └── Performance anomaly detection                                │
    │                                                                    │
    │  Driver Ecosystem Security                                         │
    │  ├── Expanded vulnerable driver blocklist                         │
    │  ├── Real-time driver reputation checking                         │
    │  └── Driver behavioral monitoring                                 │
    │                                                                    │
    │  AI/ML Defense                                                     │
    │  ├── Adversarial training                                         │
    │  ├── Ensemble detection methods                                   │
    │  └── Behavioral baselining improvements                           │
    └────────────────────────────────────────────────────────────────────┘

ARM64 Windows

Windows on ARM presents a different attack surface with unique characteristics:

As ARM-based Windows devices become more common (Surface Pro X, Qualcomm-based laptops), this platform will see increased security research.


Summary

The 2024-2025 landscape represents a mature, sophisticated arms race. Techniques that were cutting-edge in 2020 are now baseline requirements. Modern offensive operations must layer multiple techniques:

Technique Purpose Complexity CET Compatible
Syscall Randomization Evade pattern detection Medium Yes
Thread Pool Execution Legitimate call stacks Medium Yes
Module Stomping Backed executable memory Medium Yes
BYOVD ETW-TI Patching Blind kernel telemetry High N/A (kernel)
Stack Spoofing Fake call history High Partially
Behavioral Randomization Evade ML detection Medium Yes

For defenders, the message is equally clear: no single detection mechanism suffices. Defense in depth requires:

  1. Kernel-level telemetry (ETW-TI, callbacks)
  2. Behavioral analysis (ML models, sequence analysis)
  3. Hardware security (CET, VBS, HVCI)
  4. Driver control (blocklisting, allowlisting)
  5. Memory analysis (periodic scanning, anomaly detection)

The next chapters dive deeper into specific techniques, building on this overview with detailed implementations and considerations.


References

← Back to Wiki