Skip to content
KitploitKITPLOIT
ToolsExploitsBlog
Log in
Submit
ToolsExploitsBlog
Submit

Hacking, PenTest, and Cybersecurity Tools for Your Security Arsenal!

Kitploit is a directory of hacking, cybersecurity, and pentesting tools. Discover the latest project updates to find vulnerabilities, analyze systems, automate testing, and strengthen your security.

··Feeds·Contact·Privacy·© 2026 Kitploit

Tool Directory

Categories

View all categories
Loading categories
ThreadStackSpoofer — Thread Stack Spoofing - PoC for an advanced In-Memory evasion technique allowing to better hide injected shellcode's memory allocation from scanners and analysts. | Kitploit
Tools/GitHubGitHub/mgeeky/threadstackspoofer
Penetration Testing FrameworksExploit FrameworksMemory ForensicsShellcodeMalware AnalysisRed TeamingPayload Development
GitHubmgeeky/threadstackspoofer

ThreadStackSpoofer

Thread Stack Spoofing - PoC for an advanced In-Memory evasion technique allowing to better hide injected shellcode's memory allocation from scanners and analysts.

View Repository
1.2k192194 years agoReviewed by Kitploit

Most Popular

View all →

Discover the most used tools by our community.

Explore all tools

Browse our collection of tools

View all tools →
Share

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 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 hide references to the shellcode on thread's call stack thus masquerading allocations containing malware's code.

Implementation along with my ShellcodeFluctuation 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. 💪

Implementation has changed

Current implementation differs heavily to what was originally published. This is because I realised there is a way simpler approach to terminate thread's call stack processal and hide shellcode's related frames by simply writing 0 to the return address of the first frame we control:

void WINAPI MySleep(DWORD _dwMilliseconds)
{
    [...]
    auto overwrite = (PULONG_PTR)_AddressOfReturnAddress();
    const auto origReturnAddress = *overwrite;
    *overwrite = 0;

    [...]
    *overwrite = origReturnAddress;
}

The previous implementation, utilising StackWalk64 can be accessed in this commit c250724.

This implementation is much more stable and works nicely on both Debug and Release under two architectures - x64 and x86.

Demo

This is how a call stack may look like when it is NOT spoofed:

not-spoofed

This in turn, when thread stack spoofing is enabled:

spoofed

Above we can see that the last frame on our call stack is our MySleep callback. One can wonder does it immediately brings opportunities new IOCs? Hunting rules can look for threads having call stacks not unwinding into following expected thread entry points located within system libraries:

kernel32!BaseThreadInitThunk+0x14
ntdll!RtlUserThreadStart+0x21

However the call stack of the spoofed thread may look rather odd at first, a brief examination of my system shown, that there are other threads not unwinding to the above entry points as well:

legit call stack

The above screenshot shows a thread of unmodified Total Commander x64. As we can see, its call stack pretty much resembles our own in terms of initial call stack frames.

Why should we care about carefully faking our call stack when there are processes exhibiting traits that we can simply mimic?

How it works?

The rough algorithm is following:

  1. Read shellcode's contents from file.
  2. Acquire all the necessary function pointers from dbghelp.dll, call SymInitialize
  3. Hook kernel32!Sleep pointing back to our callback.
  4. Inject and launch shellcode via VirtualAlloc + memcpy + CreateThread. The thread should start from our runShellcode function to avoid having Thread's StartAddress point into somewhere unexpected and anomalous (such as ntdll!RtlUserThreadStart+0x21)
  5. As soon as Beacon attempts to sleep, our MySleep callback gets invoked.
  6. We then overwrite last return address on the stack to 0 which effectively should finish the call stack.
  7. Finally a call to ::SleepEx is made to let the Beacon's sleep while waiting for further communication.
  8. 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:

stack frame

(the above image was borrowed from Eli Bendersky's post named Stack frame layout on x86-64)

	*(PULONG_PTR)(frameAddr + sizeof(void*)) = Fake_Return_Address;

Initial implementation of ThreadStackSpoofer did that in walkCallStack and spoofCallStack functions, however the current implementation shows that these efforts are not required to maintain stealthy call stack.

Example run

Use case:

C:\> ThreadStackSpoofer.exe <shellcode> <spoof>

Where:

  • <shellcode> is a path to the shellcode file
  • <spoof> when 1 or true will enable thread stack spoofing and anything else disables it.

Example run that spoofs beacon's thread call stack:

PS D:\dev2\ThreadStackSpoofer> .\x64\Release\ThreadStackSpoofer.exe .\tests\beacon64.bin 1
[.] Reading shellcode bytes...
[.] Hooking kernel32!Sleep...
[.] Injecting shellcode...
[+] Shellcode is now running.
[>] Original return address: 0x1926747bd51. Finishing call stack...

===> MySleep(5000)

[<] Restoring original return address...
[>] Original return address: 0x1926747bd51. Finishing call stack...

===> MySleep(5000)

[<] Restoring original return address...
[>] Original return address: 0x1926747bd51. Finishing call stack...

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 (from RX/RWX) and encrypt their contents - using Shellcode Fluctuation technique - right before sleeping (that could evade scanners such as Moneta or pe-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 afterwards.

Actually this is not (yet) a true stack spoofing

As it's been pointed out to me, the technique here is not yet truly holding up to its name for being a stack spoofer. Since we're merely overwriting return addresses on the thread's stack, we're not spoofing the remaining areas of the stack itself. Moreover we're leaving our call stack unwindable meaking it look anomalous since the system will not be able to properly walk the entire call stack frames chain.

Download Tool