[LDR] Add support for .local files

CORE-187
This commit is contained in:
Mark Jansen 2018-10-14 15:45:02 +02:00
parent 88cd8d681c
commit d93e516747
No known key found for this signature in database
GPG key ID: B39240EE84BEAE8B
3 changed files with 140 additions and 6 deletions

View file

@ -203,4 +203,12 @@ VOID
NTAPI
LdrpFinalizeAndDeallocateDataTableEntry(IN PLDR_DATA_TABLE_ENTRY Entry);
/* path.c */
BOOLEAN
NTAPI
RtlDoesFileExists_UStr(
IN PUNICODE_STRING FileName
);
/* EOF */

View file

@ -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 */

View file

@ -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 */