From b54b1523e2d465ca422163c53733a505dd410871 Mon Sep 17 00:00:00 2001 From: Dan Dees Date: Mon, 12 May 2025 17:02:57 +0700 Subject: [PATCH 1/8] FIRST - add cmake build generator - CMakeLists.txt - out of source build - no projects or build artifacts polluting source tree - supports CI/CD automation - generates many build types with simple command line option - https://cmake.org/cmake/help/latest/manual/cmake-generators.7.html - ninja - FAST command line - visual studio project - msbuild - msys make - name - builds static, shared (DLL), and "reflection main" libraries - shared library includes 3rd party - no install needed of Detours as linked into DLL - support shared DLL and "relection" option DLL - creates library/header installation - installs as package - supports vcpkg, conan, CPM - supports nuget - https://cmake.org/cmake/help/latest/cpack_gen/nuget.html - builds 3rd party deps - automates debug and release builds - done with ninja/msbuild - exports config for use in other cmake project - MemoryModulePPConfigVersion.cmake - find_package(MemoryModulePP CONFIG) is enough to use in another project - https://cmake.org/cmake/help/latest/command/find_package.html - importing and exporting cmake project - https://cmake.org/cmake/help/latest/guide/importing-exporting/index.html - maintainable - LLMs such as ChatGPT can create/maintain CMakeLists.txt - no longer need to learn the book and best practices - CMakeList modern format with targets as objects - CMAKE_DEBUG_POSTIFIX allows debug and release dll/exe in same directory example ninja installation output ... -- Install configuration: "Debug" -- Install configuration: "Debug" -- Installing: x:/vs17-64/memorymodulepp/lib/MemoryModulePP-static_d.lib -- Installing: x:/vs17-64/memorymodulepp/include/BaseAddressIndex.h -- Installing: x:/vs17-64/memorymodulepp/include/ImportTable.h -- Installing: x:/vs17-64/memorymodulepp/include/Initialize.h -- Installing: x:/vs17-64/memorymodulepp/include/InvertedFunctionTable.h -- Installing: x:/vs17-64/memorymodulepp/include/LdrEntry.h -- Installing: x:/vs17-64/memorymodulepp/include/LoadDllMemoryApi.h -- Installing: x:/vs17-64/memorymodulepp/include/Loader.h -- Installing: x:/vs17-64/memorymodulepp/include/MemoryModule.h -- Installing: x:/vs17-64/memorymodulepp/include/MmpGlobalData.h -- Installing: x:/vs17-64/memorymodulepp/include/MmpDotNet.h -- Installing: x:/vs17-64/memorymodulepp/include/MmpTls.h -- Installing: x:/vs17-64/memorymodulepp/include/Utils.h -- Installing: x:/vs17-64/memorymodulepp/lib/MemoryModulePP-shared_d.lib -- Installing: x:/vs17-64/memorymodulepp/bin/MemoryModulePP-shared_d.dll -- Installing: x:/vs17-64/memorymodulepp/include/BaseAddressIndex.h -- Installing: x:/vs17-64/memorymodulepp/include/ImportTable.h -- Installing: x:/vs17-64/memorymodulepp/include/Initialize.h -- Installing: x:/vs17-64/memorymodulepp/include/InvertedFunctionTable.h -- Installing: x:/vs17-64/memorymodulepp/include/LdrEntry.h -- Installing: x:/vs17-64/memorymodulepp/include/LoadDllMemoryApi.h -- Installing: x:/vs17-64/memorymodulepp/include/Loader.h -- Installing: x:/vs17-64/memorymodulepp/include/MemoryModule.h -- Installing: x:/vs17-64/memorymodulepp/include/MmpGlobalData.h -- Installing: x:/vs17-64/memorymodulepp/include/MmpDotNet.h -- Installing: x:/vs17-64/memorymodulepp/include/MmpTls.h -- Installing: x:/vs17-64/memorymodulepp/include/Utils.h -- Installing: x:/vs17-64/memorymodulepp/lib/MemoryModulePP-relfect-shared_d.lib -- Installing: x:/vs17-64/memorymodulepp/bin/MemoryModulePP-relfect-shared_d.dll -- Installing: x:/vs17-64/memorymodulepp/include/BaseAddressIndex.h -- Installing: x:/vs17-64/memorymodulepp/include/ImportTable.h -- Installing: x:/vs17-64/memorymodulepp/include/Initialize.h -- Installing: x:/vs17-64/memorymodulepp/include/InvertedFunctionTable.h -- Installing: x:/vs17-64/memorymodulepp/include/LdrEntry.h -- Installing: x:/vs17-64/memorymodulepp/include/LoadDllMemoryApi.h -- Installing: x:/vs17-64/memorymodulepp/include/Loader.h -- Installing: x:/vs17-64/memorymodulepp/include/MemoryModule.h -- Installing: x:/vs17-64/memorymodulepp/include/MmpGlobalData.h -- Installing: x:/vs17-64/memorymodulepp/include/MmpDotNet.h -- Installing: x:/vs17-64/memorymodulepp/include/MmpTls.h -- Installing: x:/vs17-64/memorymodulepp/include/Utils.h -- Installing: x:/vs17-64/memorymodulepp/lib/cmake/MemoryModulePP/MemoryModulePPTargets.cmake -- Installing: x:/vs17-64/memorymodulepp/lib/cmake/MemoryModulePP/MemoryModulePPTargets-debug.cmake -- Installing: x:/vs17-64/memorymodulepp/lib/cmake/MemoryModulePP/MemoryModulePPConfig.cmake -- Installing: x:/vs17-64/memorymodulepp/lib/cmake/MemoryModulePP/MemoryModulePPConfigVersion.cmake --- 3rdparty/CMakelists.txt | 75 +++++++++++++++ 3rdparty/DetoursConfig.cmake.in | 4 + CMakeLists.txt | 14 +++ MemoryModule/CMakeLists.txt | 157 ++++++++++++++++++++++++++++++++ MemoryModulePPConfig.cmake.in | 4 + a/CMakeLists.txt | 29 ++++++ test/CMakeLists.txt | 43 +++++++++ 7 files changed, 326 insertions(+) create mode 100644 3rdparty/CMakelists.txt create mode 100644 3rdparty/DetoursConfig.cmake.in create mode 100644 CMakeLists.txt create mode 100644 MemoryModule/CMakeLists.txt create mode 100644 MemoryModulePPConfig.cmake.in create mode 100644 a/CMakeLists.txt create mode 100644 test/CMakeLists.txt diff --git a/3rdparty/CMakelists.txt b/3rdparty/CMakelists.txt new file mode 100644 index 00000000..c3ed36d6 --- /dev/null +++ b/3rdparty/CMakelists.txt @@ -0,0 +1,75 @@ +cmake_minimum_required(VERSION 3.30) +project(Detours LANGUAGES CXX) + +set(CMAKE_CXX_STANDARD 23) +set(CMAKE_CXX_STANDARD_REQUIRED ON) + +set(libname lib_detours) +set(DETOURS_SOURCE Detours) + +add_library(${libname} STATIC) +target_include_directories(${libname} PRIVATE ${DETOURS_SOURCE}) +target_sources(${libname} PRIVATE + ${DETOURS_SOURCE}/creatwth.cpp + ${DETOURS_SOURCE}/detours.cpp + ${DETOURS_SOURCE}/disasm.cpp + ${DETOURS_SOURCE}/disolarm.cpp + ${DETOURS_SOURCE}/disolarm64.cpp + ${DETOURS_SOURCE}/disolia64.cpp + ${DETOURS_SOURCE}/disolx64.cpp + ${DETOURS_SOURCE}/disolx86.cpp + ${DETOURS_SOURCE}/image.cpp + ${DETOURS_SOURCE}/modules.cpp + ${DETOURS_SOURCE}/uimports.cpp + ${DETOURS_SOURCE}/detours.h + ${DETOURS_SOURCE}/detver.h +) + +# This file is included and not compiled on its own +set_property ( + SOURCE ${DETOURS_SOURCE}/uimports.cpp + APPEND PROPERTY HEADER_FILE_ONLY true) + +# Install libraries and public headers +install(TARGETS ${libname} + EXPORT ${PROJECT_NAME}Targets + LIBRARY DESTINATION lib + ARCHIVE DESTINATION lib + RUNTIME DESTINATION bin + FILE_SET HEADERS DESTINATION include +) + +# Install export file +install(EXPORT ${PROJECT_NAME}Targets + FILE ${PROJECT_NAME}Targets.cmake + NAMESPACE ${PROJECT_NAME}:: + DESTINATION lib/cmake/${PROJECT_NAME} +) + +# Generate and install CMake config file +include(CMakePackageConfigHelpers) +write_basic_package_version_file( + "${CMAKE_CURRENT_BINARY_DIR}/${PROJECT_NAME}ConfigVersion.cmake" + VERSION 1.0.0 + COMPATIBILITY SameMajorVersion +) + +configure_file( + "${CMAKE_CURRENT_SOURCE_DIR}/${PROJECT_NAME}Config.cmake.in" + "${CMAKE_CURRENT_BINARY_DIR}/${PROJECT_NAME}Config.cmake" + @ONLY +) + +install(FILES + "${CMAKE_CURRENT_BINARY_DIR}/${PROJECT_NAME}Config.cmake" + "${CMAKE_CURRENT_BINARY_DIR}/${PROJECT_NAME}ConfigVersion.cmake" + DESTINATION lib/cmake/${PROJECT_NAME} +) + +# CPack configuration for packaging +set(CPACK_PACKAGE_NAME "${PROJECT_NAME}") +set(CPACK_PACKAGE_VERSION "1.0.0") +set(CPACK_PACKAGE_DESCRIPTION "A custom MemoryModulePP implementation") +set(CPACK_PACKAGE_VENDOR "xAI") +set(CPACK_GENERATOR "ZIP;TGZ") +include(CPack) diff --git a/3rdparty/DetoursConfig.cmake.in b/3rdparty/DetoursConfig.cmake.in new file mode 100644 index 00000000..9c15f36a --- /dev/null +++ b/3rdparty/DetoursConfig.cmake.in @@ -0,0 +1,4 @@ +@PACKAGE_INIT@ + +include("${CMAKE_CURRENT_LIST_DIR}/@PROJECT_NAME@Targets.cmake") +check_required_components("@PROJECT_NAME@") diff --git a/CMakeLists.txt b/CMakeLists.txt new file mode 100644 index 00000000..718b9351 --- /dev/null +++ b/CMakeLists.txt @@ -0,0 +1,14 @@ +cmake_minimum_required(VERSION 3.27) +project(MemoryModulePP LANGUAGES CXX) + +set(CMAKE_CXX_STANDARD 23) +set(CMAKE_CXX_STANDARD_REQUIRED ON) + +# add _d to debug targets +SET(CMAKE_DEBUG_POSTFIX _d) + +# build spec done in subdirectories +add_subdirectory(3rdparty) +add_subdirectory(a) +add_subdirectory(MemoryModule) +add_subdirectory(test) diff --git a/MemoryModule/CMakeLists.txt b/MemoryModule/CMakeLists.txt new file mode 100644 index 00000000..b3833f32 --- /dev/null +++ b/MemoryModule/CMakeLists.txt @@ -0,0 +1,157 @@ +cmake_minimum_required(VERSION 3.30) +project(MemoryModulePP LANGUAGES CXX) + +# Define static library target +set(static_libname "MemoryModulePP-static") +add_library(${static_libname} STATIC) + +# Define shared library target +set(shared_libname "MemoryModulePP-shared") +add_library(${shared_libname} SHARED) + +# turn on "reflection" +target_compile_definitions(${shared_libname} PRIVATE _USRDLL) + +# link libraries for DLL +target_link_libraries(${shared_libname} PRIVATE lib_detours) + +# Common sources and headers for both libraries +set(common_sources + BaseAddressIndex.cpp + ImportTable.cpp + Initialize.cpp + InvertedFunctionTable.cpp + LdrEntry.cpp + LoadDllMemoryApi.cpp + Loader.cpp + MemoryModule.cpp + MmpDotNet.cpp + MmpLdrpTls.cpp + MmpTls.cpp + MmpTlsFiber.cpp + Utils.cpp + + # exports + MemoryModulePP.def +) + +set(common_public_headers + BaseAddressIndex.h + ImportTable.h + Initialize.h + InvertedFunctionTable.h + LdrEntry.h + LoadDllMemoryApi.h + Loader.h + MemoryModule.h + MmpGlobalData.h + MmpDotNet.h + MmpTls.h + Utils.h +) + +set(common_private_headers + LoaderPrivate.h + MmpTlsFiber.h + MmpTlsp.h + ReflectiveDLLInjection.h + ReflectiveLoader.h +) + +# Specify sources and headers for static library +target_sources(${static_libname} + PRIVATE + ${common_sources} + PUBLIC + FILE_SET HEADERS + BASE_DIRS ${CMAKE_CURRENT_SOURCE_DIR} + FILES + ${common_public_headers} + PRIVATE + FILE_SET private_headers + TYPE HEADERS + BASE_DIRS ${CMAKE_CURRENT_SOURCE_DIR} + FILES + ${common_private_headers} +) + +# Specify sources and headers for shared library +target_sources(${shared_libname} + PRIVATE + ${common_sources} + PUBLIC + FILE_SET HEADERS + BASE_DIRS ${CMAKE_CURRENT_SOURCE_DIR} + FILES + ${common_public_headers} + PRIVATE + FILE_SET private_headers + TYPE HEADERS + BASE_DIRS ${CMAKE_CURRENT_SOURCE_DIR} + FILES + ${common_private_headers} +) + +# Set include directories for libraries +foreach(libname ${static_libname} ${shared_libname}) + target_include_directories(${libname} + PUBLIC + $ + $ + $ + ) + + # Ensure C++ standard + target_compile_features(${libname} PRIVATE cxx_std_23) + + # key definitions + target_compile_definitions(${libname} PRIVATE + _MEMORY_MODULE + _HAS_AUTO_INITIALIZE + MMPP_USE_TLS=1 + ) +endforeach() + +# Install libraries and public headers +install(TARGETS ${static_libname} ${shared_libname} + EXPORT ${PROJECT_NAME}Targets + LIBRARY DESTINATION lib + ARCHIVE DESTINATION lib + RUNTIME DESTINATION bin + FILE_SET HEADERS DESTINATION include +) + +# Install export file +install(EXPORT ${PROJECT_NAME}Targets + FILE ${PROJECT_NAME}Targets.cmake + NAMESPACE ${PROJECT_NAME}:: + DESTINATION lib/cmake/${PROJECT_NAME} +) + +# Generate and install CMake config file +include(CMakePackageConfigHelpers) +write_basic_package_version_file( + "${CMAKE_CURRENT_BINARY_DIR}/${PROJECT_NAME}ConfigVersion.cmake" + VERSION 1.0.0 + COMPATIBILITY SameMajorVersion +) + +configure_file( + "${CMAKE_CURRENT_SOURCE_DIR}/../${PROJECT_NAME}Config.cmake.in" + "${CMAKE_CURRENT_BINARY_DIR}/${PROJECT_NAME}Config.cmake" + @ONLY +) + +install(FILES + "${CMAKE_CURRENT_BINARY_DIR}/${PROJECT_NAME}Config.cmake" + "${CMAKE_CURRENT_BINARY_DIR}/${PROJECT_NAME}ConfigVersion.cmake" + DESTINATION lib/cmake/${PROJECT_NAME} +) + +# CPack configuration for packaging +set(CPACK_PACKAGE_NAME "${PROJECT_NAME}") +set(CPACK_PACKAGE_VERSION "1.0.0") +set(CPACK_PACKAGE_DESCRIPTION "A custom MemoryModulePP implementation") +set(CPACK_PACKAGE_VENDOR "xAI") +set(CPACK_GENERATOR "ZIP;TGZ") +include(CPack) diff --git a/MemoryModulePPConfig.cmake.in b/MemoryModulePPConfig.cmake.in new file mode 100644 index 00000000..9c15f36a --- /dev/null +++ b/MemoryModulePPConfig.cmake.in @@ -0,0 +1,4 @@ +@PACKAGE_INIT@ + +include("${CMAKE_CURRENT_LIST_DIR}/@PROJECT_NAME@Targets.cmake") +check_required_components("@PROJECT_NAME@") diff --git a/a/CMakeLists.txt b/a/CMakeLists.txt new file mode 100644 index 00000000..c54b9686 --- /dev/null +++ b/a/CMakeLists.txt @@ -0,0 +1,29 @@ +cmake_minimum_required(VERSION 3.30) +project(a-sample LANGUAGES CXX) + +set(libname "a") + +add_library(${libname} SHARED) +target_link_libraries(${libname} PRIVATE lib_detours) +target_sources(${libname} PRIVATE + # sources + dllmain.cpp + exception.cpp + gdiplus.cpp + thread.cpp + + # exports + m.def + + # resources + a.rc + resource.h +) + +# put dll in local install dir +set( INSTALL_DIR "${CMAKE_BINARY_DIR}/install") +install(TARGETS ${libname} + LIBRARY DESTINATION ${INSTALL_DIR} + ARCHIVE DESTINATION ${INSTALL_DIR} + RUNTIME DESTINATION ${INSTALL_DIR} +) diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt new file mode 100644 index 00000000..6ad5671e --- /dev/null +++ b/test/CMakeLists.txt @@ -0,0 +1,43 @@ +cmake_minimum_required(VERSION 3.27) +project(mmtest LANGUAGES CXX) + +# Define executable targets +set(static_exename "mmtest-static") +add_executable(${static_exename}) +target_link_libraries(${static_exename} PRIVATE + MemoryModulePP-static + lib_detours +) + +set(shared_exename "mmtest-shared") +add_executable(${shared_exename}) +target_link_libraries(${shared_exename} PRIVATE + MemoryModulePP-shared +) + +# use install directory under build to assemble tests +set( INSTALL_DIR "${CMAKE_BINARY_DIR}/install") + +foreach(exename ${static_exename} ${shared_exename}) + + # common sources and libs + target_sources(${exename} PRIVATE test.cpp) + + # copy exes into install dir + install(TARGETS ${exename} RUNTIME DESTINATION ${INSTALL_DIR}) + + # add shared lib to PATH + file(TO_NATIVE_PATH "$" MMSHARED_TARGET) + string(REGEX REPLACE "/" "\\\\" MMSHARED_PATH ${MMSHARED_TARGET}) + set_target_properties(${exename} PROPERTIES + VS_DEBUGGER_ENVIRONMENT + "PATH=${MMSHARED_PATH};%PATH%" + ) + + # pass path to target a_d.dll in VS debugger + file(TO_NATIVE_PATH "$" A_DLL) + set_target_properties(${exename} PROPERTIES + "VS_DEBUGGER_COMMAND_ARGUMENTS" + "${A_DLL}" + ) +endforeach() From d1e508d399e9c192292f42464f1ed33d42b1a61e Mon Sep 17 00:00:00 2001 From: Dan Dees Date: Tue, 13 May 2025 16:37:16 +0700 Subject: [PATCH 2/8] test.cpp - add error checks --- test/test.cpp | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/test/test.cpp b/test/test.cpp index e5c964af..38753334 100644 --- a/test/test.cpp +++ b/test/test.cpp @@ -65,7 +65,6 @@ PVOID ReadDllFile2(LPCSTR FileName) { } int test() { - LPVOID buffer = ReadDllFile2("a.dll"); HMODULE hModule = nullptr; FARPROC pfn = nullptr; @@ -77,7 +76,16 @@ int test() { HGLOBAL gRes; char str[10]; - if (!NT_SUCCESS(LdrLoadDllMemoryExW(&hModule, nullptr, 0, buffer, 0, L"kernel64", nullptr))) goto end; + LPVOID buffer = ReadDllFile2("a.dll"); + if ( !buffer ) { + printf("failed to find a.dll.\n"); + goto end; + } + + if (!NT_SUCCESS(LdrLoadDllMemoryExW(&hModule, nullptr, 0, buffer, 0, L"kernel64", nullptr))) { + printf("LdrLoadDllMemoryExW failed.\n"); + goto end; + } //forward export pfn = (decltype(pfn))(GetProcAddress(hModule, "Socket")); //ws2_32.WSASocketW From 6e2fcc198b22fbc17af7957302ee0afd1fefaccc Mon Sep 17 00:00:00 2001 From: Dan Dees Date: Tue, 13 May 2025 21:57:38 +0700 Subject: [PATCH 3/8] test.cpp - command line accept path to a.dll --- test/test.cpp | 38 ++++++++++++++++++++++---------------- 1 file changed, 22 insertions(+), 16 deletions(-) diff --git a/test/test.cpp b/test/test.cpp index 38753334..4181631e 100644 --- a/test/test.cpp +++ b/test/test.cpp @@ -1,6 +1,7 @@ #include "../MemoryModule/stdafx.h" #include "../MemoryModule/LoadDllMemoryApi.h" #include +#include #pragma comment(lib,"ntdll.lib") static void DisplayStatus() { @@ -28,11 +29,11 @@ LdrpHashTable = %p\n\n\ ); } -static PVOID ReadDllFile(LPCSTR FileName) { +static PVOID ReadDllFile(const std::string& FilePath) { LPVOID buffer; size_t size; FILE* f; - fopen_s(&f, FileName, "rb"); + fopen_s(&f, FilePath.c_str(), "rb"); if (!f)return 0; _fseeki64(f, 0, SEEK_END); if (!(size = _ftelli64(f))) { @@ -48,23 +49,24 @@ static PVOID ReadDllFile(LPCSTR FileName) { return buffer; } -PVOID ReadDllFile2(LPCSTR FileName) { +static std::string ResolveWithModulePath(const std::string& dll_path) +{ + std::string rc(dll_path) ; + + // expect default dll in module directory CHAR path[MAX_PATH + 4]; - DWORD len = GetModuleFileNameA(nullptr, path, sizeof(path)); + const auto len = GetModuleFileNameA(nullptr, path, sizeof(path)); if (len) { - while (len && path[len] != '\\') --len; - - if (len) { - strcpy_s(&path[len + 1], sizeof(path) - len - 1, FileName); - return ReadDllFile(path); - } + const std::string mod_path(path); + const auto last_slash = mod_path.find_last_of("/\\") ; + rc = mod_path.substr(0, last_slash + 1) + dll_path; } - return nullptr; + return rc ; } -int test() { +int test(const std::string& dll_path) { HMODULE hModule = nullptr; FARPROC pfn = nullptr; @@ -76,11 +78,12 @@ int test() { HGLOBAL gRes; char str[10]; - LPVOID buffer = ReadDllFile2("a.dll"); + LPVOID buffer = ReadDllFile(dll_path); if ( !buffer ) { - printf("failed to find a.dll.\n"); + printf("failed to find %s.\n", dll_path.c_str()); goto end; } + printf("%s read into memory.\n", dll_path.c_str()); if (!NT_SUCCESS(LdrLoadDllMemoryExW(&hModule, nullptr, 0, buffer, 0, L"kernel64", nullptr))) { printf("LdrLoadDllMemoryExW failed.\n"); @@ -136,11 +139,14 @@ int test() { return 0; } -int main() { +int main(int argc, char* argv[]) { DisplayStatus(); - test(); + std::string dll_path("a.dll"); // default + dll_path = argc > 1 ? argv[1] : ResolveWithModulePath(dll_path); + + test(dll_path); return 0; } From a6f1d0b2ff272f359b33fedc1f1335a521e71213 Mon Sep 17 00:00:00 2001 From: Dan Dees Date: Tue, 13 May 2025 14:39:26 +0700 Subject: [PATCH 4/8] Support DLL build by exporting GetMmpGlobalDataPtr() - problems with exported global at runtime - wrapping data access in a function allows additional controls --- MemoryModule/Initialize.cpp | 8 +++++++- MemoryModule/MemoryModulePP.def | 1 + MemoryModule/MmpGlobalData.h | 1 + test/test.cpp | 33 +++++++++++++++++++++------------ 4 files changed, 30 insertions(+), 13 deletions(-) diff --git a/MemoryModule/Initialize.cpp b/MemoryModule/Initialize.cpp index aa023c8e..277f77f5 100644 --- a/MemoryModule/Initialize.cpp +++ b/MemoryModule/Initialize.cpp @@ -5,6 +5,12 @@ PMMP_GLOBAL_DATA MmpGlobalDataPtr; +// DLL compliant access +PMMP_GLOBAL_DATA NTAPI GetMmpGlobalDataPtr() +{ + return MmpGlobalDataPtr; +} + #if MEMORY_MODULE_IS_PREVIEW(MEMORY_MODULE_MINOR_VERSION) #pragma message("WARNING: You are using a preview version of MemoryModulePP.") #endif @@ -621,6 +627,6 @@ BOOL APIENTRY DllMain(HMODULE hModule, DWORD ul_reason_for_call, LPVOID lpReser } #else #ifdef _HAS_AUTO_INITIALIZE -const NTSTATUS Initializer = MmInitialize(); +static const NTSTATUS Initializer = MmInitialize(); #endif #endif diff --git a/MemoryModule/MemoryModulePP.def b/MemoryModule/MemoryModulePP.def index fcbae96d..7120e75c 100644 --- a/MemoryModule/MemoryModulePP.def +++ b/MemoryModule/MemoryModulePP.def @@ -15,3 +15,4 @@ LdrUnloadDllMemoryAndExitThread LdrQuerySystemMemoryModuleFeatures MmpGlobalDataPtr +GetMmpGlobalDataPtr diff --git a/MemoryModule/MmpGlobalData.h b/MemoryModule/MmpGlobalData.h index 2a986b0e..2786f172 100644 --- a/MemoryModule/MmpGlobalData.h +++ b/MemoryModule/MmpGlobalData.h @@ -153,3 +153,4 @@ typedef struct _MMP_GLOBAL_DATA { ) extern PMMP_GLOBAL_DATA MmpGlobalDataPtr; +PMMP_GLOBAL_DATA NTAPI GetMmpGlobalDataPtr() ; diff --git a/test/test.cpp b/test/test.cpp index 4181631e..56d7d921 100644 --- a/test/test.cpp +++ b/test/test.cpp @@ -4,7 +4,12 @@ #include #pragma comment(lib,"ntdll.lib") -static void DisplayStatus() { +static int DisplayStatus() { + const auto gdp = GetMmpGlobalDataPtr(); + if ( !gdp ) { + printf("failed GetMmpGlobalDataPtr().\n"); + return -1 ; + } printf( "\ MemoryModulePP [Version %d.%d%s]\n\n\t\ @@ -16,17 +21,18 @@ RtlRbRemoveNode = %p\n\n\t\ LdrpInvertedFunctionTable = %p\n\n\t\ LdrpHashTable = %p\n\n\ ", - MmpGlobalDataPtr->MajorVersion, - MEMORY_MODULE_GET_MINOR_VERSION(MmpGlobalDataPtr->MinorVersion), - MEMORY_MODULE_IS_PREVIEW(MmpGlobalDataPtr->MinorVersion) ? " Preview" : "", - MmpGlobalDataPtr->MmpFeatures, - MmpGlobalDataPtr->MmpBaseAddressIndex->LdrpModuleBaseAddressIndex, - MmpGlobalDataPtr->MmpBaseAddressIndex->NtdllLdrEntry, - MmpGlobalDataPtr->MmpBaseAddressIndex->_RtlRbInsertNodeEx, - MmpGlobalDataPtr->MmpBaseAddressIndex->_RtlRbRemoveNode, - MmpGlobalDataPtr->MmpInvertedFunctionTable->LdrpInvertedFunctionTable, - MmpGlobalDataPtr->MmpLdrEntry->LdrpHashTable + gdp->MajorVersion, + MEMORY_MODULE_GET_MINOR_VERSION(gdp->MinorVersion), + MEMORY_MODULE_IS_PREVIEW(gdp->MinorVersion) ? " Preview" : "", + gdp->MmpFeatures, + (PVOID)gdp->MmpBaseAddressIndex->LdrpModuleBaseAddressIndex, + (PVOID)gdp->MmpBaseAddressIndex->NtdllLdrEntry, + gdp->MmpBaseAddressIndex->_RtlRbInsertNodeEx, + gdp->MmpBaseAddressIndex->_RtlRbRemoveNode, + gdp->MmpInvertedFunctionTable->LdrpInvertedFunctionTable, + (PVOID)gdp->MmpLdrEntry->LdrpHashTable ); + return 0 ; } static PVOID ReadDllFile(const std::string& FilePath) { @@ -141,7 +147,10 @@ int test(const std::string& dll_path) { int main(int argc, char* argv[]) { - DisplayStatus(); + // check MemoryModulePP initialization + if ( DisplayStatus() ) { + return -1 ; + } std::string dll_path("a.dll"); // default dll_path = argc > 1 ? argv[1] : ResolveWithModulePath(dll_path); From 5d50d3e58bf2f1060772ec6bc80e8a13713ee48d Mon Sep 17 00:00:00 2001 From: Dan Dees Date: Mon, 12 May 2025 11:44:43 +0700 Subject: [PATCH 5/8] Loader.cpp - uneeded "else" after "continue" --- MemoryModule/Loader.cpp | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) diff --git a/MemoryModule/Loader.cpp b/MemoryModule/Loader.cpp index 846ad818..b5cf717d 100644 --- a/MemoryModule/Loader.cpp +++ b/MemoryModule/Loader.cpp @@ -96,12 +96,8 @@ NTSTATUS NTAPI LdrLoadDllMemoryExW( auto dist = (CurEntry->BaseDllName.Length / sizeof(wchar_t)) - length; bool equal = false; - if (dist == 0 || dist == 4) { - equal = !_wcsnicmp(DllName, CurEntry->BaseDllName.Buffer, length); - } - else { - continue; - } + if (!(dist == 0 || dist == 4)) continue; + equal = !_wcsnicmp(DllName, CurEntry->BaseDllName.Buffer, length); /* Check if name matches */ if (equal) { From d2e8384a3c94169fa5ef51ebbaac55fbc06017b5 Mon Sep 17 00:00:00 2001 From: Dan Dees Date: Wed, 14 May 2025 10:41:17 +0700 Subject: [PATCH 6/8] Utils.cpp - uneeded "else" after "return" --- MemoryModule/Utils.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/MemoryModule/Utils.cpp b/MemoryModule/Utils.cpp index 3e4e4dac..cae8bdff 100644 --- a/MemoryModule/Utils.cpp +++ b/MemoryModule/Utils.cpp @@ -393,9 +393,9 @@ BOOL NTAPI RtlIsWindowsVersionOrGreater( ) { if (MmpGlobalDataPtr->NtVersions.MajorVersion == MajorVersion) { if (MmpGlobalDataPtr->NtVersions.MinorVersion == MinorVersion) return MmpGlobalDataPtr->NtVersions.BuildNumber >= BuildNumber; - else return (MmpGlobalDataPtr->NtVersions.MinorVersion > MinorVersion); + return (MmpGlobalDataPtr->NtVersions.MinorVersion > MinorVersion); } - else return MmpGlobalDataPtr->NtVersions.MajorVersion > MajorVersion; + return MmpGlobalDataPtr->NtVersions.MajorVersion > MajorVersion; } BOOL NTAPI RtlIsWindowsVersionInScope( From 182acf9d3aa6546cdcc73b0969c94ba619462b28 Mon Sep 17 00:00:00 2001 From: Dan Dees Date: Sun, 25 May 2025 23:22:43 +0700 Subject: [PATCH 7/8] MmpLdrpTls.cpp - prefer ternary if just return value --- MemoryModule/MmpLdrpTls.cpp | 9 +++------ 1 file changed, 3 insertions(+), 6 deletions(-) diff --git a/MemoryModule/MmpLdrpTls.cpp b/MemoryModule/MmpLdrpTls.cpp index 286ddd51..8d64e374 100644 --- a/MemoryModule/MmpLdrpTls.cpp +++ b/MemoryModule/MmpLdrpTls.cpp @@ -141,12 +141,9 @@ static NTSTATUS NTAPI RtlFindLdrpHandleTlsData10() { } static NTSTATUS NTAPI RtlFindLdrpHandleTlsData() { - if (MmpGlobalDataPtr->NtVersions.MajorVersion >= 10) { - return RtlFindLdrpHandleTlsData10(); - } - else { - return RtlFindLdrpHandleTlsDataOld(); - } + return MmpGlobalDataPtr->NtVersions.MajorVersion >= 10 + ? RtlFindLdrpHandleTlsData10() + : RtlFindLdrpHandleTlsDataOld(); } static NTSTATUS NTAPI RtlFindLdrpReleaseTlsEntry() { From 6250b393a3ca0db80c911c4d77134782d671470d Mon Sep 17 00:00:00 2001 From: Dan Dees Date: Fri, 16 May 2025 19:46:30 +0700 Subject: [PATCH 8/8] define exported extern "C" as declared --- MemoryModule/Initialize.cpp | 2 +- MemoryModule/LoadDllMemoryApi.cpp | 8 ++++---- MemoryModule/Loader.cpp | 7 ++++--- MemoryModule/MmpGlobalData.h | 2 +- 4 files changed, 10 insertions(+), 9 deletions(-) diff --git a/MemoryModule/Initialize.cpp b/MemoryModule/Initialize.cpp index 277f77f5..1142c340 100644 --- a/MemoryModule/Initialize.cpp +++ b/MemoryModule/Initialize.cpp @@ -6,7 +6,7 @@ PMMP_GLOBAL_DATA MmpGlobalDataPtr; // DLL compliant access -PMMP_GLOBAL_DATA NTAPI GetMmpGlobalDataPtr() +extern "C" PMMP_GLOBAL_DATA NTAPI GetMmpGlobalDataPtr() { return MmpGlobalDataPtr; } diff --git a/MemoryModule/LoadDllMemoryApi.cpp b/MemoryModule/LoadDllMemoryApi.cpp index 01aaeb65..8bf30901 100644 --- a/MemoryModule/LoadDllMemoryApi.cpp +++ b/MemoryModule/LoadDllMemoryApi.cpp @@ -1,7 +1,7 @@ #include "stdafx.h" #include -HMEMORYMODULE WINAPI LoadLibraryMemoryExW( +extern "C" HMEMORYMODULE WINAPI LoadLibraryMemoryExW( _In_ PVOID BufferAddress, _In_ size_t Reserved, _In_opt_ LPCWSTR DllBaseName, @@ -15,7 +15,7 @@ HMEMORYMODULE WINAPI LoadLibraryMemoryExW( return hMemoryModule; } -HMEMORYMODULE WINAPI LoadLibraryMemoryExA( +extern "C" HMEMORYMODULE WINAPI LoadLibraryMemoryExA( _In_ PVOID BufferAddress, _In_ size_t Reserved, _In_opt_ LPCSTR DllBaseName, @@ -59,11 +59,11 @@ HMEMORYMODULE WINAPI LoadLibraryMemoryExA( return result; } -HMEMORYMODULE WINAPI LoadLibraryMemory(_In_ PVOID BufferAddress) { +extern "C" HMEMORYMODULE WINAPI LoadLibraryMemory(_In_ PVOID BufferAddress) { return LoadLibraryMemoryExW(BufferAddress, 0, nullptr, nullptr, 0); } -BOOL WINAPI FreeLibraryMemory(_In_ HMEMORYMODULE hMemoryModule) { +extern "C" BOOL WINAPI FreeLibraryMemory(_In_ HMEMORYMODULE hMemoryModule) { NTSTATUS status = LdrUnloadDllMemory(hMemoryModule); if (!NT_SUCCESS(status)) { SetLastError(RtlNtStatusToDosError(status)); diff --git a/MemoryModule/Loader.cpp b/MemoryModule/Loader.cpp index b5cf717d..80c74e8d 100644 --- a/MemoryModule/Loader.cpp +++ b/MemoryModule/Loader.cpp @@ -44,7 +44,7 @@ NTSTATUS NTAPI LdrMapDllMemory( return STATUS_SUCCESS; } -NTSTATUS NTAPI LdrLoadDllMemoryExW( +extern "C" NTSTATUS NTAPI LdrLoadDllMemoryExW( _Out_ HMEMORYMODULE* BaseAddress, _Out_opt_ PVOID* LdrEntry, _In_ DWORD dwFlags, @@ -217,7 +217,7 @@ NTSTATUS NTAPI LdrLoadDllMemoryExW( return status; } -NTSTATUS NTAPI LdrUnloadDllMemory(_In_ HMEMORYMODULE BaseAddress) { +extern "C" NTSTATUS NTAPI LdrUnloadDllMemory(_In_ HMEMORYMODULE BaseAddress) { PLDR_DATA_TABLE_ENTRY CurEntry; ULONG count = 0; NTSTATUS status = STATUS_SUCCESS; @@ -288,13 +288,14 @@ NTSTATUS NTAPI LdrUnloadDllMemory(_In_ HMEMORYMODULE BaseAddress) { return status; } +extern "C" DECLSPEC_NORETURN VOID NTAPI LdrUnloadDllMemoryAndExitThread(_In_ HMEMORYMODULE BaseAddress, _In_ DWORD dwExitCode) { LdrUnloadDllMemory(BaseAddress); RtlExitUserThread(dwExitCode); } -NTSTATUS NTAPI LdrQuerySystemMemoryModuleFeatures(_Out_ PDWORD pFeatures) { +extern "C" NTSTATUS NTAPI LdrQuerySystemMemoryModuleFeatures(_Out_ PDWORD pFeatures) { NTSTATUS status = STATUS_SUCCESS; __try { *pFeatures = MmpGlobalDataPtr->MmpFeatures; diff --git a/MemoryModule/MmpGlobalData.h b/MemoryModule/MmpGlobalData.h index 2786f172..989c59f3 100644 --- a/MemoryModule/MmpGlobalData.h +++ b/MemoryModule/MmpGlobalData.h @@ -153,4 +153,4 @@ typedef struct _MMP_GLOBAL_DATA { ) extern PMMP_GLOBAL_DATA MmpGlobalDataPtr; -PMMP_GLOBAL_DATA NTAPI GetMmpGlobalDataPtr() ; +extern "C" PMMP_GLOBAL_DATA NTAPI GetMmpGlobalDataPtr() ;