Author: fireball Date: Sat Oct 8 22:33:56 2011 New Revision: 54057 URL: http://svn.reactos.org/svn/reactos?rev=54057&view=rev Log: [LDR] - Implement proper security cookie initialization code (same algorithm as in sdk/crt, however using as much data directly available as possible). - Don't initialize security cookie as a 32bit value when 16bit security cookie was requested. This fixes msi-related crashes (or any other executables which has 16bit security cookie set). See issue #6341 for more details.
Modified: trunk/reactos/dll/ntdll/ldr/ldrinit.c Modified: trunk/reactos/dll/ntdll/ldr/ldrinit.c URL: http://svn.reactos.org/svn/reactos/trunk/reactos/dll/ntdll/ldr/ldrinit.c?rev=54057&r1=54056&r2=54057&view=diff ============================================================================== --- trunk/reactos/dll/ntdll/ldr/ldrinit.c [iso-8859-1] (original) +++ trunk/reactos/dll/ntdll/ldr/ldrinit.c [iso-8859-1] Sat Oct 8 22:33:56 2011 @@ -440,7 +440,7 @@ { PULONG_PTR Cookie; LARGE_INTEGER Counter; - //ULONG NewCookie; + ULONG NewCookie; /* Fetch address of the cookie */ Cookie = LdrpFetchAddressOfSecurityCookie(LdrEntry->DllBase, LdrEntry->SizeOfImage); @@ -448,40 +448,39 @@ if (Cookie) { /* Check if it's a default one */ - if (*Cookie == DEFAULT_SECURITY_COOKIE || - *Cookie == 0xBB40) - { - /* We need to initialize it */ - + if ((*Cookie == DEFAULT_SECURITY_COOKIE) || + (*Cookie == 0xBB40)) + { + /* Make up a cookie from a bunch of values which may uniquely represent + current moment of time, environment, etc */ NtQueryPerformanceCounter(&Counter, NULL); -#if 0 - GetSystemTimeAsFileTime (&systime.ft_struct); -#ifdef _WIN64 - cookie = systime.ft_scalar; -#else - cookie = systime.ft_struct.dwLowDateTime; - cookie ^= systime.ft_struct.dwHighDateTime; -#endif - - cookie ^= GetCurrentProcessId (); - cookie ^= GetCurrentThreadId (); - cookie ^= GetTickCount (); - - QueryPerformanceCounter (&perfctr); -#ifdef _WIN64 - cookie ^= perfctr.QuadPart; -#else - cookie ^= perfctr.LowPart; - cookie ^= perfctr.HighPart; -#endif - -#ifdef _WIN64 - cookie &= 0x0000ffffffffffffll; -#endif -#endif - *Cookie = Counter.LowPart; - - //Cookie = NULL; + + NewCookie = Counter.LowPart ^ Counter.HighPart; + NewCookie ^= (ULONG)NtCurrentTeb()->ClientId.UniqueProcess; + NewCookie ^= (ULONG)NtCurrentTeb()->ClientId.UniqueThread; + + /* Loop like it's done in KeQueryTickCount(). We don't want to call it directly. */ + while (SharedUserData->SystemTime.High1Time != SharedUserData->SystemTime.High2Time) + { + YieldProcessor(); + }; + + /* Calculate the milliseconds value and xor it to the cookie */ + NewCookie ^= Int64ShrlMod32(UInt32x32To64(SharedUserData->TickCountMultiplier, SharedUserData->TickCount.LowPart), 24) + + (SharedUserData->TickCountMultiplier * (SharedUserData->TickCount.High1Time << 8)); + + /* Make the cookie 16bit if necessary */ + if (*Cookie == 0xBB40) NewCookie &= 0xFFFF; + + /* If the result is 0 or the same as we got, just subtract one from the existing value + and that's it */ + if ((NewCookie == 0) || (NewCookie == *Cookie)) + { + NewCookie = *Cookie - 1; + } + + /* Set the new cookie value */ + *Cookie = NewCookie; } }