From d93e516747e3220ba182f77824e8b1a8b548edae Mon Sep 17 00:00:00 2001 From: Mark Jansen Date: Sun, 14 Oct 2018 15:45:02 +0200 Subject: [PATCH] [LDR] Add support for .local files CORE-187 --- dll/ntdll/include/ntdllp.h | 8 +++++ dll/ntdll/ldr/ldrinit.c | 70 ++++++++++++++++++++++++++++++++++---- dll/ntdll/rtl/libsupp.c | 68 ++++++++++++++++++++++++++++++++++++ 3 files changed, 140 insertions(+), 6 deletions(-) diff --git a/dll/ntdll/include/ntdllp.h b/dll/ntdll/include/ntdllp.h index 11f1e826f36..0f122a642d2 100644 --- a/dll/ntdll/include/ntdllp.h +++ b/dll/ntdll/include/ntdllp.h @@ -203,4 +203,12 @@ VOID NTAPI LdrpFinalizeAndDeallocateDataTableEntry(IN PLDR_DATA_TABLE_ENTRY Entry); + +/* path.c */ +BOOLEAN +NTAPI +RtlDoesFileExists_UStr( + IN PUNICODE_STRING FileName +); + /* EOF */ diff --git a/dll/ntdll/ldr/ldrinit.c b/dll/ntdll/ldr/ldrinit.c index d28cb6e8a1f..39567578d91 100644 --- a/dll/ntdll/ldr/ldrinit.c +++ b/dll/ntdll/ldr/ldrinit.c @@ -25,6 +25,7 @@ UNICODE_STRING ImageExecOptionsString = RTL_CONSTANT_STRING(L"\\Registry\\Machin UNICODE_STRING Wow64OptionsString = RTL_CONSTANT_STRING(L""); UNICODE_STRING NtDllString = RTL_CONSTANT_STRING(L"ntdll.dll"); UNICODE_STRING Kernel32String = RTL_CONSTANT_STRING(L"kernel32.dll"); +const UNICODE_STRING LdrpDotLocal = RTL_CONSTANT_STRING(L".Local"); BOOLEAN LdrpInLdrInit; LONG LdrpProcessInitialized; @@ -1626,6 +1627,66 @@ LdrpInitializeProcessCompat(PVOID* pOldShimData) } } +VOID +NTAPI +LdrpInitializeDotLocalSupport(PRTL_USER_PROCESS_PARAMETERS ProcessParameters) +{ + UNICODE_STRING ImagePathName = ProcessParameters->ImagePathName; + WCHAR LocalBuffer[MAX_PATH]; + UNICODE_STRING DotLocal; + NTSTATUS Status; + ULONG RequiredSize; + + RequiredSize = ImagePathName.Length + LdrpDotLocal.Length + sizeof(UNICODE_NULL); + if (RequiredSize <= sizeof(LocalBuffer)) + { + RtlInitEmptyUnicodeString(&DotLocal, LocalBuffer, sizeof(LocalBuffer)); + } + else if (RequiredSize <= UNICODE_STRING_MAX_BYTES) + { + DotLocal.Buffer = RtlAllocateHeap(RtlGetProcessHeap(), 0, RequiredSize); + DotLocal.Length = 0; + DotLocal.MaximumLength = RequiredSize; + if (!DotLocal.Buffer) + DPRINT1("LDR: Failed to allocate memory for .local check\n"); + } + else + { + DotLocal.Buffer = NULL; + DotLocal.Length = 0; + DotLocal.MaximumLength = 0; + DPRINT1("LDR: String too big for .local check\n"); + } + + if (DotLocal.Buffer) + { + Status = RtlAppendUnicodeStringToString(&DotLocal, &ImagePathName); + ASSERT(NT_SUCCESS(Status)); + if (NT_SUCCESS(Status)) + { + Status = RtlAppendUnicodeStringToString(&DotLocal, &LdrpDotLocal); + ASSERT(NT_SUCCESS(Status)); + } + + if (NT_SUCCESS(Status)) + { + if (RtlDoesFileExists_UStr(&DotLocal)) + { + ProcessParameters->Flags |= RTL_USER_PROCESS_PARAMETERS_PRIVATE_DLL_PATH; + } + } + else + { + DPRINT1("LDR: Failed to append: 0x%lx\n", Status); + } + + if (DotLocal.Buffer != LocalBuffer) + { + RtlFreeHeap(RtlGetProcessHeap(), 0, DotLocal.Buffer); + } + } +} + NTSTATUS NTAPI @@ -2135,13 +2196,10 @@ LdrpInitializeProcess(IN PCONTEXT Context, if (FreeCurDir) RtlFreeUnicodeString(&CurrentDirectory); } - /* Check if we should look for a .local file - FIXME: Thomas suggested that this check might actually be reversed, we should check this file - if the flag is NOT set. */ - if (ProcessParameters && (ProcessParameters->Flags & RTL_USER_PROCESS_PARAMETERS_LOCAL_DLL_PATH)) + /* Check if we should look for a .local file */ + if (ProcessParameters && !(ProcessParameters->Flags & RTL_USER_PROCESS_PARAMETERS_LOCAL_DLL_PATH)) { - /* FIXME */ - DPRINT1("We don't support .local overrides yet\n"); + LdrpInitializeDotLocalSupport(ProcessParameters); } /* Check if the Application Verifier was enabled */ diff --git a/dll/ntdll/rtl/libsupp.c b/dll/ntdll/rtl/libsupp.c index d29ccaf82de..94c6f0e5b00 100644 --- a/dll/ntdll/rtl/libsupp.c +++ b/dll/ntdll/rtl/libsupp.c @@ -792,6 +792,8 @@ RtlDosApplyFileIsolationRedirection_Ustr(IN ULONG Flags, WCHAR *p; BOOLEAN GotExtension; WCHAR c; + C_ASSERT(sizeof(UNICODE_NULL) == sizeof(WCHAR)); + /* Check for invalid parameters */ if (!OriginalName) @@ -819,6 +821,72 @@ RtlDosApplyFileIsolationRedirection_Ustr(IN ULONG Flags, return STATUS_SXS_KEY_NOT_FOUND; } + if (NtCurrentPeb()->ProcessParameters && + (NtCurrentPeb()->ProcessParameters->Flags & RTL_USER_PROCESS_PARAMETERS_PRIVATE_DLL_PATH)) + { + UNICODE_STRING RealName, LocalName; + WCHAR RealNameBuf[MAX_PATH], LocalNameBuf[MAX_PATH]; + + RtlInitEmptyUnicodeString(&RealName, RealNameBuf, sizeof(RealNameBuf)); + RtlInitEmptyUnicodeString(&LocalName, LocalNameBuf, sizeof(LocalNameBuf)); + + Status = RtlComputePrivatizedDllName_U(OriginalName, &RealName, &LocalName); + if (!NT_SUCCESS(Status)) + { + DPRINT1("RtlComputePrivatizedDllName_U failed for %wZ: 0x%lx\n", OriginalName, Status); + return Status; + } + + if (RtlDoesFileExists_UStr(&LocalName)) + { + Status = get_buffer(&fullname, LocalName.Length + sizeof(UNICODE_NULL), StaticString, DynamicString != NULL); + if (NT_SUCCESS(Status)) + { + RtlCopyMemory(fullname, LocalName.Buffer, LocalName.Length + sizeof(UNICODE_NULL)); + } + else + { + DPRINT1("Error while retrieving buffer for %wZ: 0x%lx\n", OriginalName, Status); + } + } + else if (RtlDoesFileExists_UStr(&RealName)) + { + Status = get_buffer(&fullname, RealName.Length + sizeof(UNICODE_NULL), StaticString, DynamicString != NULL); + if (NT_SUCCESS(Status)) + { + RtlCopyMemory(fullname, RealName.Buffer, RealName.Length + sizeof(UNICODE_NULL)); + } + else + { + DPRINT1("Error while retrieving buffer for %wZ: 0x%lx\n", OriginalName, Status); + } + } + else + { + Status = STATUS_NOT_FOUND; + } + + if (RealName.Buffer != RealNameBuf) + RtlFreeUnicodeString(&RealName); + if (LocalName.Buffer != LocalNameBuf) + RtlFreeUnicodeString(&LocalName); + + if (NT_SUCCESS(Status)) + { + DPRINT("Redirecting %wZ to %S\n", OriginalName, fullname); + if (!StaticString || StaticString->Buffer != fullname) + { + RtlInitUnicodeString(DynamicString, fullname); + *NewName = DynamicString; + } + else + { + *NewName = StaticString; + } + return Status; + } + } + pstrParam = OriginalName; /* Get the file name with an extension */ -- 2.17.1