add LdrpReleaseTlsEntry support

This commit is contained in:
Boring
2020-12-14 12:06:45 +08:00
parent dd47c325c6
commit 948f6278f0
9 changed files with 123 additions and 31 deletions
+2 -1
View File
@@ -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;
+1
View File
@@ -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>
+10 -2
View File
@@ -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;
}
+2 -1
View File
@@ -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);
+2
View File
@@ -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 -1
View File
@@ -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
View File
@@ -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);
}
+5
View File
@@ -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);