Deceiving Windows Defender: The Big Stack Bypass
steve-s.gitbook.io
steve-s.gitbook.io
Doesn't Microsoft download important applications to analyze or whitelist itself?
No, modern AV software executes unknown binaries in an emulated system environment. Defender has an x86-to-safe-x86 JIT compiler built in to make this more performant.
Edit : a map file should show the difference if any
All 3 compilers GCC, Clang and MVSC instead of placing the whole stack initialization value in rodata and then copying from there using memcpy, chose to initialize parts of array using `mov [stack_pointer] Literal_value` . Results might be slightly different with different sizes of constant and various other factors like optimization level. This breaks up the big constant array int smaller chunks which is probably why the AV didn't detect when just scanning file, and the whole constant is only assembled during execution on stack. Even if compiler didn't break up the constant, it shouldn't be difficult to achieve similar result by having an encrpyted version of payload in read only section, and then decrypting it to stack. Manual analysis would trivially defeat such encryption with key stored next to it, but for automated analysis the solution is to execute the binary in sandboxed environment and allowing it decrypt itself, but the problem here is that Windows defender doesn't properly notice the payload if it gets stored in unusually big stack and that's why the blogpost about it.
As for why the compiler by default breaks up the constant. I assume it's because compiler heuristics are written with assumption that you wouldn't have 2MB constant initializing stack variable. And for more reasonable initial stack variable values, storing them as instruction literals can be more performant as that way it avoids additional memory loads. When array and constant is sufficiently big GCC and clang fully switches to rodata+memcpy strategy. But with optimizations disabled MSVC naively copies the values with "move [ptr], 1_byte_literal" one byte at a time even for very big arrays.
Once you get your hands on a TrustedInstaller session, you are pretty much in god mode.
This is why AV's are low on the list of security. Prevention is far better than detection.
I can't speak to Symantec, but I've worked for companies that provide endpoint protection and watched a live demo of novel "malware" getting caught escalating privileges.
I "attack simulated" as many ways as I could, disabling defender. If anything on our environment so much as changes a registry key, service or adds an exclusion we get alerts for it, no need for cloud delivered protection/atp to take its time analyzing behavior.
OPs writeup is great but it has nothing to do with behavioral analysis.
It doesn't even matter what bypass you found. I spent so much time defeating defender at one point, as soon as my payload breaks opsec on a cloud delivered box (e.g.:run "whoami") in about a day defender starts catching it.
I can almost guarantee this bypass can only last as long as attackers use it stealthily. Enough automatic detections will get human eyes on it.
That bothers me a lot.