Deceiving Defender: The Big Stack Bypass
Defeating Windows Defender detection on Windows 10 by creating a large (>2MB) payload allocated on the stack
Part One: Introduction
I stumbled upon this trick during my demonstration of the byoDLL technique documented in Unholy Unhooking. Basically, the bypass goes like this:
The default supported stack size for a program is 1 MB (1024 KB)
Variables initiated in main() are stored on the stack at run time
If you generate a payload > 1024KB and hard code it in main your payload will fail
If you compile with /STACK:*BIG_NUMBER* you'll win
Part Two: Testing it out
We start out with the following code:
If we compile this and move the executable to our test directory, we can expect to get detected.
ThreatCheck helps us out with that so we don't waste too much time validating what we already know.
Part Three: the cool part
BUT! If we move the payload inside of main, and front load it with NOPs (> 1024KB worth, you can generate this using any method of your choice, I prefer python), and compile with the, something interesting will happen.
Your code should like something like this now.
Everything should compile, but your program will fail to run!
If we look at the program with x64Dbg, we can see that we end up overflowing our own stack during execution!
Lets compile with the /STACK:2000000000 set, which should give us plenty of space to put everything we need on the stack at run time.
It works!
ThreatCheck still finds our payload though…?
Lets make it a 2KB payload, and 3KB stack. The implant comes in at over 16MB, but if we drag and drop the implant into our test folder…
Part Four: ???
[Intentionally left blank]
Part Five: Profit
We survive!
We double check our survivability with ThreatCheck.
And we can run it from our test folder without being detected by Windows Defender!
But if we move the payload outside of main and into the data section of our program, it will once again be detected by Defender.
It's also not a matter of file size, we can append some trash data to our detectable implant and it will still be detected.
Part Six: Conclusion
In this writeup, we demonstrated Windows Defender's inability to detect programs with large stacks, allowing determined attackers to craft undetectable malware so long as the payload is initialized in the .text section of the program.
The downside to this approach is that your executable file is huge by payload delivery standards. Deploying this technique in a development environment can get a little tedious as well. You can expect a lot of application crashes and the compile time for this approach is significantly longer than other methods. Nonetheless, this provides another potential avenue of attack for malicious actors and defenders should be aware of it.
Part Seven: Encore
Totally by chance I had the thought to upload this to VirusTotal as well, and look what we found.
If you only use the implant code without the bypass, you can expect something like this:
Apparently large stack usage breaks a lot of automated analysis. Who knew. This artical probably also belongs in my ZeroTotal series lol
References:
Last updated