📄 utils.c
字号:
* DESCRIPTION
* Relocate a DLL's memory image.
*
* ARGUMENTS
*
* RETURN VALUE
*
* REVISIONS
*
* NOTE
*
*/
static NTSTATUS
LdrPerformRelocations(PIMAGE_NT_HEADERS NTHeaders,
PVOID ImageBase)
{
PIMAGE_DATA_DIRECTORY RelocationDDir;
PIMAGE_BASE_RELOCATION RelocationDir, RelocationEnd;
ULONG Count, ProtectSize, OldProtect, OldProtect2;
PVOID Page, ProtectPage, ProtectPage2;
PUSHORT TypeOffset;
ULONG_PTR Delta;
NTSTATUS Status;
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)
{
return STATUS_SUCCESS;
}
ProtectSize = PAGE_SIZE;
Delta = (ULONG_PTR)ImageBase - NTHeaders->OptionalHeader.ImageBase;
RelocationDir = (PIMAGE_BASE_RELOCATION)((ULONG_PTR)ImageBase +
RelocationDDir->VirtualAddress);
RelocationEnd = (PIMAGE_BASE_RELOCATION)((ULONG_PTR)ImageBase +
RelocationDDir->VirtualAddress + RelocationDDir->Size);
while (RelocationDir < RelocationEnd &&
RelocationDir->SizeOfBlock > 0)
{
Count = (RelocationDir->SizeOfBlock - sizeof(IMAGE_BASE_RELOCATION)) /
sizeof(USHORT);
Page = (PVOID)((ULONG_PTR)ImageBase + (ULONG_PTR)RelocationDir->VirtualAddress);
TypeOffset = (PUSHORT)(RelocationDir + 1);
/* Unprotect the page(s) we're about to relocate. */
ProtectPage = Page;
Status = NtProtectVirtualMemory(NtCurrentProcess(),
&ProtectPage,
&ProtectSize,
PAGE_READWRITE,
&OldProtect);
if (!NT_SUCCESS(Status))
{
DPRINT1("Failed to unprotect relocation target.\n");
return Status;
}
if (RelocationDir->VirtualAddress + PAGE_SIZE <
NTHeaders->OptionalHeader.SizeOfImage)
{
ProtectPage2 = (PVOID)((ULONG_PTR)ProtectPage + PAGE_SIZE);
Status = NtProtectVirtualMemory(NtCurrentProcess(),
&ProtectPage2,
&ProtectSize,
PAGE_READWRITE,
&OldProtect2);
if (!NT_SUCCESS(Status))
{
DPRINT1("Failed to unprotect relocation target (2).\n");
NtProtectVirtualMemory(NtCurrentProcess(),
&ProtectPage,
&ProtectSize,
OldProtect,
&OldProtect);
return Status;
}
}
else
{
ProtectPage2 = NULL;
}
RelocationDir = LdrProcessRelocationBlock((ULONG_PTR)Page,
Count,
TypeOffset,
Delta);
if (RelocationDir == NULL)
return STATUS_UNSUCCESSFUL;
/* Restore old page protection. */
NtProtectVirtualMemory(NtCurrentProcess(),
&ProtectPage,
&ProtectSize,
OldProtect,
&OldProtect);
if (ProtectPage2 != NULL)
{
NtProtectVirtualMemory(NtCurrentProcess(),
&ProtectPage2,
&ProtectSize,
OldProtect2,
&OldProtect2);
}
}
return STATUS_SUCCESS;
}
static NTSTATUS
LdrpGetOrLoadModule(PWCHAR SerachPath,
PCHAR Name,
PLDR_DATA_TABLE_ENTRY* Module,
BOOLEAN Load)
{
UNICODE_STRING DllName;
NTSTATUS Status;
DPRINT("LdrpGetOrLoadModule() called for %s\n", Name);
RtlCreateUnicodeStringFromAsciiz (&DllName, Name);
Status = LdrFindEntryForName (&DllName, Module, Load);
if (Load && !NT_SUCCESS(Status))
{
Status = LdrpLoadModule(SerachPath,
NtCurrentPeb()->Ldr->Initialized ? 0 : LDRP_PROCESS_CREATION_TIME,
&DllName,
Module,
NULL);
if (NT_SUCCESS(Status))
{
Status = LdrFindEntryForName (&DllName, Module, FALSE);
}
if (!NT_SUCCESS(Status))
{
DPRINT1("failed to load %wZ\n", &DllName);
}
}
RtlFreeUnicodeString (&DllName);
return Status;
}
static NTSTATUS
LdrpProcessImportDirectoryEntry(PLDR_DATA_TABLE_ENTRY Module,
PLDR_DATA_TABLE_ENTRY ImportedModule,
PIMAGE_IMPORT_DESCRIPTOR ImportModuleDirectory)
{
NTSTATUS Status;
PVOID* ImportAddressList;
PULONG FunctionNameList;
PVOID IATBase;
ULONG OldProtect;
ULONG Ordinal;
ULONG IATSize;
if (ImportModuleDirectory == NULL || ImportModuleDirectory->Name == 0)
{
return STATUS_UNSUCCESSFUL;
}
/* Get the import address list. */
ImportAddressList = (PVOID *)((ULONG_PTR)Module->DllBase + (ULONG_PTR)ImportModuleDirectory->FirstThunk);
/* Get the list of functions to import. */
if (ImportModuleDirectory->OriginalFirstThunk != 0)
{
FunctionNameList = (PULONG) ((ULONG_PTR)Module->DllBase + (ULONG_PTR)ImportModuleDirectory->OriginalFirstThunk);
}
else
{
FunctionNameList = (PULONG)((ULONG_PTR)Module->DllBase + (ULONG_PTR)ImportModuleDirectory->FirstThunk);
}
/* Get the size of IAT. */
IATSize = 0;
while (FunctionNameList[IATSize] != 0L)
{
IATSize++;
}
/* Unprotect the region we are about to write into. */
IATBase = (PVOID)ImportAddressList;
IATSize *= sizeof(PVOID*);
Status = NtProtectVirtualMemory(NtCurrentProcess(),
&IATBase,
&IATSize,
PAGE_READWRITE,
&OldProtect);
if (!NT_SUCCESS(Status))
{
DPRINT1("Failed to unprotect IAT.\n");
return(Status);
}
/* Walk through function list and fixup addresses. */
while (*FunctionNameList != 0L)
{
if ((*FunctionNameList) & 0x80000000)
{
Ordinal = (*FunctionNameList) & 0x7fffffff;
*ImportAddressList = LdrGetExportByOrdinal(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(Module->DllBase, *FunctionNameList);
*ImportAddressList = LdrGetExportByName(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++;
}
/* Protect the region we are about to write into. */
Status = NtProtectVirtualMemory(NtCurrentProcess(),
&IATBase,
&IATSize,
OldProtect,
&OldProtect);
if (!NT_SUCCESS(Status))
{
DPRINT1("Failed to protect IAT.\n");
return(Status);
}
return STATUS_SUCCESS;
}
static NTSTATUS
LdrpProcessImportDirectory(
PLDR_DATA_TABLE_ENTRY Module,
PLDR_DATA_TABLE_ENTRY ImportedModule,
PCHAR ImportedName)
{
NTSTATUS Status;
PIMAGE_IMPORT_DESCRIPTOR ImportModuleDirectory;
PCHAR Name;
ULONG Size;
DPRINT("LdrpProcessImportDirectory(%p '%wZ', '%s')\n",
Module, &Module->BaseDllName, ImportedName);
ImportModuleDirectory = (PIMAGE_IMPORT_DESCRIPTOR)
RtlImageDirectoryEntryToData(Module->DllBase,
TRUE,
IMAGE_DIRECTORY_ENTRY_IMPORT,
&Size);
if (ImportModuleDirectory == NULL)
{
return STATUS_UNSUCCESSFUL;
}
while (ImportModuleDirectory->Name)
{
Name = (PCHAR)Module->DllBase + ImportModuleDirectory->Name;
if (0 == _stricmp(Name, ImportedName))
{
Status = LdrpProcessImportDirectoryEntry(Module,
ImportedModule,
ImportModuleDirectory);
if (!NT_SUCCESS(Status))
{
return Status;
}
}
ImportModuleDirectory++;
}
return STATUS_SUCCESS;
}
static NTSTATUS
LdrpAdjustImportDirectory(PLDR_DATA_TABLE_ENTRY Module,
PLDR_DATA_TABLE_ENTRY ImportedModule,
PCHAR ImportedName)
{
PIMAGE_IMPORT_DESCRIPTOR ImportModuleDirectory;
NTSTATUS Status;
PVOID* ImportAddressList;
PVOID Start;
PVOID End;
PULONG FunctionNameList;
PVOID IATBase;
ULONG OldProtect;
ULONG Offset;
ULONG IATSize;
PIMAGE_NT_HEADERS NTHeaders;
PCHAR Name;
ULONG Size;
DPRINT("LdrpAdjustImportDirectory(Module %p '%wZ', %p '%wZ', '%s')\n",
Module, &Module->BaseDllName, ImportedModule, &ImportedModule->BaseDllName, ImportedName);
ImportModuleDirectory = (PIMAGE_IMPORT_DESCRIPTOR)
RtlImageDirectoryEntryToData(Module->DllBase,
TRUE,
IMAGE_DIRECTORY_ENTRY_IMPORT,
&Size);
if (ImportModuleDirectory == NULL)
{
return STATUS_UNSUCCESSFUL;
}
while (ImportModuleDirectory->Name)
{
Name = (PCHAR)Module->DllBase + ImportModuleDirectory->Name;
if (0 == _stricmp(Name, (PCHAR)ImportedName))
{
/* Get the import address list. */
ImportAddressList = (PVOID *)((ULONG_PTR)Module->DllBase + (ULONG_PTR)ImportModuleDirectory->FirstThunk);
/* Get the list of functions to import. */
if (ImportModuleDirectory->OriginalFirstThunk != 0)
{
FunctionNameList = (PULONG) ((ULONG_PTR)Module->DllBase + (ULONG_PTR)ImportModuleDirectory->OriginalFirstThunk);
}
else
{
FunctionNameList = (PULONG)((ULONG_PTR)Module->DllBase + (ULONG_PTR)ImportModuleDirectory->FirstThunk);
}
/* Get the size of IAT. */
IATSize = 0;
while (FunctionNameList[IATSize] != 0L)
{
IATSize++;
}
/* Unprotect the region we are about to write into. */
IATBase = (PVOID)ImportAddressList;
IATSize *= sizeof(PVOID*);
Status = NtProtectVirtualMemory(NtCurrentProcess(),
&IATBase,
&IATSize,
PAGE_READWRITE,
&OldProtect);
if (!NT_SUCCESS(Status))
{
DPRINT1("Failed to unprotect IAT.\n");
return(Status);
}
NTHeaders = RtlImageNtHeader (ImportedModule->DllBase);
Start = (PVOID)NTHeaders->OptionalHeader.ImageBase;
End = (PVOID)((ULONG_PTR)Start + ImportedModule->SizeOfImage);
Offset = (ULONG)((ULONG_PTR)ImportedModule->DllBase - (ULONG_PTR)Start);
/* Walk through function list and fixup addresses. */
while (*FunctionNameList != 0L)
{
if (*ImportAddressList >= Start && *ImportAddressList < End)
{
(*ImportAddressList) = (PVOID)((ULONG_PTR)(*ImportAddressList) + Offset);
}
ImportAddressList++;
FunctionNameList++;
}
/* Protect the region we are about to write into. */
Status = NtProtectVirtualMemory(NtCurrentProcess(),
&IATBase,
&IATSize,
OldProtect,
&OldProtect);
if (!NT_SUCCESS(Status))
{
DPRINT1("Failed to protect IAT.\n");
return(Status);
}
}
ImportModuleDirectory++;
}
return STATUS_SUCCESS;
}
/**********************************************************************
* NAME LOCAL
* LdrFixupImports
*
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -