mirror of
https://github.com/bb107/MemoryModulePP
synced 2026-06-08 13:15:33 +00:00
add LdrpReleaseTlsEntry support
This commit is contained in:
@@ -57,8 +57,9 @@ typedef struct _MEMORYMODULE {
|
||||
//Load Flags
|
||||
WORD MappedDll : 1;
|
||||
WORD InsertInvertedFunctionTableEntry : 1;
|
||||
WORD TlsHandled : 1;
|
||||
WORD UseReferenceCount : 1;
|
||||
WORD reservedLoadFlags : 13;
|
||||
WORD reservedLoadFlags : 12;
|
||||
|
||||
};
|
||||
DWORD dwFlags;
|
||||
|
||||
@@ -71,6 +71,7 @@
|
||||
<UseDebugLibraries>true</UseDebugLibraries>
|
||||
<PlatformToolset>v142</PlatformToolset>
|
||||
<CharacterSet>Unicode</CharacterSet>
|
||||
<SpectreMitigation>Spectre</SpectreMitigation>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
|
||||
<ConfigurationType>StaticLibrary</ConfigurationType>
|
||||
|
||||
@@ -71,9 +71,9 @@ static NTSTATUS NTAPI RtlInsertModuleBaseAddressIndexNode(IN PLDR_DATA_TABLE_ENT
|
||||
return STATUS_SUCCESS;
|
||||
}
|
||||
static NTSTATUS NTAPI RtlRemoveModuleBaseAddressIndexNode(IN PLDR_DATA_TABLE_ENTRY DataTableEntry) {
|
||||
DebugBreak();
|
||||
static auto tree{ RtlFindLdrpModuleBaseAddressIndex() };
|
||||
if (!tree->Root)return STATUS_UNSUCCESSFUL;
|
||||
|
||||
RtlRbRemoveNode(tree, &PLDR_DATA_TABLE_ENTRY_WIN8(DataTableEntry)->BaseAddressIndexNode);
|
||||
return STATUS_SUCCESS;
|
||||
}
|
||||
@@ -646,6 +646,9 @@ NTSTATUS NTAPI LdrLoadDllMemoryExW(
|
||||
return status;
|
||||
} while (false);
|
||||
}
|
||||
else {
|
||||
module->TlsHandled = true;
|
||||
}
|
||||
}
|
||||
|
||||
return status;
|
||||
@@ -713,6 +716,11 @@ NTSTATUS NTAPI LdrUnloadDllMemory(IN HMEMORYMODULE BaseAddress) {
|
||||
status = RtlRemoveInvertedFunctionTable(BaseAddress);
|
||||
if (!NT_SUCCESS(status))__fastfail(FAST_FAIL_CORRUPT_LIST_ENTRY);
|
||||
}
|
||||
if (module->TlsHandled) {
|
||||
|
||||
status = LdrpReleaseTlsEntry(CurEntry);
|
||||
if (!NT_SUCCESS(status)) __fastfail(FAST_FAIL_FATAL_APP_EXIT);
|
||||
}
|
||||
if (!RtlFreeLdrDataTableEntry(CurEntry))__fastfail(FAST_FAIL_FATAL_APP_EXIT);
|
||||
}
|
||||
if (!MemoryFreeLibrary(BaseAddress))__fastfail(FAST_FAIL_FATAL_APP_EXIT);
|
||||
@@ -748,7 +756,7 @@ NTSTATUS NTAPI LdrQuerySystemMemoryModuleFeatures(OUT PDWORD pFeatures) {
|
||||
if (RtlFindLdrpHashTable())features |= MEMORY_FEATURE_LDRP_HASH_TABLE;
|
||||
if (RtlFindLdrpInvertedFunctionTable())features |= MEMORY_FEATURE_INVERTED_FUNCTION_TABLE;
|
||||
if (NT_SUCCESS(RtlFindLdrpHandleTlsData(&pfn, &value)) && pfn)features |= MEMORY_FEATURE_LDRP_HANDLE_TLS_DATA;
|
||||
|
||||
if (NT_SUCCESS(RtlFindLdrpReleaseTlsEntry(&pfn, &value) && pfn))features |= MEMORY_FEATURE_LDRP_RELEASE_TLS_ENTRY;
|
||||
if (features)features |= MEMORY_FEATURE_SUPPORT_VERSION;
|
||||
*pFeatures = features;
|
||||
}
|
||||
|
||||
@@ -20,7 +20,8 @@ NTSTATUS NTAPI LdrLoadDllMemory(
|
||||
#define MEMORY_FEATURE_LDRP_HASH_TABLE 0x00000008
|
||||
#define MEMORY_FEATURE_INVERTED_FUNCTION_TABLE 0x00000010
|
||||
#define MEMORY_FEATURE_LDRP_HANDLE_TLS_DATA 0x00000020
|
||||
#define MEMORY_FEATURE_ALL 0x0000003f
|
||||
#define MEMORY_FEATURE_LDRP_RELEASE_TLS_ENTRY 0x00000040
|
||||
#define MEMORY_FEATURE_ALL 0x0000007f
|
||||
|
||||
//Get the implementation of the currently running operating system.
|
||||
NTSTATUS NTAPI LdrQuerySystemMemoryModuleFeatures(OUT PDWORD pFeatures);
|
||||
|
||||
@@ -1,6 +1,8 @@
|
||||
#include "rtlldr.h"
|
||||
#pragma warning(disable:4996)
|
||||
|
||||
PLDR_DATA_TABLE_ENTRY const LdrpNtdllBase = RtlFindLdrTableEntryByBaseName(L"ntdll.dll");
|
||||
|
||||
VOID NTAPI RtlRbInsertNodeEx(IN PRTL_RB_TREE Tree, IN PRTL_BALANCED_NODE Parent, IN BOOLEAN Right, OUT PRTL_BALANCED_NODE Node) {
|
||||
decltype(&RtlRbInsertNodeEx)_RtlRbInsertNodeEx = decltype(_RtlRbInsertNodeEx)(RtlGetNtProcAddress("RtlRbInsertNodeEx"));
|
||||
if (!_RtlRbInsertNodeEx)return;
|
||||
|
||||
@@ -5,7 +5,9 @@ PLDR_DATA_TABLE_ENTRY NTAPI RtlFindLdrTableEntryByHandle(PVOID BaseAddress);
|
||||
|
||||
PLDR_DATA_TABLE_ENTRY NTAPI RtlFindLdrTableEntryByBaseName(PCWSTR BaseName);
|
||||
|
||||
#define RtlFindNtdllLdrEntry() RtlFindLdrTableEntryByBaseName(L"ntdll.dll")
|
||||
extern PLDR_DATA_TABLE_ENTRY const LdrpNtdllBase;
|
||||
|
||||
#define RtlFindNtdllLdrEntry() (LdrpNtdllBase)
|
||||
|
||||
|
||||
|
||||
@@ -330,6 +332,8 @@ typedef struct _LDR_DATA_TABLE_ENTRY_WIN10_1 :public _LDR_DATA_TABLE_ENTRY_WIN10
|
||||
//10.0.17134 Windows 10 | 2016 1803 Redstone 4 (Spring Creators Update)
|
||||
//10.0.17763 Windows 10 | 2016 1809 Redstone 5 (October Update)
|
||||
//10.0.18362 Windows 10 | 2016 1903 19H1 (May 2019 Update) | 2016 1909 19H2 (November 2019 Update)
|
||||
//10.0.19041 Windows 10 | 2016 2004 20H1 (May 2020 Update)
|
||||
//10.0.19042 Windows 10 | 2016 2009 20H2 (October 2020 Update)
|
||||
typedef struct _LDR_DATA_TABLE_ENTRY_WIN10_2 {
|
||||
_LIST_ENTRY InLoadOrderLinks; //0x0
|
||||
_LIST_ENTRY InMemoryOrderLinks; //0x10
|
||||
|
||||
+94
-19
@@ -134,32 +134,107 @@ NTSTATUS NTAPI RtlFindLdrpHandleTlsData(PVOID* _LdrpHandleTlsData, bool* stdcall
|
||||
}
|
||||
|
||||
SEARCH_CONTEXT SearchContext{ SearchContext.MemoryBuffer = const_cast<PVOID>(Feature),SearchContext.BufferLength = Size - 1 };
|
||||
if (NT_SUCCESS(RtlFindMemoryBlockFromModuleSection(GetModuleHandleW(L"ntdll.dll"), ".text", &SearchContext)))
|
||||
if (NT_SUCCESS(RtlFindMemoryBlockFromModuleSection(HMODULE(RtlFindNtdllLdrEntry()->DllBase), ".text", &SearchContext)))
|
||||
SearchContext.OutBufferPtr -= OffsetOfFunctionBegin;
|
||||
if (!(*_LdrpHandleTlsData = _LdrpHandleTlsData_ = SearchContext.MemoryBlockInSection))return STATUS_NOT_SUPPORTED;
|
||||
*stdcall = !RtlIsWindowsVersionOrGreater(6, 3, 0);
|
||||
return status;
|
||||
}
|
||||
|
||||
NTSTATUS NTAPI LdrpHandleTlsData(IN PLDR_DATA_TABLE_ENTRY LdrEntry) {
|
||||
typedef NTSTATUS(__thiscall* _PTR_WIN8_1)(PLDR_DATA_TABLE_ENTRY LdrEntry);
|
||||
typedef NTSTATUS(__stdcall* _PTR_WIN)(PLDR_DATA_TABLE_ENTRY LdrEntry);
|
||||
union _FUNCTION_SET {
|
||||
_PTR_WIN8_1 Win8_1_OrGreater;
|
||||
_PTR_WIN Default;
|
||||
_FUNCTION_SET() {
|
||||
this->Default = nullptr;
|
||||
NTSTATUS NTAPI RtlFindLdrpReleaseTlsEntry(PVOID* _LdrpReleaseTlsEntry, bool* stdcall) {
|
||||
static PVOID _LdrpReleaseTlsEntry_ = (PVOID)~0;
|
||||
NTSTATUS status = STATUS_SUCCESS;
|
||||
|
||||
__try {
|
||||
if (_LdrpReleaseTlsEntry_ != (PVOID)~0) {
|
||||
*_LdrpReleaseTlsEntry = _LdrpReleaseTlsEntry_;
|
||||
if (!_LdrpReleaseTlsEntry_)status = STATUS_NOT_SUPPORTED;
|
||||
}
|
||||
operator bool() {
|
||||
return this->Default != nullptr;
|
||||
else {
|
||||
*_LdrpReleaseTlsEntry = _LdrpReleaseTlsEntry_ = nullptr;
|
||||
*stdcall = false;
|
||||
}
|
||||
};
|
||||
static _FUNCTION_SET _LdrpHandleTlsData{};
|
||||
static bool stdcall = false;
|
||||
NTSTATUS status;
|
||||
if (!_LdrpHandleTlsData) {
|
||||
status = RtlFindLdrpHandleTlsData((PVOID*)&_LdrpHandleTlsData.Default, &stdcall);
|
||||
if (!NT_SUCCESS(status))return status;
|
||||
}
|
||||
return stdcall ? _LdrpHandleTlsData.Default(LdrEntry) : _LdrpHandleTlsData.Win8_1_OrGreater(LdrEntry);
|
||||
__except (EXCEPTION_EXECUTE_HANDLER) {
|
||||
status = GetExceptionCode();
|
||||
}
|
||||
if (!NT_SUCCESS(status))return status;
|
||||
|
||||
DWORD Versions[3]{};
|
||||
LPCVOID Feature = nullptr;
|
||||
BYTE Size = 0;
|
||||
WORD OffsetOfFunctionBegin = 0;
|
||||
RtlGetNtVersionNumbers(Versions, Versions + 1, Versions + 2);
|
||||
switch (Versions[0]) {
|
||||
case 10: {
|
||||
if (Versions[1]) {
|
||||
status = STATUS_NOT_SUPPORTED;
|
||||
break;
|
||||
}
|
||||
if (Versions[2] >= 19041) {
|
||||
Size = 0x10;
|
||||
OffsetOfFunctionBegin = 0x2F;
|
||||
Feature = "\x74\x26\x48\x8B\x00\x48\x39\x58\x08\x75\x5D\x48\x8B\x4B\x08";
|
||||
break;
|
||||
}
|
||||
}
|
||||
default:
|
||||
status = STATUS_NOT_SUPPORTED;
|
||||
}
|
||||
|
||||
if (!NT_SUCCESS(status)) {
|
||||
return status;
|
||||
}
|
||||
|
||||
SEARCH_CONTEXT SearchContext{ SearchContext.MemoryBuffer = const_cast<PVOID>(Feature),SearchContext.BufferLength = Size - 1 };
|
||||
if (NT_SUCCESS(RtlFindMemoryBlockFromModuleSection(HMODULE(RtlFindNtdllLdrEntry()->DllBase), ".text", &SearchContext)))
|
||||
SearchContext.OutBufferPtr -= OffsetOfFunctionBegin;
|
||||
if (!(*_LdrpReleaseTlsEntry = _LdrpReleaseTlsEntry_ = SearchContext.MemoryBlockInSection))return STATUS_NOT_SUPPORTED;
|
||||
*stdcall = !RtlIsWindowsVersionOrGreater(6, 3, 0);
|
||||
return status;
|
||||
}
|
||||
|
||||
static NTSTATUS NTAPI RtlInvokeTlsHandler(IN PLDR_DATA_TABLE_ENTRY LdrEntry, IN BOOLEAN Release) {
|
||||
static bool stdcall = false;
|
||||
union _FUNCTION_SET {
|
||||
struct {
|
||||
NTSTATUS(__stdcall* LdrpHandleTlsData)(PLDR_DATA_TABLE_ENTRY LdrEntry);
|
||||
NTSTATUS(__stdcall* LdrpReleaseTlsEntry)(PLDR_DATA_TABLE_ENTRY LdrEntry, DWORD);
|
||||
}Default;
|
||||
|
||||
struct {
|
||||
NTSTATUS(__thiscall* LdrpHandleTlsData)(PLDR_DATA_TABLE_ENTRY LdrEntry);
|
||||
NTSTATUS(__thiscall* LdrpReleaseTlsEntry)(PLDR_DATA_TABLE_ENTRY LdrEntry, DWORD);
|
||||
}WinBlue;
|
||||
|
||||
_FUNCTION_SET() {
|
||||
RtlFindLdrpHandleTlsData((PVOID*)(&this->Default.LdrpHandleTlsData), &stdcall);
|
||||
RtlFindLdrpReleaseTlsEntry((PVOID*)(&this->Default.LdrpReleaseTlsEntry), &stdcall);
|
||||
|
||||
if (!this->Default.LdrpHandleTlsData || !this->Default.LdrpReleaseTlsEntry) {
|
||||
this->Default = {};
|
||||
}
|
||||
}
|
||||
|
||||
}static InvokeHandler;
|
||||
|
||||
if (Release) {
|
||||
if (InvokeHandler.Default.LdrpReleaseTlsEntry) {
|
||||
return (stdcall ? InvokeHandler.Default.LdrpReleaseTlsEntry : InvokeHandler.WinBlue.LdrpReleaseTlsEntry)(LdrEntry, 0);
|
||||
}
|
||||
}
|
||||
else {
|
||||
if (InvokeHandler.Default.LdrpHandleTlsData) {
|
||||
return (stdcall ? InvokeHandler.Default.LdrpHandleTlsData : InvokeHandler.WinBlue.LdrpHandleTlsData)(LdrEntry);
|
||||
}
|
||||
}
|
||||
return STATUS_NOT_SUPPORTED;
|
||||
}
|
||||
|
||||
NTSTATUS NTAPI LdrpHandleTlsData(IN PLDR_DATA_TABLE_ENTRY LdrEntry) {
|
||||
return RtlInvokeTlsHandler(LdrEntry, FALSE);
|
||||
}
|
||||
|
||||
NTSTATUS NTAPI LdrpReleaseTlsEntry(IN PLDR_DATA_TABLE_ENTRY LdrEntry) {
|
||||
return RtlInvokeTlsHandler(LdrEntry, TRUE);
|
||||
}
|
||||
|
||||
@@ -3,4 +3,9 @@
|
||||
|
||||
NTSTATUS NTAPI RtlFindLdrpHandleTlsData(PVOID* _LdrpHandleTlsData, bool* stdcall);
|
||||
|
||||
NTSTATUS NTAPI RtlFindLdrpReleaseTlsEntry(PVOID* _LdrpReleaseTlsEntry, bool* stdcall);
|
||||
|
||||
NTSTATUS NTAPI LdrpHandleTlsData(IN PLDR_DATA_TABLE_ENTRY LdrEntry);
|
||||
|
||||
NTSTATUS NTAPI LdrpReleaseTlsEntry(IN PLDR_DATA_TABLE_ENTRY LdrEntry);
|
||||
|
||||
|
||||
Reference in New Issue
Block a user