CodeX's Terminal Window
  • root@codex
  • 🐙Red Team
    • Red Team OPSEC
      • Initial Recon
      • Weaponization
      • Infrastructure
        • Example Red Team Infra
        • Cobalt Strike Redirectors
        • Using SSH Tunneling to secure C2 infra
      • Phishing
      • Internal Recon
      • Lateral Movement
      • Post-Exploitation
      • Exfiltration
      • Cleanup
    • Red Team TTPs
      • Active Directory
      • Persistence
      • Exfiltration
      • Phishing
      • Windows Bypasses
    • Red Team Dev
      • Extending Havoc C2
        • Third Party Agents
          • 1: Understanding the interface
          • 2: Writing the agent
          • 3: Writing the agent handler
          • 4: Testing the agent
      • Loader Dev
        • In Memory OPSEC
          • PE Structures
          • Memory Permissions and Allocation Types
          • In Memory Signatures
          • Thread Stack
          • Windows Events
          • Userland Hooks
          • AMSI & ETW
        • Evasion Adventures
        • Loader basics
        • Sleep masking
        • Mimikatz vs Windows Defender
        • Indirect syscalls
    • Cobalt Strike
      • Modifying the Sleep Mask Kit
      • Discord Beacon Notifications
      • Evading Hunt-Sleeping-Beacons
      • Beacon Object Files
    • Misc. Interesting Stuff
  • 🛡️Blue Team
    • Detecting Cobalt Strike
      • Sleep Mask Kit IOCs
      • Hunting Beacon in the heap
      • Decrypting C2 traffic with known key
  • 🚩CTF Solutions
    • Cyber Defenders Discovery Camp 2021
      • 👁️‍🗨️Lets Go Hunting
      • 🐧Linux Rules The World!
      • 📻Going active
      • 🗄️File it away
      • 😷Behind the mask
  • Box challenges
    • 📦Box Writeups
  • Me myself and I
    • root@codex #
Powered by GitBook
On this page
  • What is sleep masking?
  • Using custom sleep masking to evade memory scanners
  • ShellcodeFluctuation
  • LockdExeDemo
  • Weaponization
  1. Red Team
  2. Red Team Dev
  3. Loader Dev

Sleep masking

Because sometimes set sleep_mask "true"; isnt enough

PreviousLoader basicsNextMimikatz vs Windows Defender

Last updated 2 years ago

Why do we need sleep masking?

What about the Sleep Mask Kit?

What is sleep masking?

Normal beacon: Callback -> sleep 10s -> callback

To hide the memory indicators during the sleep phase, it adds a step to the beacon callback cycle:

Sleep protected beacon: Callback -> encrypt memory -> sleep 10s -> decrypt memory -> callback

The way the encryption and decryption of memory is performed, is by applying a userland hook to the kernel32 WinAPI Sleep(), which Beacon uses to go to sleep. This userland hook is used to trigger the encryption decryption routine.

This prevents memory scanners like BeaconEye from finding your Beacon IOCs in memory. Links to existing implementations you can reference from are at the bottom of this blogpost, under the Other implementations list.

Using custom sleep masking to evade memory scanners

Demo time!

Materials list:

  • Cobalt Strike 4.x (the 3.x trial works fine if you don't have a licensed copy of 4.x)

First, disable the sleep mask if you are running Cobalt Strike 4.4 and above. This can be set in the Malleable C2 profile.

Lets run our teamserver and a beacon.

Now, on the victim, lets scan the beacon process using the following yara rule:

rule CobaltStrike { 
  strings:  
    $cobaltStrikeRule64 = {  00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  01 00 00 00 00 00 00 00 (00|01|02|04|08|10) 00 00 00 00 00 00 00  01 00 00 00 00 00 00 00 ?? ?? 00 00 00 00 00 00  02 00 00 00 00 00 00 00 ?? ?? ?? ?? 00 00 00 00  02 00 00 00 00 00 00 00 ?? ?? ?? ?? 00 00 00 00  01 00 00 00 00 00 00 00 ?? ?? 00 00 00 00 00 00 } 
    //$cobaltStrikeRule32 = {  00 00 00 00 00 00 00 00  01 00 00 00 (00|01|02|04|08|10) 00 00 00 01 00 00 00 ?? ?? 00 00  02 00 00 00 ?? ?? ?? ??  02 00 00 00 ?? ?? ?? ??  01 00 00 00 ?? ?? 00 00 }
  condition: any of them
}

We can see that the YARA rule for Cobalt Strike in memory found a match in the process, at the address 0xc0d10. We can confirm this in x64dbg.

Lets also run BeaconEye.

As you can see, Cobalt Strike's beacon is easily caught in memory. Now, lets test it with different types of sleep protection.

Before we use the different sleep protection PoCs, we should understand how they work.

ShellcodeFluctuation

The first PoC we will be using is named ShellcodeFluctuation, by mgeeky. I chose this PoC as it is one of the simpler to understand implementations of the sleep masking concept.

The purpose of this PoC is to encrypt the injected Beacon shellcode while it sleeps. It is performed as such. based on the README:

The main concept in the code can be understood as follows:

  1. The hookSleep() function redirects function calls to kernel32!Sleep to our a custom function, MySleep(). This is done by replacing bytes at the start of the Sleep() function with instructions to jump to our custom function, redirection execution.

2. The custom sleep function MySleep encrypts the shellcode, sleeps then decrypts the shellcode.

This is the core concept of this PoC. It redirects Beacon's calls to Sleep() with a custom function that encrypts and decrypts Beacon in memory before and after sleeping. This way, beacon shellcode is encrypted in memory while it sleeps. It also sets the memory permissions to RW from RX, to appear as non executable memory, which is less suspicious to memory scanners.

Lets run the YARA rule and BeaconEye again.

First, we can observe that the YARA rule does not match.

It does shows 1 implanted PE in PE-Sieve, another popular memory scanning tool. The explanation for which is in the README of the repo:

My current assumption is that PE-Sieve is picking up on the same traits that Moneta does (described below in Modified code in kernel32.dll) - the fact that PE mapped module has a non-empty Working set, being an evident fact of code injection of some sort. That is labeled as Implanted PE / Implanted. If that's the case, conclusion is similar to the Moneta's observation. I don't think we should care that much about that IOC detection-wise.

While it is true that no bytes in kernel32 differ from its file on disk due to the unhooking of Sleep() before sleeping, it should be noted that the due to the hook, private bytes are created within kernel32.dll, which is an indication of modification that remains even after the bytes have been reverted to their original values. I am not sure how often this IOC would be flagged, but it is something to take note of when using inline hooks for sleep masking.

BeaconEye still catches us like before. This is because BeaconEye locates Beacon via its heap indicators rather than shellcode:

Now that we know BeaconEye checks the heap for Beacon signatures, why don't we encrypt the heap and see if it still catches us?

LockdExeDemo

The second PoC we will be using is LockdExeDemo, by Waldo-IRC. I chose this PoC mostly because it already comes with a blog post explaining itself, as well as heap encryption.

  • What is heap encryption

  • How the PoC works

As you can see, with heap encryption, heap based signature detections are easily evaded.

Weaponization

While these PoCs are good for understanding sleep masking concepts, they are not yet operationally usable. To incorporate these techniques into an operationally usable loader, you may want to consider some of the following:

  • What memory stays RX or in plaintext during sleep? e.g. the sleep masking function

  • Do we create abnormal memory artifacts? e.g. abnormal private bytes

  • What operational implications does the implementation have? e.g. suspending all threads during sleep

  • Why do these IOCs/implications exist? Can they be removed?

  • Other implementations

Implementations have pros and cons, e.g. Cobalt Strike specific, inline hooks etc. It is up to the operator to understand them and decide which implementation is best suited for your operational needs.

Hopefully this explains how sleep protection can help evade host based detection techniques during an engagement :)

BeaconEye ()

YARA ()

x64dbg ()

LockdExeDemo ()

ShellcodeFluctuation ()

Compile and use , replacing the payload with your beacon.

Refer to the blog post for LockdExeDemo, and understand:

Download the and replace the shellcode etc.

<-- whole PE image encryption

<-- .NET sleep masking of AppDomain

<-- using ROP chains to sleep and wake (Can we encrypt our sleep masking code as well using this?)

and <-- x64 Gargoyle implementations

and <-- Sleep and wake using timers

<-- Cobalt Strike UDRL implementation of heap encryption (What are the benefits of doing it from the UDRL?)

<-- Cobalt Strike builtin sleep masking

<-- Hide in GPU memory

🐙
https://github.com/CCob/BeaconEye
https://github.com/VirusTotal/yara/releases
https://sourceforge.net/projects/x64dbg/files/snapshots/
https://github.com/waldo-irc/LockdExeDemo
https://github.com/mgeeky/ShellcodeFluctuation
https://github.com/mgeeky/ShellcodeFluctuation
Hook Heaps and Live Free
https://github.com/waldo-irc/LockdExeDemo
SleepyCrypt
dotnet-gargoyle
Gargoyle
FOLIAGE
DeepSleep
Ekko
Nighthawk
TitanLdr
Sleep Mask Kit
GPUSleep
Hunting Beacon in the heap
Sleep masking logic
Beacon caught!
Matched bytes at the address 0xc0d10
README.md
hookSleep()
the hooking function, and the bytes used to redirect execution
MySleep()
ShellcodeFluctuation
YARA rule did not match the ShellcodeFluctuation process.
2 beacon processes. Both the old and new beacons were caught :(
BeaconEye evaded!