Shellcode Fluctuation: advanced in-memory evasion technique

Shellcode Fluctuation

Shellcode Fluctuation PoC

A PoC implementation for another in-memory evasion technique that cyclically encrypts and decrypts shellcode’s contents to then make it fluctuate between RW (or NoAccess) and RX memory protection. When our shellcode resides in RW or NoAccess memory pages, scanners such as Moneta or pe-sieve will be unable to track it down and dump it for further analysis.

Intro

After releasing ThreadStackSpoofer I’ve received a few questions about the following README’s point:

Change your Beacon’s memory pages protection to RW (from RX/RWX) and encrypt their contents before sleeping (that could evade scanners such as Moneta or pe-sieve)

Beforewards I was pretty sure the community already knows how to encrypt/decrypt their payloads and flip their memory protections to simply evade memory scanners looking for anomalous executable regions. Questions proven otherwise so I decided to release this unweaponized PoC to document yet another evasion strategy and offer sample implementation for the community to work with.

This PoC is a demonstration of a rather simple technique, already known to the offensive community (so I’m not bringing anything new here really) in the hope to disclose secrecy behind magic showed by some commercial frameworks that demonstrate their evasion capabilities targeting both aforementioned memory scanners.

Here’s a comparison when fluctuating to RW (another option is to fluctuate to PAGE_NOACCESS – described below):

  1. Beacon not encrypted
  2. Beacon encrypted (fluctuating)

 

This implementation along with my ThreadStackSpoofer brings Offensive Security community sample implementations to catch up on the offering made by commercial C2 products, so that we can do no worse in our Red Team toolings. 💪

How does it work?

This program performs self-injection shellcode (roughly via classic VirtualAlloc + memcpy + CreateThread). When shellcode runs (this implementation specifically targets Cobalt Strike Beacon implants) a Windows function will be hooked intercepting the moment when Beacon falls asleep kernel32!Sleep. Whenever hooked MySleep function gets invoked, it will localise its memory allocation boundaries, flip their protection to RW and xor32 all the bytes are stored there. Having waited for an expected amount of time, when the shellcode gets back to our MySleep handler, we’ll decrypt the shellcode’s data and flip protection back to RX.

Fluctuation to PAGE_READWRITE works as follows

  1. Read shellcode’s contents from file.
  2. Hook kernel32!Sleep pointing back to our callback.
  3. Inject and launch shellcode via VirtualAlloc + memcpy + CreateThread. In contrary to what we had in ThreadStackSpoofer, here we’re not hooking anything in ntdll to launch our shellcode but rather jump to it from our own function. This attempts to avoid leaving simple IOCs in memory pointing at modified ntdll memory.
  4. As soon as Beacon attempts to sleep, our MySleep callback gets invoked.
  5. Beacon’s memory allocation gets encrypted and protection flipped to RW
  6. We then unhook original kernel32!Sleep to avoid leaving simple IOC in memory pointing that Sleep have been trampolined (in-line hooked).
  7. A call to original ::Sleep is made to let the Beacon’s sleep while waiting for further communication.
  8. After Sleep is finished, we decrypt our shellcode’s data, flip it memory protections back to RX and then re-hook kernel32!Sleep to ensure interception of subsequent sleep.

Fluctuation to PAGE_NOACCESS works as follows

  1. Read shellcode’s contents from file.
  2. Hook kernel32!Sleep pointing back to our callback.
  3. Inject and launch shellcode via VirtualAlloc + memcpy + CreateThread …
  4. Initialize Vectored Exception Handler (VEH) to setup our own handler that will catch Access Violation exceptions.
  5. As soon as Beacon attempts to sleep, our MySleep callback gets invoked.
  6. Beacon’s memory allocation gets encrypted and protection flipped to PAGE_NOACCESS
  7. We then unhook original kernel32!Sleep to avoid leaving simple IOC in memory pointing that Sleep have been trampolined (in-line hooked).
  8. A call to original ::Sleep is made to let the Beacon’s sleep while waiting for further communication.
  9. After Sleep is finished, we re-hook kernel32!Sleep to ensure interception of subsequent sleep.
  10. Shellcode then attempts to resume its execution which results in Access Violation being throwed since its pages are marked NoAccess.
  11. Our VEH Handler catches the exception, decrypts and flips memory protections back to RX and shellcode’s is resumed.

Install & Use

Author: Mariusz Banach / mgeeky, 21
<mb [at] binary-offensive.com>
(https://github.com/mgeeky)