diff --git a/.gitignore b/.gitignore index 508c3dc..a24e076 100644 --- a/.gitignore +++ b/.gitignore @@ -6,3 +6,9 @@ tests/*.res tests/SampleExports.cpp tests/SampleExports.h + +x64/ +Debug/ +*.vcxproj.user +.vs/ +CMakeSettings.json diff --git a/MemoryModule.c b/MemoryModule.c index 9f95a70..c774101 100644 --- a/MemoryModule.c +++ b/MemoryModule.c @@ -77,7 +77,7 @@ typedef struct POINTER_LIST { } POINTER_LIST; #endif -typedef struct { +typedef struct MEMORYMODULE { PIMAGE_NT_HEADERS headers; unsigned char *codeBase; HCUSTOMMODULE *modules; @@ -99,7 +99,7 @@ typedef struct { #endif } MEMORYMODULE, *PMEMORYMODULE; -typedef struct { +typedef struct SECTIONFINALIZEDATA { LPVOID address; LPVOID alignedAddress; SIZE_T size; @@ -536,12 +536,12 @@ void MemoryDefaultFreeLibrary(HCUSTOMMODULE module, void *userdata) FreeLibrary((HMODULE) module); } -HMEMORYMODULE MemoryLoadLibrary(const void *data, size_t size) +HMEMORYMODULE MemoryLoadLibrary(const void *data, size_t size, LPVOID imageBase) { - return MemoryLoadLibraryEx(data, size, MemoryDefaultAlloc, MemoryDefaultFree, MemoryDefaultLoadLibrary, MemoryDefaultGetProcAddress, MemoryDefaultFreeLibrary, NULL); + return MemoryLoadLibraryEx(data, size, imageBase, MemoryDefaultAlloc, MemoryDefaultFree, MemoryDefaultLoadLibrary, MemoryDefaultGetProcAddress, MemoryDefaultFreeLibrary, NULL); } -HMEMORYMODULE MemoryLoadLibraryEx(const void *data, size_t size, +HMEMORYMODULE MemoryLoadLibraryEx(const void *data, size_t size, LPVOID imageBase, CustomAllocFunc allocMemory, CustomFreeFunc freeMemory, CustomLoadLibraryFunc loadLibrary, @@ -616,10 +616,13 @@ HMEMORYMODULE MemoryLoadLibraryEx(const void *data, size_t size, return NULL; } + if (!imageBase) + imageBase = (LPVOID)old_header->OptionalHeader.ImageBase; + // 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), + code = (unsigned char *)allocMemory(imageBase, alignedImageSize, MEM_RESERVE | MEM_COMMIT, PAGE_READWRITE, @@ -963,8 +966,8 @@ static PIMAGE_RESOURCE_DIRECTORY_ENTRY _MemorySearchResourceEntry( // using a pre-allocated array. wchar_t _searchKeySpace[MAX_LOCAL_KEY_LENGTH+1]; LPWSTR _searchKey; + size_t _searchKeySize = (searchKeyLen + 1) * sizeof(wchar_t); if (searchKeyLen > MAX_LOCAL_KEY_LENGTH) { - size_t _searchKeySize = (searchKeyLen + 1) * sizeof(wchar_t); _searchKey = (LPWSTR) malloc(_searchKeySize); if (_searchKey == NULL) { SetLastError(ERROR_OUTOFMEMORY); @@ -974,8 +977,8 @@ static PIMAGE_RESOURCE_DIRECTORY_ENTRY _MemorySearchResourceEntry( _searchKey = &_searchKeySpace[0]; } - mbstowcs(_searchKey, key, searchKeyLen); - _searchKey[searchKeyLen] = 0; + if (mbstowcs_s(&_searchKeySize, _searchKey, searchKeyLen + 1, key, searchKeyLen)) + return NULL; searchKey = _searchKey; #endif start = 0; @@ -1102,7 +1105,7 @@ MemoryLoadStringEx(HMEMORYMODULE module, UINT id, LPTSTR buffer, int maxsize, WO { HMEMORYRSRC resource; PIMAGE_RESOURCE_DIR_STRING_U data; - DWORD size; + size_t size; if (maxsize == 0) { return 0; } @@ -1124,18 +1127,82 @@ MemoryLoadStringEx(HMEMORYMODULE module, UINT id, LPTSTR buffer, int maxsize, WO return 0; } - size = data->Length; - if (size >= (DWORD) maxsize) { - size = maxsize; + size = (size_t)data->Length; + if (size >= (size_t) maxsize) { + size = (size_t)maxsize; } else { buffer[size] = 0; } #if defined(UNICODE) - wcsncpy(buffer, data->NameString, size); + wcsncpy_s(buffer, size, data->NameString, _TRUNCATE); #else - wcstombs(buffer, data->NameString, size); + wcstombs_s(&size, buffer, maxsize, data->NameString, size); #endif - return size; + return (int)size; +} + +static LPVOID ReadLibraryFile(LPCSTR lpszFileName, PDWORD pdwSize) +{ + DWORD dwBytesRead = 0; + BOOL bResult = FALSE; + + HANDLE hFile = CreateFileA(lpszFileName, + GENERIC_READ, // open for reading + FILE_SHARE_READ, // share for reading + NULL, // default security + OPEN_EXISTING, // existing file only + FILE_ATTRIBUTE_NORMAL, // normal file + NULL // no attr. template + ); + + if (hFile != INVALID_HANDLE_VALUE) { + DWORD dwSize = GetFileSize(hFile, NULL); + void *mem = dwSize ? + HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(MEMORYMODULE)) : NULL; + BOOL bResult = mem && ReadFile(hFile, mem, dwSize, &dwBytesRead, NULL); + CloseHandle(hFile); + + if (mem) { + if (bResult) { + if (dwBytesRead == dwSize) { + if (pdwSize) + *pdwSize = dwSize; + return mem; + } + } + + free(mem); + } + } + + return NULL; +} + +HMEMORYMODULE MemoryLoadLibraryFile(LPCSTR lpszFileName, LPVOID imageBase) +{ + return MemoryLoadLibraryFileEx(lpszFileName, imageBase, MemoryDefaultAlloc, MemoryDefaultFree, MemoryDefaultLoadLibrary, MemoryDefaultGetProcAddress, MemoryDefaultFreeLibrary, NULL); +} + +HMEMORYMODULE MemoryLoadLibraryFileEx(LPCSTR lpszFileName, + LPVOID imageBase, + CustomAllocFunc allocMemory, + CustomFreeFunc freeMemory, + CustomLoadLibraryFunc loadLibrary, + CustomGetProcAddressFunc getProcAddress, + CustomFreeLibraryFunc freeLibrary, + void *userdata) +{ + DWORD dwSize = 0; + LPVOID lpData = ReadLibraryFile(lpszFileName, &dwSize); + HMEMORYMODULE hModule = NULL; + + if (lpData) { + hModule = MemoryLoadLibraryEx(lpData, (size_t)dwSize, imageBase, + allocMemory, freeMemory, loadLibrary, getProcAddress, freeLibrary, + userdata); + HeapFree(GetProcessHeap(), 0, lpData); + } + return hModule; } #ifdef TESTSUITE diff --git a/MemoryModule.h b/MemoryModule.h index a728f6b..43b00e3 100644 --- a/MemoryModule.h +++ b/MemoryModule.h @@ -51,7 +51,7 @@ typedef void (*CustomFreeLibraryFunc)(HCUSTOMMODULE, void *); * All dependencies are resolved using default LoadLibrary/GetProcAddress * calls through the Windows API. */ -HMEMORYMODULE MemoryLoadLibrary(const void *, size_t); +HMEMORYMODULE MemoryLoadLibrary(const void *, size_t, LPVOID); /** * Load EXE/DLL from memory location with the given size using custom dependency @@ -59,7 +59,7 @@ HMEMORYMODULE MemoryLoadLibrary(const void *, size_t); * * Dependencies will be resolved using passed callback methods. */ -HMEMORYMODULE MemoryLoadLibraryEx(const void *, size_t, +HMEMORYMODULE MemoryLoadLibraryEx(const void *, size_t, LPVOID, CustomAllocFunc, CustomFreeFunc, CustomLoadLibraryFunc, @@ -161,6 +161,16 @@ FARPROC MemoryDefaultGetProcAddress(HCUSTOMMODULE, LPCSTR, void *); */ void MemoryDefaultFreeLibrary(HCUSTOMMODULE, void *); +HMEMORYMODULE MemoryLoadLibraryFile(LPCSTR, LPVOID); + +HMEMORYMODULE MemoryLoadLibraryFileEx(LPCSTR, LPVOID, + CustomAllocFunc, + CustomFreeFunc, + CustomLoadLibraryFunc, + CustomGetProcAddressFunc, + CustomFreeLibraryFunc, + void *); + #ifdef __cplusplus } #endif diff --git a/MemoryModule.vcxproj b/MemoryModule.vcxproj new file mode 100644 index 0000000..37b5681 --- /dev/null +++ b/MemoryModule.vcxproj @@ -0,0 +1,162 @@ + + + + + Debug + Win32 + + + Release + Win32 + + + Debug + x64 + + + Release + x64 + + + + 15.0 + {FDD2A9C1-46F7-4CC6-A659-A6F75483CE87} + Win32Proj + MemoryModule + 10.0.17763.0 + + + + StaticLibrary + true + v141 + Unicode + + + StaticLibrary + false + v141 + true + Unicode + + + StaticLibrary + true + v141 + Unicode + + + StaticLibrary + false + v141 + true + Unicode + + + + + + + + + + + + + + + + + + + + + true + + + true + + + false + + + false + + + + NotUsing + Level3 + Disabled + true + _DEBUG;_LIB;%(PreprocessorDefinitions) + true + MultiThreadedDebug + + + Windows + true + + + + + NotUsing + Level3 + Disabled + true + WIN32;_DEBUG;_LIB;%(PreprocessorDefinitions) + true + MultiThreadedDebug + + + Windows + true + + + + + NotUsing + Level3 + MaxSpeed + true + true + true + WIN32;NDEBUG;_LIB;%(PreprocessorDefinitions) + true + MultiThreaded + + + Windows + true + true + true + + + + + NotUsing + Level3 + MaxSpeed + true + true + true + NDEBUG;_LIB;%(PreprocessorDefinitions) + true + MultiThreaded + + + Windows + true + true + true + + + + + + + + + + + + \ No newline at end of file diff --git a/MemoryModule.vcxproj.filters b/MemoryModule.vcxproj.filters new file mode 100644 index 0000000..cbe3a7d --- /dev/null +++ b/MemoryModule.vcxproj.filters @@ -0,0 +1,27 @@ + + + + + {4FC737F1-C7A5-4376-A066-2A32D752A2FF} + cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx + + + {93995380-89BD-4b04-88EB-625FBE52EBFB} + h;hh;hpp;hxx;hm;inl;inc;ipp;xsd + + + {67DA6AB6-F800-4c08-8B7A-83BB121AAD01} + rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms + + + + + Header Files + + + + + Source Files + + + \ No newline at end of file diff --git a/example/DllLoader/DllLoader.cpp b/example/DllLoader/DllLoader.cpp index 4355ea8..3688b2a 100644 --- a/example/DllLoader/DllLoader.cpp +++ b/example/DllLoader/DllLoader.cpp @@ -13,7 +13,9 @@ typedef int (*addNumberProc)(int, int); +#ifndef DLL_FILE #define DLL_FILE TEXT("..\\SampleDLL\\SampleDLL.dll") +#endif void LoadFromFile(void) { diff --git a/example/DllLoader/DllLoader.vcxproj b/example/DllLoader/DllLoader.vcxproj new file mode 100644 index 0000000..9ef3400 --- /dev/null +++ b/example/DllLoader/DllLoader.vcxproj @@ -0,0 +1,175 @@ + + + + + Debug + Win32 + + + Debug + x64 + + + Release + Win32 + + + Release + x64 + + + + {D0226BB5-3A02-4C91-893A-F36567AED5C5} + Win32Proj + 10.0.17763.0 + + + + Application + v141 + MultiByte + + + Application + v141 + MultiByte + + + Application + v141 + MultiByte + + + Application + v141 + MultiByte + + + + + + + + + + + + + + + + + + + <_ProjectFileVersion>15.0.27924.0 + + + Debug\ + Debug\ + true + MinimumRecommendedRules.ruleset + + + + + true + MinimumRecommendedRules.ruleset + + + + + Release\ + Release\ + false + MinimumRecommendedRules.ruleset + + + + + false + MinimumRecommendedRules.ruleset + + + + + + Disabled + WIN32;DLL_FILE="SampleDLL.dll";_DEBUG;_CONSOLE;%(PreprocessorDefinitions) + true + EnableFastChecks + MultiThreadedDebug + + Level3 + EditAndContinue + + + $(OutDir)DllLoader.exe + true + $(OutDir)DllLoader.pdb + Console + MachineX86 + + + + + Disabled + WIN32;DLL_FILE="SampleDLL.dll";_DEBUG;_CONSOLE;%(PreprocessorDefinitions) + EnableFastChecks + MultiThreadedDebug + + + Level3 + ProgramDatabase + + + $(OutDir)DllLoader.exe + true + $(OutDir)DllLoader.pdb + Console + + + + + WIN32;DLL_FILE="SampleDLL.dll";NDEBUG;_CONSOLE;%(PreprocessorDefinitions) + MultiThreaded + + Level3 + ProgramDatabase + + + $(OutDir)DllLoader.exe + true + Console + true + true + MachineX86 + + + + + WIN32;DLL_FILE="SampleDLL.dll";NDEBUG;_CONSOLE;%(PreprocessorDefinitions) + MultiThreaded + + + Level3 + ProgramDatabase + + + $(OutDir)DllLoader.exe + true + Console + true + true + + + + + + + + + + + + + \ No newline at end of file diff --git a/example/DllLoader/DllLoader.vcxproj.filters b/example/DllLoader/DllLoader.vcxproj.filters new file mode 100644 index 0000000..2d59ad2 --- /dev/null +++ b/example/DllLoader/DllLoader.vcxproj.filters @@ -0,0 +1,30 @@ + + + + + {4FC737F1-C7A5-4376-A066-2A32D752A2FF} + cpp;c;cxx;def;odl;idl;hpj;bat;asm;asmx + + + {93995380-89BD-4b04-88EB-625FBE52EBFB} + h;hpp;hxx;hm;inl;inc;xsd + + + {67DA6AB6-F800-4c08-8B7A-83BB121AAD01} + rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx + + + + + Source files + + + Source files + + + + + Header files + + + \ No newline at end of file diff --git a/example/DllMemory.sln b/example/DllMemory.sln index 812654b..a2c30be 100644 --- a/example/DllMemory.sln +++ b/example/DllMemory.sln @@ -1,30 +1,40 @@ -Microsoft Visual Studio Solution File, Format Version 8.00 -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "SampleDLL", "SampleDLL\SampleDLL.vcproj", "{B293DAC4-5BCA-4413-9B7B-92CB56459875}" - ProjectSection(ProjectDependencies) = postProject - {D0226BB5-3A02-4C91-893A-F36567AED5C5} = {D0226BB5-3A02-4C91-893A-F36567AED5C5} - EndProjectSection +Microsoft Visual Studio Solution File, Format Version 12.00 +# Visual Studio 15 +VisualStudioVersion = 15.0.28010.2046 +MinimumVisualStudioVersion = 10.0.40219.1 +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "SampleDLL", "SampleDLL\SampleDLL.vcxproj", "{B293DAC4-5BCA-4413-9B7B-92CB56459875}" EndProject -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "DllLoader", "DllLoader\DllLoader.vcproj", "{D0226BB5-3A02-4C91-893A-F36567AED5C5}" - ProjectSection(ProjectDependencies) = postProject - EndProjectSection +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "DllLoader", "DllLoader\DllLoader.vcxproj", "{D0226BB5-3A02-4C91-893A-F36567AED5C5}" EndProject Global - GlobalSection(SolutionConfiguration) = preSolution - Debug = Debug - Release = Release + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|x64 = Debug|x64 + Debug|x86 = Debug|x86 + Release|x64 = Release|x64 + Release|x86 = Release|x86 EndGlobalSection - GlobalSection(ProjectConfiguration) = postSolution - {B293DAC4-5BCA-4413-9B7B-92CB56459875}.Debug.ActiveCfg = Debug|Win32 - {B293DAC4-5BCA-4413-9B7B-92CB56459875}.Debug.Build.0 = Debug|Win32 - {B293DAC4-5BCA-4413-9B7B-92CB56459875}.Release.ActiveCfg = Release|Win32 - {B293DAC4-5BCA-4413-9B7B-92CB56459875}.Release.Build.0 = Release|Win32 - {D0226BB5-3A02-4C91-893A-F36567AED5C5}.Debug.ActiveCfg = Debug|Win32 - {D0226BB5-3A02-4C91-893A-F36567AED5C5}.Debug.Build.0 = Debug|Win32 - {D0226BB5-3A02-4C91-893A-F36567AED5C5}.Release.ActiveCfg = Release|Win32 - {D0226BB5-3A02-4C91-893A-F36567AED5C5}.Release.Build.0 = Release|Win32 + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {B293DAC4-5BCA-4413-9B7B-92CB56459875}.Debug|x64.ActiveCfg = Debug|x64 + {B293DAC4-5BCA-4413-9B7B-92CB56459875}.Debug|x64.Build.0 = Debug|x64 + {B293DAC4-5BCA-4413-9B7B-92CB56459875}.Debug|x86.ActiveCfg = Debug|Win32 + {B293DAC4-5BCA-4413-9B7B-92CB56459875}.Debug|x86.Build.0 = Debug|Win32 + {B293DAC4-5BCA-4413-9B7B-92CB56459875}.Release|x64.ActiveCfg = Release|x64 + {B293DAC4-5BCA-4413-9B7B-92CB56459875}.Release|x64.Build.0 = Release|x64 + {B293DAC4-5BCA-4413-9B7B-92CB56459875}.Release|x86.ActiveCfg = Release|Win32 + {B293DAC4-5BCA-4413-9B7B-92CB56459875}.Release|x86.Build.0 = Release|Win32 + {D0226BB5-3A02-4C91-893A-F36567AED5C5}.Debug|x64.ActiveCfg = Debug|x64 + {D0226BB5-3A02-4C91-893A-F36567AED5C5}.Debug|x64.Build.0 = Debug|x64 + {D0226BB5-3A02-4C91-893A-F36567AED5C5}.Debug|x86.ActiveCfg = Debug|Win32 + {D0226BB5-3A02-4C91-893A-F36567AED5C5}.Debug|x86.Build.0 = Debug|Win32 + {D0226BB5-3A02-4C91-893A-F36567AED5C5}.Release|x64.ActiveCfg = Release|x64 + {D0226BB5-3A02-4C91-893A-F36567AED5C5}.Release|x64.Build.0 = Release|x64 + {D0226BB5-3A02-4C91-893A-F36567AED5C5}.Release|x86.ActiveCfg = Release|Win32 + {D0226BB5-3A02-4C91-893A-F36567AED5C5}.Release|x86.Build.0 = Release|Win32 EndGlobalSection - GlobalSection(ExtensibilityGlobals) = postSolution + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE EndGlobalSection - GlobalSection(ExtensibilityAddIns) = postSolution + GlobalSection(ExtensibilityGlobals) = postSolution + SolutionGuid = {81506740-6F93-4E79-AC07-7B39C2C9B215} EndGlobalSection EndGlobal diff --git a/example/SampleDLL/SampleDLL.vcxproj b/example/SampleDLL/SampleDLL.vcxproj new file mode 100644 index 0000000..fd719c7 --- /dev/null +++ b/example/SampleDLL/SampleDLL.vcxproj @@ -0,0 +1,184 @@ + + + + + Debug + Win32 + + + Debug + x64 + + + Release + Win32 + + + Release + x64 + + + + {B293DAC4-5BCA-4413-9B7B-92CB56459875} + Win32Proj + 10.0.17763.0 + + + + DynamicLibrary + v141 + MultiByte + + + DynamicLibrary + v141 + MultiByte + + + DynamicLibrary + v141 + MultiByte + + + DynamicLibrary + v141 + MultiByte + + + + + + + + + + + + + + + + + + + <_ProjectFileVersion>15.0.27924.0 + + + Debug\ + Debug\ + true + MinimumRecommendedRules.ruleset + + + + + true + MinimumRecommendedRules.ruleset + + + + + Release\ + Release\ + false + MinimumRecommendedRules.ruleset + + + + + false + MinimumRecommendedRules.ruleset + + + + + + Disabled + WIN32;_DEBUG;_WINDOWS;_USRDLL;SAMPLEDLL_EXPORTS;%(PreprocessorDefinitions) + true + EnableFastChecks + MultiThreadedDebug + + Level3 + EditAndContinue + + + $(OutDir)SampleDLL.dll + true + $(OutDir)SampleDLL.pdb + Windows + $(OutDir)SampleDLL.lib + MachineX86 + + + + + Disabled + WIN32;_DEBUG;_WINDOWS;_USRDLL;SAMPLEDLL_EXPORTS;%(PreprocessorDefinitions) + EnableFastChecks + MultiThreadedDebug + + + Level3 + ProgramDatabase + + + $(OutDir)SampleDLL.dll + true + $(OutDir)SampleDLL.pdb + Windows + $(OutDir)SampleDLL.lib + + + + + WIN32;NDEBUG;_WINDOWS;_USRDLL;SAMPLEDLL_EXPORTS;%(PreprocessorDefinitions) + MultiThreaded + + Level3 + ProgramDatabase + + + $(OutDir)SampleDLL.dll + true + Windows + true + true + $(OutDir)SampleDLL.lib + MachineX86 + + + + + WIN32;NDEBUG;_WINDOWS;_USRDLL;SAMPLEDLL_EXPORTS;%(PreprocessorDefinitions) + MultiThreaded + + + Level3 + ProgramDatabase + + + $(OutDir)SampleDLL.dll + true + Windows + true + true + $(OutDir)SampleDLL.lib + + + + + + + + + + + {d0226bb5-3a02-4c91-893a-f36567aed5c5} + false + + + + + + \ No newline at end of file diff --git a/example/SampleDLL/SampleDLL.vcxproj.filters b/example/SampleDLL/SampleDLL.vcxproj.filters new file mode 100644 index 0000000..a40c1b5 --- /dev/null +++ b/example/SampleDLL/SampleDLL.vcxproj.filters @@ -0,0 +1,27 @@ + + + + + {93995380-89BD-4b04-88EB-625FBE52EBFB} + h;hpp;hxx;hm;inl;inc;xsd + + + {4FC737F1-C7A5-4376-A066-2A32D752A2FF} + cpp;c;cxx;def;odl;idl;hpj;bat;asm;asmx + + + {67DA6AB6-F800-4c08-8B7A-83BB121AAD01} + rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx + + + + + Source files + + + + + Header files + + + \ No newline at end of file