From d94ba2e0a2970bd8a42e3078ec928dd344a17816 Mon Sep 17 00:00:00 2001 From: Xjun <812054707@qq.com> Date: Fri, 9 Feb 2018 19:19:47 +0800 Subject: [PATCH] update support win10 1709 --- Example.v12.suo | Bin 33280 -> 38912 bytes MemoryModulePP.c | 1621 ++++++++++++++++++++++++---------------------- main.cpp | 1 + 3 files changed, 845 insertions(+), 777 deletions(-) diff --git a/Example.v12.suo b/Example.v12.suo index 89e1d267d7515d855013d08fbb633433a95f7d01..2b9c04eedd496586feb631449dd2fc61b58e99d0 100644 GIT binary patch literal 38912 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 delta 2787 zcmdT_|4&m_6z_d~rLRy*(Ux`;;T5ZbVkscVHo*$jfh{dXTnr(AK&Lo{Uud_1MBW%t zGe~CNL6;@_L0PhIS+cn>hh zv#oT$9mcs<9mCg&5+vbvWf?mTan28mTovnsh&ljEMptexUh*V>YZEZu7VQ>_dujH03NlAy$JDAzm8EFEvZ`wZ$%e2Aw^lD_nM=45MXV`VV%-FVu}ypvH&#a zHOS>2Rs~|E2re!U!sSV3wFj0s7wd#bwVz|o^gTNQ@#-Ty6`^8F2SjSnlhP_pJF?Ef zvpa1dhfHuXWR1C}7a6D>7xL8emX+Ur$R(k?heS3NtOJIA5=2ct8yh z^age*Tvg=6iO{(tp>TL;0H?y8SrZ z+g2i%dIXvX>+!mR@k&Pf^55~I_8||F@uF|0#44hpGKHX}z3~=*t9J6%_358R@AOTCA!v7jyJdl80c#zCsiW8ArzqUXRM9@U zHEI{BL+0ywx$xxwWb`R!K05v==rC)uMmrri0qf@*Ik~Qdr}<4G&hp^Fs9H}C{reuD zo?S|MsCUxo(Uc)E6(1#;(Y0ExvJEfS^B5CC&k3c^O z`VlF)ABIR1_Gxh~tTuUdEEoCo<4`OKH%poxB<5mk`@d&8<_Q!1=qxb43OVz-Fz+;UeNR0m_XyFX;`N6$38)H6#=nCM-F)xHks>NkSB zrveQ97h~Z*J%hRadaw_aK;wit$A@i`kE+$GxfHJvipB)^9fd|BB8USbz9XI$0%yxI zXbT*gDF^420Zt7Tz}+(~nR05i%JazE=it{+0k|UB_|5|NLzeY(?ySX3-J4!^JWvud zH6*`&ddA2N>;*Pcf=V2qpD`(h4Ud^Es^zpe?$o%oq~Y;S6^C`KGNpxF6*f|E?bV$* zdK9PGjtg%3YUS5>XlmV*G85h#cQ6|9n_&u_`UC?Yo#$a`U;^B4W13%opvG~-!yDt< a;Qp9JPs%8Pv_L<;CnjBVt78k3ZtgF%bwJAi diff --git a/MemoryModulePP.c b/MemoryModulePP.c index a79a90e..dc1609a 100644 --- a/MemoryModulePP.c +++ b/MemoryModulePP.c @@ -87,7 +87,7 @@ int __fastcall RtlInsertInvertedFunctionTable(PVOID BaseAddress, ULONG uImageSiz #if _MSC_VER // Disable warning about data -> function pointer conversion #pragma warning(disable:4055) - // C4244: conversion from 'uintptr_t' to 'DWORD', possible loss of data. +// C4244: conversion from 'uintptr_t' to 'DWORD', possible loss of data. #pragma warning(error: 4244) // C4267: conversion from 'size_t' to 'int', possible loss of data. #pragma warning(error: 4267) @@ -119,7 +119,7 @@ fnRtlInsertInvertedFunctionTable_Win7 pfnRtlInsertInvertedFunctionTable_Win7 = N typedef int(__fastcall* fnRtlInsertInvertedFunctionTable_Win8_Win10)(PVOID BaseAddress, ULONG uImageSize); fnRtlInsertInvertedFunctionTable_Win8_Win10 pfnRtlInsertInvertedFunctionTable_Win8_Win10 = NULL; -typedef BOOLEAN(__cdecl* fnRtlAddFunctionTable64)(PVOID FunctionTable,DWORD EntryCount,DWORD64 BaseAddress); +typedef BOOLEAN(__cdecl* fnRtlAddFunctionTable64)(PVOID FunctionTable, DWORD EntryCount, DWORD64 BaseAddress); fnRtlAddFunctionTable64 pfnRtlAddFunctionTable64 = NULL; static inline LONG @@ -162,378 +162,382 @@ FindPattern(unsigned char* pSrc, unsigned char* pTrait, int nSrcLen, int nTraitL static inline uintptr_t AlignValueDown(uintptr_t value, uintptr_t alignment) { - return value & ~(alignment - 1); + return value & ~(alignment - 1); } static inline LPVOID AlignAddressDown(LPVOID address, uintptr_t alignment) { - return (LPVOID) AlignValueDown((uintptr_t) address, alignment); + return (LPVOID)AlignValueDown((uintptr_t)address, alignment); } static inline size_t AlignValueUp(size_t value, size_t alignment) { - return (value + alignment - 1) & ~(alignment - 1); + return (value + alignment - 1) & ~(alignment - 1); } static inline void* OffsetPointer(void* data, ptrdiff_t offset) { - return (void*) ((uintptr_t) data + offset); + return (void*)((uintptr_t)data + offset); } static inline void OutputLastError(const char *msg) { #ifndef DEBUG_OUTPUT - UNREFERENCED_PARAMETER(msg); + 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); - tmpmsg = (char *)LocalAlloc(LPTR, strlen(msg) + strlen(tmp) + 3); - sprintf(tmpmsg, "%s: %s", msg, tmp); - OutputDebugString(tmpmsg); - LocalFree(tmpmsg); - LocalFree(tmp); + 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); + tmpmsg = (char *)LocalAlloc(LPTR, strlen(msg) + strlen(tmp) + 3); + sprintf(tmpmsg, "%s: %s", msg, tmp); + OutputDebugString(tmpmsg); + LocalFree(tmpmsg); + LocalFree(tmp); #endif } static BOOL CheckSize(size_t size, size_t expected) { - if (size < expected) { - SetLastError(ERROR_INVALID_DATA); - return FALSE; - } + if (size < expected) { + SetLastError(ERROR_INVALID_DATA); + return FALSE; + } - return TRUE; + return TRUE; } static BOOL CopySections(const unsigned char *data, size_t size, PIMAGE_NT_HEADERS old_headers, PMEMORYMODULE module) { - int i, section_size; - unsigned char *codeBase = module->codeBase; - unsigned char *dest; - PIMAGE_SECTION_HEADER section = IMAGE_FIRST_SECTION(module->headers); - for (i=0; iheaders->FileHeader.NumberOfSections; i++, section++) { - if (section->SizeOfRawData == 0) { - // section doesn't contain data in the dll itself, but may define - // uninitialized data - section_size = old_headers->OptionalHeader.SectionAlignment; - if (section_size > 0) { - dest = (unsigned char *)module->alloc(codeBase + section->VirtualAddress, - section_size, - MEM_COMMIT, - PAGE_READWRITE, - module->userdata); - if (dest == NULL) { - return FALSE; - } + int i, section_size; + unsigned char *codeBase = module->codeBase; + unsigned char *dest; + PIMAGE_SECTION_HEADER section = IMAGE_FIRST_SECTION(module->headers); + for (i = 0; i < module->headers->FileHeader.NumberOfSections; i++, section++) { + if (section->SizeOfRawData == 0) { + // section doesn't contain data in the dll itself, but may define + // uninitialized data + section_size = old_headers->OptionalHeader.SectionAlignment; + if (section_size > 0) { + dest = (unsigned char *)module->alloc(codeBase + section->VirtualAddress, + section_size, + MEM_COMMIT, + PAGE_READWRITE, + module->userdata); + if (dest == NULL) { + return FALSE; + } - // Always use position from file to support alignments smaller - // than page size (allocation above will align to page size). - dest = codeBase + section->VirtualAddress; - // NOTE: On 64bit systems we truncate to 32bit here but expand - // again later when "PhysicalAddress" is used. - section->Misc.PhysicalAddress = (DWORD) ((uintptr_t) dest & 0xffffffff); - memset(dest, 0, section_size); - } + // Always use position from file to support alignments smaller + // than page size (allocation above will align to page size). + dest = codeBase + section->VirtualAddress; + // NOTE: On 64bit systems we truncate to 32bit here but expand + // again later when "PhysicalAddress" is used. + section->Misc.PhysicalAddress = (DWORD)((uintptr_t)dest & 0xffffffff); + memset(dest, 0, section_size); + } - // section is empty - continue; - } + // section is empty + continue; + } - if (!CheckSize(size, section->PointerToRawData + section->SizeOfRawData)) { - return FALSE; - } + if (!CheckSize(size, section->PointerToRawData + section->SizeOfRawData)) { + return FALSE; + } - // commit memory block and copy data from dll - dest = (unsigned char *)module->alloc(codeBase + section->VirtualAddress, - section->SizeOfRawData, - MEM_COMMIT, - PAGE_READWRITE, - module->userdata); - if (dest == NULL) { - return FALSE; - } + // commit memory block and copy data from dll + dest = (unsigned char *)module->alloc(codeBase + section->VirtualAddress, + section->SizeOfRawData, + MEM_COMMIT, + PAGE_READWRITE, + module->userdata); + if (dest == NULL) { + return FALSE; + } - // Always use position from file to support alignments smaller - // than page size (allocation above will align to page size). - dest = codeBase + section->VirtualAddress; - memcpy(dest, data + section->PointerToRawData, section->SizeOfRawData); - // NOTE: On 64bit systems we truncate to 32bit here but expand - // again later when "PhysicalAddress" is used. - section->Misc.PhysicalAddress = (DWORD) ((uintptr_t) dest & 0xffffffff); - } + // Always use position from file to support alignments smaller + // than page size (allocation above will align to page size). + dest = codeBase + section->VirtualAddress; + memcpy(dest, data + section->PointerToRawData, section->SizeOfRawData); + // NOTE: On 64bit systems we truncate to 32bit here but expand + // again later when "PhysicalAddress" is used. + section->Misc.PhysicalAddress = (DWORD)((uintptr_t)dest & 0xffffffff); + } - return TRUE; + return TRUE; } // Protection flags for memory pages (Executable, Readable, Writeable) static int ProtectionFlags[2][2][2] = { - { - // not executable - {PAGE_NOACCESS, PAGE_WRITECOPY}, - {PAGE_READONLY, PAGE_READWRITE}, - }, { - // executable - {PAGE_EXECUTE, PAGE_EXECUTE_WRITECOPY}, - {PAGE_EXECUTE_READ, PAGE_EXECUTE_READWRITE}, - }, + { + // not executable + { PAGE_NOACCESS, PAGE_WRITECOPY }, + { PAGE_READONLY, PAGE_READWRITE }, + }, { + // executable + { PAGE_EXECUTE, PAGE_EXECUTE_WRITECOPY }, + { PAGE_EXECUTE_READ, PAGE_EXECUTE_READWRITE }, + }, }; static SIZE_T GetRealSectionSize(PMEMORYMODULE module, PIMAGE_SECTION_HEADER section) { - DWORD size = section->SizeOfRawData; - if (size == 0) { - if (section->Characteristics & IMAGE_SCN_CNT_INITIALIZED_DATA) { - size = module->headers->OptionalHeader.SizeOfInitializedData; - } else if (section->Characteristics & IMAGE_SCN_CNT_UNINITIALIZED_DATA) { - size = module->headers->OptionalHeader.SizeOfUninitializedData; - } - } - return (SIZE_T) size; + DWORD size = section->SizeOfRawData; + if (size == 0) { + if (section->Characteristics & IMAGE_SCN_CNT_INITIALIZED_DATA) { + size = module->headers->OptionalHeader.SizeOfInitializedData; + } + else if (section->Characteristics & IMAGE_SCN_CNT_UNINITIALIZED_DATA) { + size = module->headers->OptionalHeader.SizeOfUninitializedData; + } + } + return (SIZE_T)size; } static BOOL FinalizeSection(PMEMORYMODULE module, PSECTIONFINALIZEDATA sectionData) { - DWORD protect, oldProtect; - BOOL executable; - BOOL readable; - BOOL writeable; + DWORD protect, oldProtect; + BOOL executable; + BOOL readable; + BOOL writeable; - if (sectionData->size == 0) { - return TRUE; - } + if (sectionData->size == 0) { + 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 || - module->headers->OptionalHeader.SectionAlignment == module->pageSize || - (sectionData->size % module->pageSize) == 0) - ) { - // Only allowed to decommit whole pages - module->free(sectionData->address, sectionData->size, MEM_DECOMMIT, module->userdata); - } - 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 || + module->headers->OptionalHeader.SectionAlignment == module->pageSize || + (sectionData->size % module->pageSize) == 0) + ) { + // Only allowed to decommit whole pages + module->free(sectionData->address, sectionData->size, MEM_DECOMMIT, module->userdata); + } + 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; - } + // 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 - if (VirtualProtect(sectionData->address, sectionData->size, protect, &oldProtect) == 0) { - OutputLastError("Error protecting memory page"); - return FALSE; - } + // change memory access flags + if (VirtualProtect(sectionData->address, sectionData->size, protect, &oldProtect) == 0) { + OutputLastError("Error protecting memory page"); + return FALSE; + } - return TRUE; + return TRUE; } static BOOL FinalizeSections(PMEMORYMODULE module) { - int i; - PIMAGE_SECTION_HEADER section = IMAGE_FIRST_SECTION(module->headers); + int i; + PIMAGE_SECTION_HEADER section = IMAGE_FIRST_SECTION(module->headers); #ifdef _WIN64 - // "PhysicalAddress" might have been truncated to 32bit above, expand to - // 64bits again. - uintptr_t imageOffset = ((uintptr_t) module->headers->OptionalHeader.ImageBase & 0xffffffff00000000); + // "PhysicalAddress" might have been truncated to 32bit above, expand to + // 64bits again. + uintptr_t imageOffset = ((uintptr_t)module->headers->OptionalHeader.ImageBase & 0xffffffff00000000); #else - static const uintptr_t imageOffset = 0; + static const uintptr_t imageOffset = 0; #endif - SECTIONFINALIZEDATA sectionData; - sectionData.address = (LPVOID)((uintptr_t)section->Misc.PhysicalAddress | imageOffset); - sectionData.alignedAddress = AlignAddressDown(sectionData.address, module->pageSize); - sectionData.size = GetRealSectionSize(module, section); - sectionData.characteristics = section->Characteristics; - sectionData.last = FALSE; - section++; + SECTIONFINALIZEDATA sectionData; + sectionData.address = (LPVOID)((uintptr_t)section->Misc.PhysicalAddress | imageOffset); + sectionData.alignedAddress = AlignAddressDown(sectionData.address, module->pageSize); + sectionData.size = GetRealSectionSize(module, section); + sectionData.characteristics = section->Characteristics; + sectionData.last = FALSE; + section++; - // loop through all sections and change access flags - for (i=1; iheaders->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); - // Combine access flags of all sections that share a page - // TODO(fancycode): We currently share flags of a trailing large section - // with the page of a first small section. This should be optimized. - if (sectionData.alignedAddress == alignedAddress || (uintptr_t) sectionData.address + sectionData.size > (uintptr_t) alignedAddress) { - // Section shares page with previous - 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 { - sectionData.characteristics |= section->Characteristics; - } - sectionData.size = (((uintptr_t)sectionAddress) + ((uintptr_t) sectionSize)) - (uintptr_t) sectionData.address; - continue; - } + // loop through all sections and change access flags + for (i = 1; iheaders->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); + // Combine access flags of all sections that share a page + // TODO(fancycode): We currently share flags of a trailing large section + // with the page of a first small section. This should be optimized. + if (sectionData.alignedAddress == alignedAddress || (uintptr_t)sectionData.address + sectionData.size >(uintptr_t) alignedAddress) { + // Section shares page with previous + 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 { + sectionData.characteristics |= section->Characteristics; + } + sectionData.size = (((uintptr_t)sectionAddress) + ((uintptr_t)sectionSize)) - (uintptr_t)sectionData.address; + continue; + } - if (!FinalizeSection(module, §ionData)) { - return FALSE; - } - sectionData.address = sectionAddress; - sectionData.alignedAddress = alignedAddress; - sectionData.size = sectionSize; - sectionData.characteristics = section->Characteristics; - } - sectionData.last = TRUE; - if (!FinalizeSection(module, §ionData)) { - return FALSE; - } - return TRUE; + if (!FinalizeSection(module, §ionData)) { + return FALSE; + } + sectionData.address = sectionAddress; + sectionData.alignedAddress = alignedAddress; + sectionData.size = sectionSize; + sectionData.characteristics = section->Characteristics; + } + sectionData.last = TRUE; + if (!FinalizeSection(module, §ionData)) { + return FALSE; + } + return TRUE; } static BOOL ExecuteTLS(PMEMORYMODULE module) { - unsigned char *codeBase = module->codeBase; - PIMAGE_TLS_DIRECTORY tls; - PIMAGE_TLS_CALLBACK* callback; + unsigned char *codeBase = module->codeBase; + PIMAGE_TLS_DIRECTORY tls; + PIMAGE_TLS_CALLBACK* callback; - PIMAGE_DATA_DIRECTORY directory = GET_HEADER_DICTIONARY(module, IMAGE_DIRECTORY_ENTRY_TLS); - if (directory->VirtualAddress == 0) { - return TRUE; - } + PIMAGE_DATA_DIRECTORY directory = GET_HEADER_DICTIONARY(module, IMAGE_DIRECTORY_ENTRY_TLS); + if (directory->VirtualAddress == 0) { + return TRUE; + } - tls = (PIMAGE_TLS_DIRECTORY) (codeBase + directory->VirtualAddress); - callback = (PIMAGE_TLS_CALLBACK *) tls->AddressOfCallBacks; - if (callback) { - while (*callback) { - (*callback)((LPVOID) codeBase, DLL_PROCESS_ATTACH, NULL); - callback++; - } - } - return TRUE; + tls = (PIMAGE_TLS_DIRECTORY)(codeBase + directory->VirtualAddress); + callback = (PIMAGE_TLS_CALLBACK *)tls->AddressOfCallBacks; + if (callback) { + while (*callback) { + (*callback)((LPVOID)codeBase, DLL_PROCESS_ATTACH, NULL); + callback++; + } + } + return TRUE; } static BOOL PerformBaseRelocation(PMEMORYMODULE module, ptrdiff_t delta) { - unsigned char *codeBase = module->codeBase; - PIMAGE_BASE_RELOCATION relocation; + unsigned char *codeBase = module->codeBase; + PIMAGE_BASE_RELOCATION relocation; - PIMAGE_DATA_DIRECTORY directory = GET_HEADER_DICTIONARY(module, IMAGE_DIRECTORY_ENTRY_BASERELOC); - if (directory->Size == 0) { - return (delta == 0); - } + PIMAGE_DATA_DIRECTORY directory = GET_HEADER_DICTIONARY(module, IMAGE_DIRECTORY_ENTRY_BASERELOC); + if (directory->Size == 0) { + return (delta == 0); + } - relocation = (PIMAGE_BASE_RELOCATION) (codeBase + directory->VirtualAddress); - for (; relocation->VirtualAddress > 0; ) { - DWORD i; - unsigned char *dest = codeBase + relocation->VirtualAddress; - unsigned short *relInfo = (unsigned short*) OffsetPointer(relocation, IMAGE_SIZEOF_BASE_RELOCATION); - for (i=0; i<((relocation->SizeOfBlock-IMAGE_SIZEOF_BASE_RELOCATION) / 2); i++, relInfo++) { - // the upper 4 bits define the type of relocation - int type = *relInfo >> 12; - // the lower 12 bits define the offset - int offset = *relInfo & 0xfff; + relocation = (PIMAGE_BASE_RELOCATION)(codeBase + directory->VirtualAddress); + for (; relocation->VirtualAddress > 0;) { + DWORD i; + unsigned char *dest = codeBase + relocation->VirtualAddress; + unsigned short *relInfo = (unsigned short*)OffsetPointer(relocation, IMAGE_SIZEOF_BASE_RELOCATION); + for (i = 0; i < ((relocation->SizeOfBlock - IMAGE_SIZEOF_BASE_RELOCATION) / 2); i++, relInfo++) { + // the upper 4 bits define the type of relocation + int type = *relInfo >> 12; + // the lower 12 bits define the offset + int offset = *relInfo & 0xfff; - switch (type) - { - case IMAGE_REL_BASED_ABSOLUTE: - // skip relocation - break; + switch (type) + { + case IMAGE_REL_BASED_ABSOLUTE: + // skip relocation + break; - case IMAGE_REL_BASED_HIGHLOW: - // change complete 32 bit address - { - DWORD *patchAddrHL = (DWORD *) (dest + offset); - *patchAddrHL += (DWORD) delta; - } - break; + case IMAGE_REL_BASED_HIGHLOW: + // change complete 32 bit address + { + DWORD *patchAddrHL = (DWORD *)(dest + offset); + *patchAddrHL += (DWORD)delta; + } + break; #ifdef _WIN64 - case IMAGE_REL_BASED_DIR64: - { - ULONGLONG *patchAddr64 = (ULONGLONG *) (dest + offset); - *patchAddr64 += (ULONGLONG) delta; - } - break; + case IMAGE_REL_BASED_DIR64: + { + ULONGLONG *patchAddr64 = (ULONGLONG *) (dest + offset); + *patchAddr64 += (ULONGLONG) delta; + } + break; #endif - default: - //printf("Unknown relocation: %d\n", type); - break; - } - } + default: + //printf("Unknown relocation: %d\n", type); + break; + } + } - // advance to next relocation block - relocation = (PIMAGE_BASE_RELOCATION) OffsetPointer(relocation, relocation->SizeOfBlock); - } - return TRUE; + // advance to next relocation block + relocation = (PIMAGE_BASE_RELOCATION)OffsetPointer(relocation, relocation->SizeOfBlock); +} + return TRUE; } static BOOL BuildImportTable(PMEMORYMODULE module) { - unsigned char *codeBase = module->codeBase; - PIMAGE_IMPORT_DESCRIPTOR importDesc; - BOOL result = TRUE; + unsigned char *codeBase = module->codeBase; + PIMAGE_IMPORT_DESCRIPTOR importDesc; + BOOL result = TRUE; - PIMAGE_DATA_DIRECTORY directory = GET_HEADER_DICTIONARY(module, IMAGE_DIRECTORY_ENTRY_IMPORT); - if (directory->Size == 0) { - return TRUE; - } + PIMAGE_DATA_DIRECTORY directory = GET_HEADER_DICTIONARY(module, IMAGE_DIRECTORY_ENTRY_IMPORT); + if (directory->Size == 0) { + return TRUE; + } - importDesc = (PIMAGE_IMPORT_DESCRIPTOR) (codeBase + directory->VirtualAddress); - for (; !IsBadReadPtr(importDesc, sizeof(IMAGE_IMPORT_DESCRIPTOR)) && importDesc->Name; importDesc++) { - uintptr_t *thunkRef; - FARPROC *funcRef; - HCUSTOMMODULE *tmp; - HCUSTOMMODULE handle = module->loadLibrary((LPCSTR) (codeBase + importDesc->Name), module->userdata); - if (handle == NULL) { - SetLastError(ERROR_MOD_NOT_FOUND); - result = FALSE; - break; - } + importDesc = (PIMAGE_IMPORT_DESCRIPTOR)(codeBase + directory->VirtualAddress); + for (; !IsBadReadPtr(importDesc, sizeof(IMAGE_IMPORT_DESCRIPTOR)) && importDesc->Name; importDesc++) { + uintptr_t *thunkRef; + FARPROC *funcRef; + HCUSTOMMODULE *tmp; + HCUSTOMMODULE handle = module->loadLibrary((LPCSTR)(codeBase + importDesc->Name), module->userdata); + if (handle == NULL) { + SetLastError(ERROR_MOD_NOT_FOUND); + result = FALSE; + break; + } - tmp = (HCUSTOMMODULE *) realloc(module->modules, (module->numModules+1)*(sizeof(HCUSTOMMODULE))); - if (tmp == NULL) { - module->freeLibrary(handle, module->userdata); - SetLastError(ERROR_OUTOFMEMORY); - result = FALSE; - break; - } - module->modules = tmp; + tmp = (HCUSTOMMODULE *)realloc(module->modules, (module->numModules + 1)*(sizeof(HCUSTOMMODULE))); + if (tmp == NULL) { + module->freeLibrary(handle, module->userdata); + SetLastError(ERROR_OUTOFMEMORY); + result = FALSE; + break; + } + module->modules = tmp; - module->modules[module->numModules++] = handle; - if (importDesc->OriginalFirstThunk) { - thunkRef = (uintptr_t *) (codeBase + importDesc->OriginalFirstThunk); - 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 = module->getProcAddress(handle, (LPCSTR)IMAGE_ORDINAL(*thunkRef), module->userdata); - } else { - PIMAGE_IMPORT_BY_NAME thunkData = (PIMAGE_IMPORT_BY_NAME) (codeBase + (*thunkRef)); - *funcRef = module->getProcAddress(handle, (LPCSTR)&thunkData->Name, module->userdata); - } - if (*funcRef == 0) { - result = FALSE; - break; - } - } + module->modules[module->numModules++] = handle; + if (importDesc->OriginalFirstThunk) { + thunkRef = (uintptr_t *)(codeBase + importDesc->OriginalFirstThunk); + 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 = module->getProcAddress(handle, (LPCSTR)IMAGE_ORDINAL(*thunkRef), module->userdata); + } + else { + PIMAGE_IMPORT_BY_NAME thunkData = (PIMAGE_IMPORT_BY_NAME)(codeBase + (*thunkRef)); + *funcRef = module->getProcAddress(handle, (LPCSTR)&thunkData->Name, module->userdata); + } + if (*funcRef == 0) { + result = FALSE; + break; + } + } - if (!result) { - module->freeLibrary(handle, module->userdata); - SetLastError(ERROR_PROC_NOT_FOUND); - break; - } - } + if (!result) { + module->freeLibrary(handle, module->userdata); + SetLastError(ERROR_PROC_NOT_FOUND); + break; + } + } - return result; + return result; } static VOID @@ -542,11 +546,11 @@ InsertExceptionTable(PMEMORYMODULE module) #if defined(_WIN64) PIMAGE_DATA_DIRECTORY pDataTable = \ - &module->headers->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_EXCEPTION]; + &module->headers->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_EXCEPTION]; PIMAGE_RUNTIME_FUNCTION_ENTRY pFuncTable = \ (PIMAGE_RUNTIME_FUNCTION_ENTRY)((ULONG_PTR)module->codeBase + pDataTable->VirtualAddress); - + if (pfnRtlAddFunctionTable64 != NULL) { @@ -565,14 +569,14 @@ InsertExceptionTable(PMEMORYMODULE module) { if (pfnRtlInsertInvertedFunctionTable_Win8_Win10 != NULL); { - + pfnRtlInsertInvertedFunctionTable_Win8_Win10(module->codeBase, module->headers->OptionalHeader.SizeOfImage); } } else if (dwMajorVersion == 10 && dwMinorVersion == 0) //WIN10 { if (pfnRtlInsertInvertedFunctionTable_Win8_Win10 != NULL); { - + pfnRtlInsertInvertedFunctionTable_Win8_Win10(module->codeBase, module->headers->OptionalHeader.SizeOfImage); } } else @@ -587,7 +591,7 @@ InitFindExceptPrivateFunc() { PVOID pNtdllCode; ULONG uNtdllCodeSize; - + PIMAGE_DOS_HEADER pDosHead; PIMAGE_NT_HEADERS pNtHead; PIMAGE_SECTION_HEADER pSection; @@ -631,22 +635,73 @@ InitFindExceptPrivateFunc() if (lResult != -1) { LdrpInvertedFunctionTable = (PVOID)(*(LONG*)((ULONG_PTR)pNtdllCode + lResult + 0x11)); - lCallBuf = *(LONG*)((ULONG_PTR)pNtdllCode + lResult + 0x16); - pfnRtlInsertInvertedFunctionTable_Win7 = (fnRtlInsertInvertedFunctionTable_Win7)((ULONG_PTR)pNtdllCode + lResult + 0x15 + 0x5 + lCallBuf); + + pfnRtlInsertInvertedFunctionTable_Win7 = \ + (fnRtlInsertInvertedFunctionTable_Win7)((ULONG_PTR)pNtdllCode + lResult + 0x15 + 0x5 + lCallBuf); } - } else if (dwMajorVersion == 6 && dwMinorVersion == 3) //WIN8 { - + LONG lResult; + LONG lCallBuf; + unsigned char ida_chars[] = { + 0x33, 0xFF, 0x8B, 0x56, 0x20, 0x8B, 0xCB, 0xE8 + }; + lResult = FindPattern(pNtdllCode, ida_chars, uNtdllCodeSize, sizeof(ida_chars)); + if (lResult != -1) + { + lCallBuf = *(LONG*)((ULONG_PTR)pNtdllCode + lResult + 0x8); + + pfnRtlInsertInvertedFunctionTable_Win8_Win10 = \ + (fnRtlInsertInvertedFunctionTable_Win8_Win10)((ULONG_PTR)pNtdllCode + lResult + 0x7 + 0x5 + lCallBuf); + + } } else if (dwMajorVersion == 10 && dwMinorVersion == 0) //WIN10 { - + LONG lResult; + LONG lCallBuf; + unsigned char ida_chars1[] = { + 0x8B, 0x85, 0xD4, 0xFE, 0xFF, 0xFF, 0x8B, 0x70, 0x50, + 0x8B, 0xD6, 0x8B, 0xCB, 0xE8 + }; + unsigned char ida_chars2[] = { + 0x8B, 0x45, 0xF8, 0x8B, 0xCE, 0x8B, 0x40, 0x50, 0x8B, + 0xD0, 0x89, 0x45, 0xF0, 0xE8 + }; + unsigned char ida_chars3[] = { + 0x8B, 0x85, 0x18, 0xFF, 0xFF, 0xFF, 0x8B, 0x70, 0x50, + 0x8B, 0xD6, 0x8B, 0x8D, 0x34, 0xFF, 0xFF, 0xFF, 0xE8 + }; + if ((lResult = FindPattern(pNtdllCode, ida_chars1, uNtdllCodeSize, sizeof(ida_chars1))) != -1) + { + lCallBuf = *(LONG*)((ULONG_PTR)pNtdllCode + lResult + 0xE); + + pfnRtlInsertInvertedFunctionTable_Win8_Win10 = \ + (fnRtlInsertInvertedFunctionTable_Win8_Win10)((ULONG_PTR)pNtdllCode + lResult + 0xD + 0x5 + lCallBuf); + } + else if ((lResult = FindPattern(pNtdllCode, ida_chars2, uNtdllCodeSize, sizeof(ida_chars2))) != -1) + { + lCallBuf = *(LONG*)((ULONG_PTR)pNtdllCode + lResult + 0xE); + + pfnRtlInsertInvertedFunctionTable_Win8_Win10 = \ + (fnRtlInsertInvertedFunctionTable_Win8_Win10)((ULONG_PTR)pNtdllCode + lResult + 0xD + 0x5 + lCallBuf); + } + else if ((lResult = FindPattern(pNtdllCode, ida_chars3, uNtdllCodeSize, sizeof(ida_chars3))) != -1) + { + lCallBuf = *(LONG*)((ULONG_PTR)pNtdllCode + lResult + 0x12); + + pfnRtlInsertInvertedFunctionTable_Win8_Win10 = \ + (fnRtlInsertInvertedFunctionTable_Win8_Win10)((ULONG_PTR)pNtdllCode + lResult + 0x11 + 0x5 + lCallBuf); + } + else + { + // not support; + } } else { @@ -669,61 +724,61 @@ BOOL MemoryDefaultFree(LPVOID lpAddress, SIZE_T dwSize, DWORD dwFreeType, void* HCUSTOMMODULE MemoryDefaultLoadLibrary(LPCSTR filename, void *userdata) { - HMODULE result; - UNREFERENCED_PARAMETER(userdata); - result = LoadLibraryA(filename); - if (result == NULL) { - return NULL; - } + HMODULE result; + UNREFERENCED_PARAMETER(userdata); + result = LoadLibraryA(filename); + if (result == NULL) { + return NULL; + } - return (HCUSTOMMODULE) result; + return (HCUSTOMMODULE)result; } FARPROC MemoryDefaultGetProcAddress(HCUSTOMMODULE module, LPCSTR name, void *userdata) { - UNREFERENCED_PARAMETER(userdata); - return (FARPROC) GetProcAddress((HMODULE) module, name); + UNREFERENCED_PARAMETER(userdata); + return (FARPROC)GetProcAddress((HMODULE)module, name); } void MemoryDefaultFreeLibrary(HCUSTOMMODULE module, void *userdata) { - UNREFERENCED_PARAMETER(userdata); - FreeLibrary((HMODULE) module); + UNREFERENCED_PARAMETER(userdata); + FreeLibrary((HMODULE)module); } PMEMORYMODULE MemoryLoadLibrary(const void *data, size_t size) { - return MemoryLoadLibraryEx(data, size, MemoryDefaultAlloc, MemoryDefaultFree, MemoryDefaultLoadLibrary, MemoryDefaultGetProcAddress, MemoryDefaultFreeLibrary, NULL); + return MemoryLoadLibraryEx(data, size, MemoryDefaultAlloc, MemoryDefaultFree, MemoryDefaultLoadLibrary, MemoryDefaultGetProcAddress, MemoryDefaultFreeLibrary, NULL); } PMEMORYMODULE MemoryLoadLibraryEx(const void *data, size_t size, - CustomAllocFunc allocMemory, - CustomFreeFunc freeMemory, - CustomLoadLibraryFunc loadLibrary, - CustomGetProcAddressFunc getProcAddress, - CustomFreeLibraryFunc freeLibrary, - void *userdata) + CustomAllocFunc allocMemory, + CustomFreeFunc freeMemory, + CustomLoadLibraryFunc loadLibrary, + CustomGetProcAddressFunc getProcAddress, + CustomFreeLibraryFunc freeLibrary, + void *userdata) { - PMEMORYMODULE result = NULL; - PIMAGE_DOS_HEADER dos_header; - PIMAGE_NT_HEADERS old_header; - unsigned char *code, *headers; - ptrdiff_t locationDelta; - SYSTEM_INFO sysInfo; - PIMAGE_SECTION_HEADER section; - DWORD i; - size_t optionalSectionSize; - size_t lastSectionEnd = 0; - size_t alignedImageSize; + PMEMORYMODULE result = NULL; + PIMAGE_DOS_HEADER dos_header; + PIMAGE_NT_HEADERS old_header; + unsigned char *code, *headers; + ptrdiff_t locationDelta; + SYSTEM_INFO sysInfo; + PIMAGE_SECTION_HEADER section; + DWORD i; + size_t optionalSectionSize; + size_t lastSectionEnd = 0; + size_t alignedImageSize; static BOOL g_bInit = FALSE; - if (_InterlockedCompareExchange((LONG*)&g_bInit,TRUE,FALSE) == FALSE) + if (_InterlockedCompareExchange((LONG*)&g_bInit, TRUE, FALSE) == FALSE) { #if defined(_WIN64) pfnRtlAddFunctionTable64 = (fnRtlAddFunctionTable64)GetProcAddress(GetModuleHandle(TEXT("ntdll")), "RtlAddFunctionTable"); #else RTL_OSVERSIONINFOW osinfo = { 0 }; - typedef LONG(__stdcall *fnRtlGetVersion)(PRTL_OSVERSIONINFOW lpVersionInformation); + typedef LONG(__stdcall *fnRtlGetVersion)(PRTL_OSVERSIONINFOW lpVersionInformation); fnRtlGetVersion pfnRtlGetVersion = (fnRtlGetVersion)GetProcAddress(GetModuleHandle(TEXT("ntdll.dll")), "RtlGetVersion"); if (pfnRtlGetVersion != NULL && pfnRtlGetVersion(&osinfo) == 0) { @@ -736,548 +791,560 @@ PMEMORYMODULE MemoryLoadLibraryEx(const void *data, size_t size, #endif } - if (!CheckSize(size, sizeof(IMAGE_DOS_HEADER))) { - return NULL; - } - dos_header = (PIMAGE_DOS_HEADER)data; - if (dos_header->e_magic != IMAGE_DOS_SIGNATURE) { - SetLastError(ERROR_BAD_EXE_FORMAT); - return NULL; - } + if (!CheckSize(size, sizeof(IMAGE_DOS_HEADER))) { + return NULL; + } + dos_header = (PIMAGE_DOS_HEADER)data; + if (dos_header->e_magic != IMAGE_DOS_SIGNATURE) { + SetLastError(ERROR_BAD_EXE_FORMAT); + return NULL; + } - if (!CheckSize(size, dos_header->e_lfanew + sizeof(IMAGE_NT_HEADERS))) { - return NULL; - } - old_header = (PIMAGE_NT_HEADERS)&((const unsigned char *)(data))[dos_header->e_lfanew]; - if (old_header->Signature != IMAGE_NT_SIGNATURE) { - SetLastError(ERROR_BAD_EXE_FORMAT); - return NULL; - } + if (!CheckSize(size, dos_header->e_lfanew + sizeof(IMAGE_NT_HEADERS))) { + return NULL; + } + old_header = (PIMAGE_NT_HEADERS)&((const unsigned char *)(data))[dos_header->e_lfanew]; + if (old_header->Signature != IMAGE_NT_SIGNATURE) { + SetLastError(ERROR_BAD_EXE_FORMAT); + return NULL; + } - if (old_header->FileHeader.Machine != HOST_MACHINE) { - SetLastError(ERROR_BAD_EXE_FORMAT); - return NULL; - } + if (old_header->FileHeader.Machine != HOST_MACHINE) { + SetLastError(ERROR_BAD_EXE_FORMAT); + return NULL; + } - if (old_header->OptionalHeader.SectionAlignment & 1) { - // Only support section alignments that are a multiple of 2 - SetLastError(ERROR_BAD_EXE_FORMAT); - return NULL; - } + if (old_header->OptionalHeader.SectionAlignment & 1) { + // Only support section alignments that are a multiple of 2 + SetLastError(ERROR_BAD_EXE_FORMAT); + return NULL; + } - section = IMAGE_FIRST_SECTION(old_header); - optionalSectionSize = old_header->OptionalHeader.SectionAlignment; - for (i=0; iFileHeader.NumberOfSections; i++, section++) { - size_t endOfSection; - if (section->SizeOfRawData == 0) { - // Section without data in the DLL - endOfSection = section->VirtualAddress + optionalSectionSize; - } else { - endOfSection = section->VirtualAddress + section->SizeOfRawData; - } + section = IMAGE_FIRST_SECTION(old_header); + optionalSectionSize = old_header->OptionalHeader.SectionAlignment; + for (i = 0; i < old_header->FileHeader.NumberOfSections; i++, section++) { + size_t endOfSection; + if (section->SizeOfRawData == 0) { + // Section without data in the DLL + endOfSection = section->VirtualAddress + optionalSectionSize; + } + else { + endOfSection = section->VirtualAddress + section->SizeOfRawData; + } - if (endOfSection > lastSectionEnd) { - lastSectionEnd = endOfSection; - } - } + if (endOfSection > lastSectionEnd) { + lastSectionEnd = endOfSection; + } + } - GetNativeSystemInfo(&sysInfo); - alignedImageSize = AlignValueUp(old_header->OptionalHeader.SizeOfImage, sysInfo.dwPageSize); - if (alignedImageSize != AlignValueUp(lastSectionEnd, sysInfo.dwPageSize)) { - SetLastError(ERROR_BAD_EXE_FORMAT); - return NULL; - } + GetNativeSystemInfo(&sysInfo); + alignedImageSize = AlignValueUp(old_header->OptionalHeader.SizeOfImage, sysInfo.dwPageSize); + if (alignedImageSize != AlignValueUp(lastSectionEnd, sysInfo.dwPageSize)) { + SetLastError(ERROR_BAD_EXE_FORMAT); + return NULL; + } - // reserve memory for image of library - // XXX: is it correct to commit the complete memory region at once? - // calling DllEntry raises an exception if we don't... - code = (unsigned char *)allocMemory((LPVOID)(old_header->OptionalHeader.ImageBase), - alignedImageSize, - MEM_RESERVE | MEM_COMMIT, - PAGE_READWRITE, - userdata); + // reserve memory for image of library + // XXX: is it correct to commit the complete memory region at once? + // calling DllEntry raises an exception if we don't... + code = (unsigned char *)allocMemory((LPVOID)(old_header->OptionalHeader.ImageBase), + alignedImageSize, + MEM_RESERVE | MEM_COMMIT, + PAGE_READWRITE, + userdata); - if (code == NULL) { - // try to allocate memory at arbitrary position - code = (unsigned char *)allocMemory(NULL, - alignedImageSize, - MEM_RESERVE | MEM_COMMIT, - PAGE_READWRITE, - userdata); - if (code == NULL) { - SetLastError(ERROR_OUTOFMEMORY); - return NULL; - } - } + if (code == NULL) { + // try to allocate memory at arbitrary position + code = (unsigned char *)allocMemory(NULL, + alignedImageSize, + MEM_RESERVE | MEM_COMMIT, + PAGE_READWRITE, + userdata); + if (code == NULL) { + SetLastError(ERROR_OUTOFMEMORY); + return NULL; + } + } - result = (PMEMORYMODULE)HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(MEMORYMODULE)); - if (result == NULL) { - freeMemory(code, 0, MEM_RELEASE, userdata); - SetLastError(ERROR_OUTOFMEMORY); - return NULL; - } + result = (PMEMORYMODULE)HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(MEMORYMODULE)); + if (result == NULL) { + freeMemory(code, 0, MEM_RELEASE, userdata); + SetLastError(ERROR_OUTOFMEMORY); + return NULL; + } - result->codeBase = code; - result->isDLL = (old_header->FileHeader.Characteristics & IMAGE_FILE_DLL) != 0; - result->alloc = allocMemory; - result->free = freeMemory; - result->loadLibrary = loadLibrary; - result->getProcAddress = getProcAddress; - result->freeLibrary = freeLibrary; - result->userdata = userdata; - result->pageSize = sysInfo.dwPageSize; + result->codeBase = code; + result->isDLL = (old_header->FileHeader.Characteristics & IMAGE_FILE_DLL) != 0; + result->alloc = allocMemory; + result->free = freeMemory; + result->loadLibrary = loadLibrary; + result->getProcAddress = getProcAddress; + result->freeLibrary = freeLibrary; + result->userdata = userdata; + result->pageSize = sysInfo.dwPageSize; - if (!CheckSize(size, old_header->OptionalHeader.SizeOfHeaders)) { - goto error; - } + if (!CheckSize(size, old_header->OptionalHeader.SizeOfHeaders)) { + goto error; + } - // commit memory for headers - headers = (unsigned char *)allocMemory(code, - old_header->OptionalHeader.SizeOfHeaders, - MEM_COMMIT, - PAGE_READWRITE, - userdata); + // commit memory for headers + headers = (unsigned char *)allocMemory(code, + old_header->OptionalHeader.SizeOfHeaders, + MEM_COMMIT, + PAGE_READWRITE, + userdata); - // copy PE header to code - memcpy(headers, dos_header, old_header->OptionalHeader.SizeOfHeaders); - result->headers = (PIMAGE_NT_HEADERS)&((const unsigned char *)(headers))[dos_header->e_lfanew]; + // copy PE header to code + memcpy(headers, dos_header, old_header->OptionalHeader.SizeOfHeaders); + result->headers = (PIMAGE_NT_HEADERS)&((const unsigned char *)(headers))[dos_header->e_lfanew]; - // update position - result->headers->OptionalHeader.ImageBase = (uintptr_t)code; + // update position + result->headers->OptionalHeader.ImageBase = (uintptr_t)code; - // copy sections from DLL file block to new memory location - if (!CopySections((const unsigned char *) data, size, old_header, result)) { - goto error; - } + // copy sections from DLL file block to new memory location + if (!CopySections((const unsigned char *)data, size, old_header, result)) { + goto error; + } - // adjust base address of imported data - locationDelta = (ptrdiff_t)(result->headers->OptionalHeader.ImageBase - old_header->OptionalHeader.ImageBase); - if (locationDelta != 0) { + // adjust base address of imported data + locationDelta = (ptrdiff_t)(result->headers->OptionalHeader.ImageBase - old_header->OptionalHeader.ImageBase); + if (locationDelta != 0) { //if not exist reloc table? if (result->headers->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_BASERELOC].VirtualAddress == 0){ goto error; } - result->isRelocated = PerformBaseRelocation(result, locationDelta); - } else { - result->isRelocated = TRUE; - } + result->isRelocated = PerformBaseRelocation(result, locationDelta); + } + else { + result->isRelocated = TRUE; + } - // load required dlls and adjust function table of imports - if (!BuildImportTable(result)) { - goto error; - } + // load required dlls and adjust function table of imports + if (!BuildImportTable(result)) { + goto error; + } - // mark memory pages depending on section headers and release - // sections that are marked as "discardable" - if (!FinalizeSections(result)) { - goto error; - } + // mark memory pages depending on section headers and release + // sections that are marked as "discardable" + if (!FinalizeSections(result)) { + goto error; + } - // TLS callbacks are executed BEFORE the main loading - if (!ExecuteTLS(result)) { - goto error; - } + // TLS callbacks are executed BEFORE the main loading + if (!ExecuteTLS(result)) { + goto error; + } // support exception InsertExceptionTable(result); - // get entry point of loaded library - if (result->headers->OptionalHeader.AddressOfEntryPoint != 0) { - if (result->isDLL) { - DllEntryProc DllEntry = (DllEntryProc)(LPVOID)(code + result->headers->OptionalHeader.AddressOfEntryPoint); - // notify library about attaching to process - BOOL successfull = (*DllEntry)((HINSTANCE)code, DLL_PROCESS_ATTACH, 0); - if (!successfull) { - SetLastError(ERROR_DLL_INIT_FAILED); - goto error; - } - result->initialized = TRUE; - } else { - result->exeEntry = (ExeEntryProc)(LPVOID)(code + result->headers->OptionalHeader.AddressOfEntryPoint); - } - } else { - result->exeEntry = NULL; - } + // get entry point of loaded library + if (result->headers->OptionalHeader.AddressOfEntryPoint != 0) { + if (result->isDLL) { + DllEntryProc DllEntry = (DllEntryProc)(LPVOID)(code + result->headers->OptionalHeader.AddressOfEntryPoint); + // notify library about attaching to process + BOOL successfull = (*DllEntry)((HINSTANCE)code, DLL_PROCESS_ATTACH, 0); + if (!successfull) { + SetLastError(ERROR_DLL_INIT_FAILED); + goto error; + } + result->initialized = TRUE; + } + else { + result->exeEntry = (ExeEntryProc)(LPVOID)(code + result->headers->OptionalHeader.AddressOfEntryPoint); + } + } + else { + result->exeEntry = NULL; + } - return (PMEMORYMODULE)result; + return (PMEMORYMODULE)result; error: - // cleanup - MemoryFreeLibrary(result); - return NULL; + // cleanup + MemoryFreeLibrary(result); + return NULL; } static int _compare(const void *a, const void *b) { - const struct ExportNameEntry *p1 = (const struct ExportNameEntry*) a; - const struct ExportNameEntry *p2 = (const struct ExportNameEntry*) b; - return _stricmp(p1->name, p2->name); + const struct ExportNameEntry *p1 = (const struct ExportNameEntry*) a; + const struct ExportNameEntry *p2 = (const struct ExportNameEntry*) b; + return _stricmp(p1->name, p2->name); } static int _find(const void *a, const void *b) { - LPCSTR *name = (LPCSTR *) a; - const struct ExportNameEntry *p = (const struct ExportNameEntry*) b; - return _stricmp(*name, p->name); + LPCSTR *name = (LPCSTR *)a; + const struct ExportNameEntry *p = (const struct ExportNameEntry*) b; + return _stricmp(*name, p->name); } FARPROC MemoryGetProcAddress(PMEMORYMODULE mod, LPCSTR name) { - PMEMORYMODULE module = (PMEMORYMODULE)mod; - unsigned char *codeBase = module->codeBase; - DWORD idx = 0; - PIMAGE_EXPORT_DIRECTORY exports; - PIMAGE_DATA_DIRECTORY directory = GET_HEADER_DICTIONARY(module, IMAGE_DIRECTORY_ENTRY_EXPORT); - if (directory->Size == 0) { - // no export table found - SetLastError(ERROR_PROC_NOT_FOUND); - return NULL; - } + PMEMORYMODULE module = (PMEMORYMODULE)mod; + unsigned char *codeBase = module->codeBase; + DWORD idx = 0; + PIMAGE_EXPORT_DIRECTORY exports; + PIMAGE_DATA_DIRECTORY directory = GET_HEADER_DICTIONARY(module, IMAGE_DIRECTORY_ENTRY_EXPORT); + if (directory->Size == 0) { + // no export table found + SetLastError(ERROR_PROC_NOT_FOUND); + return NULL; + } - exports = (PIMAGE_EXPORT_DIRECTORY) (codeBase + directory->VirtualAddress); - if (exports->NumberOfNames == 0 || exports->NumberOfFunctions == 0) { - // DLL doesn't export anything - SetLastError(ERROR_PROC_NOT_FOUND); - return NULL; - } + exports = (PIMAGE_EXPORT_DIRECTORY)(codeBase + directory->VirtualAddress); + if (exports->NumberOfNames == 0 || exports->NumberOfFunctions == 0) { + // DLL doesn't export anything + SetLastError(ERROR_PROC_NOT_FOUND); + return NULL; + } - if (HIWORD(name) == 0) { - // load function by ordinal value - if (LOWORD(name) < exports->Base) { - SetLastError(ERROR_PROC_NOT_FOUND); - return NULL; - } + if (HIWORD(name) == 0) { + // load function by ordinal value + if (LOWORD(name) < exports->Base) { + SetLastError(ERROR_PROC_NOT_FOUND); + return NULL; + } - idx = LOWORD(name) - exports->Base; - } else if (!exports->NumberOfNames) { - SetLastError(ERROR_PROC_NOT_FOUND); - return NULL; - } else { - const struct ExportNameEntry *found; + idx = LOWORD(name) - exports->Base; + } + else if (!exports->NumberOfNames) { + SetLastError(ERROR_PROC_NOT_FOUND); + return NULL; + } + else { + const struct ExportNameEntry *found; - // Lazily build name table and sort it by names - if (!module->nameExportsTable) { - DWORD i; - DWORD *nameRef = (DWORD *) (codeBase + exports->AddressOfNames); - WORD *ordinal = (WORD *) (codeBase + exports->AddressOfNameOrdinals); - struct ExportNameEntry *entry = (struct ExportNameEntry*) malloc(exports->NumberOfNames * sizeof(struct ExportNameEntry)); - module->nameExportsTable = entry; - if (!entry) { - SetLastError(ERROR_OUTOFMEMORY); - return NULL; - } - for (i=0; iNumberOfNames; i++, nameRef++, ordinal++, entry++) { - entry->name = (const char *) (codeBase + (*nameRef)); - entry->idx = *ordinal; - } - qsort(module->nameExportsTable, - exports->NumberOfNames, - sizeof(struct ExportNameEntry), _compare); - } + // Lazily build name table and sort it by names + if (!module->nameExportsTable) { + DWORD i; + DWORD *nameRef = (DWORD *)(codeBase + exports->AddressOfNames); + WORD *ordinal = (WORD *)(codeBase + exports->AddressOfNameOrdinals); + struct ExportNameEntry *entry = (struct ExportNameEntry*) malloc(exports->NumberOfNames * sizeof(struct ExportNameEntry)); + module->nameExportsTable = entry; + if (!entry) { + SetLastError(ERROR_OUTOFMEMORY); + return NULL; + } + for (i = 0; i < exports->NumberOfNames; i++, nameRef++, ordinal++, entry++) { + entry->name = (const char *)(codeBase + (*nameRef)); + entry->idx = *ordinal; + } + qsort(module->nameExportsTable, + exports->NumberOfNames, + sizeof(struct ExportNameEntry), _compare); + } - // search function name in list of exported names with binary search - found = (const struct ExportNameEntry*) bsearch(&name, - module->nameExportsTable, - exports->NumberOfNames, - sizeof(struct ExportNameEntry), _find); - if (!found) { - // exported symbol not found - SetLastError(ERROR_PROC_NOT_FOUND); - return NULL; - } + // search function name in list of exported names with binary search + found = (const struct ExportNameEntry*) bsearch(&name, + module->nameExportsTable, + exports->NumberOfNames, + sizeof(struct ExportNameEntry), _find); + if (!found) { + // exported symbol not found + SetLastError(ERROR_PROC_NOT_FOUND); + return NULL; + } - idx = found->idx; - } + idx = found->idx; + } - if (idx > exports->NumberOfFunctions) { - // name <-> ordinal number don't match - SetLastError(ERROR_PROC_NOT_FOUND); - return NULL; - } + if (idx > exports->NumberOfFunctions) { + // name <-> ordinal number don't match + SetLastError(ERROR_PROC_NOT_FOUND); + return NULL; + } - // AddressOfFunctions contains the RVAs to the "real" functions - return (FARPROC)(LPVOID)(codeBase + (*(DWORD *) (codeBase + exports->AddressOfFunctions + (idx*4)))); + // AddressOfFunctions contains the RVAs to the "real" functions + return (FARPROC)(LPVOID)(codeBase + (*(DWORD *)(codeBase + exports->AddressOfFunctions + (idx * 4)))); } void MemoryFreeLibrary(PMEMORYMODULE mod) { - PMEMORYMODULE module = (PMEMORYMODULE)mod; + PMEMORYMODULE module = (PMEMORYMODULE)mod; - if (module == NULL) { - return; - } - if (module->initialized) { - // notify library about detaching from process - DllEntryProc DllEntry = (DllEntryProc)(LPVOID)(module->codeBase + module->headers->OptionalHeader.AddressOfEntryPoint); - (*DllEntry)((HINSTANCE)module->codeBase, DLL_PROCESS_DETACH, 0); - } + if (module == NULL) { + return; + } + if (module->initialized) { + // notify library about detaching from process + DllEntryProc DllEntry = (DllEntryProc)(LPVOID)(module->codeBase + module->headers->OptionalHeader.AddressOfEntryPoint); + (*DllEntry)((HINSTANCE)module->codeBase, DLL_PROCESS_DETACH, 0); + } - free(module->nameExportsTable); - if (module->modules != NULL) { - // free previously opened libraries - int i; - for (i=0; inumModules; i++) { - if (module->modules[i] != NULL) { - module->freeLibrary(module->modules[i], module->userdata); - } - } + free(module->nameExportsTable); + if (module->modules != NULL) { + // free previously opened libraries + int i; + for (i = 0; i < module->numModules; i++) { + if (module->modules[i] != NULL) { + module->freeLibrary(module->modules[i], module->userdata); + } + } - free(module->modules); - } + free(module->modules); + } - if (module->codeBase != NULL) { - // release memory of library - module->free(module->codeBase, 0, MEM_RELEASE, module->userdata); - } + if (module->codeBase != NULL) { + // release memory of library + module->free(module->codeBase, 0, MEM_RELEASE, module->userdata); + } - HeapFree(GetProcessHeap(), 0, module); + HeapFree(GetProcessHeap(), 0, module); } int MemoryCallEntryPoint(PMEMORYMODULE mod) { - PMEMORYMODULE module = (PMEMORYMODULE)mod; + PMEMORYMODULE module = (PMEMORYMODULE)mod; - if (module == NULL || module->isDLL || module->exeEntry == NULL || !module->isRelocated) { - return -1; - } + if (module == NULL || module->isDLL || module->exeEntry == NULL || !module->isRelocated) { + return -1; + } - return module->exeEntry(); + return module->exeEntry(); } #define DEFAULT_LANGUAGE MAKELANGID(LANG_NEUTRAL, SUBLANG_NEUTRAL) HMEMORYRSRC MemoryFindResource(PMEMORYMODULE module, LPCTSTR name, LPCTSTR type) { - return MemoryFindResourceEx(module, name, type, DEFAULT_LANGUAGE); + return MemoryFindResourceEx(module, name, type, DEFAULT_LANGUAGE); } static PIMAGE_RESOURCE_DIRECTORY_ENTRY _MemorySearchResourceEntry( - void *root, - PIMAGE_RESOURCE_DIRECTORY resources, - LPCTSTR key) + void *root, + PIMAGE_RESOURCE_DIRECTORY resources, + LPCTSTR key) { - PIMAGE_RESOURCE_DIRECTORY_ENTRY entries = (PIMAGE_RESOURCE_DIRECTORY_ENTRY) (resources + 1); - PIMAGE_RESOURCE_DIRECTORY_ENTRY result = NULL; - DWORD start; - DWORD end; - DWORD middle; + PIMAGE_RESOURCE_DIRECTORY_ENTRY entries = (PIMAGE_RESOURCE_DIRECTORY_ENTRY)(resources + 1); + PIMAGE_RESOURCE_DIRECTORY_ENTRY result = NULL; + DWORD start; + DWORD end; + DWORD middle; - if (!IS_INTRESOURCE(key) && key[0] == TEXT('#')) { - // special case: resource id given as string - TCHAR *endpos = NULL; - long int tmpkey = (WORD) _tcstol((TCHAR *) &key[1], &endpos, 10); - if (tmpkey <= 0xffff && lstrlen(endpos) == 0) { - key = MAKEINTRESOURCE(tmpkey); - } - } + if (!IS_INTRESOURCE(key) && key[0] == TEXT('#')) { + // special case: resource id given as string + TCHAR *endpos = NULL; + long int tmpkey = (WORD)_tcstol((TCHAR *)&key[1], &endpos, 10); + if (tmpkey <= 0xffff && lstrlen(endpos) == 0) { + key = MAKEINTRESOURCE(tmpkey); + } + } - // entries are stored as ordered list of named entries, - // followed by an ordered list of id entries - we can do - // a binary search to find faster... - if (IS_INTRESOURCE(key)) { - WORD check = (WORD) (uintptr_t) key; - start = resources->NumberOfNamedEntries; - end = start + resources->NumberOfIdEntries; + // entries are stored as ordered list of named entries, + // followed by an ordered list of id entries - we can do + // a binary search to find faster... + if (IS_INTRESOURCE(key)) { + WORD check = (WORD)(uintptr_t)key; + start = resources->NumberOfNamedEntries; + end = start + resources->NumberOfIdEntries; - while (end > start) { - WORD entryName; - middle = (start + end) >> 1; - entryName = (WORD) entries[middle].Name; - if (check < entryName) { - end = (end != middle ? middle : middle-1); - } else if (check > entryName) { - start = (start != middle ? middle : middle+1); - } else { - result = &entries[middle]; - break; - } - } - } else { - LPCWSTR searchKey; - size_t searchKeyLen = _tcslen(key); + while (end > start) { + WORD entryName; + middle = (start + end) >> 1; + entryName = (WORD)entries[middle].Name; + if (check < entryName) { + end = (end != middle ? middle : middle - 1); + } + else if (check > entryName) { + start = (start != middle ? middle : middle + 1); + } else { + result = &entries[middle]; + break; + } + } + } else { + LPCWSTR searchKey; + size_t searchKeyLen = _tcslen(key); #if defined(UNICODE) - searchKey = key; + searchKey = key; #else - // Resource names are always stored using 16bit characters, need to - // convert string we search for. + // Resource names are always stored using 16bit characters, need to + // convert string we search for. #define MAX_LOCAL_KEY_LENGTH 2048 - // In most cases resource names are short, so optimize for that by - // using a pre-allocated array. - wchar_t _searchKeySpace[MAX_LOCAL_KEY_LENGTH+1]; - LPWSTR _searchKey; - if (searchKeyLen > MAX_LOCAL_KEY_LENGTH) { - size_t _searchKeySize = (searchKeyLen + 1) * sizeof(wchar_t); - _searchKey = (LPWSTR) malloc(_searchKeySize); - if (_searchKey == NULL) { - SetLastError(ERROR_OUTOFMEMORY); - return NULL; - } - } else { - _searchKey = &_searchKeySpace[0]; - } + // In most cases resource names are short, so optimize for that by + // using a pre-allocated array. + wchar_t _searchKeySpace[MAX_LOCAL_KEY_LENGTH + 1]; + LPWSTR _searchKey; + if (searchKeyLen > MAX_LOCAL_KEY_LENGTH) { + size_t _searchKeySize = (searchKeyLen + 1) * sizeof(wchar_t); + _searchKey = (LPWSTR)malloc(_searchKeySize); + if (_searchKey == NULL) { + SetLastError(ERROR_OUTOFMEMORY); + return NULL; + } + } + else { + _searchKey = &_searchKeySpace[0]; + } - mbstowcs(_searchKey, key, searchKeyLen); - _searchKey[searchKeyLen] = 0; - searchKey = _searchKey; + mbstowcs(_searchKey, key, searchKeyLen); + _searchKey[searchKeyLen] = 0; + searchKey = _searchKey; #endif - start = 0; - end = resources->NumberOfNamedEntries; - while (end > start) { - int cmp; - PIMAGE_RESOURCE_DIR_STRING_U resourceString; - middle = (start + end) >> 1; - resourceString = (PIMAGE_RESOURCE_DIR_STRING_U) OffsetPointer(root, entries[middle].Name & 0x7FFFFFFF); - cmp = _wcsnicmp(searchKey, resourceString->NameString, resourceString->Length); - if (cmp == 0) { - // Handle partial match - if (searchKeyLen > resourceString->Length) { - cmp = 1; - } else if (searchKeyLen < resourceString->Length) { - cmp = -1; - } - } - if (cmp < 0) { - end = (middle != end ? middle : middle-1); - } else if (cmp > 0) { - start = (middle != start ? middle : middle+1); - } else { - result = &entries[middle]; - break; - } - } + start = 0; + end = resources->NumberOfNamedEntries; + while (end > start) { + int cmp; + PIMAGE_RESOURCE_DIR_STRING_U resourceString; + middle = (start + end) >> 1; + resourceString = (PIMAGE_RESOURCE_DIR_STRING_U)OffsetPointer(root, entries[middle].Name & 0x7FFFFFFF); + cmp = _wcsnicmp(searchKey, resourceString->NameString, resourceString->Length); + if (cmp == 0) { + // Handle partial match + if (searchKeyLen > resourceString->Length) { + cmp = 1; + } + else if (searchKeyLen < resourceString->Length) { + cmp = -1; + } + } + if (cmp < 0) { + end = (middle != end ? middle : middle - 1); + } + else if (cmp > 0) { + start = (middle != start ? middle : middle + 1); + } + else { + result = &entries[middle]; + break; + } + } #if !defined(UNICODE) - if (searchKeyLen > MAX_LOCAL_KEY_LENGTH) { - free(_searchKey); - } + if (searchKeyLen > MAX_LOCAL_KEY_LENGTH) { + free(_searchKey); + } #undef MAX_LOCAL_KEY_LENGTH #endif - } + } - return result; + return result; } HMEMORYRSRC MemoryFindResourceEx(PMEMORYMODULE module, LPCTSTR name, LPCTSTR type, WORD language) { - unsigned char *codeBase = ((PMEMORYMODULE) module)->codeBase; - PIMAGE_DATA_DIRECTORY directory = GET_HEADER_DICTIONARY((PMEMORYMODULE) module, IMAGE_DIRECTORY_ENTRY_RESOURCE); - 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 (directory->Size == 0) { - // no resource table found - SetLastError(ERROR_RESOURCE_DATA_NOT_FOUND); - return NULL; - } + unsigned char *codeBase = ((PMEMORYMODULE)module)->codeBase; + PIMAGE_DATA_DIRECTORY directory = GET_HEADER_DICTIONARY((PMEMORYMODULE)module, IMAGE_DIRECTORY_ENTRY_RESOURCE); + 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 (directory->Size == 0) { + // no resource table found + SetLastError(ERROR_RESOURCE_DATA_NOT_FOUND); + return NULL; + } - if (language == DEFAULT_LANGUAGE) { - // use language from current thread - language = LANGIDFROMLCID(GetThreadLocale()); - } + if (language == DEFAULT_LANGUAGE) { + // use language from current thread + language = LANGIDFROMLCID(GetThreadLocale()); + } - // resources are stored as three-level tree - // - first node is the type - // - second node is the name - // - third node is the language - rootResources = (PIMAGE_RESOURCE_DIRECTORY) (codeBase + directory->VirtualAddress); - foundType = _MemorySearchResourceEntry(rootResources, rootResources, type); - if (foundType == NULL) { - SetLastError(ERROR_RESOURCE_TYPE_NOT_FOUND); - return NULL; - } + // resources are stored as three-level tree + // - first node is the type + // - second node is the name + // - third node is the language + rootResources = (PIMAGE_RESOURCE_DIRECTORY)(codeBase + directory->VirtualAddress); + foundType = _MemorySearchResourceEntry(rootResources, rootResources, type); + if (foundType == NULL) { + SetLastError(ERROR_RESOURCE_TYPE_NOT_FOUND); + return NULL; + } - typeResources = (PIMAGE_RESOURCE_DIRECTORY) (codeBase + directory->VirtualAddress + (foundType->OffsetToData & 0x7fffffff)); - foundName = _MemorySearchResourceEntry(rootResources, typeResources, name); - if (foundName == NULL) { - SetLastError(ERROR_RESOURCE_NAME_NOT_FOUND); - return NULL; - } + typeResources = (PIMAGE_RESOURCE_DIRECTORY)(codeBase + directory->VirtualAddress + (foundType->OffsetToData & 0x7fffffff)); + foundName = _MemorySearchResourceEntry(rootResources, typeResources, name); + if (foundName == NULL) { + SetLastError(ERROR_RESOURCE_NAME_NOT_FOUND); + return NULL; + } - nameResources = (PIMAGE_RESOURCE_DIRECTORY) (codeBase + directory->VirtualAddress + (foundName->OffsetToData & 0x7fffffff)); - foundLanguage = _MemorySearchResourceEntry(rootResources, nameResources, (LPCTSTR) (uintptr_t) language); - if (foundLanguage == NULL) { - // requested language not found, use first available - if (nameResources->NumberOfIdEntries == 0) { - SetLastError(ERROR_RESOURCE_LANG_NOT_FOUND); - return NULL; - } + nameResources = (PIMAGE_RESOURCE_DIRECTORY)(codeBase + directory->VirtualAddress + (foundName->OffsetToData & 0x7fffffff)); + foundLanguage = _MemorySearchResourceEntry(rootResources, nameResources, (LPCTSTR)(uintptr_t)language); + if (foundLanguage == NULL) { + // requested language not found, use first available + if (nameResources->NumberOfIdEntries == 0) { + SetLastError(ERROR_RESOURCE_LANG_NOT_FOUND); + return NULL; + } - foundLanguage = (PIMAGE_RESOURCE_DIRECTORY_ENTRY) (nameResources + 1); - } + foundLanguage = (PIMAGE_RESOURCE_DIRECTORY_ENTRY)(nameResources + 1); + } - return (codeBase + directory->VirtualAddress + (foundLanguage->OffsetToData & 0x7fffffff)); + return (codeBase + directory->VirtualAddress + (foundLanguage->OffsetToData & 0x7fffffff)); } DWORD MemorySizeofResource(PMEMORYMODULE module, HMEMORYRSRC resource) { - PIMAGE_RESOURCE_DATA_ENTRY entry; - UNREFERENCED_PARAMETER(module); - entry = (PIMAGE_RESOURCE_DATA_ENTRY) resource; - if (entry == NULL) { - return 0; - } + PIMAGE_RESOURCE_DATA_ENTRY entry; + UNREFERENCED_PARAMETER(module); + entry = (PIMAGE_RESOURCE_DATA_ENTRY)resource; + if (entry == NULL) { + return 0; + } - return entry->Size; + return entry->Size; } LPVOID MemoryLoadResource(PMEMORYMODULE module, HMEMORYRSRC resource) { - unsigned char *codeBase = ((PMEMORYMODULE) module)->codeBase; - PIMAGE_RESOURCE_DATA_ENTRY entry = (PIMAGE_RESOURCE_DATA_ENTRY) resource; - if (entry == NULL) { - return NULL; - } + unsigned char *codeBase = ((PMEMORYMODULE)module)->codeBase; + PIMAGE_RESOURCE_DATA_ENTRY entry = (PIMAGE_RESOURCE_DATA_ENTRY)resource; + if (entry == NULL) { + return NULL; + } - return codeBase + entry->OffsetToData; + return codeBase + entry->OffsetToData; } int MemoryLoadString(PMEMORYMODULE module, UINT id, LPTSTR buffer, int maxsize) { - return MemoryLoadStringEx(module, id, buffer, maxsize, DEFAULT_LANGUAGE); + return MemoryLoadStringEx(module, id, buffer, maxsize, DEFAULT_LANGUAGE); } int MemoryLoadStringEx(PMEMORYMODULE module, UINT id, LPTSTR buffer, int maxsize, WORD language) { - HMEMORYRSRC resource; - PIMAGE_RESOURCE_DIR_STRING_U data; - DWORD size; - if (maxsize == 0) { - return 0; - } + HMEMORYRSRC resource; + PIMAGE_RESOURCE_DIR_STRING_U data; + DWORD size; + if (maxsize == 0) { + return 0; + } - resource = MemoryFindResourceEx(module, MAKEINTRESOURCE((id >> 4) + 1), RT_STRING, language); - if (resource == NULL) { - buffer[0] = 0; - return 0; - } + resource = MemoryFindResourceEx(module, MAKEINTRESOURCE((id >> 4) + 1), RT_STRING, language); + if (resource == NULL) { + buffer[0] = 0; + return 0; +} - data = (PIMAGE_RESOURCE_DIR_STRING_U) MemoryLoadResource(module, resource); - id = id & 0x0f; - while (id--) { - data = (PIMAGE_RESOURCE_DIR_STRING_U) OffsetPointer(data, (data->Length + 1) * sizeof(WCHAR)); - } - if (data->Length == 0) { - SetLastError(ERROR_RESOURCE_NAME_NOT_FOUND); - buffer[0] = 0; - return 0; - } + data = (PIMAGE_RESOURCE_DIR_STRING_U)MemoryLoadResource(module, resource); + id = id & 0x0f; + while (id--) { + data = (PIMAGE_RESOURCE_DIR_STRING_U)OffsetPointer(data, (data->Length + 1) * sizeof(WCHAR)); + } + if (data->Length == 0) { + SetLastError(ERROR_RESOURCE_NAME_NOT_FOUND); + buffer[0] = 0; + return 0; + } - size = data->Length; - if (size >= (DWORD) maxsize) { - size = maxsize; - } else { - buffer[size] = 0; - } + size = data->Length; + if (size >= (DWORD)maxsize) { + size = maxsize; + } + else { + buffer[size] = 0; + } #if defined(UNICODE) - wcsncpy(buffer, data->NameString, size); + wcsncpy(buffer, data->NameString, size); #else - wcstombs(buffer, data->NameString, size); + wcstombs(buffer, data->NameString, size); #endif - return size; + return size; } #ifdef TESTSUITE @@ -1292,53 +1359,53 @@ MemoryLoadStringEx(PMEMORYMODULE module, UINT id, LPTSTR buffer, int maxsize, WO #endif static const uintptr_t AlignValueDownTests[][3] = { - {16, 16, 16}, - {17, 16, 16}, - {32, 16, 32}, - {33, 16, 32}, + {16, 16, 16}, + {17, 16, 16}, + {32, 16, 32}, + {33, 16, 32}, #ifdef _WIN64 - {0x12345678abcd1000, 0x1000, 0x12345678abcd1000}, - {0x12345678abcd101f, 0x1000, 0x12345678abcd1000}, + {0x12345678abcd1000, 0x1000, 0x12345678abcd1000}, + {0x12345678abcd101f, 0x1000, 0x12345678abcd1000}, #endif - {0, 0, 0}, + {0, 0, 0}, }; static const uintptr_t AlignValueUpTests[][3] = { - {16, 16, 16}, - {17, 16, 32}, - {32, 16, 32}, - {33, 16, 48}, + {16, 16, 16}, + {17, 16, 32}, + {32, 16, 32}, + {33, 16, 48}, #ifdef _WIN64 - {0x12345678abcd1000, 0x1000, 0x12345678abcd1000}, - {0x12345678abcd101f, 0x1000, 0x12345678abcd2000}, + {0x12345678abcd1000, 0x1000, 0x12345678abcd1000}, + {0x12345678abcd101f, 0x1000, 0x12345678abcd2000}, #endif - {0, 0, 0}, + {0, 0, 0}, }; BOOL MemoryModuleTestsuite() { - BOOL success = TRUE; - size_t idx; - for (idx = 0; AlignValueDownTests[idx][0]; ++idx) { - const uintptr_t* tests = AlignValueDownTests[idx]; - uintptr_t value = AlignValueDown(tests[0], tests[1]); - if (value != tests[2]) { - printf("AlignValueDown failed for 0x%" PRIxPTR "/0x%" PRIxPTR ": expected 0x%" PRIxPTR ", got 0x%" PRIxPTR "\n", - tests[0], tests[1], tests[2], value); - success = FALSE; - } - } - for (idx = 0; AlignValueDownTests[idx][0]; ++idx) { - const uintptr_t* tests = AlignValueUpTests[idx]; - uintptr_t value = AlignValueUp(tests[0], tests[1]); - if (value != tests[2]) { - printf("AlignValueUp failed for 0x%" PRIxPTR "/0x%" PRIxPTR ": expected 0x%" PRIxPTR ", got 0x%" PRIxPTR "\n", - tests[0], tests[1], tests[2], value); - success = FALSE; - } - } - if (success) { - printf("OK\n"); - } - return success; + BOOL success = TRUE; + size_t idx; + for (idx = 0; AlignValueDownTests[idx][0]; ++idx) { + const uintptr_t* tests = AlignValueDownTests[idx]; + uintptr_t value = AlignValueDown(tests[0], tests[1]); + if (value != tests[2]) { + printf("AlignValueDown failed for 0x%" PRIxPTR "/0x%" PRIxPTR ": expected 0x%" PRIxPTR ", got 0x%" PRIxPTR "\n", + tests[0], tests[1], tests[2], value); + success = FALSE; + } + } + for (idx = 0; AlignValueDownTests[idx][0]; ++idx) { + const uintptr_t* tests = AlignValueUpTests[idx]; + uintptr_t value = AlignValueUp(tests[0], tests[1]); + if (value != tests[2]) { + printf("AlignValueUp failed for 0x%" PRIxPTR "/0x%" PRIxPTR ": expected 0x%" PRIxPTR ", got 0x%" PRIxPTR "\n", + tests[0], tests[1], tests[2], value); + success = FALSE; + } + } + if (success) { + printf("OK\n"); + } + return success; } #endif diff --git a/main.cpp b/main.cpp index 5311b5a..1b790a9 100644 --- a/main.cpp +++ b/main.cpp @@ -27,6 +27,7 @@ BOOL LoadDllFromRes(PVOID *pDllData, DWORD *dwDllSize) int main() { + PVOID pDllData = NULL; DWORD dwDllSize = 0;