AD2012: DoNotModifyStackProtectionCookie¶
Summary¶
| Property | Value |
|---|---|
| ID | AD2012 |
| Name | DoNotModifyStackProtectionCookie |
| Category | Security |
| Severity | Error |
| Applies to | PE (Windows) |
Description¶
Application code should not interfere with the stack protector. The security cookie value must be the default value generated by the compiler and linker. Custom cookies or modified values weaken the protection provided.
How It Works¶
The rule examines the load configuration directory to verify that:
- A security cookie is present
- The cookie location is valid
- The cookie value is the default (before initialization)
Expected default values:
- x86: 0xBB40E64E
- x64: 0x00002B992DDFA232
Why This Matters¶
The security cookie's effectiveness depends entirely on being unpredictable to attackers. Custom or modified cookies can completely undermine stack protection, making /GS security theater rather than actual defense.
How Cookie Protection Works¶
The security model relies on attackers not knowing the cookie value:
- Random initialization: At process start,
__security_init_cookiegenerates a random value - Entropy sources: Time, process ID, thread ID, performance counter
- Verification: Each function exit compares the stack cookie against the global value
- Attack detection: An attacker overwriting the stack cannot preserve the unknown cookie value
Why Custom Cookies Are Dangerous¶
If you define a custom __security_cookie:
// DANGEROUS: Attackers now know the cookie value
extern "C" UINT_PTR __security_cookie = 0x12345678;
An attacker can include this value in their overflow payload, bypassing all protection:
Default Cookie Values¶
The linker sets these default values before initialization:
| Architecture | Default Value | Purpose |
|---|---|---|
| x86 | 0xBB40E64E | Placeholder before randomization |
| x64 | 0x00002B992DDFA232 | Placeholder before randomization |
These defaults are well-known—the security comes from __security_init_cookie replacing them with random values at runtime.
Common Mistakes¶
- Defining custom cookie: Some developers think they're adding security by setting a "secret" value
- Skipping initialization: Custom entry points that don't call
__security_init_cookie - Post-build modification: Tools that modify the cookie after building
Real-World Bypass¶
Security researchers have exploited applications with predictable cookies:
1. Find buffer overflow in target
2. Discover target uses known/predictable cookie
3. Include correct cookie value in overflow payload
4. Stack protection check passes
5. Exploit succeeds despite /GS being "enabled"
Entropy Requirements¶
For effective protection, the cookie needs:
- At least 32 bits of entropy on x86
- At least 64 bits of entropy on x64
- Fresh value per process (not static across runs)
Resolution¶
Remove Custom Cookie Values¶
If you've defined a custom __security_cookie:
// Bad - custom cookie value
extern "C" UINT_PTR __security_cookie = MY_CUSTOM_VALUE;
// Good - let the linker/CRT handle it
// (don't define __security_cookie at all)
Check Linker Settings¶
Ensure you're not modifying the cookie via linker options or post-build tools.
Use Standard CRT¶
Ensure you're using the standard CRT initialization that properly randomizes the cookie:
When to Suppress¶
This rule should rarely be suppressed. Exceptions might include:
- Custom CRT: If implementing your own C runtime
- Boot code: Pre-CRT initialization code
- Testing: Deliberate testing of /GS mechanisms
Caveats¶
- The default value is only present before
__security_init_cookieruns - Some analysis tools may see the pre-initialized value
- Post-initialization, the cookie should be random
Understanding Security Cookies¶
Lifecycle:
1. Binary loaded - cookie = default value
2. CRT initializes - __security_init_cookie() called
3. Cookie randomized - high-entropy value from OS
4. Functions use cookie - copied to stack frames
5. Function return - cookie verified
Related Rules¶
- AD2011: EnableStackProtection
- AD2013: InitializeStackProtection
- AD2014: DoNotDisableStackProtectionForFunctions