mirror of
https://github.com/vxcontrol/MemoryModule.git
synced 2026-07-25 00:25:23 -04:00
Prevent memory of library from spanning over 4GB bounaries.
Based on code from #67 / #79, fixes #63.
This commit is contained in:
@@ -70,6 +70,13 @@ struct ExportNameEntry {
|
||||
typedef BOOL (WINAPI *DllEntryProc)(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpReserved);
|
||||
typedef int (WINAPI *ExeEntryProc)(void);
|
||||
|
||||
#ifdef _WIN64
|
||||
typedef struct POINTER_LIST {
|
||||
struct POINTER_LIST *next;
|
||||
void *address;
|
||||
} POINTER_LIST;
|
||||
#endif
|
||||
|
||||
typedef struct {
|
||||
PIMAGE_NT_HEADERS headers;
|
||||
unsigned char *codeBase;
|
||||
@@ -87,6 +94,9 @@ typedef struct {
|
||||
void *userdata;
|
||||
ExeEntryProc exeEntry;
|
||||
DWORD pageSize;
|
||||
#ifdef _WIN64
|
||||
POINTER_LIST *blockedMemory;
|
||||
#endif
|
||||
} MEMORYMODULE, *PMEMORYMODULE;
|
||||
|
||||
typedef struct {
|
||||
@@ -137,6 +147,21 @@ OutputLastError(const char *msg)
|
||||
#endif
|
||||
}
|
||||
|
||||
#ifdef _WIN64
|
||||
static void
|
||||
FreePointerList(POINTER_LIST *head, CustomFreeFunc freeMemory, void *userdata)
|
||||
{
|
||||
POINTER_LIST *node = head;
|
||||
while (node) {
|
||||
POINTER_LIST *next;
|
||||
freeMemory(node->address, 0, MEM_RELEASE, userdata);
|
||||
next = node->next;
|
||||
free(node);
|
||||
node = next;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
static BOOL
|
||||
CheckSize(size_t size, size_t expected) {
|
||||
if (size < expected) {
|
||||
@@ -535,6 +560,9 @@ HMEMORYMODULE MemoryLoadLibraryEx(const void *data, size_t size,
|
||||
size_t optionalSectionSize;
|
||||
size_t lastSectionEnd = 0;
|
||||
size_t alignedImageSize;
|
||||
#ifdef _WIN64
|
||||
POINTER_LIST *blockedMemory = NULL;
|
||||
#endif
|
||||
|
||||
if (!CheckSize(size, sizeof(IMAGE_DOS_HEADER))) {
|
||||
return NULL;
|
||||
@@ -610,9 +638,40 @@ HMEMORYMODULE MemoryLoadLibraryEx(const void *data, size_t size,
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef _WIN64
|
||||
// Memory block may not span 4 GB boundaries.
|
||||
while ((((uintptr_t) code) >> 32) < (((uintptr_t) (code + alignedImageSize)) >> 32)) {
|
||||
POINTER_LIST *node = (POINTER_LIST*) malloc(sizeof(POINTER_LIST));
|
||||
if (!node) {
|
||||
freeMemory(code, 0, MEM_RELEASE, userdata);
|
||||
FreePointerList(blockedMemory, freeMemory, userdata);
|
||||
SetLastError(ERROR_OUTOFMEMORY);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
node->next = blockedMemory;
|
||||
node->address = code;
|
||||
blockedMemory = node;
|
||||
|
||||
code = (unsigned char *)allocMemory(NULL,
|
||||
alignedImageSize,
|
||||
MEM_RESERVE | MEM_COMMIT,
|
||||
PAGE_READWRITE,
|
||||
userdata);
|
||||
if (code == NULL) {
|
||||
FreePointerList(blockedMemory, freeMemory, userdata);
|
||||
SetLastError(ERROR_OUTOFMEMORY);
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
result = (PMEMORYMODULE)HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(MEMORYMODULE));
|
||||
if (result == NULL) {
|
||||
freeMemory(code, 0, MEM_RELEASE, userdata);
|
||||
#ifdef _WIN64
|
||||
FreePointerList(blockedMemory, freeMemory, userdata);
|
||||
#endif
|
||||
SetLastError(ERROR_OUTOFMEMORY);
|
||||
return NULL;
|
||||
}
|
||||
@@ -626,6 +685,9 @@ HMEMORYMODULE MemoryLoadLibraryEx(const void *data, size_t size,
|
||||
result->freeLibrary = freeLibrary;
|
||||
result->userdata = userdata;
|
||||
result->pageSize = sysInfo.dwPageSize;
|
||||
#ifdef _WIN64
|
||||
result->blockedMemory = blockedMemory;
|
||||
#endif
|
||||
|
||||
if (!CheckSize(size, old_header->OptionalHeader.SizeOfHeaders)) {
|
||||
goto error;
|
||||
@@ -823,6 +885,9 @@ void MemoryFreeLibrary(HMEMORYMODULE mod)
|
||||
module->free(module->codeBase, 0, MEM_RELEASE, module->userdata);
|
||||
}
|
||||
|
||||
#ifdef _WIN64
|
||||
FreePointerList(module->blockedMemory, module->free, module->userdata);
|
||||
#endif
|
||||
HeapFree(GetProcessHeap(), 0, module);
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user