Difficulty: Advanced

Module 8: Full Chain, Detection & Variants

Comparing sleep obfuscation approaches, detection engineering, and the evolution of the technique.

Module Objective

Compare Ekko against other sleep obfuscation implementations (Cronos, DeathSleep, FOLIAGE), understand the specific detection vectors for each approach, review defensive tools (BeaconEye, Hunt-Sleeping-Beacons, Patriot), and analyze how the technique has evolved since its initial disclosure.

1. The Sleep Obfuscation Family

Multiple open-source implementations of sleep obfuscation have been released, each taking a different approach to the core problem of encrypting an implant's memory while it sleeps. Understanding their differences illuminates the design tradeoffs in this technique.

ToolAuthorScheduling MechanismExecution PrimitiveEncryptionHeap EncryptionContext Spoofing
EkkoCracked5piderCreateTimerQueueTimerNtContinueRC4 (SystemFunction032)NoNo
CronosIdov31Waitable Timers (CreateWaitableTimer)NtContinueRC4 (SystemFunction032)NoNo
DeathSleepjanoglezcamposThread termination & recreationThread kill + recreate with saved contextRC4 (SystemFunction032)NoYes (no thread to inspect)
FOLIAGESecIdiotNtQueueApcThreadAPC dispatchRC4 (SystemFunction032)YesYes (Patriot evasion)
KrakenMaskCracked5piderVarious (evolved Ekko)NtContinueRC4YesYes

2. Ekko vs. Cronos

Cronos by Idov31 uses the same NtContinue-based execution model as Ekko but replaces CreateTimerQueueTimer with waitable timers (CreateWaitableTimer / SetWaitableTimer). Cronos creates waitable timer objects for scheduling the sleep obfuscation operations:

C// Cronos approach (simplified):
HANDLE hTimer = CreateWaitableTimer(
    NULL,    // Security attributes
    TRUE,    // Manual reset
    NULL     // Timer name
);

// Set the timer to fire after a delay
LARGE_INTEGER dueTime;
dueTime.QuadPart = -10000LL * delay_ms;  // Negative = relative
SetWaitableTimer(hTimer, &dueTime, 0, NtContinue, &CtxProtRW, FALSE);

Key Differences from Ekko

3. Ekko vs. DeathSleep

DeathSleep by janoglezcampos takes a fundamentally different approach. Instead of using callbacks and NtContinue, it terminates the main thread entirely and recreates it after the sleep period. The key insight is that a dead thread leaves no context to inspect — there is no sleeping thread for detection tools to analyze:

C// DeathSleep approach (conceptual):
// 1. Main thread saves its own context and state
// 2. Main thread creates a helper thread with the saved state
// 3. Main thread terminates itself (the thread is killed, not suspended)
// 4. Helper thread:
//    a. VirtualProtect(main_image, RW)
//    b. Encrypt(main_image)
//    c. Sleeps for the requested duration
//    d. Decrypt(main_image)
//    e. VirtualProtect(main_image, RX)
//    f. Creates a new thread with the saved context
//       (effectively recreating the original thread)
// 5. New thread resumes execution where the old one left off

Advantages of DeathSleep

Disadvantages of DeathSleep

4. Ekko vs. FOLIAGE

FOLIAGE by SecIdiot is the most comprehensive implementation, using a chain of Asynchronous Procedure Calls (APCs) queued to the current thread:

C// FOLIAGE approach (conceptual):
// 1. Generate fresh RC4 key
// 2. Encrypt the private heap (separately from the code)
// 3. Queue 10 APCs to the current thread:
//    APC 0: Wait (setup timer)
//    APC 1: NtGetContextThread (capture)
//    APC 2: NtSetContextThread (spoof RIP to ntdll)
//    APC 3: NtProtectVirtualMemory (RX -> RW)
//    APC 4: SystemFunction032 (encrypt code)
//    APC 5: NtWaitForSingleObject (actual sleep)
//    APC 6: SystemFunction032 (decrypt code)
//    APC 7: NtProtectVirtualMemory (RW -> RX)
//    APC 8: NtSetContextThread (restore context)
//    APC 9: NtSetEvent (signal done)
// 4. Enter alertable wait (NtWaitForSingleObject with alertable=TRUE)
// 5. APCs drain in FIFO order during the alertable wait

FOLIAGE Advantages Over Ekko

5. Detection Vectors for Ekko

Understanding how defenders detect Ekko helps both offensive operators improve their implementations and defensive engineers build better detections:

Detection VectorTool / TechniqueWhat It CatchesEkko PoC Vulnerable?
Timer Queue Callback = NtContinueAPI monitoring, ETWCreateTimerQueueTimer with NtContinue as callback is extremely unusualYes
Sleeping Thread Stack WalkHunt-Sleeping-BeaconsReturn addresses in unbacked memory on sleeping threadsYes
Thread Context InspectionPatriotRIP pointing to unbacked memory on sleeping threadsYes (no context spoofing)
Memory Permission TransitionsETW, VirtualProtect monitoringRX/RWX -> RW -> RWX cycles on the same regionYes
SystemFunction032 on Image RegionAPI monitoringRC4 encrypting the process's own image is abnormalYes
Beacon Config ScanningBeaconEyeCS config patterns visible before first sleepYes (pre-sleep)
Timer Queue Object EnumerationKernel analysisTimer queues with multiple one-shot timers pointing to NtContinueYes

6. Hunt-Sleeping-Beacons Deep Dive

Hunt-Sleeping-Beacons by thefLink is the primary open-source tool targeting sleep obfuscation techniques. It operates by:

Detection Algorithm

  1. Enumerate all threads in all processes
  2. Identify sleeping threads — threads in a wait state (WaitForSingleObject, NtWaitForSingleObject, NtDelayExecution, etc.)
  3. Walk the call stack using StackWalk64 for each sleeping thread
  4. Check each return address against loaded modules — if a return address falls outside any known module's address range, it is in "unbacked" memory
  5. Flag suspicious threads — sleeping threads with unbacked return addresses are reported

Against Ekko's PoC, Hunt-Sleeping-Beacons will detect the sleeping thread because:

7. Evasion Improvements Over the PoC

A production-grade implementation based on Ekko's technique would need these enhancements:

Required Improvements for Production Use

ImprovementPurposeDifficulty
Random key per cyclePrevent key reuse across sleep cyclesEasy
Context spoofingSet RIP to ntdll during sleep to defeat PatriotMedium
Heap encryptionHide strings, config, and runtime dataMedium
Stack frame spoofingConstruct legitimate-looking call stack during sleepHard
Controlled return addressesPlace gadget addresses at [RSP] for clean returnsMedium
Restore to RX not RWXAvoid suspicious RWX memory after wakeupEasy
Syscall-based API callsBypass userland API hooks on VirtualProtect etc.Medium
Timer queue cleanupEnsure no timer artifacts remain after the cycleEasy

8. The Evolution: KrakenMask

KrakenMask, also by Cracked5pider, represents the evolution of Ekko into a more complete sleep masking solution. While the full implementation details differ, KrakenMask addresses many of the PoC's shortcomings:

KrakenMask Improvements

9. The Complete Ekko Chain — Final Review

Let us review the complete Ekko execution from start to finish with all the knowledge from this course:

Complete Ekko Execution Flow

1. Setup
CreateEvent, CreateTimerQueue
Resolve NtContinue, SysFunc032
Get ImageBase, ImageSize
2. Capture
Timer 0: RtlCaptureContext
on timer thread
Wait 50ms
3. Build Contexts
Clone baseline x6
Set RIP, args, RSP-=8
for each operation
4. Queue Timers
6 timers, 100ms apart
Callback=NtContinue
Param=CONTEXT*
5. Wait
Main thread blocks on
WaitForSingleObject
(hEvent, INFINITE)
6. Timer Chain
RW → Encrypt → Sleep
Decrypt → RWX → Signal
7. Resume
SetEvent wakes main
thread, EkkoObf returns
Beacon resumes normally
8. Cleanup
DeleteTimerQueue
Free resources

During step 6, between the encrypt and decrypt operations, the implant's entire image is RC4-encrypted in non-executable memory. This is the stealth window. A memory scanner running during this period sees only encrypted data in RW pages — no code signatures, no configuration patterns, no executable memory.

10. Defensive Recommendations

For blue team engineers and detection developers, these are the highest-value detection opportunities:

Detection Engineering Priorities

11. Summary: Sleep Obfuscation Landscape

Key Takeaways from This Course

Knowledge Check

Q1: Which sleep obfuscation tool encrypts the private heap in addition to the code region?

A) Ekko
B) Cronos
C) DeathSleep
D) FOLIAGE

Q2: What is the most distinctive detection indicator for Ekko?

A) The process loading advapi32.dll
B) CreateTimerQueueTimer with NtContinue as the callback function
C) A thread calling WaitForSingleObject
D) The process having a .text section

Q3: How does DeathSleep differ fundamentally from Ekko and Cronos?

A) It uses AES instead of RC4
B) It does not encrypt the image during sleep
C) It terminates the main thread during sleep and recreates it afterward, rather than using NtContinue callbacks
D) It works only on 32-bit systems