diff --git a/MemoryModule.c b/MemoryModule.c index 9f95a70..cf9f372 100644 --- a/MemoryModule.c +++ b/MemoryModule.c @@ -54,10 +54,16 @@ #define IMAGE_SIZEOF_BASE_RELOCATION (sizeof(IMAGE_BASE_RELOCATION)) #endif -#ifdef _WIN64 +#if defined(_M_IX86) +#define HOST_MACHINE IMAGE_FILE_MACHINE_I386 +#elif defined(_M_AMD64) #define HOST_MACHINE IMAGE_FILE_MACHINE_AMD64 +#elif defined(_M_ARM) +#define HOST_MACHINE IMAGE_FILE_MACHINE_ARMNT +#elif defined(_M_ARM64) +#define HOST_MACHINE IMAGE_FILE_MACHINE_ARM64 #else -#define HOST_MACHINE IMAGE_FILE_MACHINE_I386 +#error Unsupported architecture #endif #include "MemoryModule.h" @@ -135,13 +141,12 @@ OutputLastError(const char *msg) #ifndef DEBUG_OUTPUT UNREFERENCED_PARAMETER(msg); #else - LPVOID tmp; - char *tmpmsg; - FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS, - NULL, GetLastError(), MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), (LPTSTR)&tmp, 0, NULL); + char *tmp, *tmpmsg; + FormatMessageA(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS, + NULL, GetLastError(), MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), (LPSTR)&tmp, 0, NULL); tmpmsg = (char *)LocalAlloc(LPTR, strlen(msg) + strlen(tmp) + 3); sprintf(tmpmsg, "%s: %s", msg, tmp); - OutputDebugString(tmpmsg); + OutputDebugStringA(tmpmsg); LocalFree(tmpmsg); LocalFree(tmp); #endif @@ -406,6 +411,10 @@ PerformBaseRelocation(PMEMORYMODULE module, ptrdiff_t delta) // skip relocation break; + case IMAGE_REL_BASED_LOW: + *(WORD *)(dest + offset) += LOWORD(delta); + break; + case IMAGE_REL_BASED_HIGHLOW: // change complete 32 bit address { @@ -414,14 +423,50 @@ PerformBaseRelocation(PMEMORYMODULE module, ptrdiff_t delta) } break; -#ifdef _WIN64 case IMAGE_REL_BASED_DIR64: { ULONGLONG *patchAddr64 = (ULONGLONG *) (dest + offset); *patchAddr64 += (ULONGLONG) delta; } break; -#endif + + case IMAGE_REL_BASED_THUMB_MOV32: + { + DWORD inst = *(DWORD *)(dest + offset); + DWORD imm16 = ((inst << 1) & 0x0800) + ((inst << 12) & 0xf000) + + ((inst >> 20) & 0x0700) + ((inst >> 16) & 0x00ff); + DWORD hi_delta; + + if ((inst & 0x8000fbf0) != 0x0000f240) + fwprintf(stdout, L"wrong Thumb2 instruction %08x, expected MOVW\n", inst); + + imm16 += LOWORD(delta); + hi_delta = HIWORD(delta) + HIWORD(imm16); + *(DWORD *)(dest + offset) = (inst & 0x8f00fbf0) + ((imm16 >> 1) & 0x0400) + + ((imm16 >> 12) & 0x000f) + + ((imm16 << 20) & 0x70000000) + + ((imm16 << 16) & 0xff0000); + + if (hi_delta != 0) + { + inst = *(DWORD *)(dest + offset + 4); + imm16 = ((inst << 1) & 0x0800) + ((inst << 12) & 0xf000) + + ((inst >> 20) & 0x0700) + ((inst >> 16) & 0x00ff); + + if ((inst & 0x8000fbf0) != 0x0000f2c0) + fwprintf(stdout, L"wrong Thumb2 instruction %08x, expected MOVT\n", inst); + + imm16 += hi_delta; + if (imm16 > 0xffff) + fwprintf(stdout, L"resulting immediate value won't fit: %08x\n", imm16); + *(DWORD *)(dest + offset + 4) = (inst & 0x8f00fbf0) + + ((imm16 >> 1) & 0x0400) + + ((imm16 >> 12) & 0x000f) + + ((imm16 << 20) & 0x70000000) + + ((imm16 << 16) & 0xff0000); + } + } + break; default: //printf("Unknown relocation: %d\n", type); @@ -609,9 +654,8 @@ HMEMORYMODULE MemoryLoadLibraryEx(const void *data, size_t size, } } - GetNativeSystemInfo(&sysInfo); - alignedImageSize = AlignValueUp(old_header->OptionalHeader.SizeOfImage, sysInfo.dwPageSize); - if (alignedImageSize != AlignValueUp(lastSectionEnd, sysInfo.dwPageSize)) { + alignedImageSize = AlignValueUp(old_header->OptionalHeader.SizeOfImage, old_header->OptionalHeader.SectionAlignment); + if (alignedImageSize != AlignValueUp(lastSectionEnd, old_header->OptionalHeader.SectionAlignment)) { SetLastError(ERROR_BAD_EXE_FORMAT); return NULL; } @@ -790,7 +834,7 @@ FARPROC MemoryGetProcAddress(HMEMORYMODULE mod, LPCSTR name) } exports = (PIMAGE_EXPORT_DIRECTORY) (codeBase + directory->VirtualAddress); - if (exports->NumberOfNames == 0 || exports->NumberOfFunctions == 0) { + if (exports->NumberOfFunctions == 0) { // DLL doesn't export anything SetLastError(ERROR_PROC_NOT_FOUND); return NULL;