mirror of
https://github.com/reactos/reactos.git
synced 2024-06-01 02:01:57 +00:00
[FREELDR][NTOS:MM] Add security cookie generation to FreeLoader (#6270)
* [NTOS:MM] Misc improvements for cookie generation code - Improve support for 64 bit images - Improve LdrpFetchAddressOfSecurityCookie code * [FREELDR] Add security cookie generation to FreeLoader CORE-17808
This commit is contained in:
parent
36fa628605
commit
fec827eeef
|
@ -56,3 +56,7 @@ PeLdrCheckForLoadedDll(
|
||||||
IN OUT PLIST_ENTRY ModuleListHead,
|
IN OUT PLIST_ENTRY ModuleListHead,
|
||||||
IN PCH DllName,
|
IN PCH DllName,
|
||||||
OUT PLDR_DATA_TABLE_ENTRY *LoadedEntry);
|
OUT PLDR_DATA_TABLE_ENTRY *LoadedEntry);
|
||||||
|
|
||||||
|
PVOID
|
||||||
|
PeLdrInitSecurityCookie(
|
||||||
|
_In_ PLDR_DATA_TABLE_ENTRY LdrEntry);
|
||||||
|
|
|
@ -27,9 +27,51 @@ DBG_DEFAULT_CHANNEL(PELOADER);
|
||||||
|
|
||||||
PELDR_IMPORTDLL_LOAD_CALLBACK PeLdrImportDllLoadCallback = NULL;
|
PELDR_IMPORTDLL_LOAD_CALLBACK PeLdrImportDllLoadCallback = NULL;
|
||||||
|
|
||||||
|
#ifdef _WIN64
|
||||||
|
#define COOKIE_MAX 0x0000FFFFFFFFFFFFll
|
||||||
|
#define DEFAULT_SECURITY_COOKIE 0x00002B992DDFA232ll
|
||||||
|
#else
|
||||||
|
#define DEFAULT_SECURITY_COOKIE 0xBB40E64E
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
/* PRIVATE FUNCTIONS *********************************************************/
|
/* PRIVATE FUNCTIONS *********************************************************/
|
||||||
|
|
||||||
|
static PVOID
|
||||||
|
PeLdrpFetchAddressOfSecurityCookie(PVOID BaseAddress, ULONG SizeOfImage)
|
||||||
|
{
|
||||||
|
PIMAGE_LOAD_CONFIG_DIRECTORY ConfigDir;
|
||||||
|
ULONG DirSize;
|
||||||
|
PULONG_PTR Cookie = NULL;
|
||||||
|
|
||||||
|
/* Get the pointer to the config directory */
|
||||||
|
ConfigDir = RtlImageDirectoryEntryToData(BaseAddress,
|
||||||
|
TRUE,
|
||||||
|
IMAGE_DIRECTORY_ENTRY_LOAD_CONFIG,
|
||||||
|
&DirSize);
|
||||||
|
|
||||||
|
/* Check for sanity */
|
||||||
|
if (!ConfigDir ||
|
||||||
|
DirSize < RTL_SIZEOF_THROUGH_FIELD(IMAGE_LOAD_CONFIG_DIRECTORY, SecurityCookie))
|
||||||
|
{
|
||||||
|
/* Invalid directory*/
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Now get the cookie */
|
||||||
|
Cookie = VaToPa((PULONG_PTR)ConfigDir->SecurityCookie);
|
||||||
|
|
||||||
|
/* Check this cookie */
|
||||||
|
if ((PCHAR)Cookie <= (PCHAR)BaseAddress ||
|
||||||
|
(PCHAR)Cookie >= (PCHAR)BaseAddress + SizeOfImage - sizeof(*Cookie))
|
||||||
|
{
|
||||||
|
Cookie = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Return validated security cookie */
|
||||||
|
return Cookie;
|
||||||
|
}
|
||||||
|
|
||||||
/* DllName - physical, UnicodeString->Buffer - virtual */
|
/* DllName - physical, UnicodeString->Buffer - virtual */
|
||||||
static BOOLEAN
|
static BOOLEAN
|
||||||
PeLdrpCompareDllName(
|
PeLdrpCompareDllName(
|
||||||
|
@ -386,6 +428,9 @@ PeLdrpLoadAndScanReferencedDll(
|
||||||
return Success;
|
return Success;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Init security cookie */
|
||||||
|
PeLdrInitSecurityCookie(*DataTableEntry);
|
||||||
|
|
||||||
(*DataTableEntry)->Flags |= LDRP_DRIVER_DEPENDENT_DLL;
|
(*DataTableEntry)->Flags |= LDRP_DRIVER_DEPENDENT_DLL;
|
||||||
|
|
||||||
/* Scan its dependencies too */
|
/* Scan its dependencies too */
|
||||||
|
@ -473,6 +518,44 @@ PeLdrpScanImportAddressTable(
|
||||||
|
|
||||||
/* FUNCTIONS *****************************************************************/
|
/* FUNCTIONS *****************************************************************/
|
||||||
|
|
||||||
|
PVOID
|
||||||
|
PeLdrInitSecurityCookie(PLDR_DATA_TABLE_ENTRY LdrEntry)
|
||||||
|
{
|
||||||
|
PULONG_PTR Cookie;
|
||||||
|
ULONG_PTR NewCookie;
|
||||||
|
|
||||||
|
/* Fetch address of the cookie */
|
||||||
|
Cookie = PeLdrpFetchAddressOfSecurityCookie(VaToPa(LdrEntry->DllBase), LdrEntry->SizeOfImage);
|
||||||
|
|
||||||
|
if (!Cookie)
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
/* Check if it's a default one */
|
||||||
|
if ((*Cookie == DEFAULT_SECURITY_COOKIE) ||
|
||||||
|
(*Cookie == 0))
|
||||||
|
{
|
||||||
|
/* Generate new cookie using cookie address and time as seed */
|
||||||
|
NewCookie = (ULONG_PTR)Cookie ^ (ULONG_PTR)ArcGetRelativeTime();
|
||||||
|
#ifdef _WIN64
|
||||||
|
/* Some images expect first 16 bits to be kept clean (like in default cookie) */
|
||||||
|
if (NewCookie > COOKIE_MAX)
|
||||||
|
{
|
||||||
|
NewCookie >>= 16;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
/* If the result is 0 or the same as we got, just add one to the default value */
|
||||||
|
if ((NewCookie == 0) || (NewCookie == *Cookie))
|
||||||
|
{
|
||||||
|
NewCookie = DEFAULT_SECURITY_COOKIE + 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Set the new cookie value */
|
||||||
|
*Cookie = NewCookie;
|
||||||
|
}
|
||||||
|
|
||||||
|
return Cookie;
|
||||||
|
}
|
||||||
|
|
||||||
/* Returns TRUE if DLL has already been loaded - looks in LoadOrderList in LPB */
|
/* Returns TRUE if DLL has already been loaded - looks in LoadOrderList in LPB */
|
||||||
BOOLEAN
|
BOOLEAN
|
||||||
PeLdrCheckForLoadedDll(
|
PeLdrCheckForLoadedDll(
|
||||||
|
|
|
@ -342,6 +342,9 @@ WinLdrLoadDeviceDriver(PLIST_ENTRY LoadOrderListHead,
|
||||||
return FALSE;
|
return FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Init security cookie */
|
||||||
|
PeLdrInitSecurityCookie(*DriverDTE);
|
||||||
|
|
||||||
// Modify any flags, if needed
|
// Modify any flags, if needed
|
||||||
(*DriverDTE)->Flags |= Flags;
|
(*DriverDTE)->Flags |= Flags;
|
||||||
|
|
||||||
|
@ -537,9 +540,12 @@ LoadModule(
|
||||||
/* Cleanup and bail out */
|
/* Cleanup and bail out */
|
||||||
ERR("PeLdrAllocateDataTableEntry('%s') failed\n", FullFileName);
|
ERR("PeLdrAllocateDataTableEntry('%s') failed\n", FullFileName);
|
||||||
MmFreeMemory(BaseAddress);
|
MmFreeMemory(BaseAddress);
|
||||||
BaseAddress = NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Init security cookie */
|
||||||
|
PeLdrInitSecurityCookie(*Dte);
|
||||||
|
|
||||||
return BaseAddress;
|
return BaseAddress;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -38,6 +38,7 @@ ULONG_PTR ExPoolCodeStart, ExPoolCodeEnd, MmPoolCodeStart, MmPoolCodeEnd;
|
||||||
ULONG_PTR MmPteCodeStart, MmPteCodeEnd;
|
ULONG_PTR MmPteCodeStart, MmPteCodeEnd;
|
||||||
|
|
||||||
#ifdef _WIN64
|
#ifdef _WIN64
|
||||||
|
#define COOKIE_MAX 0x0000FFFFFFFFFFFFll
|
||||||
#define DEFAULT_SECURITY_COOKIE 0x00002B992DDFA232ll
|
#define DEFAULT_SECURITY_COOKIE 0x00002B992DDFA232ll
|
||||||
#else
|
#else
|
||||||
#define DEFAULT_SECURITY_COOKIE 0xBB40E64E
|
#define DEFAULT_SECURITY_COOKIE 0xBB40E64E
|
||||||
|
@ -2859,10 +2860,7 @@ LdrpFetchAddressOfSecurityCookie(PVOID BaseAddress, ULONG SizeOfImage)
|
||||||
{
|
{
|
||||||
PIMAGE_LOAD_CONFIG_DIRECTORY ConfigDir;
|
PIMAGE_LOAD_CONFIG_DIRECTORY ConfigDir;
|
||||||
ULONG DirSize;
|
ULONG DirSize;
|
||||||
PVOID Cookie = NULL;
|
PULONG_PTR Cookie = NULL;
|
||||||
|
|
||||||
/* Check NT header first */
|
|
||||||
if (!RtlImageNtHeader(BaseAddress)) return NULL;
|
|
||||||
|
|
||||||
/* Get the pointer to the config directory */
|
/* Get the pointer to the config directory */
|
||||||
ConfigDir = RtlImageDirectoryEntryToData(BaseAddress,
|
ConfigDir = RtlImageDirectoryEntryToData(BaseAddress,
|
||||||
|
@ -2872,19 +2870,18 @@ LdrpFetchAddressOfSecurityCookie(PVOID BaseAddress, ULONG SizeOfImage)
|
||||||
|
|
||||||
/* Check for sanity */
|
/* Check for sanity */
|
||||||
if (!ConfigDir ||
|
if (!ConfigDir ||
|
||||||
DirSize < FIELD_OFFSET(IMAGE_LOAD_CONFIG_DIRECTORY, SEHandlerTable) || /* SEHandlerTable is after SecurityCookie */
|
DirSize < RTL_SIZEOF_THROUGH_FIELD(IMAGE_LOAD_CONFIG_DIRECTORY, SecurityCookie))
|
||||||
(ConfigDir->Size != DirSize))
|
|
||||||
{
|
{
|
||||||
/* Invalid directory*/
|
/* Invalid directory*/
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Now get the cookie */
|
/* Now get the cookie */
|
||||||
Cookie = (PVOID)ConfigDir->SecurityCookie;
|
Cookie = (PULONG_PTR)ConfigDir->SecurityCookie;
|
||||||
|
|
||||||
/* Check this cookie */
|
/* Check this cookie */
|
||||||
if ((PCHAR)Cookie <= (PCHAR)BaseAddress ||
|
if ((PCHAR)Cookie <= (PCHAR)BaseAddress ||
|
||||||
(PCHAR)Cookie >= (PCHAR)BaseAddress + SizeOfImage)
|
(PCHAR)Cookie >= (PCHAR)BaseAddress + SizeOfImage - sizeof(*Cookie))
|
||||||
{
|
{
|
||||||
Cookie = NULL;
|
Cookie = NULL;
|
||||||
}
|
}
|
||||||
|
@ -2903,28 +2900,34 @@ LdrpInitSecurityCookie(PLDR_DATA_TABLE_ENTRY LdrEntry)
|
||||||
/* Fetch address of the cookie */
|
/* Fetch address of the cookie */
|
||||||
Cookie = LdrpFetchAddressOfSecurityCookie(LdrEntry->DllBase, LdrEntry->SizeOfImage);
|
Cookie = LdrpFetchAddressOfSecurityCookie(LdrEntry->DllBase, LdrEntry->SizeOfImage);
|
||||||
|
|
||||||
if (Cookie)
|
if (!Cookie)
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
/* Check if it's a default one */
|
||||||
|
if ((*Cookie == DEFAULT_SECURITY_COOKIE) ||
|
||||||
|
(*Cookie == 0))
|
||||||
{
|
{
|
||||||
/* Check if it's a default one */
|
LARGE_INTEGER Counter = KeQueryPerformanceCounter(NULL);
|
||||||
if ((*Cookie == DEFAULT_SECURITY_COOKIE) ||
|
/* The address should be unique */
|
||||||
(*Cookie == 0))
|
NewCookie = (ULONG_PTR)Cookie;
|
||||||
|
|
||||||
|
/* We just need a simple tick, don't care about precision and whatnot */
|
||||||
|
NewCookie ^= (ULONG_PTR)Counter.LowPart;
|
||||||
|
#ifdef _WIN64
|
||||||
|
/* Some images expect first 16 bits to be kept clean (like in default cookie) */
|
||||||
|
if (NewCookie > COOKIE_MAX)
|
||||||
{
|
{
|
||||||
LARGE_INTEGER Counter = KeQueryPerformanceCounter(NULL);
|
NewCookie >>= 16;
|
||||||
/* The address should be unique */
|
|
||||||
NewCookie = (ULONG_PTR)Cookie;
|
|
||||||
|
|
||||||
/* We just need a simple tick, don't care about precision and whatnot */
|
|
||||||
NewCookie ^= (ULONG_PTR)Counter.LowPart;
|
|
||||||
|
|
||||||
/* If the result is 0 or the same as we got, just add one to the default value */
|
|
||||||
if ((NewCookie == 0) || (NewCookie == *Cookie))
|
|
||||||
{
|
|
||||||
NewCookie = DEFAULT_SECURITY_COOKIE + 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Set the new cookie value */
|
|
||||||
*Cookie = NewCookie;
|
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
|
/* If the result is 0 or the same as we got, just add one to the default value */
|
||||||
|
if ((NewCookie == 0) || (NewCookie == *Cookie))
|
||||||
|
{
|
||||||
|
NewCookie = DEFAULT_SECURITY_COOKIE + 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Set the new cookie value */
|
||||||
|
*Cookie = NewCookie;
|
||||||
}
|
}
|
||||||
|
|
||||||
return Cookie;
|
return Cookie;
|
||||||
|
|
Loading…
Reference in a new issue