Interesting. Presumably this breaks the emulated environment in which Defender is running the executable, and when this fails Defender assumes the executable is safe rather than suspicious?
Sometimes I get prompts from Windows Defender that it would like to upload some files to Microsoft for further analysis. The weird thing is that they are well known binaries from official sources, for example node.exe (Node JS). Just to be sure a couple times I checked the digital signatures and all that.
Doesn't Microsoft download important applications to analyze or whitelist itself?
I get the same thing with notepad++ updates. Only time I use windows is work and the apps that usually update are vscode (which I assume they preanalyze) and notepad++. Other than that I live in WSL for …work
What section is used eventually by the payload? Somehow the stack size feels like a red herring. These tools scan the executables without executing them, don't they? The payload is surely not on the stack yet.
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.
> These tools scan the executables without executing them, don't they?
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.
What I could never get over... Windows Defender (and all other client-side AV) is effectively pointless if you are operating as administrator on the machine. A carefully-crafted powershell command (running in an elevated context) can completely erase all traces of Defender in seconds.
Once you get your hands on a TrustedInstaller session, you are pretty much in god mode.
You don't even need that. AV does not know what "malware" is. It only knows heuristics from known bad ware. If I make a program in visual studio that does some bad stuff, and give it to you, defender won't do a thing about it because it's doing the same stuff good ware could also be doing.
This is why AV's are low on the list of security. Prevention is far better than detection.
Does that also apply to things like Symantec Endpoint Protection, which has many additional modules like SONAR - is that mostly marketing and loud yelling?
Most endpoint protection systems typically use a combination of looking at known hashes or bad things and active process monitoring to identify new bad things. They're not perfect, and have varying levels of success. It is better than nothing.
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.
That's why cloud delivered detection is good as well edrs including defender atp and others.
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.
If you are administrator, you can create and launch new scheduled tasks ... as NT\SYSTEM from that you can ... anything. Get TCB privilege, get Trusted Installer account, install kernel level drivers ... god mode.
Wait until the author finds out the 1995 technique of encrypting your payload as resource and decrypting it at runtime and then just jump to it in memory data (execute data technique) - the reason why AV's implemented heuristic analysis beside the classic signature one.
23 comments
[ 0.22 ms ] story [ 29.3 ms ] threadThat bothers me a lot.
Doesn't Microsoft download important applications to analyze or whitelist itself?
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.
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.
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.