AD2013: InitializeStackProtection¶
Summary¶
| Property | Value |
|---|---|
| ID | AD2013 |
| Name | InitializeStackProtection |
| Category | Security |
| Severity | Error |
| Applies to | PE (Windows) |
Description¶
Binaries should properly initialize the stack protection cookie at startup. The __security_init_cookie function randomizes the cookie value, making it harder for attackers to predict and bypass stack buffer overflow protection.
How It Works¶
The rule checks that:
- The binary has a security cookie configured in load config
- The CRT properly initializes the cookie via
__security_init_cookie - For DLLs, the entry point calls the initialization function
Standard CRT startup code automatically calls __security_init_cookie before main() or DllMain().
Why This Matters¶
The security cookie must be randomized at process startup before any protected functions execute. Without proper initialization, the well-known default cookie value provides zero protection against stack overflow attacks.
The Initialization Race¶
There's a critical window at process startup:
Process Timeline:
[Start] → [CRT Init] → [Cookie Init] → [main()] → [Your Code]
| | |
v v v
Cookie = Cookie = Cookie =
default default random
(known) (known) (secure)
Any code running before cookie initialization has only the known default cookie—effectively no protection.
The Default Cookie Problem¶
Default cookie values are public knowledge:
| Architecture | Default (Well-Known) | After Init (Random) |
|---|---|---|
| x86 | 0xBB40E64E | Random 32-bit |
| x64 | 0x00002B992DDFA232 | Random 64-bit |
Any attacker can include these defaults in their exploit payload if initialization hasn't occurred.
Common Initialization Failures¶
- Custom entry points: Using
/ENTRY:MyMainwithout calling__security_init_cookie - Minimal CRT: Using
/NODEFAULTLIBand not providing initialization - DLL without DllMain: Some DLL patterns skip standard initialization
- Early execution: Code running from TLS callbacks or static constructors
Correct Initialization Pattern¶
For custom entry points, initialization must be the first operation:
extern "C" void __security_init_cookie(void);
void WINAPI MyCustomEntryPoint() {
// FIRST: Initialize security cookie
__security_init_cookie();
// THEN: Everything else
InitializeHeap();
LoadConfiguration();
MyMain();
}
DLL Considerations¶
DLLs must initialize their cookie on DLL_PROCESS_ATTACH:
BOOL WINAPI DllMain(HINSTANCE hInst, DWORD reason, LPVOID reserved) {
if (reason == DLL_PROCESS_ATTACH) {
__security_init_cookie(); // Before any other code
// ... rest of initialization
}
return TRUE;
}
Entropy Sources¶
__security_init_cookie gathers entropy from:
- System time (high-resolution)
- Process ID
- Thread ID
- Performance counter
- Stack pointer
This provides sufficient randomness to make guessing infeasible.
Resolution¶
Use Standard CRT¶
The simplest fix is to use the standard CRT, which handles initialization automatically:
// Standard entry point - CRT handles cookie init
int main() {
// __security_init_cookie already called by CRT
return 0;
}
Custom Entry Points¶
If you use a custom entry point, initialize the cookie first:
extern "C" void __security_init_cookie(void);
// Custom entry point
void WINAPI MyEntryPoint() {
__security_init_cookie(); // MUST be first
// Rest of initialization
MyMain();
}
DLL Entry Points¶
For DLLs with custom entry points:
extern "C" void __security_init_cookie(void);
BOOL WINAPI DllMain(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpvReserved) {
if (fdwReason == DLL_PROCESS_ATTACH) {
__security_init_cookie(); // Initialize before any work
}
return TRUE;
}
When to Suppress¶
This rule may be suppressed for:
- No CRT binaries: Intentionally avoiding CRT (must handle security manually)
- Boot code: Pre-OS initialization code
- Compatibility modes: Very specific legacy requirements
Caveats¶
- Cookie initialization must happen before any
/GS-protected function runs - DLLs loaded via
LoadLibraryafter process start still need initialization - Static CRT linking includes the initialization automatically
Initialization Timing¶
Process Start:
1. Loader maps executable
2. Entry point called (e.g., mainCRTStartup)
3. __security_init_cookie() called ← CRITICAL
4. CRT initialization
5. main() called
6. Functions with /GS now have valid cookie
Related Rules¶
- AD2011: EnableStackProtection
- AD2012: DoNotModifyStackProtectionCookie
- AD2014: DoNotDisableStackProtectionForFunctions