From 99d5d68074474d782b3af787abc78b96d7b77cba Mon Sep 17 00:00:00 2001 From: Pinwhell <60289470+pinwhell@users.noreply.github.com> Date: Sat, 28 Sep 2024 17:21:18 -0400 Subject: [PATCH 1/4] Basic CMake Support --- .gitignore | 4 +++- CMakeLists.txt | 24 ++++++++++++++++++++++++ TheCruZMMapConfig.cmake.in | 3 +++ 3 files changed, 30 insertions(+), 1 deletion(-) create mode 100644 CMakeLists.txt create mode 100644 TheCruZMMapConfig.cmake.in diff --git a/.gitignore b/.gitignore index 3a8542d..7b186d0 100644 --- a/.gitignore +++ b/.gitignore @@ -359,4 +359,6 @@ MigrationBackup/ .ionide/ # Fody - auto-generated XML schema -FodyWeavers.xsd \ No newline at end of file +FodyWeavers.xsd +out/* +CMakeSettings.json diff --git a/CMakeLists.txt b/CMakeLists.txt new file mode 100644 index 0000000..cddeb39 --- /dev/null +++ b/CMakeLists.txt @@ -0,0 +1,24 @@ +cmake_minimum_required(VERSION 3.15) + +project(TheCruZMMap) + +set(SRC_ROOT "Manual Map Injector") + +include(CBuildKit) + +add_library_ns(thecruz manualmap STATIC ${SRC_ROOT}/injector.cpp) +target_include_dir_iface(thecruz-manualmap PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}/${SRC_ROOT} include) +install_target_and_headers(thecruz manualmap) + +install(FILES + ${SRC_ROOT}/injector.h + DESTINATION include/TheCruZ) + +configure_file(TheCruZMMapConfig.cmake.in + ${CMAKE_CURRENT_BINARY_DIR}/TheCruZMMapConfig.cmake + @ONLY) + +# Realize Installation of Configuration cmake file +install(FILES + ${CMAKE_CURRENT_BINARY_DIR}/TheCruZMMapConfig.cmake + DESTINATION lib/cmake/TheCruZ) \ No newline at end of file diff --git a/TheCruZMMapConfig.cmake.in b/TheCruZMMapConfig.cmake.in new file mode 100644 index 0000000..862f3cb --- /dev/null +++ b/TheCruZMMapConfig.cmake.in @@ -0,0 +1,3 @@ +@PACKAGE_INIT@ # Init + +include(${CMAKE_CURRENT_LIST_DIR}/thecruz-manualmap-targets.cmake) \ No newline at end of file From b340c9e695c689f8045d796e1cada10522446343 Mon Sep 17 00:00:00 2001 From: Pinwhell <60289470+pinwhell@users.noreply.github.com> Date: Sun, 29 Sep 2024 10:55:45 -0400 Subject: [PATCH 2/4] TLS Handling Support Added --- CMakeLists.txt | 7 +++ Manual Map Injector/injector.cpp | 76 +++++++++++++++++++++++++------- Manual Map Injector/injector.h | 32 +++++++++++++- TheCruZMMapConfig.cmake.in | 4 ++ 4 files changed, 103 insertions(+), 16 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index cddeb39..cf673f3 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -2,14 +2,21 @@ cmake_minimum_required(VERSION 3.15) project(TheCruZMMap) +find_package(MSPDBX REQUIRED) + set(SRC_ROOT "Manual Map Injector") include(CBuildKit) add_library_ns(thecruz manualmap STATIC ${SRC_ROOT}/injector.cpp) target_include_dir_iface(thecruz-manualmap PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}/${SRC_ROOT} include) +target_link_libraries(thecruz-manualmap mspdbx::mspdbx) install_target_and_headers(thecruz manualmap) +add_executable(injector ${SRC_ROOT}/main.cpp) +target_link_libraries(injector thecruz::manualmap) +target_compile_definitions(injector PRIVATE -DUNICODE -D_UNICODE) + install(FILES ${SRC_ROOT}/injector.h DESTINATION include/TheCruZ) diff --git a/Manual Map Injector/injector.cpp b/Manual Map Injector/injector.cpp index 09a33e7..d9aedbe 100644 --- a/Manual Map Injector/injector.cpp +++ b/Manual Map Injector/injector.cpp @@ -12,7 +12,30 @@ #define CURRENT_ARCH IMAGE_FILE_MACHINE_I386 #endif -bool ManualMapDll(HANDLE hProc, BYTE* pSrcData, SIZE_T FileSize, bool ClearHeader, bool ClearNonNeededSections, bool AdjustProtections, bool SEHExceptionSupport, DWORD fdwReason, LPVOID lpReserved) { +std::optional GetModuleBaseAddress(DWORD processID, const char* moduleName) { + HANDLE hSnapshot = CreateToolhelp32Snapshot(TH32CS_SNAPMODULE | TH32CS_SNAPMODULE32, processID); + if (hSnapshot == INVALID_HANDLE_VALUE) { + return std::nullopt; + } + + MODULEENTRY32 moduleEntry; + moduleEntry.dwSize = sizeof(MODULEENTRY32); + + if (Module32First(hSnapshot, &moduleEntry)) { + do { + if (strcmp(moduleEntry.szModule, moduleName) == 0) { + CloseHandle(hSnapshot); + return moduleEntry.hModule; // Return the base address + } + } while (Module32Next(hSnapshot, &moduleEntry)); + } + + CloseHandle(hSnapshot); + return std::nullopt; // Return nullopt if the module was not found +} + +std::optional ManualMapDll(HANDLE hProc, BYTE* pSrcData, SIZE_T FileSize, std::optional symbolSolver, bool ClearHeader, bool ClearNonNeededSections, bool AdjustProtections, bool SEHExceptionSupport, DWORD fdwReason, LPVOID lpReserved) { + auto procNtdll = GetModuleBaseAddress(GetProcessId(hProc), "ntdll.dll"); IMAGE_NT_HEADERS* pOldNtHeader = nullptr; IMAGE_OPTIONAL_HEADER* pOldOptHeader = nullptr; IMAGE_FILE_HEADER* pOldFileHeader = nullptr; @@ -20,7 +43,7 @@ bool ManualMapDll(HANDLE hProc, BYTE* pSrcData, SIZE_T FileSize, bool ClearHeade if (reinterpret_cast(pSrcData)->e_magic != 0x5A4D) { //"MZ" ILog("Invalid file\n"); - return false; + return std::nullopt; } pOldNtHeader = reinterpret_cast(pSrcData + reinterpret_cast(pSrcData)->e_lfanew); @@ -29,7 +52,7 @@ bool ManualMapDll(HANDLE hProc, BYTE* pSrcData, SIZE_T FileSize, bool ClearHeade if (pOldFileHeader->Machine != CURRENT_ARCH) { ILog("Invalid platform\n"); - return false; + return std::nullopt; } ILog("File ok\n"); @@ -37,13 +60,25 @@ bool ManualMapDll(HANDLE hProc, BYTE* pSrcData, SIZE_T FileSize, bool ClearHeade pTargetBase = reinterpret_cast(VirtualAllocEx(hProc, nullptr, pOldOptHeader->SizeOfImage, MEM_COMMIT | MEM_RESERVE, PAGE_READWRITE)); if (!pTargetBase) { ILog("Target process memory allocation failed (ex) 0x%X\n", GetLastError()); - return false; + return std::nullopt; } DWORD oldp = 0; VirtualProtectEx(hProc, pTargetBase, pOldOptHeader->SizeOfImage, PAGE_EXECUTE_READWRITE, &oldp); MANUAL_MAPPING_DATA data{ 0 }; + data.pDummyLdr = (LDR_DATA_TABLE_ENTRY*)malloc(sizeof(LDR_DATA_TABLE_ENTRY)); memset(data.pDummyLdr, 0, sizeof(LDR_DATA_TABLE_ENTRY)); + data.pLdrpHandleTlsData = [&]() -> f_LdrpHandleTlsData { + if (!procNtdll || !symbolSolver) + return nullptr; + + auto ldrpHandleTlsDataRVA = (*symbolSolver).Resolve("LdrpHandleTlsData"); + + if (!ldrpHandleTlsDataRVA) + return nullptr; + + return (f_LdrpHandleTlsData)((uint64_t)(*procNtdll) + (*ldrpHandleTlsDataRVA)); + }(); data.pLoadLibraryA = LoadLibraryA; data.pGetProcAddress = GetProcAddress; #ifdef _WIN64 @@ -61,7 +96,7 @@ bool ManualMapDll(HANDLE hProc, BYTE* pSrcData, SIZE_T FileSize, bool ClearHeade if (!WriteProcessMemory(hProc, pTargetBase, pSrcData, 0x1000, nullptr)) { //only first 0x1000 bytes for the header ILog("Can't write file header 0x%X\n", GetLastError()); VirtualFreeEx(hProc, pTargetBase, 0, MEM_RELEASE); - return false; + return std::nullopt; } IMAGE_SECTION_HEADER* pSectionHeader = IMAGE_FIRST_SECTION(pOldNtHeader); @@ -70,7 +105,7 @@ bool ManualMapDll(HANDLE hProc, BYTE* pSrcData, SIZE_T FileSize, bool ClearHeade if (!WriteProcessMemory(hProc, pTargetBase + pSectionHeader->VirtualAddress, pSrcData + pSectionHeader->PointerToRawData, pSectionHeader->SizeOfRawData, nullptr)) { ILog("Can't map sections: 0x%x\n", GetLastError()); VirtualFreeEx(hProc, pTargetBase, 0, MEM_RELEASE); - return false; + return std::nullopt; } } } @@ -80,14 +115,14 @@ bool ManualMapDll(HANDLE hProc, BYTE* pSrcData, SIZE_T FileSize, bool ClearHeade if (!MappingDataAlloc) { ILog("Target process mapping allocation failed (ex) 0x%X\n", GetLastError()); VirtualFreeEx(hProc, pTargetBase, 0, MEM_RELEASE); - return false; + return std::nullopt; } if (!WriteProcessMemory(hProc, MappingDataAlloc, &data, sizeof(MANUAL_MAPPING_DATA), nullptr)) { ILog("Can't write mapping 0x%X\n", GetLastError()); VirtualFreeEx(hProc, pTargetBase, 0, MEM_RELEASE); VirtualFreeEx(hProc, MappingDataAlloc, 0, MEM_RELEASE); - return false; + return std::nullopt; } //Shell code @@ -96,7 +131,7 @@ bool ManualMapDll(HANDLE hProc, BYTE* pSrcData, SIZE_T FileSize, bool ClearHeade ILog("Memory shellcode allocation failed (ex) 0x%X\n", GetLastError()); VirtualFreeEx(hProc, pTargetBase, 0, MEM_RELEASE); VirtualFreeEx(hProc, MappingDataAlloc, 0, MEM_RELEASE); - return false; + return std::nullopt; } if (!WriteProcessMemory(hProc, pShellcode, Shellcode, 0x1000, nullptr)) { @@ -104,7 +139,7 @@ bool ManualMapDll(HANDLE hProc, BYTE* pSrcData, SIZE_T FileSize, bool ClearHeade VirtualFreeEx(hProc, pTargetBase, 0, MEM_RELEASE); VirtualFreeEx(hProc, MappingDataAlloc, 0, MEM_RELEASE); VirtualFreeEx(hProc, pShellcode, 0, MEM_RELEASE); - return false; + return std::nullopt; } ILog("Mapped DLL at %p\n", pTargetBase); @@ -125,7 +160,7 @@ bool ManualMapDll(HANDLE hProc, BYTE* pSrcData, SIZE_T FileSize, bool ClearHeade VirtualFreeEx(hProc, pTargetBase, 0, MEM_RELEASE); VirtualFreeEx(hProc, MappingDataAlloc, 0, MEM_RELEASE); VirtualFreeEx(hProc, pShellcode, 0, MEM_RELEASE); - return false; + return std::nullopt; } CloseHandle(hThread); @@ -137,7 +172,7 @@ bool ManualMapDll(HANDLE hProc, BYTE* pSrcData, SIZE_T FileSize, bool ClearHeade GetExitCodeProcess(hProc, &exitcode); if (exitcode != STILL_ACTIVE) { ILog("Process crashed, exit code: %d\n", exitcode); - return false; + return std::nullopt; } MANUAL_MAPPING_DATA data_checked{ 0 }; @@ -149,7 +184,7 @@ bool ManualMapDll(HANDLE hProc, BYTE* pSrcData, SIZE_T FileSize, bool ClearHeade VirtualFreeEx(hProc, pTargetBase, 0, MEM_RELEASE); VirtualFreeEx(hProc, MappingDataAlloc, 0, MEM_RELEASE); VirtualFreeEx(hProc, pShellcode, 0, MEM_RELEASE); - return false; + return std::nullopt; } else if (hCheck == (HINSTANCE)0x505050) { ILog("WARNING: Exception support failed!\n"); @@ -161,7 +196,7 @@ bool ManualMapDll(HANDLE hProc, BYTE* pSrcData, SIZE_T FileSize, bool ClearHeade BYTE* emptyBuffer = (BYTE*)malloc(1024 * 1024 * 20); if (emptyBuffer == nullptr) { ILog("Unable to allocate memory\n"); - return false; + return std::nullopt; } memset(emptyBuffer, 0, 1024 * 1024 * 20); @@ -225,7 +260,7 @@ bool ManualMapDll(HANDLE hProc, BYTE* pSrcData, SIZE_T FileSize, bool ClearHeade ILog("WARNING: can't release mapping data memory\n"); } - return true; + return pTargetBase; } #define RELOC_FLAG32(RelInfo) ((RelInfo >> 0x0C) == IMAGE_REL_BASED_HIGHLOW) @@ -300,6 +335,17 @@ void __stdcall Shellcode(MANUAL_MAPPING_DATA* pData) { } } + if (pData->pLdrpHandleTlsData) + { + pData->pDummyLdr->DllBase = pBase; + pData->pLdrpHandleTlsData(pData->pDummyLdr); + } + + /*Todo + * Unlink from TLS list pData->pDummyLdr + * Finally free/release pData->pDummyLdr + */ + if (pOpt->DataDirectory[IMAGE_DIRECTORY_ENTRY_TLS].Size) { auto* pTLS = reinterpret_cast(pBase + pOpt->DataDirectory[IMAGE_DIRECTORY_ENTRY_TLS].VirtualAddress); auto* pCallback = reinterpret_cast(pTLS->AddressOfCallBacks); diff --git a/Manual Map Injector/injector.h b/Manual Map Injector/injector.h index eb57755..c649889 100644 --- a/Manual Map Injector/injector.h +++ b/Manual Map Injector/injector.h @@ -6,6 +6,8 @@ #include #include #include +#include +#include using f_LoadLibraryA = HINSTANCE(WINAPI*)(const char* lpLibFilename); using f_GetProcAddress = FARPROC(WINAPI*)(HMODULE hModule, LPCSTR lpProcName); @@ -15,10 +17,38 @@ using f_DLL_ENTRY_POINT = BOOL(WINAPI*)(void* hDll, DWORD dwReason, void* pReser using f_RtlAddFunctionTable = BOOL(WINAPIV*)(PRUNTIME_FUNCTION FunctionTable, DWORD EntryCount, DWORD64 BaseAddress); #endif +struct UNICODE_STR +{ + USHORT Length; + USHORT MaximumLength; + PWSTR pBuffer; +}; + +struct LDR_DATA_TABLE_ENTRY +{ + LIST_ENTRY InLoadOrderLinks; + LIST_ENTRY InMemoryOrderModuleList; + LIST_ENTRY InInitializationOrderModuleList; + PVOID DllBase; + PVOID EntryPoint; + ULONG SizeOfImage; + UNICODE_STR FullDllName; + UNICODE_STR BaseDllName; + ULONG Flags; + SHORT LoadCount; + SHORT TlsIndex; + LIST_ENTRY HashTableEntry; + ULONG TimeDateStamp; +}; + +using f_LdrpHandleTlsData = DWORD(*)(LDR_DATA_TABLE_ENTRY*); + struct MANUAL_MAPPING_DATA { f_LoadLibraryA pLoadLibraryA; f_GetProcAddress pGetProcAddress; + f_LdrpHandleTlsData pLdrpHandleTlsData; + LDR_DATA_TABLE_ENTRY* pDummyLdr; #ifdef _WIN64 f_RtlAddFunctionTable pRtlAddFunctionTable; #endif @@ -31,5 +61,5 @@ struct MANUAL_MAPPING_DATA //Note: Exception support only x64 with build params /EHa or /EHc -bool ManualMapDll(HANDLE hProc, BYTE* pSrcData, SIZE_T FileSize, bool ClearHeader = true, bool ClearNonNeededSections = true, bool AdjustProtections = true, bool SEHExceptionSupport = true, DWORD fdwReason = DLL_PROCESS_ATTACH, LPVOID lpReserved = 0); +std::optional ManualMapDll(HANDLE hProc, BYTE* pSrcData, SIZE_T FileSize, std::optional ntSymbolSolver = std::nullopt, bool ClearHeader = true, bool ClearNonNeededSections = true, bool AdjustProtections = true, bool SEHExceptionSupport = true, DWORD fdwReason = DLL_PROCESS_ATTACH, LPVOID lpReserved = 0); void __stdcall Shellcode(MANUAL_MAPPING_DATA* pData); \ No newline at end of file diff --git a/TheCruZMMapConfig.cmake.in b/TheCruZMMapConfig.cmake.in index 862f3cb..08ab331 100644 --- a/TheCruZMMapConfig.cmake.in +++ b/TheCruZMMapConfig.cmake.in @@ -1,3 +1,7 @@ @PACKAGE_INIT@ # Init +include(CMakeFindDependencyMacro) + +find_dependency(MSPDBX) + include(${CMAKE_CURRENT_LIST_DIR}/thecruz-manualmap-targets.cmake) \ No newline at end of file From 55196ddccb1807819966ee25147e17c2b87dfc43 Mon Sep 17 00:00:00 2001 From: Pinwhell <60289470+pinwhell@users.noreply.github.com> Date: Sun, 29 Sep 2024 12:47:07 -0400 Subject: [PATCH 3/4] Allocation Managment Impl #1 --- Manual Map Injector/injector.cpp | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/Manual Map Injector/injector.cpp b/Manual Map Injector/injector.cpp index d9aedbe..d0c0e23 100644 --- a/Manual Map Injector/injector.cpp +++ b/Manual Map Injector/injector.cpp @@ -34,7 +34,7 @@ std::optional GetModuleBaseAddress(DWORD processID, const char* moduleN return std::nullopt; // Return nullopt if the module was not found } -std::optional ManualMapDll(HANDLE hProc, BYTE* pSrcData, SIZE_T FileSize, std::optional symbolSolver, bool ClearHeader, bool ClearNonNeededSections, bool AdjustProtections, bool SEHExceptionSupport, DWORD fdwReason, LPVOID lpReserved) { +std::optional ManualMapDll(HANDLE hProc, BYTE* pSrcData, SIZE_T FileSize, std::optional ntSymbolSolver, bool ClearHeader, bool ClearNonNeededSections, bool AdjustProtections, bool SEHExceptionSupport, DWORD fdwReason, LPVOID lpReserved) { auto procNtdll = GetModuleBaseAddress(GetProcessId(hProc), "ntdll.dll"); IMAGE_NT_HEADERS* pOldNtHeader = nullptr; IMAGE_OPTIONAL_HEADER* pOldOptHeader = nullptr; @@ -69,10 +69,10 @@ std::optional ManualMapDll(HANDLE hProc, BYTE* pSrcData, SIZE_T FileSize, MANUAL_MAPPING_DATA data{ 0 }; data.pDummyLdr = (LDR_DATA_TABLE_ENTRY*)malloc(sizeof(LDR_DATA_TABLE_ENTRY)); memset(data.pDummyLdr, 0, sizeof(LDR_DATA_TABLE_ENTRY)); data.pLdrpHandleTlsData = [&]() -> f_LdrpHandleTlsData { - if (!procNtdll || !symbolSolver) + if (!procNtdll || !ntSymbolSolver) return nullptr; - auto ldrpHandleTlsDataRVA = (*symbolSolver).Resolve("LdrpHandleTlsData"); + auto ldrpHandleTlsDataRVA = (*ntSymbolSolver).Resolve("LdrpHandleTlsData"); if (!ldrpHandleTlsDataRVA) return nullptr; @@ -193,7 +193,8 @@ std::optional ManualMapDll(HANDLE hProc, BYTE* pSrcData, SIZE_T FileSize, Sleep(10); } - BYTE* emptyBuffer = (BYTE*)malloc(1024 * 1024 * 20); + std::unique_ptr emptyBuffStrg = std::make_unique(1024 * 1024 * 20); + BYTE* emptyBuffer = emptyBuffStrg.get(); if (emptyBuffer == nullptr) { ILog("Unable to allocate memory\n"); return std::nullopt; From 244a29b4dfd0a58263e2614faf68ab9314d15f79 Mon Sep 17 00:00:00 2001 From: Pinwhell <60289470+pinwhell@users.noreply.github.com> Date: Sun, 29 Sep 2024 19:20:53 -0400 Subject: [PATCH 4/4] Dep Downgrade & Revisions --- CMakeLists.txt | 4 +-- Manual Map Injector/injector.cpp | 51 ++++++++++++++++++++++---------- Manual Map Injector/injector.h | 2 +- 3 files changed, 37 insertions(+), 20 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index cf673f3..b44c38d 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -2,16 +2,14 @@ cmake_minimum_required(VERSION 3.15) project(TheCruZMMap) -find_package(MSPDBX REQUIRED) - set(SRC_ROOT "Manual Map Injector") include(CBuildKit) add_library_ns(thecruz manualmap STATIC ${SRC_ROOT}/injector.cpp) target_include_dir_iface(thecruz-manualmap PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}/${SRC_ROOT} include) -target_link_libraries(thecruz-manualmap mspdbx::mspdbx) install_target_and_headers(thecruz manualmap) +target_compile_features(thecruz-manualmap PUBLIC cxx_std_17) add_executable(injector ${SRC_ROOT}/main.cpp) target_link_libraries(injector thecruz::manualmap) diff --git a/Manual Map Injector/injector.cpp b/Manual Map Injector/injector.cpp index d0c0e23..790b9fd 100644 --- a/Manual Map Injector/injector.cpp +++ b/Manual Map Injector/injector.cpp @@ -12,6 +12,11 @@ #define CURRENT_ARCH IMAGE_FILE_MACHINE_I386 #endif +std::optional GetLdrpHandleTlsDataRVA() +{ + return 0x54590; +} + std::optional GetModuleBaseAddress(DWORD processID, const char* moduleName) { HANDLE hSnapshot = CreateToolhelp32Snapshot(TH32CS_SNAPMODULE | TH32CS_SNAPMODULE32, processID); if (hSnapshot == INVALID_HANDLE_VALUE) { @@ -34,7 +39,7 @@ std::optional GetModuleBaseAddress(DWORD processID, const char* moduleN return std::nullopt; // Return nullopt if the module was not found } -std::optional ManualMapDll(HANDLE hProc, BYTE* pSrcData, SIZE_T FileSize, std::optional ntSymbolSolver, bool ClearHeader, bool ClearNonNeededSections, bool AdjustProtections, bool SEHExceptionSupport, DWORD fdwReason, LPVOID lpReserved) { +std::optional ManualMapDll(HANDLE hProc, BYTE* pSrcData, SIZE_T FileSize, bool ClearHeader, bool ClearNonNeededSections, bool AdjustProtections, bool SEHExceptionSupport, DWORD fdwReason, LPVOID lpReserved) { auto procNtdll = GetModuleBaseAddress(GetProcessId(hProc), "ntdll.dll"); IMAGE_NT_HEADERS* pOldNtHeader = nullptr; IMAGE_OPTIONAL_HEADER* pOldOptHeader = nullptr; @@ -63,21 +68,43 @@ std::optional ManualMapDll(HANDLE hProc, BYTE* pSrcData, SIZE_T FileSize, return std::nullopt; } + std::unique_ptr emptyBuffStrg = std::make_unique(1024 * 1024 * 20); + BYTE* emptyBuffer = emptyBuffStrg.get(); + if (emptyBuffer == nullptr) { + ILog("Unable to allocate memory\n"); + return std::nullopt; + } + memset(emptyBuffer, 0, 1024 * 1024 * 20); + DWORD oldp = 0; VirtualProtectEx(hProc, pTargetBase, pOldOptHeader->SizeOfImage, PAGE_EXECUTE_READWRITE, &oldp); - + MANUAL_MAPPING_DATA data{ 0 }; - data.pDummyLdr = (LDR_DATA_TABLE_ENTRY*)malloc(sizeof(LDR_DATA_TABLE_ENTRY)); memset(data.pDummyLdr, 0, sizeof(LDR_DATA_TABLE_ENTRY)); + data.pDummyLdr = (LDR_DATA_TABLE_ENTRY*)VirtualAllocEx(hProc, nullptr, sizeof(LDR_DATA_TABLE_ENTRY) * 4, MEM_COMMIT | MEM_RESERVE, PAGE_READWRITE); + WriteProcessMemory(hProc, data.pDummyLdr, emptyBuffer, sizeof(LDR_DATA_TABLE_ENTRY) * 4, nullptr); data.pLdrpHandleTlsData = [&]() -> f_LdrpHandleTlsData { - if (!procNtdll || !ntSymbolSolver) + if (!procNtdll) + return nullptr; + + auto rva = GetLdrpHandleTlsDataRVA(); + + if (!rva) + { + ILog("LdrpHandleTlsData Not found\n"); return nullptr; + } - auto ldrpHandleTlsDataRVA = (*ntSymbolSolver).Resolve("LdrpHandleTlsData"); + auto r = (f_LdrpHandleTlsData)((uint64_t)(*procNtdll) + *rva); - if (!ldrpHandleTlsDataRVA) + // Hash Like Integrity Check + if (*(uint16_t*)r != 0x8948 || + *(uint16_t*)((char*)r + 5) != 0x8948) + { + ILog("LdrpHandleTlsData Integrity Check Failed\n"); return nullptr; + } - return (f_LdrpHandleTlsData)((uint64_t)(*procNtdll) + (*ldrpHandleTlsDataRVA)); + return r; }(); data.pLoadLibraryA = LoadLibraryA; data.pGetProcAddress = GetProcAddress; @@ -193,14 +220,6 @@ std::optional ManualMapDll(HANDLE hProc, BYTE* pSrcData, SIZE_T FileSize, Sleep(10); } - std::unique_ptr emptyBuffStrg = std::make_unique(1024 * 1024 * 20); - BYTE* emptyBuffer = emptyBuffStrg.get(); - if (emptyBuffer == nullptr) { - ILog("Unable to allocate memory\n"); - return std::nullopt; - } - memset(emptyBuffer, 0, 1024 * 1024 * 20); - //CLEAR PE HEAD if (ClearHeader) { if (!WriteProcessMemory(hProc, pTargetBase, emptyBuffer, 0x1000, nullptr)) { @@ -344,7 +363,7 @@ void __stdcall Shellcode(MANUAL_MAPPING_DATA* pData) { /*Todo * Unlink from TLS list pData->pDummyLdr - * Finally free/release pData->pDummyLdr + * Finally release pData->pDummyLdr */ if (pOpt->DataDirectory[IMAGE_DIRECTORY_ENTRY_TLS].Size) { diff --git a/Manual Map Injector/injector.h b/Manual Map Injector/injector.h index c649889..4555cf5 100644 --- a/Manual Map Injector/injector.h +++ b/Manual Map Injector/injector.h @@ -61,5 +61,5 @@ struct MANUAL_MAPPING_DATA //Note: Exception support only x64 with build params /EHa or /EHc -std::optional ManualMapDll(HANDLE hProc, BYTE* pSrcData, SIZE_T FileSize, std::optional ntSymbolSolver = std::nullopt, bool ClearHeader = true, bool ClearNonNeededSections = true, bool AdjustProtections = true, bool SEHExceptionSupport = true, DWORD fdwReason = DLL_PROCESS_ATTACH, LPVOID lpReserved = 0); +std::optional ManualMapDll(HANDLE hProc, BYTE* pSrcData, SIZE_T FileSize, bool ClearHeader = true, bool ClearNonNeededSections = true, bool AdjustProtections = true, bool SEHExceptionSupport = true, DWORD fdwReason = DLL_PROCESS_ATTACH, LPVOID lpReserved = 0); void __stdcall Shellcode(MANUAL_MAPPING_DATA* pData); \ No newline at end of file