-/* $Id: loader.c,v 1.129 2003/04/03 00:06:24 hyperion Exp $
- *
+/* $Id$
+ *
* COPYRIGHT: See COPYING in the top level directory
* PROJECT: ReactOS kernel
* FILE: ntoskrnl/ldr/loader.c
* PURPOSE: Loaders for PE executables
+ *
* PROGRAMMERS: Jean Michault
* Rex Jolliff (rex@lvcablemodem.com)
* Jason Filby (jasonfilby@yahoo.com)
* Casper S. Hornstrup (chorns@users.sourceforge.net)
- * UPDATE HISTORY:
- * DW 22/05/98 Created
- * RJJ 10/12/98 Completed image loader function and added hooks for MZ/PE
- * RJJ 10/12/98 Built driver loader function and added hooks for PE/COFF
- * RJJ 10/12/98 Rolled in David's code to load COFF drivers
- * JM 14/12/98 Built initial PE user module loader
- * RJJ 06/03/99 Moved user PE loader into NTDLL
- * JF 26/01/2000 Recoded some parts to retrieve export details correctly
- * DW 27/06/2000 Removed redundant header files
- * CSH 11/04/2001 Added automatic loading of module symbols if they exist
- * KJK 02/04/2003 Nebbet-ized a couple of type names
*/
/* INCLUDES *****************************************************************/
-#include <limits.h>
-#include <ddk/ntddk.h>
-#include <roscfg.h>
-#include <internal/module.h>
-#include <internal/ntoskrnl.h>
-#include <internal/kd.h>
-#include <internal/io.h>
-#include <internal/mm.h>
-#include <internal/ps.h>
-#include <internal/ldr.h>
-#include <internal/pool.h>
-#include <internal/kd.h>
-#include <ntos/minmax.h>
+#include <ntoskrnl.h>
#ifdef HALDBG
#include <internal/ntosdbg.h>
#else
+#ifdef __GNUC__
#define ps(args...)
+#else
+#define ps
+#endif /* __GNUC__ */
+#endif
+
+#if 0
+#undef ps
+#define ps(args...) DPRINT1(args)
#endif
#define NDEBUG
#include <internal/debug.h>
+#if defined (ALLOC_PRAGMA)
+#pragma alloc_text(INIT, LdrInit1)
+#pragma alloc_text(INIT, LdrInitModuleManagement)
+#pragma alloc_text(INIT, LdrSafePEProcessModule)
+#endif
+
/* GLOBALS *******************************************************************/
LIST_ENTRY ModuleListHead;
KSPIN_LOCK ModuleListLock;
+LDR_DATA_TABLE_ENTRY NtoskrnlModuleObject;
+LDR_DATA_TABLE_ENTRY HalModuleObject;
-LIST_ENTRY ModuleTextListHead;
-STATIC MODULE_TEXT_SECTION NtoskrnlTextSection;
-STATIC MODULE_TEXT_SECTION LdrHalTextSection;
ULONG_PTR LdrHalBase;
-#define TAG_DRIVER_MEM TAG('D', 'R', 'V', 'M')
-
/* FORWARD DECLARATIONS ******************************************************/
NTSTATUS
-LdrProcessModule(PVOID ModuleLoadBase,
- PUNICODE_STRING ModuleName,
- PMODULE_OBJECT *ModuleObject);
-
-PVOID
-LdrGetExportAddress(PMODULE_OBJECT ModuleObject,
- char *Name,
- unsigned short Hint);
+LdrProcessModule (
+ PVOID ModuleLoadBase,
+ PUNICODE_STRING ModuleName,
+ PLDR_DATA_TABLE_ENTRY *ModuleObject );
static VOID
-LdrpBuildModuleBaseName(PUNICODE_STRING BaseName,
- PUNICODE_STRING FullName);
+LdrpBuildModuleBaseName (
+ PUNICODE_STRING BaseName,
+ PUNICODE_STRING FullName );
static LONG
-LdrpCompareModuleNames(IN PUNICODE_STRING String1,
- IN PUNICODE_STRING String2);
+LdrpCompareModuleNames (
+ IN PUNICODE_STRING String1,
+ IN PUNICODE_STRING String2 );
/* PE Driver load support */
-static NTSTATUS LdrPEProcessModule(PVOID ModuleLoadBase,
- PUNICODE_STRING FileName,
- PMODULE_OBJECT *ModuleObject);
-static PVOID
-LdrPEGetExportAddress(PMODULE_OBJECT ModuleObject,
- PCHAR Name,
- USHORT Hint);
+static NTSTATUS
+LdrPEProcessModule (
+ PVOID ModuleLoadBase,
+ PUNICODE_STRING FileName,
+ PLDR_DATA_TABLE_ENTRY *ModuleObject );
static PVOID
-LdrSafePEGetExportAddress(PVOID ImportModuleBase,
- PCHAR Name,
- USHORT Hint);
+LdrPEGetExportByName (
+ PVOID BaseAddress,
+ PUCHAR SymbolName,
+ WORD Hint );
static PVOID
-LdrPEFixupForward(PCHAR ForwardName);
+LdrPEFixupForward ( PCHAR ForwardName );
+static NTSTATUS
+LdrPEPerformRelocations (
+ PVOID DriverBase,
+ ULONG DriverSize );
+
+static NTSTATUS
+LdrPEFixupImports ( PLDR_DATA_TABLE_ENTRY Module );
/* FUNCTIONS *****************************************************************/
VOID
-LdrInitDebug(PLOADER_MODULE Module, PWCH Name)
+NTAPI
+LdrInitDebug ( PLOADER_MODULE Module, PWCH Name )
{
- PLIST_ENTRY current_entry;
- MODULE_TEXT_SECTION* current;
-
- current_entry = ModuleTextListHead.Flink;
- while (current_entry != &ModuleTextListHead)
- {
- current =
- CONTAINING_RECORD(current_entry, MODULE_TEXT_SECTION, ListEntry);
- if (wcscmp(current->Name, Name) == 0)
- {
- break;
- }
- current_entry = current_entry->Flink;
- }
-
- if (current_entry == &ModuleTextListHead)
- {
- return;
- }
}
VOID
-LdrInit1(VOID)
+INIT_FUNCTION
+NTAPI
+LdrInit1 ( VOID )
{
- PIMAGE_DOS_HEADER DosHeader;
- PIMAGE_FILE_HEADER FileHeader;
- PIMAGE_OPTIONAL_HEADER OptionalHeader;
- PIMAGE_SECTION_HEADER SectionList;
-
- InitializeListHead(&ModuleTextListHead);
-
- /* Setup ntoskrnl.exe text section */
- DosHeader = (PIMAGE_DOS_HEADER) KERNEL_BASE;
- FileHeader =
- (PIMAGE_FILE_HEADER) ((DWORD)KERNEL_BASE +
- DosHeader->e_lfanew + sizeof(ULONG));
- OptionalHeader = (PIMAGE_OPTIONAL_HEADER)
- ((DWORD)FileHeader + sizeof(IMAGE_FILE_HEADER));
- SectionList = (PIMAGE_SECTION_HEADER)
- ((DWORD)OptionalHeader + sizeof(IMAGE_OPTIONAL_HEADER));
- NtoskrnlTextSection.Base = KERNEL_BASE;
- NtoskrnlTextSection.Length = SectionList[0].Misc.VirtualSize +
- SectionList[0].VirtualAddress;
- NtoskrnlTextSection.Name = KERNEL_MODULE_NAME;
- NtoskrnlTextSection.OptionalHeader = OptionalHeader;
- InsertTailList(&ModuleTextListHead, &NtoskrnlTextSection.ListEntry);
-
- /* Setup hal.dll text section */
- DosHeader = (PIMAGE_DOS_HEADER)LdrHalBase;
- FileHeader =
- (PIMAGE_FILE_HEADER) ((DWORD)LdrHalBase +
- DosHeader->e_lfanew + sizeof(ULONG));
- OptionalHeader = (PIMAGE_OPTIONAL_HEADER)
- ((DWORD)FileHeader + sizeof(IMAGE_FILE_HEADER));
- SectionList = (PIMAGE_SECTION_HEADER)
- ((DWORD)OptionalHeader + sizeof(IMAGE_OPTIONAL_HEADER));
- LdrHalTextSection.Base = LdrHalBase;
- LdrHalTextSection.Length = SectionList[0].Misc.VirtualSize +
- SectionList[0].VirtualAddress;
- LdrHalTextSection.Name = HAL_MODULE_NAME;
- LdrHalTextSection.OptionalHeader = OptionalHeader;
- InsertTailList(&ModuleTextListHead, &LdrHalTextSection.ListEntry);
-
- /* Hook for KDB on initialization of the loader. */
- KDB_LOADERINIT_HOOK(&NtoskrnlTextSection, &LdrHalTextSection);
+ /* Hook for KDB on initialization of the loader. */
+ KDB_LOADERINIT_HOOK(&NtoskrnlModuleObject, &HalModuleObject);
}
-
VOID
-LdrInitModuleManagement(VOID)
+INIT_FUNCTION
+NTAPI
+LdrInitModuleManagement ( VOID )
{
- PIMAGE_DOS_HEADER DosHeader;
- PMODULE_OBJECT ModuleObject;
-
- /* Initialize the module list and spinlock */
- InitializeListHead(&ModuleListHead);
- KeInitializeSpinLock(&ModuleListLock);
-
- /* Create module object for NTOSKRNL */
- ModuleObject = ExAllocatePool(NonPagedPool, sizeof(MODULE_OBJECT));
- assert(ModuleObject != NULL);
- RtlZeroMemory(ModuleObject, sizeof(MODULE_OBJECT));
-
- /* Initialize ModuleObject data */
- ModuleObject->Base = (PVOID) KERNEL_BASE;
- ModuleObject->Flags = MODULE_FLAG_PE;
- RtlCreateUnicodeString(&ModuleObject->FullName,
- KERNEL_MODULE_NAME);
- LdrpBuildModuleBaseName(&ModuleObject->BaseName,
- &ModuleObject->FullName);
-
- DosHeader = (PIMAGE_DOS_HEADER) KERNEL_BASE;
- ModuleObject->Image.PE.FileHeader =
- (PIMAGE_FILE_HEADER) ((DWORD) ModuleObject->Base +
- DosHeader->e_lfanew + sizeof(ULONG));
- ModuleObject->Image.PE.OptionalHeader = (PIMAGE_OPTIONAL_HEADER)
- ((DWORD)ModuleObject->Image.PE.FileHeader + sizeof(IMAGE_FILE_HEADER));
- ModuleObject->Image.PE.SectionList = (PIMAGE_SECTION_HEADER)
- ((DWORD)ModuleObject->Image.PE.OptionalHeader + sizeof(IMAGE_OPTIONAL_HEADER));
- ModuleObject->EntryPoint = (PVOID) ((DWORD) ModuleObject->Base +
- ModuleObject->Image.PE.OptionalHeader->AddressOfEntryPoint);
- DPRINT("ModuleObject:%08x entrypoint at %x\n", ModuleObject, ModuleObject->EntryPoint);
- ModuleObject->Length = ModuleObject->Image.PE.OptionalHeader->SizeOfImage;
- ModuleObject->TextSection = &NtoskrnlTextSection;
-
- InsertTailList(&ModuleListHead,
- &ModuleObject->ListEntry);
-
- /* Create module object for HAL */
- ModuleObject = ExAllocatePool(NonPagedPool, sizeof(MODULE_OBJECT));
- assert(ModuleObject != NULL);
- RtlZeroMemory(ModuleObject, sizeof(MODULE_OBJECT));
-
- /* Initialize ModuleObject data */
- ModuleObject->Base = (PVOID) LdrHalBase;
- ModuleObject->Flags = MODULE_FLAG_PE;
-
- RtlCreateUnicodeString(&ModuleObject->FullName,
- HAL_MODULE_NAME);
- LdrpBuildModuleBaseName(&ModuleObject->BaseName,
- &ModuleObject->FullName);
-
- DosHeader = (PIMAGE_DOS_HEADER) LdrHalBase;
- ModuleObject->Image.PE.FileHeader =
- (PIMAGE_FILE_HEADER) ((DWORD) ModuleObject->Base +
- DosHeader->e_lfanew + sizeof(ULONG));
- ModuleObject->Image.PE.OptionalHeader = (PIMAGE_OPTIONAL_HEADER)
- ((DWORD)ModuleObject->Image.PE.FileHeader + sizeof(IMAGE_FILE_HEADER));
- ModuleObject->Image.PE.SectionList = (PIMAGE_SECTION_HEADER)
- ((DWORD)ModuleObject->Image.PE.OptionalHeader + sizeof(IMAGE_OPTIONAL_HEADER));
- ModuleObject->EntryPoint = (PVOID) ((DWORD) ModuleObject->Base +
- ModuleObject->Image.PE.OptionalHeader->AddressOfEntryPoint);
- DPRINT("ModuleObject:%08x entrypoint at %x\n", ModuleObject, ModuleObject->EntryPoint);
- ModuleObject->Length = ModuleObject->Image.PE.OptionalHeader->SizeOfImage;
- ModuleObject->TextSection = &LdrHalTextSection;
-
- InsertTailList(&ModuleListHead,
- &ModuleObject->ListEntry);
+ PIMAGE_NT_HEADERS NtHeader;
+
+ /* Initialize the module list and spinlock */
+ InitializeListHead(&ModuleListHead);
+ KeInitializeSpinLock(&ModuleListLock);
+
+ /* Initialize ModuleObject for NTOSKRNL */
+ RtlZeroMemory(&NtoskrnlModuleObject, sizeof(LDR_DATA_TABLE_ENTRY));
+ NtoskrnlModuleObject.DllBase = (PVOID) KERNEL_BASE;
+ RtlInitUnicodeString(&NtoskrnlModuleObject.FullDllName, KERNEL_MODULE_NAME);
+ LdrpBuildModuleBaseName(&NtoskrnlModuleObject.BaseDllName, &NtoskrnlModuleObject.FullDllName);
+
+ NtHeader = RtlImageNtHeader((PVOID)KERNEL_BASE);
+ NtoskrnlModuleObject.EntryPoint = (PVOID) ((ULONG_PTR) NtoskrnlModuleObject.DllBase + NtHeader->OptionalHeader.AddressOfEntryPoint);
+ DPRINT("ModuleObject:%08x entrypoint at %x\n", &NtoskrnlModuleObject, NtoskrnlModuleObject.EntryPoint);
+ NtoskrnlModuleObject.SizeOfImage = NtHeader->OptionalHeader.SizeOfImage;
+
+ InsertTailList(&ModuleListHead, &NtoskrnlModuleObject.InLoadOrderLinks);
+
+ /* Initialize ModuleObject for HAL */
+ RtlZeroMemory(&HalModuleObject, sizeof(LDR_DATA_TABLE_ENTRY));
+ HalModuleObject.DllBase = (PVOID) LdrHalBase;
+
+ RtlInitUnicodeString(&HalModuleObject.FullDllName, HAL_MODULE_NAME);
+ LdrpBuildModuleBaseName(&HalModuleObject.BaseDllName, &HalModuleObject.FullDllName);
+
+ NtHeader = RtlImageNtHeader((PVOID)LdrHalBase);
+ HalModuleObject.EntryPoint = (PVOID) ((ULONG_PTR) HalModuleObject.DllBase + NtHeader->OptionalHeader.AddressOfEntryPoint);
+ DPRINT("ModuleObject:%08x entrypoint at %x\n", &HalModuleObject, HalModuleObject.EntryPoint);
+ HalModuleObject.SizeOfImage = NtHeader->OptionalHeader.SizeOfImage;
+
+ InsertTailList(&ModuleListHead, &HalModuleObject.InLoadOrderLinks);
}
NTSTATUS
-LdrpLoadImage(PUNICODE_STRING DriverName,
- PVOID *ModuleBase,
- PVOID *SectionPointer,
- PVOID *EntryPoint,
- PVOID *ExportSectionPointer)
+NTAPI
+LdrpLoadImage (
+ PUNICODE_STRING DriverName,
+ PVOID *ModuleBase,
+ PVOID *SectionPointer,
+ PVOID *EntryPoint,
+ PVOID *ExportSectionPointer )
{
- PMODULE_OBJECT ModuleObject;
- NTSTATUS Status;
+ PLDR_DATA_TABLE_ENTRY ModuleObject;
+ NTSTATUS Status;
- ModuleObject = LdrGetModuleObject(DriverName);
- if (ModuleObject == NULL)
+ ModuleObject = LdrGetModuleObject(DriverName);
+ if (ModuleObject == NULL)
{
- Status = LdrLoadModule(DriverName, &ModuleObject);
- if (!NT_SUCCESS(Status))
- {
- return(Status);
- }
+ Status = LdrLoadModule(DriverName, &ModuleObject);
+ if (!NT_SUCCESS(Status))
+ {
+ return(Status);
+ }
}
- if (ModuleBase)
- *ModuleBase = ModuleObject->Base;
+ if (ModuleBase)
+ *ModuleBase = ModuleObject->DllBase;
-// if (SectionPointer)
-// *SectionPointer = ModuleObject->
+ if (SectionPointer)
+ *SectionPointer = ModuleObject;
- if (EntryPoint)
- *EntryPoint = ModuleObject->EntryPoint;
+ if (EntryPoint)
+ *EntryPoint = ModuleObject->EntryPoint;
-// if (ExportSectionPointer)
-// *ExportSectionPointer = ModuleObject->
+ //if (ExportSectionPointer)
+ // *ExportSectionPointer = ModuleObject->
- return(STATUS_SUCCESS);
+ return(STATUS_SUCCESS);
}
NTSTATUS
-LdrpUnloadImage(PVOID ModuleBase)
+NTAPI
+LdrpUnloadImage ( PVOID ModuleBase )
{
- return(STATUS_NOT_IMPLEMENTED);
+ return(STATUS_NOT_IMPLEMENTED);
}
NTSTATUS
-LdrpLoadAndCallImage(PUNICODE_STRING ModuleName)
+NTAPI
+LdrpLoadAndCallImage ( PUNICODE_STRING ModuleName )
{
- PDRIVER_INITIALIZE DriverEntry;
- PMODULE_OBJECT ModuleObject;
- NTSTATUS Status;
+ PDRIVER_INITIALIZE DriverEntry;
+ PLDR_DATA_TABLE_ENTRY ModuleObject;
+ DRIVER_OBJECT DriverObject;
+ NTSTATUS Status;
- ModuleObject = LdrGetModuleObject(ModuleName);
- if (ModuleObject != NULL)
+ ModuleObject = LdrGetModuleObject(ModuleName);
+ if (ModuleObject != NULL)
{
- return(STATUS_IMAGE_ALREADY_LOADED);
+ return(STATUS_IMAGE_ALREADY_LOADED);
}
- Status = LdrLoadModule(ModuleName, &ModuleObject);
- if (!NT_SUCCESS(Status))
+ Status = LdrLoadModule(ModuleName, &ModuleObject);
+ if (!NT_SUCCESS(Status))
{
- return(Status);
+ return(Status);
}
- DriverEntry = (PDRIVER_INITIALIZE)ModuleObject->EntryPoint;
+ DriverEntry = (PDRIVER_INITIALIZE)ModuleObject->EntryPoint;
+
+ RtlZeroMemory(&DriverObject, sizeof(DriverObject));
+// DriverObject.DriverStart = ModuleObject->DllBase;
- Status = DriverEntry(NULL, NULL);
- if (!NT_SUCCESS(Status))
+ Status = DriverEntry(&DriverObject, NULL);
+ if (!NT_SUCCESS(Status))
{
- LdrUnloadModule(ModuleObject);
+ LdrUnloadModule(ModuleObject);
}
- return(Status);
+ return(Status);
}
NTSTATUS
-LdrLoadModule(PUNICODE_STRING Filename,
- PMODULE_OBJECT *ModuleObject)
+NTAPI
+LdrLoadModule(
+ PUNICODE_STRING Filename,
+ PLDR_DATA_TABLE_ENTRY *ModuleObject )
{
- PVOID ModuleLoadBase;
- NTSTATUS Status;
- HANDLE FileHandle;
- OBJECT_ATTRIBUTES ObjectAttributes;
- PMODULE_OBJECT Module;
- FILE_STANDARD_INFORMATION FileStdInfo;
- IO_STATUS_BLOCK IoStatusBlock;
-
- *ModuleObject = NULL;
-
- DPRINT("Loading Module %wZ...\n", Filename);
-
- /* Open the Module */
- InitializeObjectAttributes(&ObjectAttributes,
- Filename,
- 0,
- NULL,
- NULL);
- CHECKPOINT;
- Status = NtOpenFile(&FileHandle,
- FILE_ALL_ACCESS,
- &ObjectAttributes,
- &IoStatusBlock,
- 0,
- FILE_SYNCHRONOUS_IO_NONALERT);
- CHECKPOINT;
- if (!NT_SUCCESS(Status))
+ PVOID ModuleLoadBase;
+ NTSTATUS Status;
+ HANDLE FileHandle;
+ OBJECT_ATTRIBUTES ObjectAttributes;
+ PLDR_DATA_TABLE_ENTRY Module;
+ FILE_STANDARD_INFORMATION FileStdInfo;
+ IO_STATUS_BLOCK IoStatusBlock;
+
+ *ModuleObject = NULL;
+
+ DPRINT("Loading Module %wZ...\n", Filename);
+
+ /* Open the Module */
+ InitializeObjectAttributes(&ObjectAttributes,
+ Filename,
+ OBJ_CASE_INSENSITIVE,
+ NULL,
+ NULL);
+ CHECKPOINT;
+ Status = ZwOpenFile(&FileHandle,
+ GENERIC_READ,
+ &ObjectAttributes,
+ &IoStatusBlock,
+ FILE_SHARE_READ,
+ FILE_SYNCHRONOUS_IO_NONALERT);
+ CHECKPOINT;
+ if (!NT_SUCCESS(Status))
{
- CPRINT("Could not open module file: %wZ\n", Filename);
- return(Status);
+ CPRINT("Could not open module file: %wZ (Status 0x%08lx)\n", Filename, Status);
+ return(Status);
}
- CHECKPOINT;
-
- /* Get the size of the file */
- Status = NtQueryInformationFile(FileHandle,
- &IoStatusBlock,
- &FileStdInfo,
- sizeof(FileStdInfo),
- FileStandardInformation);
- if (!NT_SUCCESS(Status))
+ CHECKPOINT;
+
+ /* Get the size of the file */
+ Status = ZwQueryInformationFile(FileHandle,
+ &IoStatusBlock,
+ &FileStdInfo,
+ sizeof(FileStdInfo),
+ FileStandardInformation);
+ if (!NT_SUCCESS(Status))
{
- CPRINT("Could not get file size\n");
- NtClose(FileHandle);
- return(Status);
+ CPRINT("Could not get file size\n");
+ NtClose(FileHandle);
+ return(Status);
}
- CHECKPOINT;
+ CHECKPOINT;
- /* Allocate nonpageable memory for driver */
- ModuleLoadBase = ExAllocatePoolWithTag(NonPagedPool,
- FileStdInfo.EndOfFile.u.LowPart,
- TAG_DRIVER_MEM);
- if (ModuleLoadBase == NULL)
+ /* Allocate nonpageable memory for driver */
+ ModuleLoadBase = ExAllocatePoolWithTag(NonPagedPool,
+ FileStdInfo.EndOfFile.u.LowPart,
+ TAG_DRIVER_MEM);
+ if (ModuleLoadBase == NULL)
{
- CPRINT("Could not allocate memory for module");
- NtClose(FileHandle);
- return(STATUS_INSUFFICIENT_RESOURCES);
+ CPRINT("Could not allocate memory for module");
+ NtClose(FileHandle);
+ return(STATUS_INSUFFICIENT_RESOURCES);
}
- CHECKPOINT;
-
- /* Load driver into memory chunk */
- Status = NtReadFile(FileHandle,
- 0, 0, 0,
- &IoStatusBlock,
- ModuleLoadBase,
- FileStdInfo.EndOfFile.u.LowPart,
- 0, 0);
- if (!NT_SUCCESS(Status))
+ CHECKPOINT;
+
+ /* Load driver into memory chunk */
+ Status = ZwReadFile(FileHandle,
+ 0, 0, 0,
+ &IoStatusBlock,
+ ModuleLoadBase,
+ FileStdInfo.EndOfFile.u.LowPart,
+ 0, 0);
+ if (!NT_SUCCESS(Status))
{
- CPRINT("Could not read module file into memory");
- ExFreePool(ModuleLoadBase);
- NtClose(FileHandle);
- return(Status);
+ CPRINT("Could not read module file into memory");
+ ExFreePool(ModuleLoadBase);
+ NtClose(FileHandle);
+ return(Status);
}
- CHECKPOINT;
+ CHECKPOINT;
- NtClose(FileHandle);
+ ZwClose(FileHandle);
- Status = LdrProcessModule(ModuleLoadBase,
- Filename,
- &Module);
- if (!NT_SUCCESS(Status))
+ Status = LdrProcessModule(ModuleLoadBase,
+ Filename,
+ &Module);
+ if (!NT_SUCCESS(Status))
{
- CPRINT("Could not process module");
- ExFreePool(ModuleLoadBase);
- return(Status);
+ CPRINT("Could not process module\n");
+ ExFreePool(ModuleLoadBase);
+ return(Status);
}
- /* Cleanup */
- ExFreePool(ModuleLoadBase);
+ /* Cleanup */
+ ExFreePool(ModuleLoadBase);
- *ModuleObject = Module;
+ *ModuleObject = Module;
- /* Hook for KDB on loading a driver. */
- KDB_LOADDRIVER_HOOK(Filename, Module);
+ /* Hook for KDB on loading a driver. */
+ KDB_LOADDRIVER_HOOK(Filename, Module);
- return(STATUS_SUCCESS);
+ return(STATUS_SUCCESS);
}
NTSTATUS
-LdrUnloadModule(PMODULE_OBJECT ModuleObject)
+NTAPI
+LdrUnloadModule ( PLDR_DATA_TABLE_ENTRY ModuleObject )
{
- KIRQL Irql;
-
- /* Remove the module from the module list */
- KeAcquireSpinLock(&ModuleListLock,&Irql);
- RemoveEntryList(&ModuleObject->ListEntry);
- KeReleaseSpinLock(&ModuleListLock, Irql);
+ KIRQL Irql;
- /* Hook for KDB on unloading a driver. */
- KDB_UNLOADDRIVER_HOOK(ModuleObject);
+ /* Remove the module from the module list */
+ KeAcquireSpinLock(&ModuleListLock,&Irql);
+ RemoveEntryList(&ModuleObject->InLoadOrderLinks);
+ KeReleaseSpinLock(&ModuleListLock, Irql);
- /* Free text section */
- if (ModuleObject->TextSection != NULL)
- {
- ExFreePool(ModuleObject->TextSection->Name);
- RemoveEntryList(&ModuleObject->TextSection->ListEntry);
- ExFreePool(ModuleObject->TextSection);
- ModuleObject->TextSection = NULL;
- }
+ /* Hook for KDB on unloading a driver. */
+ KDB_UNLOADDRIVER_HOOK(ModuleObject);
- /* Free module section */
-// MmFreeSection(ModuleObject->Base);
+ /* Free module section */
+ // MmFreeSection(ModuleObject->DllBase);
- ExFreePool(ModuleObject);
+ ExFreePool(ModuleObject->FullDllName.Buffer);
+ ExFreePool(ModuleObject);
- return(STATUS_SUCCESS);
+ return(STATUS_SUCCESS);
}
NTSTATUS
-LdrInitializeBootStartDriver(PVOID ModuleLoadBase,
- PCHAR FileName,
- ULONG ModuleLength)
+LdrProcessModule(
+ PVOID ModuleLoadBase,
+ PUNICODE_STRING ModuleName,
+ PLDR_DATA_TABLE_ENTRY *ModuleObject )
{
- PMODULE_OBJECT ModuleObject;
- UNICODE_STRING ModuleName;
- PDEVICE_NODE DeviceNode;
- NTSTATUS Status;
-
- WCHAR Buffer[MAX_PATH];
- ULONG Length;
- LPWSTR Start;
- LPWSTR Ext;
- PCHAR FileExt;
- CHAR TextBuffer [256];
- ULONG x, y, cx, cy;
-
- HalQueryDisplayParameters(&x, &y, &cx, &cy);
- RtlFillMemory(TextBuffer, x, ' ');
- TextBuffer[x] = '\0';
- HalSetDisplayParameters(0, y-1);
- HalDisplayString(TextBuffer);
-
- sprintf(TextBuffer, "Initializing %s...\n", FileName);
- HalSetDisplayParameters(0, y-1);
- HalDisplayString(TextBuffer);
- HalSetDisplayParameters(cx, cy);
-
- /* Split the filename into base name and extension */
- FileExt = strrchr(FileName, '.');
- if (FileExt != NULL)
- Length = FileExt - FileName;
- else
- Length = strlen(FileName);
-
- if ((FileExt != NULL) && (strcmp(FileExt, ".sym") == 0))
- {
- KDB_SYMBOLFILE_HOOK(ModuleLoadBase, FileName, Length);
- return(STATUS_SUCCESS);
- }
- else if ((FileExt != NULL) && !(strcmp(FileExt, ".sys") == 0))
- {
- CPRINT("Ignoring non-driver file %s\n", FileName);
- return STATUS_SUCCESS;
- }
-
- /* Use IopRootDeviceNode for now */
- Status = IopCreateDeviceNode(IopRootDeviceNode, NULL, &DeviceNode);
- if (!NT_SUCCESS(Status))
- {
- CPRINT("Driver load failed, status (%x)\n", Status);
- return(Status);
- }
-
- RtlCreateUnicodeStringFromAsciiz(&ModuleName,
- FileName);
- Status = LdrProcessModule(ModuleLoadBase,
- &ModuleName,
- &ModuleObject);
- RtlFreeUnicodeString(&ModuleName);
- if (ModuleObject == NULL)
- {
- IopFreeDeviceNode(DeviceNode);
- CPRINT("Driver load failed, status (%x)\n", Status);
- return(STATUS_UNSUCCESSFUL);
- }
+ PIMAGE_DOS_HEADER PEDosHeader;
-
- /* Get the service name from the module name */
- Start = wcsrchr(ModuleObject->BaseName.Buffer, L'\\');
- if (Start == NULL)
- Start = ModuleObject->BaseName.Buffer;
- else
- Start++;
-
- Ext = wcsrchr(ModuleObject->BaseName.Buffer, L'.');
- if (Ext != NULL)
- Length = Ext - Start;
- else
- Length = wcslen(Start);
-
- wcsncpy(Buffer, Start, Length);
- Buffer[Length] = 0;
- RtlCreateUnicodeString(&DeviceNode->ServiceName, Buffer);
-
- Status = IopInitializeDriver(ModuleObject->EntryPoint,
- DeviceNode, FALSE);
- if (!NT_SUCCESS(Status))
+ /* If MZ header exists */
+ PEDosHeader = (PIMAGE_DOS_HEADER) ModuleLoadBase;
+ if (PEDosHeader->e_magic == IMAGE_DOS_SIGNATURE && PEDosHeader->e_lfanew != 0L)
{
- IopFreeDeviceNode(DeviceNode);
- CPRINT("Driver load failed, status (%x)\n", Status);
+ return LdrPEProcessModule(ModuleLoadBase,
+ ModuleName,
+ ModuleObject);
}
- return(Status);
+ CPRINT("Module wasn't PE\n");
+ return STATUS_UNSUCCESSFUL;
}
-
NTSTATUS
-LdrProcessModule(PVOID ModuleLoadBase,
- PUNICODE_STRING ModuleName,
- PMODULE_OBJECT *ModuleObject)
+NTAPI
+LdrpQueryModuleInformation (
+ PVOID Buffer,
+ ULONG Size,
+ PULONG ReqSize )
{
- PIMAGE_DOS_HEADER PEDosHeader;
-
- /* If MZ header exists */
- PEDosHeader = (PIMAGE_DOS_HEADER) ModuleLoadBase;
- if (PEDosHeader->e_magic == IMAGE_DOS_MAGIC && PEDosHeader->e_lfanew != 0L)
+ PLIST_ENTRY current_entry;
+ PLDR_DATA_TABLE_ENTRY current;
+ ULONG ModuleCount = 0;
+ PRTL_PROCESS_MODULES Smi;
+ ANSI_STRING AnsiName;
+ PCHAR p;
+ KIRQL Irql;
+ PUNICODE_STRING UnicodeName;
+ ULONG tmpBufferSize = 0;
+ PWCHAR tmpNameBuffer;
+
+ KeAcquireSpinLock(&ModuleListLock,&Irql);
+
+ /* calculate required size */
+ current_entry = ModuleListHead.Flink;
+ while (current_entry != (&ModuleListHead))
{
- return LdrPEProcessModule(ModuleLoadBase,
- ModuleName,
- ModuleObject);
+ ModuleCount++;
+ current = CONTAINING_RECORD(current_entry,LDR_DATA_TABLE_ENTRY,InLoadOrderLinks);
+ tmpBufferSize += current->FullDllName.Length + sizeof(WCHAR) + sizeof(UNICODE_STRING);
+ current_entry = current_entry->Flink;
}
- CPRINT("Module wasn't PE\n");
- return STATUS_UNSUCCESSFUL;
-}
-
+ *ReqSize = sizeof(RTL_PROCESS_MODULES)+
+ (ModuleCount - 1) * sizeof(RTL_PROCESS_MODULE_INFORMATION);
-PVOID
-LdrGetExportAddress(PMODULE_OBJECT ModuleObject,
- char *Name,
- unsigned short Hint)
-{
- if (ModuleObject->Flags & MODULE_FLAG_PE)
+ if (Size < *ReqSize)
{
- return LdrPEGetExportAddress(ModuleObject, Name, Hint);
+ KeReleaseSpinLock(&ModuleListLock, Irql);
+ return(STATUS_INFO_LENGTH_MISMATCH);
}
- else
- {
- return 0;
- }
-}
-
-NTSTATUS
-LdrpQueryModuleInformation(PVOID Buffer,
- ULONG Size,
- PULONG ReqSize)
-{
- PLIST_ENTRY current_entry;
- PMODULE_OBJECT current;
- ULONG ModuleCount = 0;
- PSYSTEM_MODULES Smi;
- ANSI_STRING AnsiName;
- PCHAR p;
- KIRQL Irql;
-
- KeAcquireSpinLock(&ModuleListLock,&Irql);
-
- /* calculate required size */
- current_entry = ModuleListHead.Flink;
- while (current_entry != (&ModuleListHead))
+ /* allocate a temp buffer to store the module names */
+ UnicodeName = ExAllocatePool(NonPagedPool, tmpBufferSize);
+ if (UnicodeName == NULL)
{
- ModuleCount++;
- current_entry = current_entry->Flink;
+ KeReleaseSpinLock(&ModuleListLock, Irql);
+ return STATUS_INSUFFICIENT_RESOURCES;
}
+ tmpNameBuffer = (PWCHAR)((ULONG_PTR)UnicodeName + ModuleCount * sizeof(UNICODE_STRING));
+
+ /* fill the buffer */
+ memset(Buffer, '=', Size);
- *ReqSize = sizeof(SYSTEM_MODULES)+
- (ModuleCount - 1) * sizeof(SYSTEM_MODULE_INFORMATION);
+ Smi = (PRTL_PROCESS_MODULES)Buffer;
+ Smi->NumberOfModules = ModuleCount;
- if (Size < *ReqSize)
+ ModuleCount = 0;
+ current_entry = ModuleListHead.Flink;
+ while (current_entry != (&ModuleListHead))
{
- KeReleaseSpinLock(&ModuleListLock, Irql);
- return(STATUS_INFO_LENGTH_MISMATCH);
+ current = CONTAINING_RECORD(current_entry,LDR_DATA_TABLE_ENTRY,InLoadOrderLinks);
+
+ Smi->Modules[ModuleCount].Section = 0; /* Always 0 */
+ Smi->Modules[ModuleCount].MappedBase = 0; /* Always 0 */
+ Smi->Modules[ModuleCount].ImageBase = current->DllBase;
+ Smi->Modules[ModuleCount].ImageSize = current->SizeOfImage;
+ Smi->Modules[ModuleCount].Flags = 0; /* Flags ??? (GN) */
+ Smi->Modules[ModuleCount].LoadOrderIndex = (USHORT)ModuleCount;
+ Smi->Modules[ModuleCount].InitOrderIndex = 0;
+ Smi->Modules[ModuleCount].LoadCount = 0; /* FIXME */
+ UnicodeName[ModuleCount].Buffer = tmpNameBuffer;
+ UnicodeName[ModuleCount].MaximumLength = current->FullDllName.Length + sizeof(WCHAR);
+ tmpNameBuffer += UnicodeName[ModuleCount].MaximumLength / sizeof(WCHAR);
+ RtlCopyUnicodeString(&UnicodeName[ModuleCount], ¤t->FullDllName);
+
+ ModuleCount++;
+ current_entry = current_entry->Flink;
}
- /* fill the buffer */
- memset(Buffer, '=', Size);
-
- Smi = (PSYSTEM_MODULES)Buffer;
- Smi->Count = ModuleCount;
+ KeReleaseSpinLock(&ModuleListLock, Irql);
- ModuleCount = 0;
- current_entry = ModuleListHead.Flink;
- while (current_entry != (&ModuleListHead))
+ for (ModuleCount = 0; ModuleCount < Smi->NumberOfModules; ModuleCount++)
{
- current = CONTAINING_RECORD(current_entry,MODULE_OBJECT,ListEntry);
-
- Smi->Modules[ModuleCount].Reserved[0] = 0; /* Always 0 */
- Smi->Modules[ModuleCount].Reserved[1] = 0; /* Always 0 */
- Smi->Modules[ModuleCount].Base = current->Base;
- Smi->Modules[ModuleCount].Size = current->Length;
- Smi->Modules[ModuleCount].Flags = 0; /* Flags ??? (GN) */
- Smi->Modules[ModuleCount].Index = ModuleCount;
- Smi->Modules[ModuleCount].Unknown = 0;
- Smi->Modules[ModuleCount].LoadCount = 0; /* FIXME */
-
- AnsiName.Length = 0;
- AnsiName.MaximumLength = 256;
- AnsiName.Buffer = Smi->Modules[ModuleCount].ImageName;
- RtlUnicodeStringToAnsiString(&AnsiName,
- ¤t->FullName,
- FALSE);
-
- p = strrchr(AnsiName.Buffer, '\\');
- if (p == NULL)
- {
- Smi->Modules[ModuleCount].ModuleNameOffset = 0;
- }
- else
- {
- p++;
- Smi->Modules[ModuleCount].ModuleNameOffset = p - AnsiName.Buffer;
- }
-
- ModuleCount++;
- current_entry = current_entry->Flink;
+ AnsiName.Length = 0;
+ AnsiName.MaximumLength = 255;
+ AnsiName.Buffer = Smi->Modules[ModuleCount].FullPathName;
+ RtlUnicodeStringToAnsiString(&AnsiName, &UnicodeName[ModuleCount], FALSE);
+ AnsiName.Buffer[AnsiName.Length] = 0;
+ Smi->Modules[ModuleCount].InitOrderIndex = AnsiName.Length;
+
+ p = strrchr(AnsiName.Buffer, '\\');
+ if (p == NULL)
+ {
+ Smi->Modules[ModuleCount].OffsetToFileName = 0;
+ }
+ else
+ {
+ p++;
+ Smi->Modules[ModuleCount].OffsetToFileName = p - AnsiName.Buffer;
+ }
}
- KeReleaseSpinLock(&ModuleListLock, Irql);
+ ExFreePool(UnicodeName);
- return(STATUS_SUCCESS);
+ return(STATUS_SUCCESS);
}
static VOID
-LdrpBuildModuleBaseName(PUNICODE_STRING BaseName,
- PUNICODE_STRING FullName)
+LdrpBuildModuleBaseName (
+ PUNICODE_STRING BaseName,
+ PUNICODE_STRING FullName )
{
- UNICODE_STRING Name;
- PWCHAR p;
- PWCHAR q;
-
- DPRINT("LdrpBuildModuleBaseName()\n");
- DPRINT("FullName %wZ\n", FullName);
-
- p = wcsrchr(FullName->Buffer, L'\\');
- if (p == NULL)
- {
- p = FullName->Buffer;
- }
- else
- {
- p++;
- }
-
- DPRINT("p %S\n", p);
+ PWCHAR p;
- RtlCreateUnicodeString(&Name, p);
+ DPRINT("LdrpBuildModuleBaseName()\n");
+ DPRINT("FullName %wZ\n", FullName);
- q = wcschr(Name.Buffer, L'.');
- if (q != NULL)
- {
- *q = (WCHAR)0;
- }
+ p = wcsrchr(FullName->Buffer, L'\\');
+ if (p == NULL)
+ {
+ p = FullName->Buffer;
+ }
+ else
+ {
+ p++;
+ }
- DPRINT("p %S\n", p);
+ DPRINT("p %S\n", p);
- RtlCreateUnicodeString(BaseName, Name.Buffer);
- RtlFreeUnicodeString(&Name);
+ RtlInitUnicodeString(BaseName, p);
}
static LONG
-LdrpCompareModuleNames(IN PUNICODE_STRING String1,
- IN PUNICODE_STRING String2)
+LdrpCompareModuleNames (
+ IN PUNICODE_STRING String1,
+ IN PUNICODE_STRING String2 )
{
- ULONG len1, len2, i;
- PWCHAR s1, s2, p;
- WCHAR c1, c2;
+ ULONG len1, len2, i;
+ PWCHAR s1, s2, p;
+ WCHAR c1, c2;
- if (String1 && String2)
+ if (String1 && String2)
{
- /* Search String1 for last path component */
- len1 = String1->Length / sizeof(WCHAR);
- s1 = String1->Buffer;
- for (i = 0, p = String1->Buffer; i < String1->Length; i = i + sizeof(WCHAR), p++)
- {
- if (*p == L'\\')
- {
- if (i == String1->Length - sizeof(WCHAR))
- {
- s1 = NULL;
- len1 = 0;
- }
- else
- {
- s1 = p + 1;
- len1 = (String1->Length - i) / sizeof(WCHAR);
- }
- }
- }
-
- /* Search String2 for last path component */
- len2 = String2->Length / sizeof(WCHAR);
- s2 = String2->Buffer;
- for (i = 0, p = String2->Buffer; i < String2->Length; i = i + sizeof(WCHAR), p++)
- {
- if (*p == L'\\')
- {
- if (i == String2->Length - sizeof(WCHAR))
- {
- s2 = NULL;
- len2 = 0;
- }
- else
- {
- s2 = p + 1;
- len2 = (String2->Length - i) / sizeof(WCHAR);
- }
- }
- }
-
- /* Compare last path components */
- if (s1 && s2)
- {
- while (1)
- {
- c1 = len1-- ? RtlUpcaseUnicodeChar (*s1++) : 0;
- c2 = len2-- ? RtlUpcaseUnicodeChar (*s2++) : 0;
- if ((c1 == 0 && c2 == L'.') || (c1 == L'.' && c2 == 0))
- return(0);
- if (!c1 || !c2 || c1 != c2)
- return(c1 - c2);
- }
- }
+ /* Search String1 for last path component */
+ len1 = String1->Length / sizeof(WCHAR);
+ s1 = String1->Buffer;
+ for (i = 0, p = String1->Buffer; i < String1->Length; i = i + sizeof(WCHAR), p++)
+ {
+ if (*p == L'\\')
+ {
+ if (i == String1->Length - sizeof(WCHAR))
+ {
+ s1 = NULL;
+ len1 = 0;
+ }
+ else
+ {
+ s1 = p + 1;
+ len1 = (String1->Length - i) / sizeof(WCHAR);
+ }
+ }
+ }
+
+ /* Search String2 for last path component */
+ len2 = String2->Length / sizeof(WCHAR);
+ s2 = String2->Buffer;
+ for (i = 0, p = String2->Buffer; i < String2->Length; i = i + sizeof(WCHAR), p++)
+ {
+ if (*p == L'\\')
+ {
+ if (i == String2->Length - sizeof(WCHAR))
+ {
+ s2 = NULL;
+ len2 = 0;
+ }
+ else
+ {
+ s2 = p + 1;
+ len2 = (String2->Length - i) / sizeof(WCHAR);
+ }
+ }
+ }
+
+ /* Compare last path components */
+ if (s1 && s2)
+ {
+ while (1)
+ {
+ c1 = len1-- ? RtlUpcaseUnicodeChar (*s1++) : 0;
+ c2 = len2-- ? RtlUpcaseUnicodeChar (*s2++) : 0;
+ if ((c1 == 0 && c2 == L'.') || (c1 == L'.' && c2 == 0))
+ return(0);
+ if (!c1 || !c2 || c1 != c2)
+ return(c1 - c2);
+ }
+ }
}
- return(0);
+ return(0);
}
-
-PMODULE_OBJECT
-LdrGetModuleObject(PUNICODE_STRING ModuleName)
+PLDR_DATA_TABLE_ENTRY
+NTAPI
+LdrGetModuleObject ( PUNICODE_STRING ModuleName )
{
- PMODULE_OBJECT Module;
- PLIST_ENTRY Entry;
- KIRQL Irql;
+ PLDR_DATA_TABLE_ENTRY Module;
+ PLIST_ENTRY Entry;
+ KIRQL Irql;
- DPRINT("LdrpGetModuleObject(%wZ) called\n", ModuleName);
+ DPRINT("LdrGetModuleObject(%wZ) called\n", ModuleName);
- KeAcquireSpinLock(&ModuleListLock,&Irql);
+ KeAcquireSpinLock(&ModuleListLock,&Irql);
- Entry = ModuleListHead.Flink;
- while (Entry != &ModuleListHead)
+ Entry = ModuleListHead.Flink;
+ while (Entry != &ModuleListHead)
{
- Module = CONTAINING_RECORD(Entry, MODULE_OBJECT, ListEntry);
+ Module = CONTAINING_RECORD(Entry, LDR_DATA_TABLE_ENTRY, InLoadOrderLinks);
- DPRINT("Comparing %wZ and %wZ\n",
- &Module->BaseName,
- ModuleName);
+ DPRINT("Comparing %wZ and %wZ\n",
+ &Module->BaseDllName,
+ ModuleName);
- if (!LdrpCompareModuleNames(&Module->BaseName, ModuleName))
- {
- DPRINT("Module %wZ\n", &Module->BaseName);
- KeReleaseSpinLock(&ModuleListLock, Irql);
- return(Module);
- }
+ if (!LdrpCompareModuleNames(&Module->BaseDllName, ModuleName))
+ {
+ DPRINT("Module %wZ\n", &Module->BaseDllName);
+ KeReleaseSpinLock(&ModuleListLock, Irql);
+ return(Module);
+ }
- Entry = Entry->Flink;
+ Entry = Entry->Flink;
}
- KeReleaseSpinLock(&ModuleListLock, Irql);
+ KeReleaseSpinLock(&ModuleListLock, Irql);
- DPRINT("Could not find module '%wZ'\n", ModuleName);
+ DPRINT("Could not find module '%wZ'\n", ModuleName);
- return(NULL);
+ return(NULL);
}
/* ---------------------------------------------- PE Module support */
-static BOOL
-PageNeedsWriteAccess(PVOID PageStart,
- PVOID DriverBase,
- PIMAGE_FILE_HEADER PEFileHeader,
- PIMAGE_SECTION_HEADER PESectionHeaders)
+static ULONG
+LdrLookupPageProtection (
+ PVOID PageStart,
+ PVOID DriverBase,
+ PIMAGE_FILE_HEADER PEFileHeader,
+ PIMAGE_SECTION_HEADER PESectionHeaders )
{
- BOOL NeedsWriteAccess;
- unsigned Idx;
- ULONG Characteristics;
- ULONG Length;
- PVOID BaseAddress;
-
- NeedsWriteAccess = FALSE;
- /* Set the protections for the various parts of the driver */
- for (Idx = 0; Idx < PEFileHeader->NumberOfSections && ! NeedsWriteAccess; Idx++)
+ BOOLEAN Write = FALSE;
+ BOOLEAN Execute = FALSE;
+ ULONG Characteristics;
+ ULONG Idx;
+ ULONG Length;
+ PVOID BaseAddress;
+
+ for (Idx = 0; Idx < PEFileHeader->NumberOfSections && (!Write || !Execute); Idx++)
+ {
+ Characteristics = PESectionHeaders[Idx].Characteristics;
+ if (!(Characteristics & IMAGE_SCN_TYPE_NOLOAD))
+ {
+ Length = max(PESectionHeaders[Idx].Misc.VirtualSize, PESectionHeaders[Idx].SizeOfRawData);
+ BaseAddress = PESectionHeaders[Idx].VirtualAddress + (char*)DriverBase;
+ if (BaseAddress < (PVOID)((ULONG_PTR)PageStart + PAGE_SIZE) &&
+ PageStart < (PVOID)((ULONG_PTR)BaseAddress + Length))
+ {
+ if (Characteristics & IMAGE_SCN_CNT_CODE)
+ {
+ Execute = TRUE;
+ }
+ if (Characteristics & (IMAGE_SCN_MEM_WRITE|IMAGE_SCN_CNT_UNINITIALIZED_DATA))
+ {
+ Write = TRUE;
+ }
+ }
+ }
+ }
+ if (Write && Execute)
{
- Characteristics = PESectionHeaders[Idx].Characteristics;
- if (!(Characteristics & IMAGE_SECTION_CHAR_CODE) ||
- (Characteristics & IMAGE_SECTION_CHAR_WRITABLE ||
- Characteristics & IMAGE_SECTION_CHAR_DATA ||
- Characteristics & IMAGE_SECTION_CHAR_BSS))
- {
- Length =
- max(PESectionHeaders[Idx].Misc.VirtualSize,
- PESectionHeaders[Idx].SizeOfRawData);
- BaseAddress = PESectionHeaders[Idx].VirtualAddress + DriverBase;
- NeedsWriteAccess = BaseAddress < PageStart + PAGE_SIZE &&
- PageStart < (PVOID)((PCHAR) BaseAddress + Length);
- }
+ return PAGE_EXECUTE_READWRITE;
+ }
+ else if (Execute)
+ {
+ return PAGE_EXECUTE_READ;
+ }
+ else if (Write)
+ {
+ return PAGE_READWRITE;
+ }
+ else
+ {
+ return PAGE_READONLY;
}
-
- return(NeedsWriteAccess);
}
static NTSTATUS
-LdrPEProcessModule(PVOID ModuleLoadBase,
- PUNICODE_STRING FileName,
- PMODULE_OBJECT *ModuleObject)
+LdrPEProcessModule(
+ PVOID ModuleLoadBase,
+ PUNICODE_STRING FileName,
+ PLDR_DATA_TABLE_ENTRY *ModuleObject )
{
- unsigned int DriverSize, Idx;
- ULONG RelocDelta, NumRelocs;
- DWORD CurrentSize, TotalRelocs;
- PVOID DriverBase;
- PULONG PEMagic;
- PIMAGE_DOS_HEADER PEDosHeader;
- PIMAGE_FILE_HEADER PEFileHeader;
- PIMAGE_OPTIONAL_HEADER PEOptionalHeader;
- PIMAGE_SECTION_HEADER PESectionHeaders;
- PRELOCATION_DIRECTORY RelocDir;
- PRELOCATION_ENTRY RelocEntry;
- PMODULE_OBJECT LibraryModuleObject;
- PMODULE_OBJECT CreatedModuleObject;
- PVOID *ImportAddressList;
- PULONG FunctionNameList;
- PCHAR pName;
- WORD Hint;
- UNICODE_STRING ModuleName;
- UNICODE_STRING NameString;
- WCHAR NameBuffer[60];
- MODULE_TEXT_SECTION* ModuleTextSection;
- NTSTATUS Status;
- KIRQL Irql;
-
- DPRINT("Processing PE Module at module base:%08lx\n", ModuleLoadBase);
-
- /* Get header pointers */
- PEDosHeader = (PIMAGE_DOS_HEADER) ModuleLoadBase;
- PEMagic = (PULONG) ((unsigned int) ModuleLoadBase +
- PEDosHeader->e_lfanew);
- PEFileHeader = (PIMAGE_FILE_HEADER) ((unsigned int) ModuleLoadBase +
- PEDosHeader->e_lfanew + sizeof(ULONG));
- PEOptionalHeader = (PIMAGE_OPTIONAL_HEADER) ((unsigned int) ModuleLoadBase +
- PEDosHeader->e_lfanew + sizeof(ULONG) + sizeof(IMAGE_FILE_HEADER));
- PESectionHeaders = (PIMAGE_SECTION_HEADER) ((unsigned int) ModuleLoadBase +
- PEDosHeader->e_lfanew + sizeof(ULONG) + sizeof(IMAGE_FILE_HEADER) +
- sizeof(IMAGE_OPTIONAL_HEADER));
- CHECKPOINT;
-
- /* Check file magic numbers */
- if (PEDosHeader->e_magic != IMAGE_DOS_MAGIC)
+ unsigned int DriverSize, Idx;
+ DWORD CurrentSize;
+ PVOID DriverBase;
+ PIMAGE_DOS_HEADER PEDosHeader;
+ PIMAGE_NT_HEADERS PENtHeaders;
+ PIMAGE_SECTION_HEADER PESectionHeaders;
+ PLDR_DATA_TABLE_ENTRY CreatedModuleObject;
+ NTSTATUS Status;
+ KIRQL Irql;
+
+ DPRINT("Processing PE Module at module base:%08lx\n", ModuleLoadBase);
+
+ /* Get header pointers */
+ PEDosHeader = (PIMAGE_DOS_HEADER) ModuleLoadBase;
+ PENtHeaders = RtlImageNtHeader(ModuleLoadBase);
+ PESectionHeaders = IMAGE_FIRST_SECTION(PENtHeaders);
+ CHECKPOINT;
+
+ /* Check file magic numbers */
+ if (PEDosHeader->e_magic != IMAGE_DOS_SIGNATURE)
{
- CPRINT("Incorrect MZ magic: %04x\n", PEDosHeader->e_magic);
- return STATUS_UNSUCCESSFUL;
+ CPRINT("Incorrect MZ magic: %04x\n", PEDosHeader->e_magic);
+ return STATUS_UNSUCCESSFUL;
}
- if (PEDosHeader->e_lfanew == 0)
+ if (PEDosHeader->e_lfanew == 0)
{
- CPRINT("Invalid lfanew offset: %08x\n", PEDosHeader->e_lfanew);
- return STATUS_UNSUCCESSFUL;
+ CPRINT("Invalid lfanew offset: %08x\n", PEDosHeader->e_lfanew);
+ return STATUS_UNSUCCESSFUL;
}
- if (*PEMagic != IMAGE_PE_MAGIC)
+ if (PENtHeaders->Signature != IMAGE_NT_SIGNATURE)
{
- CPRINT("Incorrect PE magic: %08x\n", *PEMagic);
- return STATUS_UNSUCCESSFUL;
+ CPRINT("Incorrect PE magic: %08x\n", PENtHeaders->Signature);
+ return STATUS_UNSUCCESSFUL;
}
- if (PEFileHeader->Machine != IMAGE_FILE_MACHINE_I386)
+ if (PENtHeaders->FileHeader.Machine != IMAGE_FILE_MACHINE_I386)
{
- CPRINT("Incorrect Architechture: %04x\n", PEFileHeader->Machine);
- return STATUS_UNSUCCESSFUL;
+ CPRINT("Incorrect Architechture: %04x\n", PENtHeaders->FileHeader.Machine);
+ return STATUS_UNSUCCESSFUL;
}
- CHECKPOINT;
+ CHECKPOINT;
- /* FIXME: if image is fixed-address load, then fail */
+ /* FIXME: if image is fixed-address load, then fail */
- /* FIXME: check/verify OS version number */
+ /* FIXME: check/verify OS version number */
- DPRINT("OptionalHdrMagic:%04x LinkVersion:%d.%d\n",
- PEOptionalHeader->Magic,
- PEOptionalHeader->MajorLinkerVersion,
- PEOptionalHeader->MinorLinkerVersion);
- DPRINT("Entry Point:%08lx\n", PEOptionalHeader->AddressOfEntryPoint);
- CHECKPOINT;
+ DPRINT("OptionalHdrMagic:%04x LinkVersion:%d.%d\n",
+ PENtHeaders->OptionalHeader.Magic,
+ PENtHeaders->OptionalHeader.MajorLinkerVersion,
+ PENtHeaders->OptionalHeader.MinorLinkerVersion);
+ DPRINT("Entry Point:%08lx\n", PENtHeaders->OptionalHeader.AddressOfEntryPoint);
- /* Determine the size of the module */
- DriverSize = PEOptionalHeader->SizeOfImage;
- DPRINT("DriverSize %x\n",DriverSize);
+ /* Determine the size of the module */
+ DriverSize = 0;
+ for (Idx = 0; Idx < PENtHeaders->FileHeader.NumberOfSections; Idx++)
+ {
+ if (!(PESectionHeaders[Idx].Characteristics & IMAGE_SCN_TYPE_NOLOAD))
+ {
+ CurrentSize = PESectionHeaders[Idx].VirtualAddress + PESectionHeaders[Idx].Misc.VirtualSize;
+ DriverSize = max(DriverSize, CurrentSize);
+ }
+ }
+ DriverSize = ROUND_UP(DriverSize, PENtHeaders->OptionalHeader.SectionAlignment);
+ DPRINT("DriverSize %x, SizeOfImage %x\n",DriverSize, PENtHeaders->OptionalHeader.SizeOfImage);
- /* Allocate a virtual section for the module */
- DriverBase = MmAllocateSection(DriverSize);
- if (DriverBase == 0)
+ /* Allocate a virtual section for the module */
+ DriverBase = NULL;
+ DriverBase = MmAllocateSection(DriverSize, DriverBase);
+ if (DriverBase == 0)
{
- CPRINT("Failed to allocate a virtual section for driver\n");
- return STATUS_UNSUCCESSFUL;
+ CPRINT("Failed to allocate a virtual section for driver\n");
+ return STATUS_UNSUCCESSFUL;
}
- DbgPrint("DriverBase for %wZ: %x\n", FileName, DriverBase);
- CHECKPOINT;
- /* Copy headers over */
- memcpy(DriverBase, ModuleLoadBase, PEOptionalHeader->SizeOfHeaders);
- CurrentSize = 0;
- /* Copy image sections into virtual section */
- for (Idx = 0; Idx < PEFileHeader->NumberOfSections; Idx++)
+ DPRINT("DriverBase for %wZ: %x\n", FileName, DriverBase);
+
+ /* Copy headers over */
+ memcpy(DriverBase, ModuleLoadBase, PENtHeaders->OptionalHeader.SizeOfHeaders);
+
+ /* Copy image sections into virtual section */
+ for (Idx = 0; Idx < PENtHeaders->FileHeader.NumberOfSections; Idx++)
{
- // Copy current section into current offset of virtual section
- if (PESectionHeaders[Idx].Characteristics &
- (IMAGE_SECTION_CHAR_CODE | IMAGE_SECTION_CHAR_DATA))
+ CurrentSize = PESectionHeaders[Idx].VirtualAddress + PESectionHeaders[Idx].Misc.VirtualSize;
+ /* Copy current section into current offset of virtual section */
+ if (CurrentSize <= DriverSize &&
+ PESectionHeaders[Idx].SizeOfRawData)
{
- DPRINT("PESectionHeaders[Idx].VirtualAddress + DriverBase %x\n",
- PESectionHeaders[Idx].VirtualAddress + DriverBase);
- memcpy(PESectionHeaders[Idx].VirtualAddress + DriverBase,
- (PVOID)(ModuleLoadBase + PESectionHeaders[Idx].PointerToRawData),
- PESectionHeaders[Idx].Misc.VirtualSize > PESectionHeaders[Idx].SizeOfRawData
- ? PESectionHeaders[Idx].SizeOfRawData : PESectionHeaders[Idx].Misc.VirtualSize );
+ DPRINT("PESectionHeaders[Idx].VirtualAddress + DriverBase %x\n",
+ PESectionHeaders[Idx].VirtualAddress + (ULONG_PTR)DriverBase);
+ memcpy((PVOID)((ULONG_PTR)DriverBase + PESectionHeaders[Idx].VirtualAddress),
+ (PVOID)((ULONG_PTR)ModuleLoadBase + PESectionHeaders[Idx].PointerToRawData),
+ PESectionHeaders[Idx].Misc.VirtualSize > PESectionHeaders[Idx].SizeOfRawData
+ ? PESectionHeaders[Idx].SizeOfRawData : PESectionHeaders[Idx].Misc.VirtualSize );
}
- else
- {
- DPRINT("PESectionHeaders[Idx].VirtualAddress + DriverBase %x\n",
- PESectionHeaders[Idx].VirtualAddress + DriverBase);
- memset(PESectionHeaders[Idx].VirtualAddress + DriverBase,
- '\0', PESectionHeaders[Idx].Misc.VirtualSize);
+ }
- }
- CurrentSize += ROUND_UP(PESectionHeaders[Idx].Misc.VirtualSize,
- PEOptionalHeader->SectionAlignment);
+ /* Perform relocation fixups */
+ Status = LdrPEPerformRelocations(DriverBase, DriverSize);
+ if (!NT_SUCCESS(Status))
+ {
+ // MmFreeSection(DriverBase);
+ return Status;
+ }
+
+ /* Create the module */
+ CreatedModuleObject = ExAllocatePoolWithTag (
+ NonPagedPool, sizeof(LDR_DATA_TABLE_ENTRY), TAG_MODULE_OBJECT );
+ if (CreatedModuleObject == NULL)
+ {
+ // MmFreeSection(DriverBase);
+ return STATUS_INSUFFICIENT_RESOURCES;
+ }
+ RtlZeroMemory(CreatedModuleObject, sizeof(LDR_DATA_TABLE_ENTRY));
-// CurrentBase = (PVOID)((DWORD)CurrentBase +
- // ROUND_UP(PESectionHeaders[Idx].SizeOfRawData.Misc.VirtualSize,
- // PEOptionalHeader->SectionAlignment));
+ /* Initialize ModuleObject data */
+ CreatedModuleObject->DllBase = DriverBase;
+
+ CreatedModuleObject->FullDllName.Length = 0;
+ CreatedModuleObject->FullDllName.MaximumLength = FileName->Length + sizeof(UNICODE_NULL);
+ CreatedModuleObject->FullDllName.Buffer =
+ ExAllocatePoolWithTag(PagedPool, CreatedModuleObject->FullDllName.MaximumLength, TAG_LDR_WSTR);
+ if (CreatedModuleObject->FullDllName.Buffer == NULL)
+ {
+ ExFreePool(CreatedModuleObject);
+ // MmFreeSection(DriverBase);
+ return STATUS_INSUFFICIENT_RESOURCES;
}
- /* Perform relocation fixups */
- RelocDelta = (DWORD) DriverBase - PEOptionalHeader->ImageBase;
- RelocDir = (PRELOCATION_DIRECTORY)(PEOptionalHeader->DataDirectory[
- IMAGE_DIRECTORY_ENTRY_BASERELOC].VirtualAddress);
- DPRINT("DrvrBase:%08lx ImgBase:%08lx RelocDelta:%08lx\n",
- DriverBase,
- PEOptionalHeader->ImageBase,
- RelocDelta);
- DPRINT("RelocDir %x\n",RelocDir);
-#if 1
- for (Idx = 0; Idx < PEFileHeader->NumberOfSections; Idx++)
+ RtlCopyUnicodeString(&CreatedModuleObject->FullDllName, FileName);
+ CreatedModuleObject->FullDllName.Buffer[FileName->Length / sizeof(WCHAR)] = 0;
+ LdrpBuildModuleBaseName(&CreatedModuleObject->BaseDllName,
+ &CreatedModuleObject->FullDllName);
+
+ CreatedModuleObject->EntryPoint =
+ (PVOID)((ULONG_PTR)DriverBase +
+ PENtHeaders->OptionalHeader.AddressOfEntryPoint);
+ CreatedModuleObject->SizeOfImage = DriverSize;
+ DPRINT("EntryPoint at %x\n", CreatedModuleObject->EntryPoint);
+
+ /* Perform import fixups */
+ Status = LdrPEFixupImports(CreatedModuleObject);
+ if (!NT_SUCCESS(Status))
{
- if (PESectionHeaders[Idx].VirtualAddress == (DWORD)RelocDir)
- {
- DPRINT("Name %.8s PESectionHeader[Idx].PointerToRawData %x\n",
- PESectionHeaders[Idx].Name,
- PESectionHeaders[Idx].PointerToRawData);
- RelocDir = PESectionHeaders[Idx].PointerToRawData +
- ModuleLoadBase;
- CurrentSize = PESectionHeaders[Idx].Misc.VirtualSize;
- break;
- }
+ // MmFreeSection(DriverBase);
+ ExFreePool(CreatedModuleObject->FullDllName.Buffer);
+ ExFreePool(CreatedModuleObject);
+ return Status;
}
-#else
- RelocDir = RelocDir + (ULONG)DriverBase;
- CurrentSize = PEOptionalHeader->DataDirectory
- [IMAGE_DIRECTORY_ENTRY_BASERELOC].Size;
-#endif
- DPRINT("RelocDir %08lx CurrentSize %08lx\n", RelocDir, CurrentSize);
- TotalRelocs = 0;
- while (TotalRelocs < CurrentSize && RelocDir->SizeOfBlock != 0)
+
+ MmSetPageProtect(NULL, DriverBase, PAGE_READONLY);
+ /* Set the protections for the various parts of the driver */
+ for (Idx = 0; Idx < PENtHeaders->FileHeader.NumberOfSections; Idx++)
{
- NumRelocs = (RelocDir->SizeOfBlock - sizeof(RELOCATION_DIRECTORY)) /
- sizeof(WORD);
-/* DPRINT("RelocDir at %08lx for VA %08lx with %08lx relocs\n",
- RelocDir,
- RelocDir->VirtualAddress,
- NumRelocs);*/
- RelocEntry = (PRELOCATION_ENTRY) ((DWORD)RelocDir +
- sizeof(RELOCATION_DIRECTORY));
- for (Idx = 0; Idx < NumRelocs; Idx++)
+ ULONG Characteristics = PESectionHeaders[Idx].Characteristics;
+ ULONG Length;
+ PVOID BaseAddress;
+ PVOID PageAddress;
+ ULONG Protect;
+ Length = PESectionHeaders[Idx].Misc.VirtualSize;
+ BaseAddress = PESectionHeaders[Idx].VirtualAddress + (char*)DriverBase;
+ PageAddress = (PVOID)PAGE_ROUND_DOWN(BaseAddress);
+
+ Protect = LdrLookupPageProtection(PageAddress, DriverBase, &PENtHeaders->FileHeader, PESectionHeaders);
+#if 1
+ /*
+ * FIXME:
+ * This driver modifies a string in the first page of the text section while initialising.
+ */
+ if (0 == _wcsicmp(L"fireport.sys", FileName->Buffer))
{
- ULONG Offset;
- ULONG Type;
- PDWORD RelocItem;
-
- Offset = RelocEntry[Idx].TypeOffset & 0xfff;
- Type = (RelocEntry[Idx].TypeOffset >> 12) & 0xf;
- RelocItem = (PDWORD)(DriverBase + RelocDir->VirtualAddress +
- Offset);
-/* DPRINT(" reloc at %08lx %x %s old:%08lx new:%08lx\n",
- RelocItem,
- Type,
- Type ? "HIGHLOW" : "ABS",
- *RelocItem,
- (*RelocItem) + RelocDelta); */
- if (Type == 3)
- {
- (*RelocItem) += RelocDelta;
- }
- else if (Type != 0)
- {
- CPRINT("Unknown relocation type %x at %x\n",Type, &Type);
- return STATUS_UNSUCCESSFUL;
- }
+ Protect = PAGE_EXECUTE_READWRITE;
}
- TotalRelocs += RelocDir->SizeOfBlock;
- RelocDir = (PRELOCATION_DIRECTORY)((DWORD)RelocDir +
- RelocDir->SizeOfBlock);
-// DPRINT("TotalRelocs: %08lx CurrentSize: %08lx\n", TotalRelocs, CurrentSize);
- }
-
- DPRINT("PEOptionalHeader->DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT] %x\n",
- PEOptionalHeader->DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT]
- .VirtualAddress);
- /* Perform import fixups */
- if (PEOptionalHeader->DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT].VirtualAddress)
- {
- PIMAGE_IMPORT_MODULE_DIRECTORY ImportModuleDirectory;
-
- /* Process each import module */
- ImportModuleDirectory = (PIMAGE_IMPORT_MODULE_DIRECTORY)
- ((DWORD)DriverBase + PEOptionalHeader->
- DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT].VirtualAddress);
- DPRINT("Processeing import directory at %p\n", ImportModuleDirectory);
- while (ImportModuleDirectory->dwRVAModuleName)
+#endif
+ if (PageAddress < RVA(DriverBase, DriverSize))
{
- /* Check to make sure that import lib is kernel */
- pName = (PCHAR) DriverBase +
- ImportModuleDirectory->dwRVAModuleName;
-
- RtlCreateUnicodeStringFromAsciiz(&ModuleName, pName);
- DPRINT("Import module: %wZ\n", &ModuleName);
-
- LibraryModuleObject = LdrGetModuleObject(&ModuleName);
- if (LibraryModuleObject == NULL)
- {
- DPRINT("Module '%wZ' not loaded yet\n", &ModuleName);
- wcscpy(NameBuffer, L"\\SystemRoot\\system32\\drivers\\");
- wcscat(NameBuffer, ModuleName.Buffer);
- RtlInitUnicodeString(&NameString, NameBuffer);
- Status = LdrLoadModule(&NameString, &LibraryModuleObject);
- if (!NT_SUCCESS(Status))
- {
- wcscpy(NameBuffer, L"\\SystemRoot\\system32\\");
- wcscat(NameBuffer, ModuleName.Buffer);
- RtlInitUnicodeString(&NameString, NameBuffer);
- Status = LdrLoadModule(&NameString, &LibraryModuleObject);
- if (!NT_SUCCESS(Status))
- {
- DPRINT1("Unknown import module: %wZ (Status %lx)\n", &ModuleName, Status);
- return(Status);
- }
- }
- }
- /* Get the import address list */
- ImportAddressList = (PVOID *) ((DWORD)DriverBase +
- ImportModuleDirectory->dwRVAFunctionAddressList);
+ MmSetPageProtect(NULL, PageAddress, Protect);
+ }
- /* Get the list of functions to import */
- if (ImportModuleDirectory->dwRVAFunctionNameList != 0)
+ if (Characteristics & IMAGE_SCN_CNT_CODE)
+ {
+ if (Characteristics & IMAGE_SCN_MEM_WRITE)
{
- FunctionNameList = (PULONG) ((DWORD)DriverBase +
- ImportModuleDirectory->dwRVAFunctionNameList);
+ Protect = PAGE_EXECUTE_READWRITE;
}
- else
+ else
{
- FunctionNameList = (PULONG) ((DWORD)DriverBase +
- ImportModuleDirectory->dwRVAFunctionAddressList);
+ Protect = PAGE_EXECUTE_READ;
}
- /* Walk through function list and fixup addresses */
- while (*FunctionNameList != 0L)
+ }
+ else if (Characteristics & (IMAGE_SCN_MEM_WRITE|IMAGE_SCN_CNT_UNINITIALIZED_DATA))
+ {
+ Protect = PAGE_READWRITE;
+ }
+ else
+ {
+ Protect = PAGE_READONLY;
+ }
+ PageAddress = (PVOID)((ULONG_PTR)PageAddress + PAGE_SIZE);
+ while ((ULONG_PTR)PageAddress + PAGE_SIZE < (ULONG_PTR)BaseAddress + Length)
+ {
+ if (PageAddress < RVA(DriverBase, DriverSize))
{
- if ((*FunctionNameList) & 0x80000000) // hint
- {
- pName = NULL;
-
-
- Hint = (*FunctionNameList) & 0xffff;
- }
- else // hint-name
- {
- pName = (PCHAR)((DWORD)DriverBase +
- *FunctionNameList + 2);
- Hint = *(PWORD)((DWORD)DriverBase + *FunctionNameList);
- }
- DPRINT(" Hint:%04x Name:%s\n", Hint, pName);
-
- /* Fixup the current import symbol */
- if (LibraryModuleObject != NULL)
- {
- *ImportAddressList = LdrGetExportAddress(LibraryModuleObject,
- pName,
- Hint);
- }
- else
- {
- CPRINT("Unresolved kernel symbol: %s\n", pName);
- return STATUS_UNSUCCESSFUL;
- }
- ImportAddressList++;
- FunctionNameList++;
+ MmSetPageProtect(NULL, PageAddress, Protect);
}
-
- RtlFreeUnicodeString(&ModuleName);
-
- ImportModuleDirectory++;
+ PageAddress = (PVOID)((ULONG_PTR)PageAddress + PAGE_SIZE);
+ }
+ if (PageAddress < (PVOID)((ULONG_PTR)BaseAddress + Length) &&
+ PageAddress < RVA(DriverBase, DriverSize))
+ {
+ Protect = LdrLookupPageProtection(PageAddress, DriverBase, &PENtHeaders->FileHeader, PESectionHeaders);
+ MmSetPageProtect(NULL, PageAddress, Protect);
}
}
- /* Set the protections for the various parts of the driver */
- for (Idx = 0; Idx < PEFileHeader->NumberOfSections; Idx++)
- {
- ULONG Characteristics = PESectionHeaders[Idx].Characteristics;
- ULONG Length;
- PVOID BaseAddress;
- PVOID PageAddress;
- if (Characteristics & IMAGE_SECTION_CHAR_CODE &&
- !(Characteristics & IMAGE_SECTION_CHAR_WRITABLE ||
- Characteristics & IMAGE_SECTION_CHAR_DATA ||
- Characteristics & IMAGE_SECTION_CHAR_BSS))
- {
- Length =
- max(PESectionHeaders[Idx].Misc.VirtualSize,
- PESectionHeaders[Idx].SizeOfRawData);
- BaseAddress = PESectionHeaders[Idx].VirtualAddress + DriverBase;
- PageAddress = (PVOID)PAGE_ROUND_DOWN(BaseAddress);
- if (! PageNeedsWriteAccess(PageAddress, DriverBase, PEFileHeader, PESectionHeaders))
- {
- MmSetPageProtect(NULL, PageAddress, PAGE_READONLY);
- }
- PageAddress = (PVOID)((PCHAR) PageAddress + PAGE_SIZE);
- while ((PVOID)((PCHAR) PageAddress + PAGE_SIZE) <
- (PVOID)((PCHAR) BaseAddress + Length))
- {
- MmSetPageProtect(NULL, PageAddress, PAGE_READONLY);
- PageAddress = (PVOID)((PCHAR) PageAddress + PAGE_SIZE);
- }
- if (PageAddress < (PVOID)((PCHAR) BaseAddress + Length) &&
- ! PageNeedsWriteAccess(PageAddress, DriverBase, PEFileHeader, PESectionHeaders))
- {
- MmSetPageProtect(NULL, PageAddress, PAGE_READONLY);
- }
- }
- }
+ /* Insert module */
+ KeAcquireSpinLock(&ModuleListLock, &Irql);
+ InsertTailList(&ModuleListHead,
+ &CreatedModuleObject->InLoadOrderLinks);
+ KeReleaseSpinLock(&ModuleListLock, Irql);
- /* Create the module */
- CreatedModuleObject = ExAllocatePool(NonPagedPool, sizeof(MODULE_OBJECT));
- if (CreatedModuleObject == NULL)
- {
- return(STATUS_INSUFFICIENT_RESOURCES);
- }
+ *ModuleObject = CreatedModuleObject;
- RtlZeroMemory(CreatedModuleObject, sizeof(MODULE_OBJECT));
-
- /* Initialize ModuleObject data */
- CreatedModuleObject->Base = DriverBase;
- CreatedModuleObject->Flags = MODULE_FLAG_PE;
-
- RtlCreateUnicodeString(&CreatedModuleObject->FullName,
- FileName->Buffer);
- LdrpBuildModuleBaseName(&CreatedModuleObject->BaseName,
- &CreatedModuleObject->FullName);
-
- CreatedModuleObject->EntryPoint =
- (PVOID)((DWORD)DriverBase +
- PEOptionalHeader->AddressOfEntryPoint);
- CreatedModuleObject->Length = DriverSize;
- DPRINT("EntryPoint at %x\n", CreatedModuleObject->EntryPoint);
-
- CreatedModuleObject->Image.PE.FileHeader =
- (PIMAGE_FILE_HEADER) ((unsigned int) DriverBase + PEDosHeader->e_lfanew + sizeof(ULONG));
-
- DPRINT("FileHeader at %x\n", CreatedModuleObject->Image.PE.FileHeader);
- CreatedModuleObject->Image.PE.OptionalHeader =
- (PIMAGE_OPTIONAL_HEADER) ((unsigned int) DriverBase + PEDosHeader->e_lfanew + sizeof(ULONG) +
- sizeof(IMAGE_FILE_HEADER));
- DPRINT("OptionalHeader at %x\n", CreatedModuleObject->Image.PE.OptionalHeader);
- CreatedModuleObject->Image.PE.SectionList =
- (PIMAGE_SECTION_HEADER) ((unsigned int) DriverBase + PEDosHeader->e_lfanew + sizeof(ULONG) +
- sizeof(IMAGE_FILE_HEADER) + sizeof(IMAGE_OPTIONAL_HEADER));
- DPRINT("SectionList at %x\n", CreatedModuleObject->Image.PE.SectionList);
-
- /* Insert module */
- KeAcquireSpinLock(&ModuleListLock, &Irql);
- InsertTailList(&ModuleListHead,
- &CreatedModuleObject->ListEntry);
- KeReleaseSpinLock(&ModuleListLock, Irql);
-
-
- ModuleTextSection = ExAllocatePool(NonPagedPool,
- sizeof(MODULE_TEXT_SECTION));
- assert(ModuleTextSection);
- RtlZeroMemory(ModuleTextSection, sizeof(MODULE_TEXT_SECTION));
- ModuleTextSection->Base = (ULONG)DriverBase;
- ModuleTextSection->Length = DriverSize;
- ModuleTextSection->Name = ExAllocatePool(NonPagedPool,
- (wcslen(CreatedModuleObject->BaseName.Buffer) + 1) * sizeof(WCHAR));
- wcscpy(ModuleTextSection->Name, CreatedModuleObject->BaseName.Buffer);
- ModuleTextSection->OptionalHeader =
- CreatedModuleObject->Image.PE.OptionalHeader;
- InsertTailList(&ModuleTextListHead, &ModuleTextSection->ListEntry);
-
- CreatedModuleObject->TextSection = ModuleTextSection;
-
- *ModuleObject = CreatedModuleObject;
-
- DPRINT("Loading Module %wZ...\n", FileName);
-
- if ((KdDebuggerEnabled == TRUE) && (KdDebugState & KD_DEBUG_GDB))
- {
- DPRINT("Module %wZ loaded at 0x%.08x.\n",
- FileName, CreatedModuleObject->Base);
- }
+ DPRINT("Loading Module %wZ...\n", FileName);
+
+ DPRINT("Module %wZ loaded at 0x%.08x.\n",
+ FileName, CreatedModuleObject->DllBase);
- return STATUS_SUCCESS;
+ return STATUS_SUCCESS;
}
PVOID
-LdrSafePEProcessModule(PVOID ModuleLoadBase,
- PVOID DriverBase,
- PVOID ImportModuleBase,
- PULONG DriverSize)
+INIT_FUNCTION
+NTAPI
+LdrSafePEProcessModule (
+ PVOID ModuleLoadBase,
+ PVOID DriverBase,
+ PVOID ImportModuleBase,
+ PULONG DriverSize)
{
- unsigned int Idx;
- ULONG RelocDelta, NumRelocs;
- ULONG CurrentSize, TotalRelocs;
- PULONG PEMagic;
- PIMAGE_DOS_HEADER PEDosHeader;
- PIMAGE_FILE_HEADER PEFileHeader;
- PIMAGE_OPTIONAL_HEADER PEOptionalHeader;
- PIMAGE_SECTION_HEADER PESectionHeaders;
- PRELOCATION_DIRECTORY RelocDir;
- PRELOCATION_ENTRY RelocEntry;
- PVOID *ImportAddressList;
- PULONG FunctionNameList;
- PCHAR pName;
- USHORT Hint;
-
- ps("Processing PE Module at module base:%08lx\n", ModuleLoadBase);
-
- /* Get header pointers */
- PEDosHeader = (PIMAGE_DOS_HEADER) ModuleLoadBase;
- PEMagic = (PULONG) ((unsigned int) ModuleLoadBase +
- PEDosHeader->e_lfanew);
- PEFileHeader = (PIMAGE_FILE_HEADER) ((unsigned int) ModuleLoadBase +
- PEDosHeader->e_lfanew + sizeof(ULONG));
- PEOptionalHeader = (PIMAGE_OPTIONAL_HEADER) ((unsigned int) ModuleLoadBase +
- PEDosHeader->e_lfanew + sizeof(ULONG) + sizeof(IMAGE_FILE_HEADER));
- PESectionHeaders = (PIMAGE_SECTION_HEADER) ((unsigned int) ModuleLoadBase +
- PEDosHeader->e_lfanew + sizeof(ULONG) + sizeof(IMAGE_FILE_HEADER) +
- sizeof(IMAGE_OPTIONAL_HEADER));
- CHECKPOINT;
-
- /* Check file magic numbers */
- if (PEDosHeader->e_magic != IMAGE_DOS_MAGIC)
+ unsigned int Idx;
+ ULONG CurrentSize;
+ PIMAGE_DOS_HEADER PEDosHeader;
+ PIMAGE_NT_HEADERS PENtHeaders;
+ PIMAGE_SECTION_HEADER PESectionHeaders;
+ NTSTATUS Status;
+
+ ps("Processing PE Module at module base:%08lx\n", ModuleLoadBase);
+
+ /* Get header pointers */
+ PEDosHeader = (PIMAGE_DOS_HEADER) ModuleLoadBase;
+ PENtHeaders = RtlImageNtHeader(ModuleLoadBase);
+ PESectionHeaders = IMAGE_FIRST_SECTION(PENtHeaders);
+ CHECKPOINT;
+
+ /* Check file magic numbers */
+ if (PEDosHeader->e_magic != IMAGE_DOS_SIGNATURE)
{
- return 0;
+ return NULL;
}
- if (PEDosHeader->e_lfanew == 0)
+ if (PEDosHeader->e_lfanew == 0)
{
- return 0;
+ return NULL;
}
- if (*PEMagic != IMAGE_PE_MAGIC)
+ if (PENtHeaders->Signature != IMAGE_NT_SIGNATURE)
{
- return 0;
+ return NULL;
}
- if (PEFileHeader->Machine != IMAGE_FILE_MACHINE_I386)
+ if (PENtHeaders->FileHeader.Machine != IMAGE_FILE_MACHINE_I386)
{
- return 0;
+ return NULL;
}
- ps("OptionalHdrMagic:%04x LinkVersion:%d.%d\n",
- PEOptionalHeader->Magic,
- PEOptionalHeader->MajorLinkerVersion,
- PEOptionalHeader->MinorLinkerVersion);
- ps("Entry Point:%08lx\n", PEOptionalHeader->AddressOfEntryPoint);
+ ps("OptionalHdrMagic:%04x LinkVersion:%d.%d\n",
+ PENtHeaders->OptionalHeader.Magic,
+ PENtHeaders->OptionalHeader.MajorLinkerVersion,
+ PENtHeaders->OptionalHeader.MinorLinkerVersion);
+ ps("Entry Point:%08lx\n", PENtHeaders->OptionalHeader.AddressOfEntryPoint);
- /* Determine the size of the module */
- *DriverSize = PEOptionalHeader->SizeOfImage;
- ps("DriverSize %x\n",*DriverSize);
+ /* Determine the size of the module */
+ *DriverSize = PENtHeaders->OptionalHeader.SizeOfImage;
+ ps("DriverSize %x\n",*DriverSize);
- /* Copy headers over */
- if (DriverBase != ModuleLoadBase)
+ /* Copy headers over */
+ if (DriverBase != ModuleLoadBase)
{
- memcpy(DriverBase, ModuleLoadBase, PEOptionalHeader->SizeOfHeaders);
+ memcpy(DriverBase, ModuleLoadBase, PENtHeaders->OptionalHeader.SizeOfHeaders);
}
- ps("Hdr: 0x%X\n", (ULONG)PEOptionalHeader);
- ps("Hdr->SizeOfHeaders: 0x%X\n", (ULONG)PEOptionalHeader->SizeOfHeaders);
- ps("FileHdr->NumberOfSections: 0x%X\n", (ULONG)PEFileHeader->NumberOfSections);
+ ps("Hdr: 0x%X\n", PENtHeaders);
+ ps("Hdr->SizeOfHeaders: 0x%X\n", PENtHeaders->OptionalHeader.SizeOfHeaders);
+ ps("FileHdr->NumberOfSections: 0x%X\n", PENtHeaders->FileHeader.NumberOfSections);
- /* Ntoskrnl.exe need no relocation fixups since it is linked to run at the same
- address as it is mapped */
- if (DriverBase != ModuleLoadBase)
+ /* Ntoskrnl.exe need no relocation fixups since it is linked to run at the same
+ address as it is mapped */
+ if (DriverBase != ModuleLoadBase)
{
- CurrentSize = 0;
+ CurrentSize = 0;
- /* Copy image sections into virtual section */
- for (Idx = 0; Idx < PEFileHeader->NumberOfSections; Idx++)
- {
- // Copy current section into current offset of virtual section
- if (PESectionHeaders[Idx].Characteristics &
- (IMAGE_SECTION_CHAR_CODE | IMAGE_SECTION_CHAR_DATA))
- {
- //ps("PESectionHeaders[Idx].VirtualAddress (%X) + DriverBase %x\n",
- //PESectionHeaders[Idx].VirtualAddress, PESectionHeaders[Idx].VirtualAddress + DriverBase);
- memcpy(PESectionHeaders[Idx].VirtualAddress + DriverBase,
- (PVOID)(ModuleLoadBase + PESectionHeaders[Idx].PointerToRawData),
- PESectionHeaders[Idx].Misc.VirtualSize > PESectionHeaders[Idx].SizeOfRawData ?
- PESectionHeaders[Idx].SizeOfRawData : PESectionHeaders[Idx].Misc.VirtualSize );
- }
- else
- {
- ps("PESectionHeaders[Idx].VirtualAddress (%X) + DriverBase %x\n",
- PESectionHeaders[Idx].VirtualAddress, PESectionHeaders[Idx].VirtualAddress + DriverBase);
- memset(PESectionHeaders[Idx].VirtualAddress + DriverBase,
- '\0',
- PESectionHeaders[Idx].Misc.VirtualSize);
- }
- CurrentSize += ROUND_UP(PESectionHeaders[Idx].Misc.VirtualSize,
- PEOptionalHeader->SectionAlignment);
+ /* Copy image sections into virtual section */
+ for (Idx = 0; Idx < PENtHeaders->FileHeader.NumberOfSections; Idx++)
+ {
+ PIMAGE_SECTION_HEADER Section = &PESectionHeaders[Idx];
+ // Copy current section into current offset of virtual section
+ if (Section->SizeOfRawData)
+ {
+ // ps("PESectionHeaders[Idx].VirtualAddress (%X) + DriverBase %x\n",
+ // PESectionHeaders[Idx].VirtualAddress, PESectionHeaders[Idx].VirtualAddress + DriverBase);
+ memcpy(Section->VirtualAddress + (char*)DriverBase,
+ Section->PointerToRawData + (char*)ModuleLoadBase,
+ Section->Misc.VirtualSize > Section->SizeOfRawData ? Section->SizeOfRawData : Section->Misc.VirtualSize);
+ }
+ if (Section->SizeOfRawData < Section->Misc.VirtualSize)
+ {
+ memset(Section->VirtualAddress + Section->SizeOfRawData + (char*)DriverBase,
+ 0,
+ Section->Misc.VirtualSize - Section->SizeOfRawData);
+ }
+ CurrentSize += ROUND_UP(Section->Misc.VirtualSize,
+ PENtHeaders->OptionalHeader.SectionAlignment);
+ }
+
+ /* Perform relocation fixups */
+ Status = LdrPEPerformRelocations(DriverBase, *DriverSize);
+ if (!NT_SUCCESS(Status))
+ {
+ return NULL;
+ }
}
- /* Perform relocation fixups */
- RelocDelta = (ULONG) DriverBase - PEOptionalHeader->ImageBase;
- RelocDir = (PRELOCATION_DIRECTORY)(PEOptionalHeader->DataDirectory[
- IMAGE_DIRECTORY_ENTRY_BASERELOC].VirtualAddress);
- ps("DrvrBase:%08lx ImgBase:%08lx RelocDelta:%08lx\n",
- DriverBase,
- PEOptionalHeader->ImageBase,
- RelocDelta);
- ps("RelocDir %x\n",RelocDir);
-
- for (Idx = 0; Idx < PEFileHeader->NumberOfSections; Idx++)
+ /* Perform import fixups */
+ Status = LdrPEFixupImports(DriverBase == ModuleLoadBase ? &NtoskrnlModuleObject : &HalModuleObject);
+ if (!NT_SUCCESS(Status))
{
- if (PESectionHeaders[Idx].VirtualAddress == (ULONG)RelocDir)
- {
- DPRINT("Name %.8s PESectionHeader[Idx].PointerToRawData %x\n",
- PESectionHeaders[Idx].Name,
- PESectionHeaders[Idx].PointerToRawData);
- RelocDir = PESectionHeaders[Idx].PointerToRawData + ModuleLoadBase;
- CurrentSize = PESectionHeaders[Idx].Misc.VirtualSize;
- break;
- }
+ return NULL;
}
- ps("RelocDir %08lx CurrentSize %08lx\n", RelocDir, CurrentSize);
-
- TotalRelocs = 0;
- while (TotalRelocs < CurrentSize && RelocDir->SizeOfBlock != 0)
+ /* Set the page protection for the virtual sections */
+ MmSetPageProtect(NULL, DriverBase, PAGE_READONLY);
+ for (Idx = 0; Idx < PENtHeaders->FileHeader.NumberOfSections; Idx++)
{
- NumRelocs = (RelocDir->SizeOfBlock - sizeof(RELOCATION_DIRECTORY)) /
- sizeof(USHORT);
- RelocEntry = (PRELOCATION_ENTRY)((ULONG)RelocDir +
- sizeof(RELOCATION_DIRECTORY));
- for (Idx = 0; Idx < NumRelocs; Idx++)
+ ULONG Characteristics = PESectionHeaders[Idx].Characteristics;
+ ULONG Length;
+ PVOID BaseAddress;
+ PVOID PageAddress;
+ ULONG Protect;
+ Length = PESectionHeaders[Idx].Misc.VirtualSize;
+ BaseAddress = PESectionHeaders[Idx].VirtualAddress + (char*)DriverBase;
+ PageAddress = (PVOID)PAGE_ROUND_DOWN(BaseAddress);
+
+ if (Characteristics & IMAGE_SCN_MEM_EXECUTE)
+ {
+ if (Characteristics & IMAGE_SCN_MEM_WRITE)
+ {
+ Protect = PAGE_EXECUTE_READWRITE;
+ }
+ else
+ {
+ Protect = PAGE_EXECUTE_READ;
+ }
+ }
+ else if (Characteristics & IMAGE_SCN_MEM_WRITE)
{
- ULONG Offset;
- ULONG Type;
- PDWORD RelocItem;
-
- Offset = RelocEntry[Idx].TypeOffset & 0xfff;
- Type = (RelocEntry[Idx].TypeOffset >> 12) & 0xf;
- RelocItem = (PULONG)(DriverBase + RelocDir->VirtualAddress + Offset);
- if (Type == 3)
- {
- (*RelocItem) += RelocDelta;
- }
- else if (Type != 0)
- {
- CPRINT("Unknown relocation type %x at %x\n",Type, &Type);
- return(0);
- }
- }
- TotalRelocs += RelocDir->SizeOfBlock;
- RelocDir = (PRELOCATION_DIRECTORY)((ULONG)RelocDir +
- RelocDir->SizeOfBlock);
+ Protect = PAGE_READWRITE;
+ }
+ else
+ {
+ Protect = PAGE_READONLY;
+ }
+ while ((ULONG_PTR)PageAddress < (ULONG_PTR)BaseAddress + Length)
+ {
+ MmSetPageProtect(NULL, PageAddress, Protect);
+ PageAddress = (PVOID)((ULONG_PTR)PageAddress + PAGE_SIZE);
+ }
+ if (DriverBase == ModuleLoadBase &&
+ Characteristics & IMAGE_SCN_CNT_UNINITIALIZED_DATA)
+ {
+ /* For ntoskrnl, we must stop after the bss section */
+ break;
+ }
+
}
- ps("PEOptionalHeader->DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT] %x\n",
- PEOptionalHeader->DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT]
- .VirtualAddress);
- }
+ return DriverBase;
+}
+
+static PVOID
+LdrPEFixupForward ( PCHAR ForwardName )
+{
+ CHAR NameBuffer[128];
+ UNICODE_STRING ModuleName;
+ PCHAR p;
+ PLDR_DATA_TABLE_ENTRY ModuleObject;
+
+ DPRINT("LdrPEFixupForward (%s)\n", ForwardName);
- /* Perform import fixups */
- if (PEOptionalHeader->DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT].VirtualAddress)
+ strcpy(NameBuffer, ForwardName);
+ p = strchr(NameBuffer, '.');
+ if (p == NULL)
{
- PIMAGE_IMPORT_MODULE_DIRECTORY ImportModuleDirectory;
-
- /* Process each import module */
- ImportModuleDirectory = (PIMAGE_IMPORT_MODULE_DIRECTORY)
- ((ULONG)DriverBase + PEOptionalHeader->
- DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT].VirtualAddress);
-
- ps("Processeing import directory at %p\n", ImportModuleDirectory);
-
- /* Check to make sure that import lib is kernel */
- pName = (PCHAR)DriverBase + ImportModuleDirectory->dwRVAModuleName;
-
- ps("Import module: %s\n", pName);
-
- /* Get the import address list */
- ImportAddressList = (PVOID *)((ULONG)DriverBase +
- ImportModuleDirectory->dwRVAFunctionAddressList);
-
- ps(" ImportModuleDirectory->dwRVAFunctionAddressList: 0x%X\n",
- ImportModuleDirectory->dwRVAFunctionAddressList);
- ps(" ImportAddressList: 0x%X\n", ImportAddressList);
-
- /* Get the list of functions to import */
- if (ImportModuleDirectory->dwRVAFunctionNameList != 0)
- {
- ps("Using function name list.\n");
-
- FunctionNameList = (PULONG)((ULONG)DriverBase +
- ImportModuleDirectory->dwRVAFunctionNameList);
- }
- else
- {
- ps("Using function address list.\n");
-
- FunctionNameList = (PULONG)((ULONG)DriverBase +
- ImportModuleDirectory->dwRVAFunctionAddressList);
- }
-
- /* Walk through function list and fixup addresses */
- while (*FunctionNameList != 0L)
- {
- if ((*FunctionNameList) & 0x80000000)
- {
- /* Hint */
- pName = NULL;
- Hint = (*FunctionNameList) & 0xffff;
- }
- else
- {
- /* Hint name */
- pName = (PCHAR)((ULONG)DriverBase + *FunctionNameList + 2);
- Hint = *(PWORD)((ULONG)DriverBase + *FunctionNameList);
- }
- //ps(" Hint:%04x Name:%s(0x%X)(%x)\n", Hint, pName, pName, ImportAddressList);
-
- *ImportAddressList = LdrSafePEGetExportAddress(ImportModuleBase,
- pName,
- Hint);
-
- ImportAddressList++;
- FunctionNameList++;
- }
+ return NULL;
}
- ps("Finished importing.\n");
+ *p = 0;
- return(0);
-}
+ DPRINT("Driver: %s Function: %s\n", NameBuffer, p+1);
+ RtlCreateUnicodeStringFromAsciiz(&ModuleName,
+ NameBuffer);
+ ModuleObject = LdrGetModuleObject(&ModuleName);
+ RtlFreeUnicodeString(&ModuleName);
-static PVOID
-LdrPEGetExportAddress(PMODULE_OBJECT ModuleObject,
- PCHAR Name,
- USHORT Hint)
+ DPRINT("ModuleObject: %p\n", ModuleObject);
+
+ if (ModuleObject == NULL)
+ {
+ CPRINT("LdrPEFixupForward: failed to find module %s\n", NameBuffer);
+ return NULL;
+ }
+ return LdrPEGetExportByName(ModuleObject->DllBase, (PUCHAR)(p+1), 0xffff);
+}
+
+static NTSTATUS
+LdrPEPerformRelocations (
+ PVOID DriverBase,
+ ULONG DriverSize)
{
- PIMAGE_EXPORT_DIRECTORY ExportDir;
- ULONG ExportDirSize;
- USHORT Idx;
- PVOID ExportAddress;
- PWORD OrdinalList;
- PDWORD FunctionList, NameList;
-
- ExportDir = (PIMAGE_EXPORT_DIRECTORY)
- RtlImageDirectoryEntryToData(ModuleObject->Base,
- TRUE,
- IMAGE_DIRECTORY_ENTRY_EXPORT,
- &ExportDirSize);
- DPRINT("ExportDir %p ExportDirSize %lx\n", ExportDir, ExportDirSize);
- if (ExportDir == NULL)
- {
- return NULL;
- }
-
- FunctionList = (PDWORD)((DWORD)ExportDir->AddressOfFunctions + ModuleObject->Base);
- NameList = (PDWORD)((DWORD)ExportDir->AddressOfNames + ModuleObject->Base);
- OrdinalList = (PWORD)((DWORD)ExportDir->AddressOfNameOrdinals + ModuleObject->Base);
-
- ExportAddress = 0;
-
- if (Name != NULL)
+ PIMAGE_NT_HEADERS NtHeaders;
+ PIMAGE_DATA_DIRECTORY RelocationDDir;
+ PIMAGE_BASE_RELOCATION RelocationDir, RelocationEnd;
+ ULONG Count, i;
+ PVOID Address, MaxAddress;
+ PUSHORT TypeOffset;
+ ULONG_PTR Delta;
+ SHORT Offset;
+ USHORT Type;
+ PUSHORT ShortPtr;
+ PULONG LongPtr;
+
+ NtHeaders = RtlImageNtHeader(DriverBase);
+
+ if (NtHeaders->FileHeader.Characteristics & IMAGE_FILE_RELOCS_STRIPPED)
+ {
+ return STATUS_UNSUCCESSFUL;
+ }
+
+ RelocationDDir = &NtHeaders->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_BASERELOC];
+
+ if (RelocationDDir->VirtualAddress == 0 || RelocationDDir->Size == 0)
{
- for (Idx = 0; Idx < ExportDir->NumberOfNames; Idx++)
+ return STATUS_SUCCESS;
+ }
+
+ Delta = (ULONG_PTR)DriverBase - NtHeaders->OptionalHeader.ImageBase;
+ RelocationDir = (PIMAGE_BASE_RELOCATION)((ULONG_PTR)DriverBase + RelocationDDir->VirtualAddress);
+ RelocationEnd = (PIMAGE_BASE_RELOCATION)((ULONG_PTR)RelocationDir + RelocationDDir->Size);
+ MaxAddress = RVA(DriverBase, DriverSize);
+
+ while (RelocationDir < RelocationEnd &&
+ RelocationDir->SizeOfBlock > 0)
+ {
+ Count = (RelocationDir->SizeOfBlock - sizeof(IMAGE_BASE_RELOCATION)) / sizeof(USHORT);
+ Address = RVA(DriverBase, RelocationDir->VirtualAddress);
+ TypeOffset = (PUSHORT)(RelocationDir + 1);
+
+ for (i = 0; i < Count; i++)
{
-#if 0
- DPRINT(" Name:%s NameList[%d]:%s\n",
- Name,
- Idx,
- (DWORD) ModuleObject->Base + NameList[Idx]);
+ Offset = *TypeOffset & 0xFFF;
+ Type = *TypeOffset >> 12;
+ ShortPtr = (PUSHORT)(RVA(Address, Offset));
-#endif
- if (!strcmp(Name, (PCHAR) ((DWORD)ModuleObject->Base + NameList[Idx])))
+ /* Don't relocate after the end of the loaded driver */
+ if ((PVOID)ShortPtr >= MaxAddress)
{
- ExportAddress = (PVOID) ((DWORD)ModuleObject->Base +
- FunctionList[OrdinalList[Idx]]);
- if (((ULONG)ExportAddress >= (ULONG)ExportDir) &&
- ((ULONG)ExportAddress < (ULONG)ExportDir + ExportDirSize))
- {
- DPRINT("Forward: %s\n", (PCHAR)ExportAddress);
- ExportAddress = LdrPEFixupForward((PCHAR)ExportAddress);
- DPRINT("ExportAddress: %p\n", ExportAddress);
- }
-
- break;
+ break;
}
+
+ /*
+ * Don't relocate within the relocation section itself.
+ * GCC/LD generates sometimes relocation records for the relocation section.
+ * This is a bug in GCC/LD.
+ */
+ if ((ULONG_PTR)ShortPtr < (ULONG_PTR)RelocationDir ||
+ (ULONG_PTR)ShortPtr >= (ULONG_PTR)RelocationEnd)
+ {
+ switch (Type)
+ {
+ case IMAGE_REL_BASED_ABSOLUTE:
+ break;
+
+ case IMAGE_REL_BASED_HIGH:
+ *ShortPtr += HIWORD(Delta);
+ break;
+
+ case IMAGE_REL_BASED_LOW:
+ *ShortPtr += LOWORD(Delta);
+ break;
+
+ case IMAGE_REL_BASED_HIGHLOW:
+ LongPtr = (PULONG)ShortPtr;
+ *LongPtr += Delta;
+ break;
+
+ case IMAGE_REL_BASED_HIGHADJ:
+ case IMAGE_REL_BASED_MIPS_JMPADDR:
+ default:
+ DPRINT1("Unknown/unsupported fixup type %hu.\n", Type);
+ DPRINT1("Address %x, Current %d, Count %d, *TypeOffset %x\n", Address, i, Count, *TypeOffset);
+ return STATUS_UNSUCCESSFUL;
+ }
+ }
+ TypeOffset++;
}
+ RelocationDir = (PIMAGE_BASE_RELOCATION)((ULONG_PTR)RelocationDir + RelocationDir->SizeOfBlock);
}
- else /* use hint */
+
+ return STATUS_SUCCESS;
+}
+#ifndef PATH_MAX
+#define PATH_MAX 260
+#endif
+
+static NTSTATUS
+LdrPEGetOrLoadModule (
+ PLDR_DATA_TABLE_ENTRY Module,
+ PCHAR ImportedName,
+ PLDR_DATA_TABLE_ENTRY* ImportedModule)
+{
+ UNICODE_STRING DriverName;
+ UNICODE_STRING NameString;
+ WCHAR NameBuffer[PATH_MAX];
+ NTSTATUS Status = STATUS_SUCCESS;
+
+ if (0 == _stricmp(ImportedName, "ntoskrnl") ||
+ 0 == _stricmp(ImportedName, "ntoskrnl.exe"))
{
- ExportAddress = (PVOID) ((DWORD)ModuleObject->Base +
- FunctionList[Hint - ExportDir->Base]);
+ *ImportedModule = &NtoskrnlModuleObject;
+ return STATUS_SUCCESS;
}
- if (ExportAddress == NULL)
+ if (0 == _stricmp(ImportedName, "hal") ||
+ 0 == _stricmp(ImportedName, "hal.dll"))
{
- CPRINT("Export not found for %d:%s\n",
- Hint,
- Name != NULL ? Name : "(Ordinal)");
- KeBugCheck(0);
+ *ImportedModule = &HalModuleObject;
+ return STATUS_SUCCESS;
}
- return(ExportAddress);
-}
+ RtlCreateUnicodeStringFromAsciiz (&DriverName, ImportedName);
+ DPRINT("Import module: %wZ\n", &DriverName);
+ *ImportedModule = LdrGetModuleObject(&DriverName);
+ if (*ImportedModule == NULL)
+ {
+ PWCHAR PathEnd;
+ ULONG PathLength;
-static PVOID
-LdrSafePEGetExportAddress(PVOID ImportModuleBase,
- PCHAR Name,
- USHORT Hint)
-{
- USHORT Idx;
- PVOID ExportAddress;
- PWORD OrdinalList;
- PDWORD FunctionList, NameList;
- PIMAGE_EXPORT_DIRECTORY ExportDir;
- ULONG ExportDirSize;
+ PathEnd = wcsrchr(Module->FullDllName.Buffer, L'\\');
+ if (NULL != PathEnd)
+ {
+ PathLength = (PathEnd - Module->FullDllName.Buffer + 1) * sizeof(WCHAR);
+ RtlCopyMemory(NameBuffer, Module->FullDllName.Buffer, PathLength);
+ RtlCopyMemory(NameBuffer + (PathLength / sizeof(WCHAR)), DriverName.Buffer, DriverName.Length);
+ NameString.Buffer = NameBuffer;
+ NameString.MaximumLength = NameString.Length = PathLength + DriverName.Length;
- static BOOLEAN EP = FALSE;
+ /* NULL-terminate */
+ NameString.MaximumLength++;
+ NameBuffer[NameString.Length / sizeof(WCHAR)] = 0;
- ExportDir = (PIMAGE_EXPORT_DIRECTORY)
- RtlImageDirectoryEntryToData(ImportModuleBase,
- TRUE,
- IMAGE_DIRECTORY_ENTRY_EXPORT,
- &ExportDirSize);
+ Status = LdrLoadModule(&NameString, ImportedModule);
+ }
+ else
+ {
+ DPRINT("Module '%wZ' not loaded yet\n", &DriverName);
+ wcscpy(NameBuffer, L"\\SystemRoot\\system32\\drivers\\");
+ wcsncat(NameBuffer, DriverName.Buffer, DriverName.Length / sizeof(WCHAR));
+ RtlInitUnicodeString(&NameString, NameBuffer);
+ Status = LdrLoadModule(&NameString, ImportedModule);
+ }
+ if (!NT_SUCCESS(Status))
+ {
+ wcscpy(NameBuffer, L"\\SystemRoot\\system32\\");
+ wcsncat(NameBuffer, DriverName.Buffer, DriverName.Length / sizeof(WCHAR));
+ RtlInitUnicodeString(&NameString, NameBuffer);
+ Status = LdrLoadModule(&NameString, ImportedModule);
+ if (!NT_SUCCESS(Status))
+ {
+ DPRINT1("Unknown import module: %wZ (Status %lx)\n", &DriverName, Status);
+ }
+ }
+ }
+ RtlFreeUnicodeString(&DriverName);
+ return Status;
+}
- if (!EP) {
- EP = TRUE;
- ps("ExportDir %x\n", ExportDir);
- }
+static PVOID
+LdrPEGetExportByName (
+ PVOID BaseAddress,
+ PUCHAR SymbolName,
+ WORD Hint )
+{
+ PIMAGE_EXPORT_DIRECTORY ExportDir;
+ PDWORD * ExFunctions;
+ PDWORD * ExNames;
+ USHORT * ExOrdinals;
+ PVOID ExName;
+ ULONG Ordinal;
+ PVOID Function;
+ LONG minn, maxn, mid, res;
+ ULONG ExportDirSize;
+
+ DPRINT("LdrPEGetExportByName %x %s %hu\n", BaseAddress, SymbolName, Hint);
+
+ ExportDir = (PIMAGE_EXPORT_DIRECTORY)RtlImageDirectoryEntryToData(BaseAddress,
+ TRUE,
+ IMAGE_DIRECTORY_ENTRY_EXPORT,
+ &ExportDirSize);
+ if (ExportDir == NULL)
+ {
+ DPRINT1("LdrPEGetExportByName(): no export directory!\n");
+ return NULL;
+ }
- FunctionList = (PDWORD)((DWORD)ExportDir->AddressOfFunctions + ImportModuleBase);
- NameList = (PDWORD)((DWORD)ExportDir->AddressOfNames + ImportModuleBase);
- OrdinalList = (PWORD)((DWORD)ExportDir->AddressOfNameOrdinals + ImportModuleBase);
- ExportAddress = 0;
+ /* The symbol names may be missing entirely */
+ if (ExportDir->AddressOfNames == 0)
+ {
+ DPRINT("LdrPEGetExportByName(): symbol names missing entirely\n");
+ return NULL;
+ }
- if (Name != NULL)
+ /*
+ * Get header pointers
+ */
+ ExNames = (PDWORD *)RVA(BaseAddress, ExportDir->AddressOfNames);
+ ExOrdinals = (USHORT *)RVA(BaseAddress, ExportDir->AddressOfNameOrdinals);
+ ExFunctions = (PDWORD *)RVA(BaseAddress, ExportDir->AddressOfFunctions);
+
+ /*
+ * Check the hint first
+ */
+ if (Hint < ExportDir->NumberOfNames)
{
- for (Idx = 0; Idx < ExportDir->NumberOfNames; Idx++)
+ ExName = RVA(BaseAddress, ExNames[Hint]);
+ if (strcmp(ExName, (PCHAR)SymbolName) == 0)
{
- if (!strcmp(Name, (PCHAR) ((DWORD)ImportModuleBase + NameList[Idx])))
- {
- ExportAddress = (PVOID) ((DWORD)ImportModuleBase +
- FunctionList[OrdinalList[Idx]]);
- break;
+ Ordinal = ExOrdinals[Hint];
+ Function = RVA(BaseAddress, ExFunctions[Ordinal]);
+ if ((ULONG_PTR)Function >= (ULONG_PTR)ExportDir &&
+ (ULONG_PTR)Function < (ULONG_PTR)ExportDir + ExportDirSize)
+ {
+ DPRINT("Forward: %s\n", (PCHAR)Function);
+ Function = LdrPEFixupForward((PCHAR)Function);
+ if (Function == NULL)
+ {
+ DPRINT1("LdrPEGetExportByName(): failed to find %s\n",SymbolName);
+ }
+ return Function;
+ }
+ if (Function != NULL)
+ {
+ return Function;
}
}
}
- else /* use hint */
+
+ /*
+ * Binary search
+ */
+ minn = 0;
+ maxn = ExportDir->NumberOfNames - 1;
+ while (minn <= maxn)
{
- ExportAddress = (PVOID) ((DWORD)ImportModuleBase +
+ mid = (minn + maxn) / 2;
- FunctionList[Hint - ExportDir->Base]);
+ ExName = RVA(BaseAddress, ExNames[mid]);
+ res = strcmp(ExName, (PCHAR)SymbolName);
+ if (res == 0)
+ {
+ Ordinal = ExOrdinals[mid];
+ Function = RVA(BaseAddress, ExFunctions[Ordinal]);
+ if ((ULONG_PTR)Function >= (ULONG_PTR)ExportDir &&
+ (ULONG_PTR)Function < (ULONG_PTR)ExportDir + ExportDirSize)
+ {
+ DPRINT("Forward: %s\n", (PCHAR)Function);
+ Function = LdrPEFixupForward((PCHAR)Function);
+ if (Function == NULL)
+ {
+ DPRINT1("LdrPEGetExportByName(): failed to find %s\n",SymbolName);
+ }
+ return Function;
+ }
+ if (Function != NULL)
+ {
+ return Function;
+ }
+ }
+ else if (res > 0)
+ {
+ maxn = mid - 1;
+ }
+ else
+ {
+ minn = mid + 1;
+ }
}
- if (ExportAddress == 0)
+ ExName = RVA(BaseAddress, ExNames[mid]);
+ DPRINT1("LdrPEGetExportByName(): failed to find %s\n",SymbolName);
+ return (PVOID)NULL;
+}
+
+static PVOID
+LdrPEGetExportByOrdinal (
+ PVOID BaseAddress,
+ ULONG Ordinal )
+{
+ PIMAGE_EXPORT_DIRECTORY ExportDir;
+ ULONG ExportDirSize;
+ PDWORD * ExFunctions;
+ PVOID Function;
+
+ ExportDir = (PIMAGE_EXPORT_DIRECTORY)RtlImageDirectoryEntryToData (
+ BaseAddress,
+ TRUE,
+ IMAGE_DIRECTORY_ENTRY_EXPORT,
+ &ExportDirSize);
+
+ ExFunctions = (PDWORD *)RVA(BaseAddress,
+ ExportDir->AddressOfFunctions);
+ DPRINT("LdrPEGetExportByOrdinal(Ordinal %d) = %x\n",
+ Ordinal,
+ RVA(BaseAddress, ExFunctions[Ordinal - ExportDir->Base]));
+
+ Function = 0 != ExFunctions[Ordinal - ExportDir->Base]
+ ? RVA(BaseAddress, ExFunctions[Ordinal - ExportDir->Base] )
+ : NULL;
+
+ if (((ULONG_PTR)Function >= (ULONG_PTR)ExportDir) &&
+ ((ULONG_PTR)Function < (ULONG_PTR)ExportDir + ExportDirSize))
{
- ps("Export not found for %d:%s\n",
- Hint,
- Name != NULL ? Name : "(Ordinal)");
- KeBugCheck(0);
+ DPRINT("Forward: %s\n", (PCHAR)Function);
+ Function = LdrPEFixupForward((PCHAR)Function);
}
- return ExportAddress;
-}
+ return Function;
+}
-static PVOID
-LdrPEFixupForward(PCHAR ForwardName)
+static NTSTATUS
+LdrPEProcessImportDirectoryEntry(
+ PVOID DriverBase,
+ PLDR_DATA_TABLE_ENTRY ImportedModule,
+ PIMAGE_IMPORT_DESCRIPTOR ImportModuleDirectory )
{
- CHAR NameBuffer[128];
- UNICODE_STRING ModuleName;
- PCHAR p;
- PMODULE_OBJECT ModuleObject;
+ PVOID* ImportAddressList;
+ PULONG FunctionNameList;
+ ULONG Ordinal;
- DPRINT("LdrPEFixupForward (%s)\n", ForwardName);
+ if (ImportModuleDirectory == NULL || ImportModuleDirectory->Name == 0)
+ {
+ return STATUS_UNSUCCESSFUL;
+ }
- strcpy(NameBuffer, ForwardName);
- p = strchr(NameBuffer, '.');
- if (p == NULL)
- {
- return NULL;
- }
+ /* Get the import address list. */
+ ImportAddressList = (PVOID*)RVA(DriverBase, ImportModuleDirectory->FirstThunk);
- *p = 0;
+ /* Get the list of functions to import. */
+ if (ImportModuleDirectory->OriginalFirstThunk != 0)
+ {
+ FunctionNameList = (PULONG)RVA(DriverBase, ImportModuleDirectory->OriginalFirstThunk);
+ }
+ else
+ {
+ FunctionNameList = (PULONG)RVA(DriverBase, ImportModuleDirectory->FirstThunk);
+ }
- DPRINT("Driver: %s Function: %s\n", NameBuffer, p+1);
+ /* Walk through function list and fixup addresses. */
+ while (*FunctionNameList != 0L)
+ {
+ if ((*FunctionNameList) & 0x80000000)
+ {
+ Ordinal = (*FunctionNameList) & 0x7fffffff;
+ *ImportAddressList = LdrPEGetExportByOrdinal(ImportedModule->DllBase, Ordinal);
+ if ((*ImportAddressList) == NULL)
+ {
+ DPRINT1("Failed to import #%ld from %wZ\n", Ordinal, &ImportedModule->FullDllName);
+ return STATUS_UNSUCCESSFUL;
+ }
+ }
+ else
+ {
+ IMAGE_IMPORT_BY_NAME *pe_name;
+ pe_name = RVA(DriverBase, *FunctionNameList);
+ *ImportAddressList = LdrPEGetExportByName(ImportedModule->DllBase, pe_name->Name, pe_name->Hint);
+ if ((*ImportAddressList) == NULL)
+ {
+ DPRINT1("Failed to import %s from %wZ\n", pe_name->Name, &ImportedModule->FullDllName);
+ return STATUS_UNSUCCESSFUL;
+ }
+ }
+ ImportAddressList++;
+ FunctionNameList++;
+ }
+ return STATUS_SUCCESS;
+}
- RtlCreateUnicodeStringFromAsciiz(&ModuleName,
- NameBuffer);
- ModuleObject = LdrGetModuleObject(&ModuleName);
- RtlFreeUnicodeString(&ModuleName);
+static NTSTATUS
+LdrPEFixupImports ( PLDR_DATA_TABLE_ENTRY Module )
+{
+ PIMAGE_IMPORT_DESCRIPTOR ImportModuleDirectory;
+ PCHAR ImportedName;
+ PLDR_DATA_TABLE_ENTRY ImportedModule;
+ NTSTATUS Status;
+ ULONG Size;
+
+ /* Process each import module */
+ ImportModuleDirectory = (PIMAGE_IMPORT_DESCRIPTOR)
+ RtlImageDirectoryEntryToData(Module->DllBase,
+ TRUE,
+ IMAGE_DIRECTORY_ENTRY_IMPORT,
+ &Size);
+ DPRINT("Processeing import directory at %p\n", ImportModuleDirectory);
+ while (ImportModuleDirectory->Name)
+ {
+ if (Module->SizeOfImage <= ImportModuleDirectory->Name)
+ {
+ DPRINT1("Invalid import directory in %wZ\n", &Module->FullDllName);
+ return STATUS_SECTION_NOT_IMAGE;
+ }
- DPRINT("ModuleObject: %p\n", ModuleObject);
+ /* Check to make sure that import lib is kernel */
+ ImportedName = (PCHAR) Module->DllBase + ImportModuleDirectory->Name;
- if (ModuleObject == NULL)
- {
- CPRINT("LdrPEFixupForward: failed to find module %s\n", NameBuffer);
- return NULL;
- }
+ Status = LdrPEGetOrLoadModule(Module, ImportedName, &ImportedModule);
+ if (!NT_SUCCESS(Status))
+ {
+ return Status;
+ }
- return(LdrPEGetExportAddress(ModuleObject, p+1, 0));
+ Status = LdrPEProcessImportDirectoryEntry(Module->DllBase, ImportedModule, ImportModuleDirectory);
+ if (!NT_SUCCESS(Status))
+ {
+ return Status;
+ }
+
+ ImportModuleDirectory++;
+ }
+ return STATUS_SUCCESS;
}
/* EOF */