VC++的栈Cookie算法据称非常安全。
这是真的吗?那我们亲自来探寻一下:
先创建一个空程序。
Cookie算法:
从这里进去:
这一段就是Cookie的算法:
我将其翻译成了下面一段伪程序:
/*
FILETIME ft;
GetSystemTimeAsFileTime(&ft);FT
GetCurrentThreadId();
GetCurrentProcessId();
LARGE_INTEGER li;
QueryPerformanceCounter(&li);QPC
*/
x=0^FT^ThreadID^ProcessID^QPC(高)^QPC(低)
x^=&x
if x==(0xBB40E64E)
{
x=0xBB4054F;
}
else
{
y=x& 0xFFFF0000
if(y==0)
{
z=x;
x=((z|0x4711)<<0x10)^x
}
}
return x
看了右边,有符号信息!原来有源码。猝不及防
gs_support.c
赋上源码:
void __cdecl __security_init_cookie(void)
{
UINT_PTR cookie;
FT systime={0};
LARGE_INTEGER perfctr;
/*
* Do nothing if the global cookie has already been initialized. On x86,
* reinitialize the cookie if it has been previously initialized to a
* value with the high word 0x0000. Some versions of Windows will init
* the cookie in the loader, but using an older mechanism which forced the
* high word to zero.
*/
if (__security_cookie != DEFAULT_SECURITY_COOKIE
#if defined (_M_IX86)
&& (__security_cookie & 0xFFFF0000) != 0
#endif /* defined (_M_IX86) */
)
{
__security_cookie_complement = ~__security_cookie;
return;
}
/*
* Initialize the global cookie with an unpredictable value which is
* different for each module in a process. Combine a number of sources
* of randomness.
*/
GetSystemTimeAsFileTime(&systime.ft_struct);
#if defined (_WIN64)
cookie = systime.ft_scalar;
#else /* defined (_WIN64) */
cookie = systime.ft_struct.dwLowDateTime;
cookie ^= systime.ft_struct.dwHighDateTime;
#endif /* defined (_WIN64) */
cookie ^= GetCurrentThreadId();
cookie ^= GetCurrentProcessId();
#if _CRT_NTDDI_MIN >= NTDDI_VISTA
#if defined (_WIN64)
cookie ^= (((UINT_PTR)GetTickCount64()) << 56);
#endif /* defined (_WIN64) */
cookie ^= (UINT_PTR)GetTickCount64();
#endif /* _CRT_NTDDI_MIN >= NTDDI_VISTA */
QueryPerformanceCounter(&perfctr);
#if defined (_WIN64)
cookie ^= (((UINT_PTR)perfctr.LowPart << 32) ^ perfctr.QuadPart);
#else /* defined (_WIN64) */
cookie ^= perfctr.LowPart;
cookie ^= perfctr.HighPart;
#endif /* defined (_WIN64) */
/*
* Increase entropy using ASLR relocation
*/
cookie ^= (UINT_PTR)&cookie;
#if defined (_WIN64)
/*
* On Win64, generate a cookie with the most significant word set to zero,
* as a defense against buffer overruns involving null-terminated strings.
* Don't do so on Win32, as it's more important to keep 32 bits of cookie.
*/
cookie &= 0x0000FFFFffffFFFFi64;
#endif /* defined (_WIN64) */
/*
* Make sure the cookie is initialized to a value that will prevent us from
* reinitializing it if this routine is ever called twice.
*/
if (cookie == DEFAULT_SECURITY_COOKIE)
{
cookie = DEFAULT_SECURITY_COOKIE + 1;
}
#if defined (_M_IX86)
else if ((cookie & 0xFFFF0000) == 0)
{
cookie |= ( (cookie|0x4711) << 16);
}
#endif /* defined (_M_IX86) */
__security_cookie = cookie;
__security_cookie_complement = ~cookie;
}