You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
This is an example implementation for _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.
4
+
The idea is to walk back thread's call stack and overwrite return addresses in subsequent function frames thus masquerading allocations containing malware's code.
5
+
6
+
An implementation may differ, however the idea is roughly similar to what [MDSec's Nighthawk C2](https://www.mdsec.co.uk/nighthawk/) offers for its agents.
This program performs self-injection shellcode (roughly via classic `VirtualAlloc` + `memcpy` + `CreateThread`).
15
+
Then when shellcode runs (this implementation specifically targets Cobalt Strike Beacon implants) a Windows function will be hooked intercepting moment when Beacon falls asleep `kernel32!Sleep`.
16
+
Whenever hooked `MySleep` function gets invoked, it will spoof its own call stack leading to this `MySleep` function and begin sleeping.
17
+
Having awaited for expected amount of time, the Thread's call stack will get restored assuring stable return and shellcode's execution resumption.
18
+
19
+
The rough algorithm is following:
20
+
21
+
1. Read shellcode's contents from file.
22
+
2. Acquire all the necessary function pointers from `dbghelp.dll`, call `SymInitialize`
23
+
3. Hook `kernel32!Sleep` pointing back to our callback.
24
+
4. Inject and launch shellcode via `VirtualAlloc` + `memcpy` + `CreateThread`
25
+
5. As soon as Beacon attempts to sleep, our `MySleep` callback gets invoked.
26
+
6. Stack Spoofing begins.
27
+
7. Firstly we walk call stack of our current thread, utilising `ntdll!RtlCaptureContext` and `dbghelp!StackWalk64`
28
+
8. 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 being `MEM_PRIVATE` or `Type = 0`, or memory's protection flags are not `R/RX/RWX`)
29
+
9. We terate over collected frames (gathered function frame pointers `RBP/EBP` - in `frame.frameAddr`) and overwrite _on-stack_ return addresses with a fake `::CreateFileW` address.
30
+
10. Finally a call to `::SleepEx` is made to let the Beacon's sleep while waiting for further communication.
31
+
11. After Sleep is finished, we restore previously saved original function return addresses and execution is resumed.
32
+
33
+
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:
0 commit comments