📄 utils.c
字号:
* DESCRIPTION
* Compute the entry point for every symbol the DLL imports
* from other modules.
*
* ARGUMENTS
*
* RETURN VALUE
*
* REVISIONS
*
* NOTE
*
*/
static NTSTATUS
LdrFixupImports(IN PWSTR SearchPath OPTIONAL,
IN PLDR_DATA_TABLE_ENTRY Module)
{
PIMAGE_IMPORT_DESCRIPTOR ImportModuleDirectory;
PIMAGE_IMPORT_DESCRIPTOR ImportModuleDirectoryCurrent;
PIMAGE_BOUND_IMPORT_DESCRIPTOR BoundImportDescriptor;
PIMAGE_BOUND_IMPORT_DESCRIPTOR BoundImportDescriptorCurrent;
PIMAGE_TLS_DIRECTORY TlsDirectory;
ULONG TlsSize = 0;
NTSTATUS Status;
PLDR_DATA_TABLE_ENTRY ImportedModule;
PCHAR ImportedName;
ULONG Size;
DPRINT("LdrFixupImports(SearchPath %S, Module %p)\n", SearchPath, Module);
/* Check for tls data */
TlsDirectory = (PIMAGE_TLS_DIRECTORY)
RtlImageDirectoryEntryToData(Module->DllBase,
TRUE,
IMAGE_DIRECTORY_ENTRY_TLS,
&Size);
if (TlsDirectory)
{
TlsSize = TlsDirectory->EndAddressOfRawData
- TlsDirectory->StartAddressOfRawData
+ TlsDirectory->SizeOfZeroFill;
if (TlsSize > 0 &&
NtCurrentPeb()->Ldr->Initialized)
{
TRACE_LDR("Trying to load dynamicly %wZ which contains a tls directory\n",
&Module->BaseDllName);
return STATUS_UNSUCCESSFUL;
}
}
/*
* Process each import module.
*/
ImportModuleDirectory = (PIMAGE_IMPORT_DESCRIPTOR)
RtlImageDirectoryEntryToData(Module->DllBase,
TRUE,
IMAGE_DIRECTORY_ENTRY_IMPORT,
&Size);
BoundImportDescriptor = (PIMAGE_BOUND_IMPORT_DESCRIPTOR)
RtlImageDirectoryEntryToData(Module->DllBase,
TRUE,
IMAGE_DIRECTORY_ENTRY_BOUND_IMPORT,
&Size);
if (BoundImportDescriptor != NULL && ImportModuleDirectory == NULL)
{
DPRINT1("%wZ has only a bound import directory\n", &Module->BaseDllName);
return STATUS_UNSUCCESSFUL;
}
if (BoundImportDescriptor)
{
DPRINT("BoundImportDescriptor %p\n", BoundImportDescriptor);
BoundImportDescriptorCurrent = BoundImportDescriptor;
while (BoundImportDescriptorCurrent->OffsetModuleName)
{
ImportedName = (PCHAR)BoundImportDescriptor + BoundImportDescriptorCurrent->OffsetModuleName;
TRACE_LDR("%wZ bound to %s\n", &Module->BaseDllName, ImportedName);
Status = LdrpGetOrLoadModule(SearchPath, ImportedName, &ImportedModule, TRUE);
if (!NT_SUCCESS(Status))
{
DPRINT1("failed to load %s\n", ImportedName);
return Status;
}
if (Module == ImportedModule)
{
LdrpDecrementLoadCount(Module, FALSE);
}
if (ImportedModule->TimeDateStamp != BoundImportDescriptorCurrent->TimeDateStamp)
{
TRACE_LDR("%wZ has stale binding to %wZ\n",
&Module->BaseDllName, &ImportedModule->BaseDllName);
Status = LdrpProcessImportDirectory(Module, ImportedModule, ImportedName);
if (!NT_SUCCESS(Status))
{
DPRINT1("failed to import %s\n", ImportedName);
return Status;
}
}
else
{
BOOLEAN WrongForwarder;
WrongForwarder = FALSE;
if (ImportedModule->Flags & LDRP_IMAGE_NOT_AT_BASE)
{
TRACE_LDR("%wZ has stale binding to %s\n",
&Module->BaseDllName, ImportedName);
}
else
{
TRACE_LDR("%wZ has correct binding to %wZ\n",
&Module->BaseDllName, &ImportedModule->BaseDllName);
}
if (BoundImportDescriptorCurrent->NumberOfModuleForwarderRefs)
{
PIMAGE_BOUND_FORWARDER_REF BoundForwarderRef;
ULONG i;
PLDR_DATA_TABLE_ENTRY ForwarderModule;
PCHAR ForwarderName;
BoundForwarderRef = (PIMAGE_BOUND_FORWARDER_REF)(BoundImportDescriptorCurrent + 1);
for (i = 0; i < BoundImportDescriptorCurrent->NumberOfModuleForwarderRefs; i++, BoundForwarderRef++)
{
ForwarderName = (PCHAR)BoundImportDescriptor + BoundForwarderRef->OffsetModuleName;
TRACE_LDR("%wZ bound to %s via forwardes from %s\n",
&Module->BaseDllName, ForwarderName, ImportedName);
Status = LdrpGetOrLoadModule(SearchPath, ForwarderName, &ForwarderModule, TRUE);
if (!NT_SUCCESS(Status))
{
DPRINT1("failed to load %s\n", ForwarderName);
return Status;
}
if (Module == ImportedModule)
{
LdrpDecrementLoadCount(Module, FALSE);
}
if (ForwarderModule->TimeDateStamp != BoundForwarderRef->TimeDateStamp ||
ForwarderModule->Flags & LDRP_IMAGE_NOT_AT_BASE)
{
TRACE_LDR("%wZ has stale binding to %s\n",
&Module->BaseDllName, ForwarderName);
WrongForwarder = TRUE;
}
else
{
TRACE_LDR("%wZ has correct binding to %s\n",
&Module->BaseDllName, ForwarderName);
}
}
}
if (WrongForwarder ||
ImportedModule->Flags & LDRP_IMAGE_NOT_AT_BASE)
{
Status = LdrpProcessImportDirectory(Module, ImportedModule, ImportedName);
if (!NT_SUCCESS(Status))
{
DPRINT1("failed to import %s\n", ImportedName);
return Status;
}
}
else if (ImportedModule->Flags & LDRP_IMAGE_NOT_AT_BASE)
{
TRACE_LDR("Adjust imports for %s from %wZ\n",
ImportedName, &Module->BaseDllName);
Status = LdrpAdjustImportDirectory(Module, ImportedModule, ImportedName);
if (!NT_SUCCESS(Status))
{
DPRINT1("failed to adjust import entries for %s\n", ImportedName);
return Status;
}
}
else if (WrongForwarder)
{
/*
* FIXME:
* Update only forwarders
*/
TRACE_LDR("Stale BIND %s from %wZ\n",
ImportedName, &Module->BaseDllName);
Status = LdrpProcessImportDirectory(Module, ImportedModule, ImportedName);
if (!NT_SUCCESS(Status))
{
DPRINT1("faild to import %s\n", ImportedName);
return Status;
}
}
else
{
/* nothing to do */
}
}
BoundImportDescriptorCurrent += BoundImportDescriptorCurrent->NumberOfModuleForwarderRefs + 1;
}
}
else if (ImportModuleDirectory)
{
DPRINT("ImportModuleDirectory %p\n", ImportModuleDirectory);
ImportModuleDirectoryCurrent = ImportModuleDirectory;
while (ImportModuleDirectoryCurrent->Name)
{
ImportedName = (PCHAR)Module->DllBase + ImportModuleDirectoryCurrent->Name;
TRACE_LDR("%wZ imports functions from %s\n", &Module->BaseDllName, ImportedName);
Status = LdrpGetOrLoadModule(SearchPath, ImportedName, &ImportedModule, TRUE);
if (!NT_SUCCESS(Status))
{
DPRINT1("failed to load %s\n", ImportedName);
return Status;
}
if (Module == ImportedModule)
{
LdrpDecrementLoadCount(Module, FALSE);
}
TRACE_LDR("Initializing imports for %wZ from %s\n",
&Module->BaseDllName, ImportedName);
Status = LdrpProcessImportDirectoryEntry(Module, ImportedModule, ImportModuleDirectoryCurrent);
if (!NT_SUCCESS(Status))
{
DPRINT1("failed to import %s\n", ImportedName);
return Status;
}
ImportModuleDirectoryCurrent++;
}
}
if (TlsDirectory && TlsSize > 0)
{
LdrpAcquireTlsSlot(Module, TlsSize, FALSE);
}
return STATUS_SUCCESS;
}
/**********************************************************************
* NAME
* LdrPEStartup
*
* DESCRIPTION
* 1. Relocate, if needed the EXE.
* 2. Fixup any imported symbol.
* 3. Compute the EXE's entry point.
*
* ARGUMENTS
* ImageBase
* Address at which the EXE's image
* is loaded.
*
* SectionHandle
* Handle of the section that contains
* the EXE's image.
*
* RETURN VALUE
* NULL on error; otherwise the entry point
* to call for initializing the DLL.
*
* REVISIONS
*
* NOTE
* 04.01.2004 hb Previous this function was used for all images (dll + exe).
* Currently the function is only used for the exe.
*/
PEPFUNC LdrPEStartup (PVOID ImageBase,
HANDLE SectionHandle,
PLDR_DATA_TABLE_ENTRY* Module,
PWSTR FullDosName)
{
NTSTATUS Status;
PEPFUNC EntryPoint = NULL;
PIMAGE_DOS_HEADER DosHeader;
PIMAGE_NT_HEADERS NTHeaders;
PLDR_DATA_TABLE_ENTRY tmpModule;
DPRINT("LdrPEStartup(ImageBase %p SectionHandle %p)\n",
ImageBase, SectionHandle);
/*
* Overlay DOS and WNT headers structures
* to the DLL's image.
*/
DosHeader = (PIMAGE_DOS_HEADER) ImageBase;
NTHeaders = (PIMAGE_NT_HEADERS) ((ULONG_PTR)ImageBase + DosHeader->e_lfanew);
/*
* If the base address is different from the
* one the DLL is actually loaded, perform any
* relocation.
*/
if (ImageBase != (PVOID) NTHeaders->OptionalHeader.ImageBase)
{
DPRINT("LDR: Performing relocations\n");
Status = LdrPerformRelocations(NTHeaders, ImageBase);
if (!NT_SUCCESS(Status))
{
DPRINT1("LdrPerformRelocations() failed\n");
return NULL;
}
}
if (Module != NULL)
{
*Module = LdrAddModuleEntry(ImageBase, NTHeaders, FullDosName);
(*Module)->SectionPointer = SectionHandle;
}
else
{
Module = &tmpModule;
Status = LdrFindEntryForAddress(ImageBase, Module);
if (!NT_SUCCESS(Status))
{
return NULL;
}
}
if (ImageBase != (PVOID) NTHeaders->OptionalHeader.ImageBase)
{
(*Module)->Flags |= LDRP_IMAGE_NOT_AT_BASE;
}
/*
* If the DLL's imports symbols from other
* modules, fixup the imported calls entry points.
*/
DPRINT("About to fixup imports\n");
Status = LdrFixupImports(NULL, *Module);
if (!NT_SUCCESS(Status))
{
DPRINT1("LdrFixupImports() failed for %wZ\n", &(*Module)->BaseDllName);
return NULL;
}
DPRINT("Fixup done\n");
RtlEnterCriticalSection(NtCurrentPeb()->LoaderLock);
Status = LdrpInitializeTlsForProccess();
if (NT_SUCCESS(Status))
{
Status = LdrpAttachProcess();
}
if (NT_SUCCESS(Status))
{
LdrpTlsCallback(*Module, DLL_PROCESS_ATTACH);
}
RtlLeaveCriticalSection(NtCurrentPeb()->LoaderLock);
if (!NT_SUCCESS(Status))
{
return NULL;
}
/*
* Compute the DLL's entry point's address.
*/
DPRINT("ImageBase = %p\n", ImageBase);
DPRINT("AddressOfEntryPoint = 0x%lx\n",(ULONG)NTHeaders->OptionalHeader.AddressOfEntryPoint);
if (NTHeaders->OptionalHeader.AddressOfEntryPoint != 0)
{
EntryPoint = (PEPFUNC) ((ULONG_PTR)ImageBase
+ NTHeaders->OptionalHeader.AddressOfEntryPoint);
}
DPRINT("LdrPEStartup() = %p\n",EntryPoint);
return EntryPoint;
}
static NTSTATUS
LdrpLoadModule(IN PWSTR SearchPath OPTIONAL,
IN ULONG LoadFlags,
IN PUNICODE_STRING Name,
PLDR_DATA_TABLE_ENTRY *Module,
PVOID *BaseAddress OPTIONAL)
{
UNICODE_STRING AdjustedName;
UNICODE_STRING FullDosName;
NTSTATUS Status;
PLDR_DATA_TABLE_ENTRY tmpModule;
HANDLE SectionHandle;
ULONG ViewSize;
PVOID ImageBase;
PIMAGE_NT_HEADERS NtHeaders;
BOOLEAN MappedAsDataFile;
PVOID ArbitraryUserPointer;
if (Module == NULL)
{
Module = &tmpModule;
}
/* adjust the full dll name */
LdrAdjustDllName(&AdjustedName, Name, FALSE);
DPRINT("%wZ\n", &AdjustedName);
MappedAsDataFile = FALSE;
/* Test if dll is already loaded */
Status = LdrFindEntryForName(&AdjustedName, Module, TRUE);
if (NT_SUCCESS(Status))
{
RtlFreeUnicodeString(&AdjustedName);
if (NULL != BaseAddress)
{
*BaseAddress = (*Module)->DllBase;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -