24 ms·
Here a test in godbolt https://godbolt.org/z/rKao1ssb9 https://godbolt.org/z/rKao1ssb9 . All 3 compilers GCC, Clang and MVSC instead of placing the whole stac
by Karliss 4y ago
Here a test in godbolt https://godbolt.org/z/rKao1ssb9 https://godbolt.org/z/rKao1ssb9 .
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.
- muststopmyths 4y agoyes, I just tested with VC and was going to post that I found exactly what you said. Thanks for explaining in detail.
- Karliss 4y agoI guess that every byte being stored as `mov [stack_ptr], 0x12` is why executable with 2MB array takes 16MB of disk space.