mirror of
https://github.com/reactos/reactos.git
synced 2024-08-21 19:03:01 +00:00
[NTDLL]: Cleanup and half-fix LdrpCheckForLoadedDll, including adding comments for where it's broken. This uses RtlImageNtHeaderEx with much stringent checks as well.
svn path=/trunk/; revision=52621
This commit is contained in:
parent
f1c4df527e
commit
1b775b8d8a
|
@ -1394,6 +1394,7 @@ LdrpCheckForLoadedDllHandle(IN PVOID Base,
|
||||||
return FALSE;
|
return FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* NOTE: This function is b0rked and in the process of being slowly unf*cked */
|
||||||
BOOLEAN
|
BOOLEAN
|
||||||
NTAPI
|
NTAPI
|
||||||
LdrpCheckForLoadedDll(IN PWSTR DllPath,
|
LdrpCheckForLoadedDll(IN PWSTR DllPath,
|
||||||
|
@ -1417,11 +1418,13 @@ LdrpCheckForLoadedDll(IN PWSTR DllPath,
|
||||||
PVOID ViewBase = NULL;
|
PVOID ViewBase = NULL;
|
||||||
SIZE_T ViewSize = 0;
|
SIZE_T ViewSize = 0;
|
||||||
PIMAGE_NT_HEADERS NtHeader, NtHeader2;
|
PIMAGE_NT_HEADERS NtHeader, NtHeader2;
|
||||||
|
|
||||||
DPRINT("LdrpCheckForLoadedDll('%S' '%wZ' %d %d %p)\n", DllPath, DllName, Flag, RedirectedDll, LdrEntry);
|
DPRINT("LdrpCheckForLoadedDll('%S' '%wZ' %d %d %p)\n", DllPath, DllName, Flag, RedirectedDll, LdrEntry);
|
||||||
|
|
||||||
/* Check if a dll name was provided */
|
/* Check if a dll name was provided */
|
||||||
if (!DllName->Buffer || !DllName->Buffer[0]) return FALSE;
|
if (!(DllName->Buffer) || !(DllName->Buffer[0])) return FALSE;
|
||||||
|
|
||||||
|
/* FIXME: Warning, "Flag" is used as magic instead of "Static" */
|
||||||
|
/* FIXME: Warning, code does not support redirection at all */
|
||||||
|
|
||||||
/* Look in the hash table if flag was set */
|
/* Look in the hash table if flag was set */
|
||||||
lookinhash:
|
lookinhash:
|
||||||
|
@ -1459,7 +1462,7 @@ lookinhash:
|
||||||
while (*wc)
|
while (*wc)
|
||||||
{
|
{
|
||||||
/* Check for a slash in the current position*/
|
/* Check for a slash in the current position*/
|
||||||
if (*wc == L'\\' || *wc == L'/')
|
if ((*wc == L'\\') || (*wc == L'/'))
|
||||||
{
|
{
|
||||||
/* Found the slash, so dll name contains path */
|
/* Found the slash, so dll name contains path */
|
||||||
FullPath = TRUE;
|
FullPath = TRUE;
|
||||||
|
@ -1467,6 +1470,7 @@ lookinhash:
|
||||||
/* Setup full dll name string */
|
/* Setup full dll name string */
|
||||||
FullDllName.Buffer = NameBuf;
|
FullDllName.Buffer = NameBuf;
|
||||||
|
|
||||||
|
/* FIXME: This is from the Windows 2000 loader, not XP/2003, we should call LdrpSearchPath */
|
||||||
Length = RtlDosSearchPath_U(DllPath ? DllPath : LdrpDefaultPath.Buffer,
|
Length = RtlDosSearchPath_U(DllPath ? DllPath : LdrpDefaultPath.Buffer,
|
||||||
DllName->Buffer,
|
DllName->Buffer,
|
||||||
NULL,
|
NULL,
|
||||||
|
@ -1475,7 +1479,7 @@ lookinhash:
|
||||||
NULL);
|
NULL);
|
||||||
|
|
||||||
/* Check if that was successful */
|
/* Check if that was successful */
|
||||||
if (!Length || Length > sizeof(NameBuf) - sizeof(UNICODE_NULL))
|
if (!(Length) || (Length > (sizeof(NameBuf) - sizeof(UNICODE_NULL))))
|
||||||
{
|
{
|
||||||
if (ShowSnaps)
|
if (ShowSnaps)
|
||||||
{
|
{
|
||||||
|
@ -1503,17 +1507,21 @@ lookinhash:
|
||||||
goto lookinhash;
|
goto lookinhash;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Now go through the InLoadOrder module list */
|
/* FIXME: Warning, activation context missing */
|
||||||
|
/* NOTE: From here on down, everything looks good */
|
||||||
|
|
||||||
|
/* Loop the module list */
|
||||||
ListHead = &NtCurrentPeb()->Ldr->InLoadOrderModuleList;
|
ListHead = &NtCurrentPeb()->Ldr->InLoadOrderModuleList;
|
||||||
ListEntry = ListHead->Flink;
|
ListEntry = ListHead->Flink;
|
||||||
|
|
||||||
while (ListEntry != ListHead)
|
while (ListEntry != ListHead)
|
||||||
{
|
{
|
||||||
/* Get the containing record of the current entry and advance to the next one */
|
/* Get the current entry and advance to the next one */
|
||||||
CurEntry = CONTAINING_RECORD(ListEntry, LDR_DATA_TABLE_ENTRY, InLoadOrderLinks);
|
CurEntry = CONTAINING_RECORD(ListEntry,
|
||||||
|
LDR_DATA_TABLE_ENTRY,
|
||||||
|
InLoadOrderLinks);
|
||||||
ListEntry = ListEntry->Flink;
|
ListEntry = ListEntry->Flink;
|
||||||
|
|
||||||
/* Check if it's already being unloaded */
|
/* Check if it's being unloaded */
|
||||||
if (!CurEntry->InMemoryOrderModuleList.Flink) continue;
|
if (!CurEntry->InMemoryOrderModuleList.Flink) continue;
|
||||||
|
|
||||||
/* Check if name matches */
|
/* Check if name matches */
|
||||||
|
@ -1523,18 +1531,10 @@ lookinhash:
|
||||||
{
|
{
|
||||||
/* Found it */
|
/* Found it */
|
||||||
*LdrEntry = CurEntry;
|
*LdrEntry = CurEntry;
|
||||||
|
|
||||||
/* Find activation context */
|
|
||||||
//Status = RtlFindActivationContextSectionString(0, NULL, ACTIVATION_CONTEXT_SECTION_DLL_REDIRECTION, DllName, NULL);
|
|
||||||
//if (!NT_SUCCESS(Status))
|
|
||||||
// return FALSE;
|
|
||||||
//else
|
|
||||||
return TRUE;
|
return TRUE;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* The DLL was not found in the load order modules list. Perform a complex check */
|
|
||||||
|
|
||||||
/* Convert given path to NT path */
|
/* Convert given path to NT path */
|
||||||
if (!RtlDosPathNameToNtPathName_U(FullDllName.Buffer,
|
if (!RtlDosPathNameToNtPathName_U(FullDllName.Buffer,
|
||||||
&NtPathName,
|
&NtPathName,
|
||||||
|
@ -1551,7 +1551,6 @@ lookinhash:
|
||||||
OBJ_CASE_INSENSITIVE,
|
OBJ_CASE_INSENSITIVE,
|
||||||
NULL,
|
NULL,
|
||||||
NULL);
|
NULL);
|
||||||
|
|
||||||
Status = NtOpenFile(&FileHandle,
|
Status = NtOpenFile(&FileHandle,
|
||||||
SYNCHRONIZE | FILE_EXECUTE,
|
SYNCHRONIZE | FILE_EXECUTE,
|
||||||
&ObjectAttributes,
|
&ObjectAttributes,
|
||||||
|
@ -1567,7 +1566,9 @@ lookinhash:
|
||||||
|
|
||||||
/* Create a section for this file */
|
/* Create a section for this file */
|
||||||
Status = NtCreateSection(&SectionHandle,
|
Status = NtCreateSection(&SectionHandle,
|
||||||
SECTION_MAP_READ | SECTION_MAP_EXECUTE | SECTION_MAP_WRITE,
|
SECTION_MAP_READ |
|
||||||
|
SECTION_MAP_EXECUTE |
|
||||||
|
SECTION_MAP_WRITE,
|
||||||
NULL,
|
NULL,
|
||||||
NULL,
|
NULL,
|
||||||
PAGE_EXECUTE,
|
PAGE_EXECUTE,
|
||||||
|
@ -1591,6 +1592,7 @@ lookinhash:
|
||||||
ViewShare,
|
ViewShare,
|
||||||
0,
|
0,
|
||||||
PAGE_EXECUTE);
|
PAGE_EXECUTE);
|
||||||
|
|
||||||
/* Close section handle */
|
/* Close section handle */
|
||||||
NtClose(SectionHandle);
|
NtClose(SectionHandle);
|
||||||
|
|
||||||
|
@ -1598,52 +1600,51 @@ lookinhash:
|
||||||
if (!NT_SUCCESS(Status)) return FALSE;
|
if (!NT_SUCCESS(Status)) return FALSE;
|
||||||
|
|
||||||
/* Get pointer to the NT header of this section */
|
/* Get pointer to the NT header of this section */
|
||||||
NtHeader = RtlImageNtHeader(ViewBase);
|
Status = RtlImageNtHeaderEx(0, ViewBase, ViewSize, &NtHeader);
|
||||||
if (!NtHeader)
|
if (!(NT_SUCCESS(Status)) || !(NtHeader))
|
||||||
{
|
{
|
||||||
/* Unmap the section and fail */
|
/* Unmap the section and fail */
|
||||||
NtUnmapViewOfSection(NtCurrentProcess(), ViewBase);
|
NtUnmapViewOfSection(NtCurrentProcess(), ViewBase);
|
||||||
return FALSE;
|
return FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Go through the list of modules */
|
/* Go through the list of modules again */
|
||||||
ListHead = &NtCurrentPeb()->Ldr->InLoadOrderModuleList;
|
ListHead = &NtCurrentPeb()->Ldr->InLoadOrderModuleList;
|
||||||
ListEntry = ListHead->Flink;
|
ListEntry = ListHead->Flink;
|
||||||
|
|
||||||
while (ListEntry != ListHead)
|
while (ListEntry != ListHead)
|
||||||
{
|
{
|
||||||
CurEntry = CONTAINING_RECORD(ListEntry, LDR_DATA_TABLE_ENTRY, InLoadOrderLinks);
|
/* Get the current entry and advance to the next one */
|
||||||
|
CurEntry = CONTAINING_RECORD(ListEntry,
|
||||||
|
LDR_DATA_TABLE_ENTRY,
|
||||||
|
InLoadOrderLinks);
|
||||||
ListEntry = ListEntry->Flink;
|
ListEntry = ListEntry->Flink;
|
||||||
|
|
||||||
/* Check if it's already being unloaded */
|
/* Check if it's in the process of being unloaded */
|
||||||
if (!CurEntry->InMemoryOrderModuleList.Flink) continue;
|
if (!CurEntry->InMemoryOrderModuleList.Flink) continue;
|
||||||
|
|
||||||
|
/* The header is untrusted, use SEH */
|
||||||
_SEH2_TRY
|
_SEH2_TRY
|
||||||
{
|
{
|
||||||
/* Check if timedate stamp and sizes match */
|
/* Check if timedate stamp and sizes match */
|
||||||
if (CurEntry->TimeDateStamp == NtHeader->FileHeader.TimeDateStamp &&
|
if ((CurEntry->TimeDateStamp == NtHeader->FileHeader.TimeDateStamp) &&
|
||||||
CurEntry->SizeOfImage == NtHeader->OptionalHeader.SizeOfImage)
|
(CurEntry->SizeOfImage == NtHeader->OptionalHeader.SizeOfImage))
|
||||||
{
|
{
|
||||||
/* Time, date and size match. Let's compare their headers */
|
/* Time, date and size match. Let's compare their headers */
|
||||||
NtHeader2 = RtlImageNtHeader(CurEntry->DllBase);
|
NtHeader2 = RtlImageNtHeader(CurEntry->DllBase);
|
||||||
|
|
||||||
if (RtlCompareMemory(NtHeader2, NtHeader, sizeof(IMAGE_NT_HEADERS)))
|
if (RtlCompareMemory(NtHeader2, NtHeader, sizeof(IMAGE_NT_HEADERS)))
|
||||||
{
|
{
|
||||||
/* Headers match too! Finally ask the kernel to compare mapped files */
|
/* Headers match too! Finally ask the kernel to compare mapped files */
|
||||||
Status = ZwAreMappedFilesTheSame(CurEntry->DllBase, ViewBase);
|
Status = ZwAreMappedFilesTheSame(CurEntry->DllBase, ViewBase);
|
||||||
|
|
||||||
if (!NT_SUCCESS(Status))
|
if (!NT_SUCCESS(Status))
|
||||||
{
|
{
|
||||||
|
/* Almost identical, but not quite, keep trying */
|
||||||
_SEH2_YIELD(continue;)
|
_SEH2_YIELD(continue;)
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
/* This is our entry! */
|
/* This is our entry!, unmap and return success */
|
||||||
*LdrEntry = CurEntry;
|
*LdrEntry = CurEntry;
|
||||||
|
|
||||||
/* Unmap the section */
|
|
||||||
NtUnmapViewOfSection(NtCurrentProcess(), ViewBase);
|
NtUnmapViewOfSection(NtCurrentProcess(), ViewBase);
|
||||||
|
|
||||||
_SEH2_YIELD(return TRUE;)
|
_SEH2_YIELD(return TRUE;)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1656,9 +1657,8 @@ lookinhash:
|
||||||
_SEH2_END;
|
_SEH2_END;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Unmap the section */
|
/* Unmap the section and fail */
|
||||||
NtUnmapViewOfSection(NtCurrentProcess(), ViewBase);
|
NtUnmapViewOfSection(NtCurrentProcess(), ViewBase);
|
||||||
|
|
||||||
return FALSE;
|
return FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue