ThreadStackSpoofer v0.2 releases: advanced in-memory evasion technique
Thread Stack Spoofing / Call Stack Spoofing PoC
A PoC implementation for an advanced in-memory evasion technique that spoofs Thread Call Stack. This technique allows to bypass thread-based memory examination rules and better hide shellcodes while in-process memory.
Intro
This is an example implementation for the Thread Stack Spoofing technique aiming to evade Malware Analysts, AVs, and EDRs looking for references to shellcode’s frames in an examined thread’s call stack. The idea is to walk back the thread’s call stack and overwrite return addresses in subsequent function frames thus masquerading allocations containing malware’s code.
An implementation may differ, however, the idea is roughly similar to what MDSec’s Nighthawk C2 offers for its agents. Especially demonstrated in this video:
Nighthawk – Thread Stack Spoofing
A note on wording – some may argue that the technique presented in this implementation is not strictly Thread Stack Spoofing but rather Call Stack Spoofing to some extent. I myself believe, that whatever wording is used here, the outcome remains similar to what was presented in an originally named technique – thus the borrowed name for this code. Since we’re clobbering some pointers on the thread’s stack, wouldn’t we call it spoofing the stack anyway and ultimately still resort to – Thread Stack Spoofing? The answer is left to the reader.
How does it work?
This program performs self-injection shellcode (roughly via classic VirtualAlloc
+ memcpy
+ CreateThread
). Then 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 spoof its own call stack leading to this MySleep
function and begin sleeping. Having awaited for expected amount of time, the Thread’s call stack will get restored assuring stable return and shellcode’s execution resumption.
The rough algorithm is following:
- Read shellcode’s contents from file.
- Acquire all the necessary function pointers from
dbghelp.dll
, callSymInitialize
- Hook
kernel32!Sleep
pointing back to our callback. - Inject and launch shellcode via
VirtualAlloc
+memcpy
+CreateThread
. A slight twist here is that our thread starts from a legitimatentdll!RltUserThreadStart+0x21
address to mimic other threads - As soon as Beacon attempts to sleep, our
MySleep
callback gets invoked. - Stack Spoofing begins.
- Firstly we walk call stack of our current thread, utilising
ntdll!RtlCaptureContext
anddbghelp!StackWalk64
- We save all of the stack frames that match our
seems-to-be-beacon-frame
criterias (such as return address points back to a memory beingMEM_PRIVATE
orType = 0
, or memory’s protection flags are notR/RX/RWX
) - We terate over collected frames (gathered function frame pointers
RBP/EBP
– inframe.frameAddr
) and overwrite on-stack return addresses with a fake::CreateFileW
address. - Finally a call to
::SleepEx
is made to let the Beacon’s sleep while waiting for further communication. - After Sleep is finished, we restore previously saved original function return addresses and execution is resumed.
Function return addresses are scattered all around the thread’s stack memory area, pointed to by RBP/EBP
register. In order to find them on the stack, we need to firstly collect frame pointers, then dereference them for overwriting:
How do I use it?
Look at the code and its implementation, understand the concept and re-implement the concept within your own Shellcode Loaders that you utilise to deliver your Red Team engagements. This is an yet another technique for advanced in-memory evasion that increases your Teams’ chances for not getting caught by Anti-Viruses, EDRs and Malware Analysts taking look at your implants.
While developing your advanced shellcode loader, you might also want to implement:
- Process Heap Encryption – take an inspiration from this blog post: Hook Heaps and Live Free – which can let you evade Beacon configuration extractors like
BeaconEye
- Change your Beacon’s memory pages protection to
RW
(fromRX/RWX
) and encrypt their contents before sleeping (that could evade scanners such asMoneta
orpe-sieve
) - Clear out any leftovers from Reflective Loader to avoid in-memory signatured detections
- Unhook everything you might have hooked (such as AMSI, ETW, WLDP) before sleeping and then re-hook afterward.
Changelog v0.2
Now the Thread Stack Spoofer simply overwrites MySleep
‘s return address with 0
making the call stack cut in half. This should be enough to fend off AVs and EDRs while not being that anomalous at the same time.
Download & Use
Author: Mariusz Banach / mgeeky, <mb [at] binary-offensive.com>, ’21