diff --git a/MemoryModule.c b/MemoryModule.c index cf38388..b4690a8 100644 --- a/MemoryModule.c +++ b/MemoryModule.c @@ -59,6 +59,15 @@ typedef BOOL (WINAPI *DllEntryProc)(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpReserved); typedef int (WINAPI *ExeEntryProc)(void); +#ifdef _WIN64 +// simple linked list to store memory blocks that span the 4GB boundary +// (which can't be used as memory for memorymodule) +typedef struct tagPOINTER_LIST{ + struct tagPOINTER_LIST* next; + unsigned char *address; +}POINTER_LIST; +#endif + typedef struct { PIMAGE_NT_HEADERS headers; unsigned char *codeBase; @@ -75,6 +84,9 @@ typedef struct { void *userdata; ExeEntryProc exeEntry; DWORD pageSize; +#ifdef _WIN64 + POINTER_LIST* blockedMemory; +#endif } MEMORYMODULE, *PMEMORYMODULE; typedef struct { @@ -125,6 +137,18 @@ OutputLastError(const char *msg) #endif } +#ifdef _WIN64 +static void FreePointerList(POINTER_LIST* head, CustomFreeFunc freeMemory, void* userdata) { + POINTER_LIST* node = head; + while(node != NULL) { + POINTER_LIST* current = node; + freeMemory(current->address, 0, MEM_RELEASE, userdata); + current = current->next; + free(node); + } +} +#endif + static BOOL CheckSize(size_t size, size_t expected) { if (size < expected) { @@ -523,6 +547,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; @@ -598,9 +625,41 @@ HMEMORYMODULE MemoryLoadLibraryEx(const void *data, size_t size, } } +#ifdef _WIN64 + // check that memory-block does not span over the 4GB border + if ((unsigned long long)(code) / 0x100000000 < (unsigned long long)(code + alignedImageSize) / 0x100000000) + { + POINTER_LIST** current_node_ptr = &blockedMemory; + + do + { + // store code to keep bad address blocked + *current_node_ptr = (POINTER_LIST*)malloc(sizeof(POINTER_LIST)); + (*current_node_ptr)->next = NULL; + (*current_node_ptr)->address = code; + current_node_ptr = &(*current_node_ptr)->next; + + 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; + } + } while((unsigned long long)(code) / 0x100000000 < (unsigned long long)(code + alignedImageSize) / 0x100000000); + } +#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; } @@ -614,6 +673,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; @@ -776,6 +838,11 @@ void MemoryFreeLibrary(HMEMORYMODULE mod) module->free(module->codeBase, 0, MEM_RELEASE, module->userdata); } +#ifdef _WIN64 + // release blockeded memory + FreePointerList(module->blockedMemory, module->free, module->userdata); +#endif + HeapFree(GetProcessHeap(), 0, module); }
Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.
Alternative Proxies: