I run a program on my Windows 10 machine with windbg, and let it break on the initial breakpoint. I take the address of the physical bottom of the stack (stackBase of the TEB), and subtract the rsp
value of ntdll!LdrInitializeThunk
. I just did this 5 times on the same program, and I got 5 different values:
0x600
0x9f0
0xa40
0x5d0
0x570
You get similar results if you do the same with ntdll!RtlUserThreadStart
, etc. This suggests that the "logical bottom" of the stack is somewhat randomized. Why is that? Is this some kind of "mini-ASLR" inside of the stack? Is this documented anywhere?
After some googling for ASLR in Vista specifically (ASLR was introduced in Vista), I found this document from Symantec. On page 5, it mentions the phenomenon that my question is about (emphasis mine):
Once the stack has been placed, the initial stack pointer is further randomized by a random decremental amount. The initial offset is selected to be up to half a page (2,048 bytes), but is limited to naturally aligned addresses [...]
So it seems it's done intentionally for security reasons (this way it's harder to figure out addresses of things that reside at fixed offsets relative to the stack base).
I'm leaving this question open for some time hoping that someone can provide a more insightful answer. If no one does, I will accept this answer.