diff --git a/MemoryModule/Initialize.cpp b/MemoryModule/Initialize.cpp
index 173f337..fe1d12e 100644
--- a/MemoryModule/Initialize.cpp
+++ b/MemoryModule/Initialize.cpp
@@ -446,6 +446,7 @@ NTSTATUS InitializeLockHeld() {
MmpGlobalDataPtr->MmpLdrEntry = (PMMP_LDR_ENTRY_DATA)((LPBYTE)MmpGlobalDataPtr->MmpInvertedFunctionTable + sizeof(MMP_INVERTED_FUNCTION_TABLE_DATA));
MmpGlobalDataPtr->MmpTls = (PMMP_TLS_DATA)((LPBYTE)MmpGlobalDataPtr->MmpLdrEntry + sizeof(MMP_LDR_ENTRY_DATA));
MmpGlobalDataPtr->MmpDotNet = (PMMP_DOT_NET_DATA)((LPBYTE)MmpGlobalDataPtr->MmpTls + sizeof(MMP_TLS_DATA));
+ MmpGlobalDataPtr->MmpFunctions = (PMMP_FUNCTIONS)((LPBYTE)MmpGlobalDataPtr->MmpDotNet + sizeof(MMP_DOT_NET_DATA));
PLDR_DATA_TABLE_ENTRY pNtdllEntry = RtlFindLdrTableEntryByBaseName(L"ntdll.dll");
MmpGlobalDataPtr->MmpBaseAddressIndex->NtdllLdrEntry = pNtdllEntry;
@@ -462,6 +463,12 @@ NTSTATUS InitializeLockHeld() {
if (MmpGlobalDataPtr->MmpLdrEntry->LdrpHashTable)MmpGlobalDataPtr->MmpFeatures |= MEMORY_FEATURE_LDRP_HASH_TABLE;
if (MmpGlobalDataPtr->MmpInvertedFunctionTable->LdrpInvertedFunctionTable)MmpGlobalDataPtr->MmpFeatures |= MEMORY_FEATURE_INVERTED_FUNCTION_TABLE;
+ MmpGlobalDataPtr->MmpFunctions->_LdrLoadDllMemoryExW = LdrLoadDllMemoryExW;
+ MmpGlobalDataPtr->MmpFunctions->_LdrUnloadDllMemory = LdrUnloadDllMemory;
+ MmpGlobalDataPtr->MmpFunctions->_LdrUnloadDllMemoryAndExitThread = LdrUnloadDllMemoryAndExitThread;
+ MmpGlobalDataPtr->MmpFunctions->_MmpHandleTlsData = MmpHandleTlsData;
+ MmpGlobalDataPtr->MmpFunctions->_MmpReleaseTlsEntry = MmpReleaseTlsEntry;
+
MmpTlsInitialize();
MmpGlobalDataPtr->MmpDotNet->Initialized = MmpGlobalDataPtr->MmpDotNet->PreHooked = FALSE;
diff --git a/MemoryModule/Loader.cpp b/MemoryModule/Loader.cpp
index efc5c46..d2ebde3 100644
--- a/MemoryModule/Loader.cpp
+++ b/MemoryModule/Loader.cpp
@@ -158,7 +158,7 @@ NTSTATUS NTAPI LdrLoadDllMemoryExW(
}
if (!(dwFlags & LOAD_FLAGS_NOT_HANDLE_TLS)) {
- status = MmpHandleTlsData(ModuleEntry);
+ status = MmpGlobalDataPtr->MmpFunctions->_MmpHandleTlsData(ModuleEntry);
if (!NT_SUCCESS(status)) {
if (dwFlags & LOAD_FLAGS_NOT_FAIL_IF_HANDLE_TLS) status = 0x7fffffff;
if (!NT_SUCCESS(status))break;
@@ -246,7 +246,7 @@ NTSTATUS NTAPI LdrUnloadDllMemory(_In_ HMEMORYMODULE BaseAddress) {
}
if (module->TlsHandled) {
- status = MmpReleaseTlsEntry(CurEntry);
+ status = MmpGlobalDataPtr->MmpFunctions->_MmpReleaseTlsEntry(CurEntry);
if (!NT_SUCCESS(status)) __fastfail(FAST_FAIL_FATAL_APP_EXIT);
}
diff --git a/MemoryModule/MemoryModule.vcxproj b/MemoryModule/MemoryModule.vcxproj
index 526246d..faee58b 100644
--- a/MemoryModule/MemoryModule.vcxproj
+++ b/MemoryModule/MemoryModule.vcxproj
@@ -49,6 +49,7 @@
+
diff --git a/MemoryModule/MemoryModule.vcxproj.filters b/MemoryModule/MemoryModule.vcxproj.filters
index 2aa9155..201a6b5 100644
--- a/MemoryModule/MemoryModule.vcxproj.filters
+++ b/MemoryModule/MemoryModule.vcxproj.filters
@@ -90,6 +90,9 @@
Source Files
+
+ Source Files
+
diff --git a/MemoryModule/MmpGlobalData.h b/MemoryModule/MmpGlobalData.h
index e93adf1..6bc58f8 100644
--- a/MemoryModule/MmpGlobalData.h
+++ b/MemoryModule/MmpGlobalData.h
@@ -63,6 +63,15 @@ typedef struct _MMP_DOT_NET_DATA {
}Hooks;
}MMP_DOT_NET_DATA, * PMMP_DOT_NET_DATA;
+typedef struct _MMP_FUNCTIONS {
+ decltype(&LdrLoadDllMemoryExW) _LdrLoadDllMemoryExW;
+ decltype(&LdrUnloadDllMemory) _LdrUnloadDllMemory;
+ decltype(&LdrUnloadDllMemoryAndExitThread) _LdrUnloadDllMemoryAndExitThread;
+
+ decltype(&MmpHandleTlsData) _MmpHandleTlsData;
+ decltype(&MmpReleaseTlsEntry) _MmpReleaseTlsEntry;
+}MMP_FUNCTIONS, * PMMP_FUNCTIONS;
+
typedef enum class _WINDOWS_VERSION :BYTE {
null,
xp,
@@ -78,7 +87,7 @@ typedef enum class _WINDOWS_VERSION :BYTE {
}WINDOWS_VERSION;
#define MEMORY_MODULE_MAJOR_VERSION 1
-#define MEMORY_MODULE_MINOR_VERSION 2
+#define MEMORY_MODULE_MINOR_VERSION 3
typedef struct _MMP_GLOBAL_DATA {
@@ -111,6 +120,8 @@ typedef struct _MMP_GLOBAL_DATA {
PVOID BaseAddress;
+ PMMP_FUNCTIONS MmpFunctions;
+
}MMP_GLOBAL_DATA, * PMMP_GLOBAL_DATA;
#define MMP_GLOBAL_DATA_SIZE (\
@@ -119,7 +130,8 @@ typedef struct _MMP_GLOBAL_DATA {
sizeof(MMP_INVERTED_FUNCTION_TABLE_DATA) + \
sizeof(MMP_LDR_ENTRY_DATA) + \
sizeof(MMP_TLS_DATA) + \
- sizeof(MMP_DOT_NET_DATA)\
+ sizeof(MMP_DOT_NET_DATA) + \
+ sizeof(PMMP_FUNCTIONS)\
)
extern PMMP_GLOBAL_DATA MmpGlobalDataPtr;
diff --git a/MemoryModule/MmpLdrpTls.cpp b/MemoryModule/MmpLdrpTls.cpp
new file mode 100644
index 0000000..008de30
--- /dev/null
+++ b/MemoryModule/MmpLdrpTls.cpp
@@ -0,0 +1,189 @@
+#include "stdafx.h"
+
+#if (!MMPP_USE_TLS)
+
+static bool stdcall;
+static PVOID LdrpHandleTlsData;
+static PVOID LdrpReleaseTlsEntry;
+
+static NTSTATUS NTAPI RtlFindLdrpHandleTlsData() {
+ NTSTATUS status = STATUS_SUCCESS;
+ LPCVOID Feature = nullptr;
+ BYTE Size = 0;
+ WORD OffsetOfFunctionBegin = 0;
+
+ switch (MmpGlobalDataPtr->NtVersions.MajorVersion) {
+ case 10: {
+ if (MmpGlobalDataPtr->NtVersions.MinorVersion)return STATUS_NOT_SUPPORTED;
+
+ if (MmpGlobalDataPtr->NtVersions.BuildNumber >= 22621) {
+#ifdef _WIN64
+ Feature = "\x39\x1D\x23\xFC\x17\x00\x74\x37\x44\x8D\x43\x09\x44\x39\x81\x0C\x01\x00\x00\x74\x2A";
+ Size = 22;
+ OffsetOfFunctionBegin = 0x43;
+#else
+ return STATUS_NOT_SUPPORTED;
+#endif
+ }
+ //
+ // Add more conditions here.
+ //
+ // else if (MmpGlobalDataPtr->NtVersions.BuildNumber >= XXXXXXXXX)
+ else {
+ return STATUS_NOT_SUPPORTED;
+ }
+
+ break;
+ }
+ case 6: {
+ switch (MmpGlobalDataPtr->NtVersions.MinorVersion) {
+ //8.1
+ case 3: {
+#ifdef _WIN64
+ Size = 10;
+ OffsetOfFunctionBegin = 0x43;
+ Feature = "\x44\x8d\x43\x09\x4c\x8d\x4c\x24\x38";
+#else
+ Size = 8;
+ OffsetOfFunctionBegin = 0x1B;
+ Feature = "\x50\x6a\x09\x6a\x01\x8b\xc1";
+#endif
+ break;
+ }
+ //8
+ case 2: {
+#ifdef _WIN64
+ Size = 9;
+ OffsetOfFunctionBegin = 0x49;
+ Feature = "\x48\x8b\x79\x30\x45\x8d\x66\x01";
+#else
+ Size = 7;
+ OffsetOfFunctionBegin = 0xC;
+ Feature = "\x8b\x45\x08\x89\x45\xa0";
+#endif
+ break;
+ }
+ //7
+ case 1: {
+#ifdef _WIN64
+ Size = 12;
+ OffsetOfFunctionBegin = 0x27;
+ Feature = "\x41\xb8\x09\x00\x00\x00\x48\x8d\x44\x24\x38";
+#else
+ Size = 9;
+ OffsetOfFunctionBegin = 0x14;
+ Feature = "\x74\x20\x8d\x45\xd4\x50\x6a\x09";
+#endif
+ break;
+ }
+ default:return STATUS_NOT_SUPPORTED;
+ }
+ break;
+ }
+
+ default: {
+ return STATUS_NOT_SUPPORTED;
+ }
+ }
+
+ SEARCH_CONTEXT SearchContext{ SearchContext.SearchPattern = LPBYTE(Feature),SearchContext.PatternSize = Size - 1 };
+ if (!NT_SUCCESS(RtlFindMemoryBlockFromModuleSection(HMODULE(MmpGlobalDataPtr->MmpBaseAddressIndex->NtdllLdrEntry->DllBase), ".text", &SearchContext)))
+ return STATUS_NOT_SUPPORTED;
+
+ LdrpHandleTlsData = SearchContext.Result - OffsetOfFunctionBegin;
+ return status;
+}
+
+static NTSTATUS NTAPI RtlFindLdrpReleaseTlsEntry() {
+ NTSTATUS status = STATUS_SUCCESS;
+ LPCVOID Feature = nullptr;
+ BYTE Size = 0;
+ WORD OffsetOfFunctionBegin = 0;
+
+ switch (MmpGlobalDataPtr->NtVersions.MajorVersion) {
+ case 10: {
+ if (MmpGlobalDataPtr->NtVersions.MinorVersion) return STATUS_NOT_SUPPORTED;
+
+ if (MmpGlobalDataPtr->NtVersions.BuildNumber >= 22621) {
+#ifdef _WIN64
+ Feature = "\x74\x34\x48\x8B\x08\x48\x39\x41\x08\x75\x65\x48\x8B\x40\x08\x48\x39\x18\x75\x5C\x48\x89\x08";
+ Size = 24;
+ OffsetOfFunctionBegin = 0x2F;
+#else
+ return STATUS_NOT_SUPPORTED;
+#endif
+ }
+ //
+ // Add more conditions here.
+ //
+ // else if (MmpGlobalDataPtr->NtVersions.BuildNumber >= XXXXXXXXX)
+ else {
+ return STATUS_NOT_SUPPORTED;
+ }
+
+ break;
+ }
+ default:
+ return STATUS_NOT_SUPPORTED;
+ }
+
+ SEARCH_CONTEXT SearchContext{ SearchContext.SearchPattern = LPBYTE(Feature),SearchContext.PatternSize = Size - 1 };
+ if (!NT_SUCCESS(RtlFindMemoryBlockFromModuleSection(HMODULE(MmpGlobalDataPtr->MmpBaseAddressIndex->NtdllLdrEntry->DllBase), ".text", &SearchContext)))
+ return STATUS_NOT_SUPPORTED;
+
+ LdrpReleaseTlsEntry = SearchContext.Result - OffsetOfFunctionBegin;
+ return status;
+}
+
+BOOL NTAPI MmpTlsInitialize() {
+ if (!NT_SUCCESS(RtlFindLdrpHandleTlsData()) ||
+ !NT_SUCCESS(RtlFindLdrpReleaseTlsEntry())) {
+ MmpGlobalDataPtr->MmpFeatures &= ~MEMORY_FEATURE_LDRP_HANDLE_TLS_DATA;
+ return FALSE;
+ }
+
+ stdcall = !RtlIsWindowsVersionOrGreater(6, 3, 0);
+ return TRUE;
+}
+
+NTSTATUS NTAPI MmpReleaseTlsEntry(_In_ PLDR_DATA_TABLE_ENTRY lpModuleEntry) {
+ typedef NTSTATUS(__stdcall* STDCALL)(PLDR_DATA_TABLE_ENTRY);
+ typedef NTSTATUS(__stdcall* THISCALL)(PLDR_DATA_TABLE_ENTRY);
+
+ union {
+ STDCALL stdcall;
+ THISCALL thiscall;
+
+ PVOID ptr;
+ }fp;
+ fp.ptr = LdrpReleaseTlsEntry;
+
+ if (fp.ptr) {
+ return stdcall ? fp.stdcall(lpModuleEntry): fp.thiscall(lpModuleEntry);
+ }
+ else {
+ return STATUS_NOT_SUPPORTED;
+ }
+}
+
+NTSTATUS NTAPI MmpHandleTlsData(_In_ PLDR_DATA_TABLE_ENTRY lpModuleEntry) {
+ typedef NTSTATUS(__stdcall* STDCALL)(PLDR_DATA_TABLE_ENTRY);
+ typedef NTSTATUS(__stdcall* THISCALL)(PLDR_DATA_TABLE_ENTRY);
+
+ union {
+ STDCALL stdcall;
+ THISCALL thiscall;
+
+ PVOID ptr;
+ }fp;
+ fp.ptr = LdrpHandleTlsData;
+
+ if (fp.ptr) {
+ return stdcall ? fp.stdcall(lpModuleEntry) : fp.thiscall(lpModuleEntry);
+ }
+ else {
+ return STATUS_NOT_SUPPORTED;
+ }
+}
+
+#endif
diff --git a/MemoryModule/MmpTls.cpp b/MemoryModule/MmpTls.cpp
index 4f1960b..98f6fb7 100644
--- a/MemoryModule/MmpTls.cpp
+++ b/MemoryModule/MmpTls.cpp
@@ -1,4 +1,6 @@
#include "stdafx.h"
+
+#if (MMPP_USE_TLS)
#include
#include
#include <3rdparty/Detours/detours.h>
@@ -849,3 +851,5 @@ BOOL NTAPI MmpTlsInitialize() {
return TRUE;
}
+
+#endif
diff --git a/MemoryModule/stdafx.h b/MemoryModule/stdafx.h
index 0affb02..3e8708e 100644
--- a/MemoryModule/stdafx.h
+++ b/MemoryModule/stdafx.h
@@ -8,6 +8,11 @@
#include
#endif
+//
+// Determine whether to use MmpTls(1) or LdrpTls(0)
+//
+#define MMPP_USE_TLS 1
+
// offsetof()
#include