mirror of
https://github.com/bb107/MemoryModulePP
synced 2026-06-08 13:15:33 +00:00
support win8.1
This commit is contained in:
@@ -0,0 +1,38 @@
|
||||
#include "LoadDllMemoryApi.h"
|
||||
#include "Native.h"
|
||||
|
||||
HMEMORYMODULE WINAPI LoadLibraryMemory(PVOID BufferAddress) {
|
||||
HMEMORYMODULE hMemoryModule = nullptr;
|
||||
NTSTATUS status = NtLoadDllMemory(&hMemoryModule, BufferAddress, 0);
|
||||
if (!NT_SUCCESS(status)) {
|
||||
SetLastError(RtlNtStatusToDosError(status));
|
||||
}
|
||||
return hMemoryModule;
|
||||
}
|
||||
|
||||
HMEMORYMODULE WINAPI LoadLibraryMemoryExA(PVOID BufferAddress, size_t Reserved, LPCSTR DllBaseName, LPCSTR DllFullName, DWORD Flags) {
|
||||
HMEMORYMODULE hMemoryModule = nullptr;
|
||||
NTSTATUS status = NtLoadDllMemoryExA(&hMemoryModule, nullptr, Flags, BufferAddress, Reserved, DllBaseName, DllFullName);
|
||||
if (!NT_SUCCESS(status)) {
|
||||
SetLastError(RtlNtStatusToDosError(status));
|
||||
}
|
||||
return hMemoryModule;
|
||||
}
|
||||
|
||||
HMEMORYMODULE WINAPI LoadLibraryMemoryExW(PVOID BufferAddress, size_t Reserved, LPCWSTR DllBaseName, LPCWSTR DllFullName, DWORD Flags) {
|
||||
HMEMORYMODULE hMemoryModule = nullptr;
|
||||
NTSTATUS status = NtLoadDllMemoryExW(&hMemoryModule, nullptr, Flags, BufferAddress, Reserved, DllBaseName, DllFullName);
|
||||
if (!NT_SUCCESS(status)) {
|
||||
SetLastError(RtlNtStatusToDosError(status));
|
||||
}
|
||||
return hMemoryModule;
|
||||
}
|
||||
|
||||
BOOL WINAPI FreeLibraryMemory(HMEMORYMODULE hMemoryModule) {
|
||||
NTSTATUS status = NtUnloadDllMemory(hMemoryModule);
|
||||
if (!NT_SUCCESS(status)) {
|
||||
SetLastError(RtlNtStatusToDosError(status));
|
||||
return FALSE;
|
||||
}
|
||||
return TRUE;
|
||||
}
|
||||
@@ -1,72 +1,49 @@
|
||||
#pragma once
|
||||
#include <Windows.h>
|
||||
typedef PVOID HMEMORYMODULE, HMEMORYRSRC;
|
||||
typedef HMODULE HMEMORYMODULE;
|
||||
typedef PVOID HMEMORYRSRC;
|
||||
|
||||
#define MemoryModuleToModule(_hMemoryModule_) (HMODULE(_hMemoryModule_))
|
||||
|
||||
#ifndef NT_SUCCESS
|
||||
#define NT_SUCCESS(Status) (((NTSTATUS)(Status)) >= 0)
|
||||
#endif
|
||||
|
||||
//Deprecated API
|
||||
#ifndef _DEPRECATED
|
||||
/**
|
||||
* Load DLL from memory location with the given size.
|
||||
*
|
||||
* All dependencies are resolved using default LoadLibrary/GetProcAddress
|
||||
* calls through the Windows API.
|
||||
*/
|
||||
|
||||
NOT_BUILD_WINDOWS_DEPRECATE
|
||||
__drv_preferredFunction("NtLoadDllMemory*", "Deprecated. Use NtLoadDllMemory or NtLoadDllMemoryEx.")
|
||||
__drv_preferredFunction("LoadLibraryMemory", "Deprecated. Use LoadLibraryMemory.")
|
||||
HMEMORYMODULE MemoryLoadLibrary(const void*);
|
||||
|
||||
/**
|
||||
* Get address of exported method. Supports loading both by name and by
|
||||
* ordinal value.
|
||||
*/
|
||||
NOT_BUILD_WINDOWS_DEPRECATE
|
||||
__drv_preferredFunction("GetProcAddress", "Deprecated. Use Win32API GetProcAddress.")
|
||||
FARPROC MemoryGetProcAddress(HMEMORYMODULE, LPCSTR);
|
||||
|
||||
/**
|
||||
* Free previously loaded DLL.
|
||||
*/
|
||||
NOT_BUILD_WINDOWS_DEPRECATE
|
||||
__drv_preferredFunction("NtUnloadDllMemory", "Deprecated. Use NtUnloadDllMemory.")
|
||||
__drv_preferredFunction("FreeLibrayMemory", "Deprecated. Use FreeLibrayMemory.")
|
||||
bool MemoryFreeLibrary(HMEMORYMODULE);
|
||||
|
||||
/**
|
||||
* Find the location of a resource with the specified type and name.
|
||||
*/
|
||||
NOT_BUILD_WINDOWS_DEPRECATE
|
||||
__drv_preferredFunction("FindResource", "Deprecated. Use Win32API FindResource.")
|
||||
HMEMORYRSRC MemoryFindResource(HMEMORYMODULE, LPCTSTR, LPCTSTR);
|
||||
|
||||
/**
|
||||
* Find the location of a resource with the specified type, name and language.
|
||||
*/
|
||||
NOT_BUILD_WINDOWS_DEPRECATE
|
||||
__drv_preferredFunction("FindResourceEx", "Deprecated. Use Win32API FindResourceEx.")
|
||||
HMEMORYRSRC MemoryFindResourceEx(HMEMORYMODULE, LPCTSTR, LPCTSTR, WORD);
|
||||
|
||||
/**
|
||||
* Get the size of the resource in bytes.
|
||||
*/
|
||||
NOT_BUILD_WINDOWS_DEPRECATE
|
||||
__drv_preferredFunction("SizeofResource", "Deprecated. Use Win32API SizeofResource.")
|
||||
DWORD MemorySizeofResource(HMEMORYMODULE, HMEMORYRSRC);
|
||||
|
||||
/**
|
||||
* Get a pointer to the contents of the resource.
|
||||
*/
|
||||
NOT_BUILD_WINDOWS_DEPRECATE
|
||||
__drv_preferredFunction("LoadResource", "Deprecated. Use Win32API LoadResource.")
|
||||
LPVOID MemoryLoadResource(HMEMORYMODULE, HMEMORYRSRC);
|
||||
|
||||
/**
|
||||
* Load a string resource.
|
||||
*/
|
||||
NOT_BUILD_WINDOWS_DEPRECATE
|
||||
__drv_preferredFunction("LoadString*", "Deprecated. Use Win32API LoadStringA or LoadStringW.")
|
||||
int MemoryLoadString(HMEMORYMODULE, UINT, LPTSTR, int);
|
||||
|
||||
/**
|
||||
* Load a string resource with a given language.
|
||||
*/
|
||||
NOT_BUILD_WINDOWS_DEPRECATE
|
||||
__drv_preferredFunction("LoadString*", "Deprecated. Use Win32API LoadStringA or LoadStringW.")
|
||||
int MemoryLoadStringEx(HMEMORYMODULE, UINT, LPTSTR, int, WORD);
|
||||
@@ -104,6 +81,9 @@ NTSTATUS NTAPI NtLoadDllMemory(
|
||||
//If this flag is specified, this routine will not fail even if the call to LdrpTlsData fails.
|
||||
#define LOAD_FLAGS_NOT_FAIL_IF_HANDLE_TLS 0x20000000
|
||||
|
||||
//If this flag is specified, the input image buffer will not be checked before loading.
|
||||
#define LOAD_FLAGS_PASS_IMAGE_CHECK 0x40000000
|
||||
|
||||
//If this flag is specified, exception handling will not be supported.
|
||||
#define LOAD_FLAGS_NOT_ADD_INVERTED_FUNCTION 0x00000001
|
||||
|
||||
@@ -157,15 +137,21 @@ extern "C" {
|
||||
__declspec(noreturn) VOID NTAPI NtUnloadDllMemoryAndExitThread(IN HMEMORYMODULE BaseAddress, IN DWORD dwExitCode);
|
||||
}
|
||||
|
||||
#define LoadLibraryMemory NtLoadDllMemory
|
||||
#define FreeLibraryMemory NtUnloadDllMemory
|
||||
HMEMORYMODULE WINAPI LoadLibraryMemory(PVOID BufferAddress);
|
||||
|
||||
HMEMORYMODULE WINAPI LoadLibraryMemoryExA(PVOID BufferAddress, size_t Reserved, LPCSTR DllBaseName, LPCSTR DllFullName, DWORD Flags);
|
||||
|
||||
HMEMORYMODULE WINAPI LoadLibraryMemoryExW(PVOID BufferAddress, size_t Reserved, LPCWSTR DllBaseName, LPCWSTR DllFullName, DWORD Flags);
|
||||
|
||||
BOOL WINAPI FreeLibraryMemory(HMEMORYMODULE hMemoryModule);
|
||||
|
||||
#define FreeLibraryMemoryAndExitThread NtUnloadDllMemoryAndExitThread
|
||||
#ifdef UNICODE
|
||||
#define NtLoadDllMemoryEx NtLoadDllMemoryExW
|
||||
#define LoadLibraryMemoryEx NtLoadDllMemoryExW
|
||||
#define LoadLibraryMemoryEx LoadLibraryMemoryExW
|
||||
#else
|
||||
#define NtLoadDllMemoryEx NtLoadDllMemoryExA
|
||||
#define LoadLibraryMemoryEx NtLoadDllMemoryExA
|
||||
#define LoadLibraryMemoryEx LoadLibraryMemoryExA
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
+121
-103
@@ -28,7 +28,7 @@ static PIMAGE_NT_HEADERS WINAPI GetImageNtHeaders(PMEMORYMODULE pModule) {
|
||||
if (pModule->Signature != MEMORY_MODULE_SIGNATURE)return nullptr;
|
||||
PIMAGE_DOS_HEADER dos = (PIMAGE_DOS_HEADER)((LPBYTE)pModule - pModule->SizeofHeaders);
|
||||
PIMAGE_NT_HEADERS headers = (PIMAGE_NT_HEADERS)((LPBYTE)dos + dos->e_lfanew);
|
||||
if (headers->OptionalHeader.ImageBase /*+ pModule->headers_align*/ != (ULONG64)pModule->codeBase)return nullptr;
|
||||
if (headers->OptionalHeader.ImageBase != (ULONG64)pModule->codeBase)return nullptr;
|
||||
return headers;
|
||||
}
|
||||
|
||||
@@ -109,53 +109,35 @@ static int ProtectionFlags[2][2][2] = {
|
||||
{PAGE_EXECUTE_READ, PAGE_EXECUTE_READWRITE},
|
||||
},
|
||||
};
|
||||
static SIZE_T GetRealSectionSize(PMEMORYMODULE module, PIMAGE_SECTION_HEADER section);
|
||||
static VOID FinalSectionsProtect(PMEMORYMODULE module) {
|
||||
PIMAGE_NT_HEADERS headers = GetImageNtHeaders(module);
|
||||
PIMAGE_SECTION_HEADER sections = IMAGE_FIRST_SECTION(headers);
|
||||
DWORD protect, oldProtect;
|
||||
bool executable, readable, writeable;
|
||||
#ifdef _WIN64
|
||||
uintptr_t imageOffset = ((uintptr_t)headers->OptionalHeader.ImageBase & 0xffffffff00000000);
|
||||
#else
|
||||
static const uintptr_t imageOffset = 0;
|
||||
#endif
|
||||
for (WORD i = 0; i < headers->FileHeader.NumberOfSections; ++i, ++sections) {
|
||||
executable = (sections->Characteristics & IMAGE_SCN_MEM_EXECUTE);
|
||||
readable = (sections->Characteristics & IMAGE_SCN_MEM_READ);
|
||||
writeable = (sections->Characteristics & IMAGE_SCN_MEM_WRITE);
|
||||
protect = ProtectionFlags[executable][readable][writeable];
|
||||
if (sections->Characteristics & IMAGE_SCN_MEM_NOT_CACHED) protect |= PAGE_NOCACHE;
|
||||
VirtualProtect((LPVOID)((uintptr_t)sections->Misc.PhysicalAddress | imageOffset),
|
||||
GetRealSectionSize(module, sections), protect, &oldProtect);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
static BOOL CopySections(const unsigned char* data, PMEMORYMODULE module) {
|
||||
LPBYTE codeBase = module->codeBase;
|
||||
LPVOID dest;
|
||||
PIMAGE_NT_HEADERS headers = GetImageNtHeaders(module);
|
||||
PIMAGE_SECTION_HEADER section = IMAGE_FIRST_SECTION(headers);
|
||||
PIMAGE_SECTION_HEADER section = headers ? IMAGE_FIRST_SECTION(headers) : nullptr;
|
||||
size_t alloc_size = 0;
|
||||
bool cp = false;
|
||||
|
||||
if (!headers) {
|
||||
SetLastError(ERROR_BAD_EXE_FORMAT);
|
||||
return FALSE;
|
||||
}
|
||||
for (int i = 0; i < headers->FileHeader.NumberOfSections; i++, section++) {
|
||||
alloc_size = headers->OptionalHeader.SectionAlignment;
|
||||
cp = false;
|
||||
if (section->SizeOfRawData) {
|
||||
__try {
|
||||
ProbeForRead(data, static_cast<size_t>(section->PointerToRawData) + section->SizeOfRawData);
|
||||
ProbeForRead(data + static_cast<size_t>(section->PointerToRawData), section->SizeOfRawData);
|
||||
}
|
||||
__except (EXCEPTION_EXECUTE_HANDLER) {
|
||||
SetLastError(ERROR_BAD_EXE_FORMAT);
|
||||
return FALSE;
|
||||
}
|
||||
alloc_size = section->SizeOfRawData;
|
||||
cp = true;
|
||||
}
|
||||
if (alloc_size) {
|
||||
if (!(dest = VirtualAlloc(codeBase + section->VirtualAddress, alloc_size, MEM_COMMIT, PAGE_READWRITE))) {
|
||||
//section = IMAGE_FIRST_SECTION(headers);
|
||||
//for (int j = 0; j < i; ++j, ++section)VirtualFree(codeBase + section->VirtualAddress, 0, MEM_RELEASE);
|
||||
if (!(dest = VirtualAlloc((LPSTR)headers->OptionalHeader.ImageBase + section->VirtualAddress, alloc_size, MEM_COMMIT, PAGE_READWRITE))) {
|
||||
SetLastError(ERROR_OUTOFMEMORY);
|
||||
return FALSE;
|
||||
}
|
||||
section->Misc.PhysicalAddress = (DWORD)((uintptr_t)dest & 0xffffffff);
|
||||
@@ -184,18 +166,34 @@ static SIZE_T GetRealSectionSize(PMEMORYMODULE module, PIMAGE_SECTION_HEADER sec
|
||||
}
|
||||
|
||||
static BOOL FinalizeSection(PMEMORYMODULE module, PSECTIONFINALIZEDATA sectionData) {
|
||||
DWORD protect, oldProtect;
|
||||
BOOL executable;
|
||||
BOOL readable;
|
||||
BOOL writeable;
|
||||
PIMAGE_NT_HEADERS headers = GetImageNtHeaders(module);
|
||||
|
||||
if (!sectionData->size) return TRUE;
|
||||
if (sectionData->characteristics & IMAGE_SCN_MEM_DISCARDABLE) {
|
||||
// section is not needed any more and can safely be freed
|
||||
if (sectionData->address == sectionData->alignedAddress &&
|
||||
(sectionData->last || GetImageNtHeaders(module)->OptionalHeader.SectionAlignment == module->pageSize || !(sectionData->size % module->pageSize))) {
|
||||
#pragma warning (disable:6250)
|
||||
(sectionData->last || headers->OptionalHeader.SectionAlignment == module->pageSize ||
|
||||
(sectionData->size % module->pageSize) == 0)
|
||||
)
|
||||
#pragma warning(disable:6250)
|
||||
VirtualFree(sectionData->address, sectionData->size, MEM_DECOMMIT);
|
||||
#pragma warning (default:6250)
|
||||
}
|
||||
#pragma warning(default:6250)
|
||||
return TRUE;
|
||||
}
|
||||
return TRUE;
|
||||
|
||||
// determine protection flags based on characteristics
|
||||
executable = (sectionData->characteristics & IMAGE_SCN_MEM_EXECUTE) != 0;
|
||||
readable = (sectionData->characteristics & IMAGE_SCN_MEM_READ) != 0;
|
||||
writeable = (sectionData->characteristics & IMAGE_SCN_MEM_WRITE) != 0;
|
||||
protect = ProtectionFlags[executable][readable][writeable];
|
||||
if (sectionData->characteristics & IMAGE_SCN_MEM_NOT_CACHED) protect |= PAGE_NOCACHE;
|
||||
|
||||
// change memory access flags
|
||||
return VirtualProtect(sectionData->address, sectionData->size, protect, &oldProtect);
|
||||
}
|
||||
|
||||
static BOOL FinalizeSections(PMEMORYMODULE module) {
|
||||
@@ -214,16 +212,17 @@ static BOOL FinalizeSections(PMEMORYMODULE module) {
|
||||
sectionData.last = FALSE;
|
||||
section++;
|
||||
|
||||
// loop through all sections and change access flags
|
||||
for (int i = 1; i < headers->FileHeader.NumberOfSections; i++, section++) {
|
||||
LPVOID sectionAddress = (LPVOID)((uintptr_t)section->Misc.PhysicalAddress | imageOffset);
|
||||
LPVOID alignedAddress = AlignAddressDown(sectionAddress, module->pageSize);
|
||||
SIZE_T sectionSize = GetRealSectionSize(module, section);
|
||||
if (sectionData.alignedAddress == alignedAddress || (uintptr_t)sectionData.address + sectionData.size > (uintptr_t) alignedAddress) {
|
||||
if (!(section->Characteristics & IMAGE_SCN_MEM_DISCARDABLE) || !(sectionData.characteristics & IMAGE_SCN_MEM_DISCARDABLE))
|
||||
if ((section->Characteristics & IMAGE_SCN_MEM_DISCARDABLE) == 0 || (sectionData.characteristics & IMAGE_SCN_MEM_DISCARDABLE) == 0) {
|
||||
sectionData.characteristics = (sectionData.characteristics | section->Characteristics) & ~IMAGE_SCN_MEM_DISCARDABLE;
|
||||
else
|
||||
}
|
||||
else {
|
||||
sectionData.characteristics |= section->Characteristics;
|
||||
}
|
||||
sectionData.size = (((uintptr_t)sectionAddress) + ((uintptr_t)sectionSize)) - (uintptr_t)sectionData.address;
|
||||
continue;
|
||||
}
|
||||
@@ -293,68 +292,80 @@ static BOOL PerformBaseRelocation(PMEMORYMODULE module, ptrdiff_t delta) {
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static BOOL GetImportAddressTableEntryCountAndVerify(PMEMORYMODULE module, LPDWORD Count, PIMAGE_IMPORT_DESCRIPTOR* IAT) {
|
||||
__try {
|
||||
PIMAGE_NT_HEADERS headers = GetImageNtHeaders(module);
|
||||
PIMAGE_DATA_DIRECTORY dir = GET_HEADER_DICTIONARY(headers, IMAGE_DIRECTORY_ENTRY_IMPORT);
|
||||
PIMAGE_IMPORT_DESCRIPTOR iat = *IAT = (dir && dir->Size) ? decltype(iat)(headers->OptionalHeader.ImageBase + dir->VirtualAddress) : nullptr;
|
||||
*Count = 0;
|
||||
if (!iat)return TRUE;
|
||||
ProbeForRead(iat, sizeof(IMAGE_IMPORT_DESCRIPTOR));
|
||||
while (iat->Name) {
|
||||
++*Count;
|
||||
++iat;
|
||||
ProbeForRead(iat, sizeof(IMAGE_IMPORT_DESCRIPTOR));
|
||||
}
|
||||
return TRUE;
|
||||
}
|
||||
__except (EXCEPTION_EXECUTE_HANDLER) {
|
||||
SetLastError(RtlNtStatusToDosError(GetExceptionCode()));
|
||||
return FALSE;
|
||||
}
|
||||
}
|
||||
static void FreeLoadedModule(PMEMORYMODULE module) {
|
||||
for (DWORD i = 0; i < module->dwModulesCount; ++i) FreeLibrary(module->hModulesList[i]);
|
||||
delete[]module->hModulesList;
|
||||
module->hModulesList = nullptr;
|
||||
module->dwModulesCount = 0;
|
||||
return;
|
||||
}
|
||||
static BOOL BuildImportTable(PMEMORYMODULE module) {
|
||||
unsigned char* codeBase = module->codeBase;
|
||||
PIMAGE_IMPORT_DESCRIPTOR importDesc;
|
||||
BOOL result = TRUE;
|
||||
PIMAGE_NT_HEADERS headers = GetImageNtHeaders(module);
|
||||
PIMAGE_DATA_DIRECTORY directory = GET_HEADER_DICTIONARY(headers, IMAGE_DIRECTORY_ENTRY_IMPORT);
|
||||
if (directory->Size == 0) {
|
||||
return TRUE;
|
||||
DWORD count;
|
||||
if (!GetImportAddressTableEntryCountAndVerify(module, &count, &importDesc)) {
|
||||
SetLastError(ERROR_BAD_EXE_FORMAT);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
importDesc = (PIMAGE_IMPORT_DESCRIPTOR)(codeBase + directory->VirtualAddress);
|
||||
for (; !IsBadReadPtr(importDesc, sizeof(IMAGE_IMPORT_DESCRIPTOR)) && importDesc->Name; importDesc++) {
|
||||
uintptr_t* thunkRef;
|
||||
FARPROC* funcRef;
|
||||
HMODULE* tmp;
|
||||
HMODULE handle = LoadLibraryA((LPCSTR)(codeBase + importDesc->Name));
|
||||
if (!handle) {
|
||||
SetLastError(ERROR_MOD_NOT_FOUND);
|
||||
result = FALSE;
|
||||
break;
|
||||
}
|
||||
|
||||
if (!(tmp = (HMODULE*)realloc(module->hModulesList, (static_cast<size_t>(module->dwModulesCount) + 1)* (sizeof(HMODULE))))) {
|
||||
FreeLibrary(handle);
|
||||
SetLastError(ERROR_OUTOFMEMORY);
|
||||
result = FALSE;
|
||||
break;
|
||||
}
|
||||
module->hModulesList = tmp;
|
||||
|
||||
module->hModulesList[module->dwModulesCount++] = handle;
|
||||
if (importDesc->OriginalFirstThunk) {
|
||||
thunkRef = (uintptr_t*)(codeBase + importDesc->OriginalFirstThunk);
|
||||
if (!importDesc || !count)return TRUE;
|
||||
if (!(module->hModulesList = new HMODULE[count])) {
|
||||
SetLastError(ERROR_OUTOFMEMORY);
|
||||
return FALSE;
|
||||
}
|
||||
RtlZeroMemory(module->hModulesList, sizeof(HMODULE) * count);
|
||||
__try {
|
||||
for (DWORD i = 0; i < count; ++i, ++importDesc) {
|
||||
uintptr_t* thunkRef;
|
||||
FARPROC* funcRef;
|
||||
HMODULE handle = LoadLibraryA((LPCSTR)(codeBase + importDesc->Name));
|
||||
if (!handle) {
|
||||
FreeLoadedModule(module);
|
||||
SetLastError(ERROR_MOD_NOT_FOUND);
|
||||
return FALSE;
|
||||
}
|
||||
module->hModulesList[module->dwModulesCount++] = handle;
|
||||
thunkRef = (uintptr_t*)(codeBase + (importDesc->OriginalFirstThunk ? importDesc->OriginalFirstThunk : importDesc->FirstThunk));
|
||||
funcRef = (FARPROC*)(codeBase + importDesc->FirstThunk);
|
||||
}
|
||||
else {
|
||||
// no hint table
|
||||
thunkRef = (uintptr_t*)(codeBase + importDesc->FirstThunk);
|
||||
funcRef = (FARPROC*)(codeBase + importDesc->FirstThunk);
|
||||
}
|
||||
for (; *thunkRef; thunkRef++, funcRef++) {
|
||||
if (IMAGE_SNAP_BY_ORDINAL(*thunkRef)) {
|
||||
*funcRef = GetProcAddress(handle, (LPCSTR)IMAGE_ORDINAL(*thunkRef));
|
||||
while (*thunkRef) {
|
||||
*funcRef = GetProcAddress(
|
||||
handle,
|
||||
IMAGE_SNAP_BY_ORDINAL(*thunkRef) ? (LPCSTR)IMAGE_ORDINAL(*thunkRef) : (LPCSTR)PIMAGE_IMPORT_BY_NAME(codeBase + (*thunkRef))->Name
|
||||
);
|
||||
if (!*funcRef) {
|
||||
FreeLoadedModule(module);
|
||||
SetLastError(ERROR_PROC_NOT_FOUND);
|
||||
return FALSE;
|
||||
}
|
||||
++thunkRef;
|
||||
++funcRef;
|
||||
}
|
||||
else {
|
||||
PIMAGE_IMPORT_BY_NAME thunkData = (PIMAGE_IMPORT_BY_NAME)(codeBase + (*thunkRef));
|
||||
*funcRef = GetProcAddress(handle, (LPCSTR)&thunkData->Name);
|
||||
}
|
||||
if (*funcRef == 0) {
|
||||
result = FALSE;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (!result) {
|
||||
FreeLibrary(handle);
|
||||
SetLastError(ERROR_PROC_NOT_FOUND);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
__except (EXCEPTION_EXECUTE_HANDLER) {
|
||||
SetLastError(RtlNtStatusToDosError(GetExceptionCode()));
|
||||
return FALSE;
|
||||
}
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
HMEMORYMODULE MemoryLoadLibrary(const void* data) {
|
||||
@@ -423,7 +434,7 @@ HMEMORYMODULE MemoryLoadLibrary(const void* data) {
|
||||
SetLastError(ERROR_BAD_EXE_FORMAT);
|
||||
return nullptr;
|
||||
}
|
||||
alignedImageSize += headers_align = (DWORD)AlignValueUp(sizeof(HMEMORYMODULE) + old_header->OptionalHeader.SizeOfHeaders, sysInfo.dwPageSize);
|
||||
alignedImageSize += headers_align = (DWORD)AlignValueUp(sizeof(MEMORYMODULE) + old_header->OptionalHeader.SizeOfHeaders, sysInfo.dwPageSize);
|
||||
|
||||
// reserve memory for image of library
|
||||
// XXX: is it correct to commit the complete memory region at once?
|
||||
@@ -494,7 +505,6 @@ HMEMORYMODULE MemoryLoadLibrary(const void* data) {
|
||||
// mark memory pages depending on section headers and release
|
||||
// sections that are marked as "discardable"
|
||||
if (!FinalizeSections(hMemoryModule)) goto error;
|
||||
FinalSectionsProtect(hMemoryModule);
|
||||
|
||||
// TLS callbacks are executed BEFORE the main loading
|
||||
if (!ExecuteTLS(hMemoryModule)) goto error;
|
||||
@@ -509,16 +519,16 @@ HMEMORYMODULE MemoryLoadLibrary(const void* data) {
|
||||
}
|
||||
}
|
||||
__except (EXCEPTION_EXECUTE_HANDLER) {
|
||||
SetLastError(ERROR_ACCESS_DENIED);
|
||||
SetLastError(RtlNtStatusToDosError(GetExceptionCode()));
|
||||
goto error;
|
||||
}
|
||||
hMemoryModule->initialized = TRUE;
|
||||
}
|
||||
|
||||
return base;
|
||||
return (HMEMORYMODULE)base;
|
||||
error:
|
||||
// cleanup
|
||||
MemoryFreeLibrary(hMemoryModule);
|
||||
MemoryFreeLibrary((HMEMORYMODULE)base);
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
@@ -533,19 +543,18 @@ bool MemoryFreeLibrary(HMEMORYMODULE mod) {
|
||||
(*DllEntry)((HINSTANCE)module->codeBase, DLL_PROCESS_DETACH, 0);
|
||||
}
|
||||
if (module->nameExportsTable)delete[] module->nameExportsTable;
|
||||
if (module->hModulesList != nullptr) {
|
||||
int i;
|
||||
for (i = 0; i < module->dwModulesCount; i++) {
|
||||
if (module->hModulesList) {
|
||||
for (DWORD i = 0; i < module->dwModulesCount; ++i) {
|
||||
if (module->hModulesList[i]) {
|
||||
FreeLibrary(module->hModulesList[i]);
|
||||
}
|
||||
}
|
||||
free(module->hModulesList);
|
||||
delete[] module->hModulesList;
|
||||
}
|
||||
#ifdef _WIN64
|
||||
FreePointerList(module->blockedMemory);
|
||||
#endif
|
||||
if (module->codeBase != nullptr) VirtualFree(mod, 0, MEM_RELEASE);
|
||||
if (module->codeBase) VirtualFree(mod, 0, MEM_RELEASE);
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -570,7 +579,11 @@ FARPROC MemoryGetProcAddress(HMEMORYMODULE mod, LPCSTR name) {
|
||||
DWORD idx = 0;
|
||||
PIMAGE_EXPORT_DIRECTORY exports;
|
||||
PIMAGE_NT_HEADERS headers = GetImageNtHeaders(module);
|
||||
PIMAGE_DATA_DIRECTORY directory = GET_HEADER_DICTIONARY(headers, IMAGE_DIRECTORY_ENTRY_EXPORT);
|
||||
PIMAGE_DATA_DIRECTORY directory = headers ? GET_HEADER_DICTIONARY(headers, IMAGE_DIRECTORY_ENTRY_EXPORT) : nullptr;
|
||||
if (!headers) {
|
||||
SetLastError(ERROR_INVALID_HANDLE);
|
||||
return nullptr;
|
||||
}
|
||||
if (directory->Size == 0) {
|
||||
// no export table found
|
||||
SetLastError(ERROR_PROC_NOT_FOUND);
|
||||
@@ -756,13 +769,18 @@ static PIMAGE_RESOURCE_DIRECTORY_ENTRY _MemorySearchResourceEntry(void* root, PI
|
||||
HMEMORYRSRC MemoryFindResourceEx(HMEMORYMODULE module, LPCTSTR name, LPCTSTR type, WORD language) {
|
||||
PMEMORYMODULE mod = MapMemoryModuleHandle(module);
|
||||
unsigned char* codeBase = mod->codeBase;
|
||||
PIMAGE_DATA_DIRECTORY directory = GET_HEADER_DICTIONARY(GetImageNtHeaders(mod), IMAGE_DIRECTORY_ENTRY_RESOURCE);
|
||||
PIMAGE_NT_HEADERS headers = GetImageNtHeaders(mod);
|
||||
PIMAGE_DATA_DIRECTORY directory = headers ? GET_HEADER_DICTIONARY(headers, IMAGE_DIRECTORY_ENTRY_RESOURCE) : nullptr;
|
||||
PIMAGE_RESOURCE_DIRECTORY rootResources;
|
||||
PIMAGE_RESOURCE_DIRECTORY nameResources;
|
||||
PIMAGE_RESOURCE_DIRECTORY typeResources;
|
||||
PIMAGE_RESOURCE_DIRECTORY_ENTRY foundType;
|
||||
PIMAGE_RESOURCE_DIRECTORY_ENTRY foundName;
|
||||
PIMAGE_RESOURCE_DIRECTORY_ENTRY foundLanguage;
|
||||
if (!headers) {
|
||||
SetLastError(ERROR_INVALID_HANDLE);
|
||||
return nullptr;
|
||||
}
|
||||
if (directory->Size == 0) {
|
||||
// no resource table found
|
||||
SetLastError(ERROR_RESOURCE_DATA_NOT_FOUND);
|
||||
|
||||
@@ -24,7 +24,7 @@ typedef struct POINTER_LIST {
|
||||
void* address;
|
||||
} POINTER_LIST;
|
||||
#endif
|
||||
typedef void* HMEMORYMODULE;
|
||||
typedef HMODULE HMEMORYMODULE;
|
||||
typedef void* HMEMORYRSRC;
|
||||
typedef struct _MEMORYMODULE {
|
||||
/*
|
||||
|
||||
@@ -19,6 +19,7 @@
|
||||
</ProjectConfiguration>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClCompile Include="LoadDllMemoryApi.cpp" />
|
||||
<ClCompile Include="MemoryModule.cpp" />
|
||||
<ClCompile Include="Native.cpp" />
|
||||
<ClCompile Include="NativeFunctionsInternal.cpp" />
|
||||
|
||||
@@ -24,6 +24,9 @@
|
||||
<ClCompile Include="NativeFunctionsInternal.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="LoadDllMemoryApi.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClInclude Include="MemoryModule.h">
|
||||
|
||||
@@ -82,7 +82,7 @@ static ULONG NTAPI LdrHashEntry(IN const UNICODE_STRING& str, IN bool _xor = tru
|
||||
return result;
|
||||
}
|
||||
|
||||
static HANDLE NTAPI RtlFindtLdrpHeap() {
|
||||
static HANDLE NTAPI RtlFindLdrpHeap() {
|
||||
PLIST_ENTRY ListHead, ListEntry;
|
||||
PLDR_DATA_TABLE_ENTRY CurEntry;
|
||||
MEMORY_BASIC_INFORMATION mbi{};
|
||||
@@ -109,13 +109,13 @@ static PLIST_ENTRY NTAPI RtlFindLdrpHashTable() {
|
||||
}
|
||||
|
||||
static PVOID NTAPI NtAllocateLdrpHeap(IN size_t size) {
|
||||
HANDLE heap = RtlFindtLdrpHeap();
|
||||
HANDLE heap = RtlFindLdrpHeap();
|
||||
if (!heap)return nullptr;
|
||||
|
||||
return RtlAllocateHeap(heap, HEAP_ZERO_MEMORY, size);
|
||||
}
|
||||
static BOOL NTAPI NtFreeLdrpHeap(IN PVOID buffer) {
|
||||
HANDLE LdrpHeap = RtlFindtLdrpHeap();
|
||||
HANDLE LdrpHeap = RtlFindLdrpHeap();
|
||||
if (!LdrpHeap)return FALSE;
|
||||
return RtlFreeHeap(LdrpHeap, 0, buffer);
|
||||
}
|
||||
@@ -455,7 +455,19 @@ static bool NTAPI NtFreeLdrDataTableEntry(IN PLDR_DATA_TABLE_ENTRY LdrEntry) {
|
||||
NtRemoveModuleBaseAddressIndexNode(LdrEntry);
|
||||
}
|
||||
case win7:
|
||||
case vista:
|
||||
case vista: {
|
||||
if (NtLdrDataTableEntrySize() == sizeof(LDR_DATA_TABLE_ENTRY_VISTA) ||
|
||||
NtLdrDataTableEntrySize() == sizeof(LDR_DATA_TABLE_ENTRY_WIN7)) {
|
||||
PLDR_DATA_TABLE_ENTRY_VISTA entry = (decltype(entry))LdrEntry;
|
||||
PLIST_ENTRY head = &entry->ForwarderLinks, next = head->Flink;
|
||||
while (head != next) {
|
||||
PLDR_DATA_TABLE_ENTRY dep = *(decltype(&dep))((size_t*)next + 2);
|
||||
LdrUnloadDll(dep->DllBase);
|
||||
next = next->Flink;
|
||||
NtFreeLdrpHeap(next->Blink);
|
||||
}
|
||||
}
|
||||
}
|
||||
case xp: {
|
||||
NtFreeLdrpHeap(LdrEntry->BaseDllName.Buffer);
|
||||
NtFreeLdrpHeap(LdrEntry->FullDllName.Buffer);
|
||||
@@ -646,6 +658,52 @@ static NTSTATUS NTAPI NtMapDllMemory(IN HMEMORYMODULE ViewBase, IN DWORD dwFlags
|
||||
return STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
#ifndef _INLINE_INTERNALS
|
||||
static __forceinline WORD CalcCheckSum(DWORD StartValue, LPVOID BaseAddress, DWORD WordCount) {
|
||||
LPWORD Ptr = (LPWORD)BaseAddress;
|
||||
DWORD Sum = StartValue;
|
||||
for (DWORD i = 0; i < WordCount; i++) {
|
||||
Sum += *Ptr;
|
||||
if (HIWORD(Sum) != 0) Sum = LOWORD(Sum) + HIWORD(Sum);
|
||||
Ptr++;
|
||||
}
|
||||
return (WORD)(LOWORD(Sum) + HIWORD(Sum));
|
||||
}
|
||||
BOOLEAN __forceinline WINAPI CheckSumBufferedFile(LPVOID BaseAddress, DWORD BufferLength) {
|
||||
PIMAGE_NT_HEADERS header = RtlImageNtHeader(BaseAddress);
|
||||
DWORD CalcSum = CalcCheckSum(0, BaseAddress, (BufferLength + 1) / sizeof(WORD));
|
||||
DWORD HdrSum = header->OptionalHeader.CheckSum;
|
||||
if (!HdrSum)return TRUE;
|
||||
|
||||
if (!header) return FALSE;
|
||||
if (LOWORD(CalcSum) >= LOWORD(HdrSum)) CalcSum -= LOWORD(HdrSum);
|
||||
else CalcSum = ((LOWORD(CalcSum) - LOWORD(HdrSum)) & 0xFFFF) - 1;
|
||||
if (LOWORD(CalcSum) >= HIWORD(HdrSum)) CalcSum -= HIWORD(HdrSum);
|
||||
else CalcSum = ((LOWORD(CalcSum) - HIWORD(HdrSum)) & 0xFFFF) - 1;
|
||||
CalcSum += BufferLength;
|
||||
return HdrSum == CalcSum;
|
||||
}
|
||||
#endif
|
||||
BOOLEAN NTAPI RtlIsValidImageBuffer(PVOID Buffer) {
|
||||
BOOLEAN result = FALSE;
|
||||
__try {
|
||||
PIMAGE_NT_HEADERS headers = RtlImageNtHeader(Buffer);
|
||||
PIMAGE_SECTION_HEADER sections = headers ? IMAGE_FIRST_SECTION(headers) : nullptr;
|
||||
size_t SizeofImage = headers ? headers->OptionalHeader.SizeOfHeaders : 0;
|
||||
if (!sections)return result;
|
||||
|
||||
ProbeForRead(sections, headers->FileHeader.NumberOfSections * sizeof(IMAGE_SECTION_HEADER));
|
||||
for (WORD i = 0; i < headers->FileHeader.NumberOfSections; ++i, ++sections)
|
||||
SizeofImage += sections->SizeOfRawData;
|
||||
ProbeForRead(Buffer, SizeofImage);
|
||||
result = CheckSumBufferedFile(Buffer, SizeofImage);
|
||||
}
|
||||
__except (EXCEPTION_EXECUTE_HANDLER) {
|
||||
SetLastError(RtlNtStatusToDosError(GetExceptionCode()));
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
NTSTATUS NTAPI NtLoadDllMemory(OUT HMEMORYMODULE* BaseAddress, IN LPVOID BufferAddress, IN size_t BufferSize) {
|
||||
return NtLoadDllMemoryExW(BaseAddress, nullptr, LOAD_FLAGS_NOT_FAIL_IF_HANDLE_TLS, BufferAddress, BufferSize, nullptr, nullptr);
|
||||
}
|
||||
@@ -662,13 +720,12 @@ NTSTATUS NTAPI NtLoadDllMemoryExW(
|
||||
NTSTATUS status = STATUS_SUCCESS;
|
||||
PLDR_DATA_TABLE_ENTRY ModuleEntry = nullptr;
|
||||
PIMAGE_NT_HEADERS headers = nullptr;
|
||||
UNREFERENCED_PARAMETER(BufferSize);
|
||||
|
||||
if (BufferSize)return STATUS_INVALID_PARAMETER_5;
|
||||
__try {
|
||||
//ProbeForRead(BufferAddress, BufferSize);
|
||||
if (BufferSize)status = STATUS_INVALID_PARAMETER_5;
|
||||
*BaseAddress = nullptr;
|
||||
if (LdrEntry)*LdrEntry = nullptr;
|
||||
if (!(dwFlags & LOAD_FLAGS_PASS_IMAGE_CHECK) && !RtlIsValidImageBuffer(BufferAddress))status = STATUS_INVALID_IMAGE_FORMAT;
|
||||
}
|
||||
__except (EXCEPTION_EXECUTE_HANDLER) {
|
||||
status = GetExceptionCode();
|
||||
@@ -697,13 +754,13 @@ NTSTATUS NTAPI NtLoadDllMemoryExW(
|
||||
!wcsnicmp(DllName, CurEntry->BaseDllName.Buffer, CurEntry->BaseDllName.Length / sizeof(wchar_t))) {
|
||||
/* Let's compare their headers */
|
||||
if (!(h2 = RtlImageNtHeader(CurEntry->DllBase)))continue;
|
||||
if (!(module = MapMemoryModuleHandle(CurEntry->DllBase)))continue;
|
||||
if (!(module = MapMemoryModuleHandle((HMEMORYMODULE)CurEntry->DllBase)))continue;
|
||||
if ((h1->OptionalHeader.SizeOfCode == h2->OptionalHeader.SizeOfCode) &&
|
||||
(h1->OptionalHeader.SizeOfHeaders == h2->OptionalHeader.SizeOfHeaders)) {
|
||||
/* This is our entry!, update load count and return success */
|
||||
if (!module->UseReferenceCount || dwFlags & LOAD_FLAGS_NOT_USE_REFERENCE_COUNT)return STATUS_INVALID_PARAMETER_3;
|
||||
NtUpdateReferenceCount(CurEntry, FLAG_REFERENCE);
|
||||
*BaseAddress = CurEntry->DllBase;
|
||||
*BaseAddress = (HMEMORYMODULE)CurEntry->DllBase;
|
||||
if (LdrEntry)*LdrEntry = CurEntry;
|
||||
return STATUS_SUCCESS;
|
||||
}
|
||||
@@ -880,14 +937,11 @@ static VOID NTAPI RtlpInsertInvertedFunctionTable(IN PRTL_INVERTED_FUNCTION_TABL
|
||||
PIMAGE_RUNTIME_FUNCTION_ENTRY FunctionTable;
|
||||
ULONG Index;
|
||||
ULONG SizeOfTable = 0;
|
||||
PIMAGE_NT_HEADERS headers = RtlImageNtHeader(ImageBase);
|
||||
PIMAGE_DATA_DIRECTORY dir = &headers->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_EXCEPTION];
|
||||
bool need = RtlIsWindowsVersionOrGreater(6, 2, 0);
|
||||
bool IsWin8OrGreater = RtlIsWindowsVersionOrGreater(6, 2, 0);
|
||||
|
||||
Index = (ULONG)need;
|
||||
Index = (ULONG)IsWin8OrGreater;
|
||||
CurrentSize = InvertedTable->Count;
|
||||
if (CurrentSize != InvertedTable->MaxCount) {
|
||||
//if (need)_InterlockedIncrement(&InvertedTable->Epoch);
|
||||
if (CurrentSize != 0) {
|
||||
while (Index < CurrentSize) {
|
||||
if (ImageBase < InvertedTable->Entries[Index].ImageBase)break;
|
||||
@@ -901,21 +955,15 @@ static VOID NTAPI RtlpInsertInvertedFunctionTable(IN PRTL_INVERTED_FUNCTION_TABL
|
||||
}
|
||||
}
|
||||
|
||||
FunctionTable = (decltype(FunctionTable))((size_t)ImageBase + dir->VirtualAddress);
|
||||
if (FunctionTable != RtlImageDirectoryEntryToData(ImageBase, TRUE, IMAGE_DIRECTORY_ENTRY_EXCEPTION, &SizeOfTable) || SizeOfTable != dir->Size) {
|
||||
__fastfail(STATUS_BAD_DATA);
|
||||
}
|
||||
//SizeOfTable = dir->Size;
|
||||
|
||||
FunctionTable = (decltype(FunctionTable))RtlImageDirectoryEntryToData(ImageBase, TRUE, IMAGE_DIRECTORY_ENTRY_EXCEPTION, &SizeOfTable);
|
||||
InvertedTable->Entries[Index].ExceptionDirectory = FunctionTable;
|
||||
InvertedTable->Entries[Index].ImageBase = ImageBase;
|
||||
InvertedTable->Entries[Index].ImageSize = SizeOfImage;
|
||||
InvertedTable->Entries[Index].ExceptionDirectorySize = SizeOfTable;
|
||||
InvertedTable->Count++;
|
||||
//if (need)_InterlockedIncrement(&InvertedTable->Epoch);
|
||||
}
|
||||
else {
|
||||
need ? (InvertedTable->Overflow = TRUE) : (InvertedTable->Epoch = TRUE);
|
||||
IsWin8OrGreater ? (InvertedTable->Overflow = TRUE) : (InvertedTable->Epoch = TRUE);
|
||||
}
|
||||
|
||||
#else
|
||||
@@ -1007,16 +1055,12 @@ static VOID NTAPI RtlpRemoveInvertedFunctionTable(IN PRTL_INVERTED_FUNCTION_TABL
|
||||
}
|
||||
|
||||
if (InvertedTable->Count != InvertedTable->MaxCount) {
|
||||
#ifdef _WIN64
|
||||
//InvertedTable->Overflow = FALSE;
|
||||
#else
|
||||
if (IsWin8OrGreater) {
|
||||
InvertedTable->NextEntrySEHandlerTableEncoded = FALSE;
|
||||
PRTL_INVERTED_FUNCTION_TABLE_64(InvertedTable)->Overflow = FALSE;
|
||||
}
|
||||
else {
|
||||
InvertedTable->Overflow = FALSE;
|
||||
PRTL_INVERTED_FUNCTION_TABLE_WIN7_32(InvertedTable)->Overflow = FALSE;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
return;
|
||||
@@ -1107,7 +1151,7 @@ static __forceinline bool NTAPI RtlIsModuleUnloaded(PLDR_DATA_TABLE_ENTRY entry)
|
||||
}
|
||||
else {
|
||||
return entry->DllBase == nullptr;
|
||||
}
|
||||
}
|
||||
}
|
||||
static PVOID FindLdrpInvertedFunctionTable32() {
|
||||
// _RTL_INVERTED_FUNCTION_TABLE x86
|
||||
@@ -1133,14 +1177,14 @@ static PVOID FindLdrpInvertedFunctionTable32() {
|
||||
DWORD SEHTable, SEHCount;
|
||||
BYTE Offset = 0x20; //sizeof(_RTL_INVERTED_FUNCTION_TABLE_ENTRY)*2
|
||||
|
||||
if (RtlIsWindowsVersionOrGreater(10, 0, 0)) lpSectionName = ".mrdata";
|
||||
if (RtlIsWindowsVersionOrGreater(6, 3, 0)) lpSectionName = ".mrdata";
|
||||
else if (!RtlIsWindowsVersionOrGreater(6, 2, 0)) Offset = 0xC;
|
||||
|
||||
while (ListEntry != ListHead) {
|
||||
CurEntry = CONTAINING_RECORD(ListEntry, LDR_DATA_TABLE_ENTRY, InMemoryOrderLinks);
|
||||
ListEntry = ListEntry->Flink;
|
||||
if (RtlIsModuleUnloaded(CurEntry))continue; //skip unloaded module
|
||||
if (IsValidMemoryModuleHandle(CurEntry->DllBase))continue; //skip our memory module.
|
||||
if (IsValidMemoryModuleHandle((HMEMORYMODULE)CurEntry->DllBase))continue; //skip our memory module.
|
||||
if (CurEntry->DllBase == hNtdll && Offset == 0x20)continue; //Win10 skip first entry, if the base of ntdll is smallest.
|
||||
hModule = (HMODULE)(hModule ? min(hModule, CurEntry->DllBase) : CurEntry->DllBase);
|
||||
}
|
||||
@@ -1200,7 +1244,7 @@ static PVOID FindLdrpInvertedFunctionTable64() {
|
||||
CurEntry = CONTAINING_RECORD(ListEntry, LDR_DATA_TABLE_ENTRY, InLoadOrderLinks);
|
||||
ListEntry = ListEntry->Flink;
|
||||
//Make sure the smallest base address is not our memory module
|
||||
if (IsValidMemoryModuleHandle(CurEntry->DllBase))continue;
|
||||
if (IsValidMemoryModuleHandle((HMEMORYMODULE)CurEntry->DllBase))continue;
|
||||
hModule = (HMODULE)(hModule ? min(hModule, CurEntry->DllBase) : CurEntry->DllBase);
|
||||
}
|
||||
ModuleHeaders = RtlImageNtHeader(hModule);
|
||||
@@ -1255,7 +1299,7 @@ static NTSTATUS NTAPI RtlProtectMrdata(IN SIZE_T Protect) {
|
||||
NTSTATUS NTAPI RtlInsertInvertedFunctionTable(IN PVOID BaseAddress, IN size_t ImageSize) {
|
||||
static auto table = PRTL_INVERTED_FUNCTION_TABLE(RtlFindLdrpInvertedFunctionTable());
|
||||
if (!table)return STATUS_NOT_SUPPORTED;
|
||||
bool need_virtual_protect = RtlIsWindowsVersionOrGreater(8, 3, 0);
|
||||
bool need_virtual_protect = RtlIsWindowsVersionOrGreater(6, 3, 0);
|
||||
NTSTATUS status;
|
||||
|
||||
if (need_virtual_protect) {
|
||||
@@ -1267,17 +1311,12 @@ NTSTATUS NTAPI RtlInsertInvertedFunctionTable(IN PVOID BaseAddress, IN size_t Im
|
||||
status = RtlProtectMrdata(PAGE_READONLY);
|
||||
if (!NT_SUCCESS(status))return status;
|
||||
}
|
||||
|
||||
#ifdef _WIN64
|
||||
if (RtlIsWindowsVersionOrGreater(6, 2, 0)) return table->Overflow ? STATUS_INVALID_ADDRESS : STATUS_SUCCESS;
|
||||
else return table->Epoch ? STATUS_INVALID_ADDRESS : STATUS_SUCCESS;
|
||||
#else
|
||||
return (need_virtual_protect ? table->NextEntrySEHandlerTableEncoded : table->Overflow) ? STATUS_INVALID_ADDRESS : STATUS_SUCCESS;
|
||||
#endif
|
||||
return (RtlIsWindowsVersionOrGreater(6, 2, 0) ? PRTL_INVERTED_FUNCTION_TABLE_64(table)->Overflow : PRTL_INVERTED_FUNCTION_TABLE_WIN7_32(table)->Overflow) ?
|
||||
STATUS_NO_MEMORY : STATUS_SUCCESS;
|
||||
}
|
||||
NTSTATUS NTAPI RtlRemoveInvertedFunctionTable(IN PVOID ImageBase) {
|
||||
static auto table = PRTL_INVERTED_FUNCTION_TABLE(RtlFindLdrpInvertedFunctionTable());
|
||||
bool need_virtual_protect = RtlIsWindowsVersionOrGreater(10, 0, 0);
|
||||
bool need_virtual_protect = RtlIsWindowsVersionOrGreater(6, 3, 0);
|
||||
NTSTATUS status;
|
||||
|
||||
if (need_virtual_protect) {
|
||||
@@ -1297,10 +1336,18 @@ static NTSTATUS NTAPI LdrpHandleTlsDataXp(PLDR_DATA_TABLE_ENTRY LdrEntry) {
|
||||
return STATUS_NOT_SUPPORTED;
|
||||
}
|
||||
static NTSTATUS NTAPI RtlFindLdrpHandleTlsData(PVOID* _LdrpHandleTlsData, bool* stdcall) {
|
||||
static PVOID _LdrpHandleTlsData_ = (PVOID)~0;
|
||||
NTSTATUS status = STATUS_SUCCESS;
|
||||
|
||||
__try {
|
||||
*_LdrpHandleTlsData = nullptr;
|
||||
*stdcall = false;
|
||||
if (_LdrpHandleTlsData_ != (PVOID)~0) {
|
||||
*_LdrpHandleTlsData = _LdrpHandleTlsData_;
|
||||
if (_LdrpHandleTlsData_ == nullptr)status = STATUS_NOT_SUPPORTED;
|
||||
}
|
||||
else {
|
||||
*_LdrpHandleTlsData = _LdrpHandleTlsData_ = nullptr;
|
||||
*stdcall = false;
|
||||
}
|
||||
}
|
||||
__except (EXCEPTION_EXECUTE_HANDLER) {
|
||||
status = GetExceptionCode();
|
||||
@@ -1420,7 +1467,7 @@ static NTSTATUS NTAPI RtlFindLdrpHandleTlsData(PVOID* _LdrpHandleTlsData, bool*
|
||||
SEARCH_CONTEXT SearchContext{ SearchContext.MemoryBuffer = const_cast<PVOID>(Feature),SearchContext.BufferLength = Size - 1 };
|
||||
if (NT_SUCCESS(RtlFindMemoryBlockFromModuleSection(GetModuleHandleW(L"ntdll.dll"), ".text", &SearchContext)))
|
||||
SearchContext.OutBufferPtr -= OffsetOfFunctionBegin;
|
||||
if (!(*_LdrpHandleTlsData = SearchContext.MemoryBlockInSection))return STATUS_NOT_SUPPORTED;
|
||||
if (!(*_LdrpHandleTlsData = _LdrpHandleTlsData_ = SearchContext.MemoryBlockInSection))return STATUS_NOT_SUPPORTED;
|
||||
*stdcall = !RtlIsWindowsVersionOrGreater(6, 3, 0);
|
||||
return status;
|
||||
}
|
||||
@@ -1493,7 +1540,7 @@ NTSTATUS NTAPI NtQuerySystemMemoryModuleFeatures(OUT PDWORD pFeatures) {
|
||||
}
|
||||
|
||||
if (RtlFindLdrpModuleBaseAddressIndex())features |= MEMORY_FEATURE_MODULE_BASEADDRESS_INDEX;
|
||||
if (RtlFindtLdrpHeap())features |= MEMORY_FEATURE_LDRP_HEAP;
|
||||
if (RtlFindLdrpHeap())features |= MEMORY_FEATURE_LDRP_HEAP;
|
||||
if (RtlFindLdrpHashTable())features |= MEMORY_FEATURE_LDRP_HASH_TABLE;
|
||||
if (RtlFindLdrpInvertedFunctionTable())features |= MEMORY_FEATURE_INVERTED_FUNCTION_TABLE;
|
||||
if (NT_SUCCESS(RtlFindLdrpHandleTlsData(&pfn, &value)) && pfn)features |= MEMORY_FEATURE_LDRP_HANDLE_TLS_DATA;
|
||||
|
||||
@@ -421,6 +421,9 @@ NTSTATUS NTAPI NtLoadDllMemory(
|
||||
//If this flag is specified, this routine will not fail even if the call to LdrpTlsData fails.
|
||||
#define LOAD_FLAGS_NOT_FAIL_IF_HANDLE_TLS 0x20000000
|
||||
|
||||
//If this flag is specified, the input image buffer will not be checked before loading.
|
||||
#define LOAD_FLAGS_PASS_IMAGE_CHECK 0x40000000
|
||||
|
||||
//If this flag is specified, exception handling will not be supported.
|
||||
#define LOAD_FLAGS_NOT_ADD_INVERTED_FUNCTION 0x00000001
|
||||
|
||||
|
||||
Reference in New Issue
Block a user