Difficulty: Advanced

Module 8: Full Chain, Detection & Comparison

Comparing Ekko, FOLIAGE, and ShellcodeFluctuation — detection vectors, Moneta/pe-sieve bypass results, limitations, and the state of the art.

Module Objective

Synthesize everything from the course into a complete end-to-end understanding. Compare ShellcodeFluctuation against Ekko and FOLIAGE, analyze real-world detection results from Moneta and pe-sieve, identify remaining detection vectors, understand fundamental limitations, and assess the current state of sleep evasion research.

1. The Complete Execution Chain

Here is the full end-to-end execution flow of ShellcodeFluctuation with ThreadStackSpoofer integration, from initial loading through multiple beacon cycles:

// ============================================
// PHASE 0: LOADER INITIALIZATION
// ============================================
// 1. Read shellcode (beacon.bin) from disk/resource
// 2. VirtualAlloc(NULL, size, MEM_COMMIT|MEM_RESERVE, PAGE_READWRITE)
// 3. memcpy(allocation, shellcode, size)
// 4. VirtualProtect(allocation, size, PAGE_EXECUTE_READ, &old)
// 5. Generate random XOR32 key
// 6. Resolve kernel32!Sleep via GetProcAddress
// 7. Install inline hook: Sleep -> MySleep
// 8. Save original bytes + hook bytes
// 9. (Optional) Register VEH for Mode 2
// 10. CreateThread(NULL, 0, allocation, NULL, 0, NULL)
//     -> Beacon shellcode begins executing

// ============================================
// PHASE 1: BEACON ACTIVE (repeats each cycle)
// ============================================
// Beacon performs its check-in:
// - Connects to C2 server
// - Downloads tasks
// - Executes commands
// - Uploads results
// Duration: ~100ms

// ============================================
// PHASE 2: BEACON CALLS Sleep(interval)
// ============================================
// Beacon's sleep call is redirected to MySleep via inline hook

// ============================================
// PHASE 3: MySleep HANDLER
// ============================================
// 3a. Spoof stack: *_AddressOfReturnAddress() = 0
// 3b. VirtualProtect(shellcode, RW)
// 3c. xor32(shellcode, key)  [encrypt]
// 3d. Unhook: restore original bytes to kernel32!Sleep
// 3e. Sleep(interval)        [actual sleep - maximally hidden]
// 3f. Rehook: restore hook bytes to kernel32!Sleep
// 3g. xor32(shellcode, key)  [decrypt]
// 3h. VirtualProtect(shellcode, RX)
// 3i. Restore stack: *_AddressOfReturnAddress() = origAddr

// ============================================
// PHASE 4: RETURN TO BEACON
// ============================================
// MySleep returns, Beacon resumes at next instruction
// -> Back to Phase 1

Full Lifecycle

Loader Init
Inject + Hook
Beacon Active
C2 check-in
MySleep
Encrypt+Spoof
Sleep
Hidden state
MySleep
Decrypt+Restore

2. Technique Comparison: Ekko vs FOLIAGE vs Fluctuation

Three prominent sleep evasion techniques take fundamentally different architectural approaches to the same problem:

PropertyEkko (C5pider)FOLIAGE (Austin Hudson)ShellcodeFluctuation (mgeeky)
Sleep mechanismTimer queue callbacks via CreateTimerQueueTimerAPC queuing with NtContinue context manipulationInline hook on kernel32!Sleep
EncryptionRC4 via SystemFunction032XOR or RC4 via ROP/APC chainXOR32 (custom, no imports)
Protection changeVia timer callback to VirtualProtectVia APC-queued NtProtectVirtualMemoryDirect VirtualProtect call in hook handler
Call stackClean — callbacks from ntdll!TppWorkerThreadClean — NtContinue creates clean contextRequires ThreadStackSpoofer for clean stack
Code complexityModerate — chained timer callbacksHigh — APC manipulation + context craftingLow — straightforward hook handler
Hook IOCNo function hooks neededNo function hooks neededInline hook on Sleep (mitigated by unhooking)
CET compatibleNo — uses ROP-like callback chainsPartially — NtContinue may be restrictedYes — standard call/ret flow
Suspicious importsSystemFunction032, CreateTimerQueueTimerNtContinue, NtQueueApcThreadNone beyond standard APIs

3. Moneta Detection Results

Moneta is the gold standard for memory anomaly detection. Here are the actual detection results for each configuration:

Moneta Scan: Unprotected Beacon

// Moneta output for unprotected Cobalt Strike Beacon:
[!] SUSPICIOUS: Private executable memory
    Process: beacon.exe (PID: 4832)
    Region:  0x000001A00000 - 0x000001A4C000
    Size:    0x4C000 (311,296 bytes)
    Protect: PAGE_EXECUTE_READ
    Type:    MEM_PRIVATE
    IOC:     Abnormal private executable memory

Moneta Scan: Fluctuating Beacon (during sleep)

// Moneta output for ShellcodeFluctuation Mode 1 during sleep:
// Region 0x000001A00000 - 0x000001A4C000:
//   Protect: PAGE_READWRITE
//   Type:    MEM_PRIVATE
//   Content: Encrypted (no recognizable patterns)
//   IOC:     None - RW private memory is normal

// However, kernel32.dll shows:
[*] MODIFIED: kernel32.dll
    Region:  0x00007FFB1A240000
    IOC:     Modified code (private working set page)
    Note:    Page modified but content matches disk
             (hook was removed before sleep)

The fluctuating Beacon eliminates the "Abnormal private executable memory" IOC. The remaining IOC is the kernel32 private page artifact from the copy-on-write caused by the hook installation. Crucially, the content matches the on-disk file (because the hook bytes are restored), so the IOC is a weaker "private working set" anomaly rather than a clear "modified code" detection.

4. pe-sieve Detection Results

Configurationpe-sieve ResultDetails
Unprotected BeaconDetectedShellcode found in private executable memory via implant scanning
Fluctuation Mode 1 (during sleep)Not detected (shellcode)Encrypted RW memory does not match any shellcode signatures
Fluctuation Mode 1 (during sleep)Possible IOC (kernel32)pe-sieve can detect that kernel32 has modified working set pages
Fluctuation Mode 2 (NOACCESS)Not detectedNOACCESS memory cannot even be read by the scanner
Fluctuation + Stack SpoofNot detectedNeither memory nor stack analysis reveals the implant

5. BeaconEye Detection Results

BeaconEye specifically targets Cobalt Strike Beacon configuration structures in memory:

ConfigurationBeaconEye ResultWhy
Unprotected BeaconDetectedSingle-byte XOR config found via brute force (256 keys)
Fluctuation Mode 1 (during sleep)Not detectedXOR32 encryption with ~4.3 billion possible keys; brute force infeasible
Fluctuation (during active execution)DetectedConfig is decrypted while Beacon is active; original single-byte XOR remains

Active Window Vulnerability

During the brief active window (~100ms per cycle), the Beacon's memory is fully decrypted and scannable. BeaconEye or any other scanner that happens to scan during this window will find the implant. ShellcodeFluctuation only protects during the sleep window. This is the fundamental limitation of all sleep-time-only evasion techniques.

6. Remaining Detection Vectors

Even with both ShellcodeFluctuation and ThreadStackSpoofer active, several detection paths remain available to defenders:

Detection VectorDescriptionDifficulty to Detect
Thread start addressThe thread was created with CreateThread pointing to private memory. The start address is recorded in the ETHREAD structure and cannot be changed post-creationEasy — visible via NtQueryInformationThread
Private working set pages in kernel32Copy-on-write from hook installation creates private pages that persist even after unhookingModerate — requires working set analysis
ETW telemetryVirtualProtect calls generate ETW events. Periodic RW/RX toggling on the same region is an anomalous patternModerate — requires ETW consumer + pattern analysis
Timing correlationPeriodic VirtualProtect calls correlated with network beaconing can reveal the sleep cycleHard — requires cross-signal correlation
Active window scanningScanning during the ~100ms active window catches the decrypted shellcodeHard — requires fast, frequent scanning or triggered scanning
Kernel callbacksPsSetCreateThreadNotifyRoutine logs thread creation with private memory start addressesEasy from kernel mode
Memory allocation patternsLarge VirtualAlloc + PAGE_EXECUTE_READ for private memory is itself suspiciousModerate — many legitimate uses exist

7. Fundamental Limitations

What Sleep Evasion Cannot Solve

8. State of the Art and Evolution

ShellcodeFluctuation represents one point in the evolution of sleep evasion research. Understanding where it fits helps assess its current relevance:

Evolution of Sleep Evasion

EraTechniqueInnovation
2021ShellcodeFluctuation (mgeeky)Inline-hook approach with unhook/rehook cycle and XOR32 encryption
2021ThreadStackSpoofer (mgeeky)Return address overwriting for call stack evasion
2022Ekko (C5pider)First public timer-callback-based sleep encryption with clean call stacks
2022FOLIAGE (Austin Hudson)APC + NtContinue for clean execution context
2022Cobalt Strike Sleep Mask Kit v2Official CS support for custom sleep masks with heap encryption
2022-23SilentMoonwalk, UnwinderFull call stack fabrication with synthetic unwind metadata
2023+Nighthawk, BruteRatelCommercial C2 frameworks with built-in sleep evasion suites
2025FunctionPeekaboo (MDSec)Per-function encryption at the LLVM compiler level — active-time protection

Where ShellcodeFluctuation Excels

9. Defense Recommendations

For blue team operators and detection engineers, the following approaches can detect ShellcodeFluctuation and similar techniques:

Detection Strategies

  1. Thread start address auditing — flag threads whose start address is in private (non-image) memory. This is a fundamental IOC that no user-mode sleep evasion technique can eliminate
  2. ETW VirtualProtect monitoring — look for periodic NtProtectVirtualMemory calls toggling the same region between RW and RX. Correlate with sleep timing
  3. Working set analysis — detect private pages in normally-shared DLL sections (kernel32.dll .text). This survives the unhook/rehook cycle
  4. Triggered scanning — instead of periodic scans, trigger memory scans on behavioral events (network connections, process creation) that occur during the active window
  5. Kernel callbacks — use kernel-mode notification routines that fire before user-mode code can react
  6. Hardware-assisted detection — Intel PT (Processor Trace) can record control flow history, revealing the hook and encryption operations

10. Course Summary

ModuleKey Concept
1. Memory Scanning Threat ModelScanners target the 99.8% sleep window where shellcode sits idle in executable memory
2. XOR EncryptionXOR32 is self-inverse, in-place, zero-import, and fast enough to toggle on every sleep cycle
3. VirtualProtect & PagesToggle between RW (writable, not executable) and RX (executable, not writable) — never RWX
4. Sleep Function HookingInline hook on kernel32!Sleep intercepts every beacon cycle with an unhook/rehook IOC reduction
5. The Fluctuation Algorithm7-phase cycle: RW → encrypt → unhook → sleep → rehook → decrypt → RX
6. Shellcode Region TrackingVirtualQuery + AllocationBase identify the region; page alignment is guaranteed by the OS
7. Thread Stack SpoofingOverwrite return address to 0 during sleep; combined with fluctuation for dual-layer evasion
8. Full Chain & DetectionBypasses Moneta/pe-sieve/BeaconEye during sleep; remaining IOCs are thread start address and working set anomalies

Knowledge Check

Q1: Which detection vector persists even with ShellcodeFluctuation + ThreadStackSpoofer active during sleep?

A) Private executable memory
B) Thread start address pointing to private (non-image) memory
C) Beacon configuration in cleartext
D) RWX pages

Q2: What architectural advantage does ShellcodeFluctuation have over Ekko regarding Intel CET?

A) ShellcodeFluctuation uses hardware encryption
B) ShellcodeFluctuation operates in kernel mode
C) ShellcodeFluctuation uses standard call/ret flow (CET-compatible), while Ekko uses ROP-like timer callback chains
D) ShellcodeFluctuation disables CET before executing

Q3: What fundamental limitation do ALL sleep-time-only evasion techniques share?

A) During the active execution window, the entire shellcode is decrypted and scannable
B) They cannot encrypt memory larger than 1 MB
C) They only work on Windows 10 and later
D) They require administrator privileges