mirror of
https://github.com/bb107/MemoryModulePP
synced 2026-06-08 13:15:33 +00:00
update
This commit is contained in:
@@ -1,35 +1,7 @@
|
||||
#include "stdafx.h"
|
||||
|
||||
PRTL_RB_TREE NTAPI RtlFindLdrpModuleBaseAddressIndex() {
|
||||
static PRTL_RB_TREE LdrpModuleBaseAddressIndex = nullptr;
|
||||
if (LdrpModuleBaseAddressIndex)return LdrpModuleBaseAddressIndex;
|
||||
|
||||
PLDR_DATA_TABLE_ENTRY_WIN10 nt10 = decltype(nt10)(RtlFindNtdllLdrEntry());
|
||||
PRTL_BALANCED_NODE node = nullptr;
|
||||
if (!nt10 || !RtlIsWindowsVersionOrGreater(6, 2, 0))return nullptr;
|
||||
node = &nt10->BaseAddressIndexNode;
|
||||
while (node->ParentValue & (~7)) node = decltype(node)(node->ParentValue & (~7));
|
||||
|
||||
if (!node->Red) {
|
||||
BYTE count = 0;
|
||||
PRTL_RB_TREE tmp = nullptr;
|
||||
SEARCH_CONTEXT SearchContext{};
|
||||
SearchContext.MemoryBuffer = &node;
|
||||
SearchContext.BufferLength = sizeof(size_t);
|
||||
while (NT_SUCCESS(RtlFindMemoryBlockFromModuleSection((HMODULE)nt10->DllBase, ".data", &SearchContext))) {
|
||||
if (count++)return nullptr;
|
||||
tmp = (decltype(tmp))SearchContext.MemoryBlockInSection;
|
||||
}
|
||||
if (count && tmp && tmp->Root && tmp->Min) {
|
||||
LdrpModuleBaseAddressIndex = tmp;
|
||||
}
|
||||
}
|
||||
|
||||
return LdrpModuleBaseAddressIndex;
|
||||
}
|
||||
|
||||
NTSTATUS NTAPI RtlInsertModuleBaseAddressIndexNode(IN PLDR_DATA_TABLE_ENTRY DataTableEntry, IN PVOID BaseAddress) {
|
||||
static auto LdrpModuleBaseAddressIndex = RtlFindLdrpModuleBaseAddressIndex();
|
||||
auto LdrpModuleBaseAddressIndex = MmpGlobalDataPtr->LdrpModuleBaseAddressIndex;
|
||||
if (!LdrpModuleBaseAddressIndex)return STATUS_UNSUCCESSFUL;
|
||||
|
||||
PLDR_DATA_TABLE_ENTRY_WIN8 LdrNode = decltype(LdrNode)((size_t)LdrpModuleBaseAddressIndex - offsetof(LDR_DATA_TABLE_ENTRY_WIN8, BaseAddressIndexNode));
|
||||
@@ -61,7 +33,7 @@ NTSTATUS NTAPI RtlInsertModuleBaseAddressIndexNode(IN PLDR_DATA_TABLE_ENTRY Data
|
||||
}
|
||||
|
||||
NTSTATUS NTAPI RtlRemoveModuleBaseAddressIndexNode(IN PLDR_DATA_TABLE_ENTRY DataTableEntry) {
|
||||
static auto tree{ RtlFindLdrpModuleBaseAddressIndex() };
|
||||
static auto tree{ MmpGlobalDataPtr->LdrpModuleBaseAddressIndex };
|
||||
if (!tree->Root)return STATUS_UNSUCCESSFUL;
|
||||
RtlRbRemoveNode(tree, &PLDR_DATA_TABLE_ENTRY_WIN8(DataTableEntry)->BaseAddressIndexNode);
|
||||
return STATUS_SUCCESS;
|
||||
|
||||
@@ -1,7 +1,5 @@
|
||||
#pragma once
|
||||
|
||||
PRTL_RB_TREE NTAPI RtlFindLdrpModuleBaseAddressIndex();
|
||||
|
||||
NTSTATUS NTAPI RtlInsertModuleBaseAddressIndexNode(IN PLDR_DATA_TABLE_ENTRY DataTableEntry, IN PVOID BaseAddress);
|
||||
|
||||
NTSTATUS NTAPI RtlRemoveModuleBaseAddressIndexNode(IN PLDR_DATA_TABLE_ENTRY DataTableEntry);
|
||||
|
||||
+237
-4
@@ -1,6 +1,14 @@
|
||||
#include "stdafx.h"
|
||||
#include <wchar.h>
|
||||
|
||||
PMMP_GLOBAL_DATA MmpGlobalDataPtr;
|
||||
|
||||
#ifdef _WIN64
|
||||
#define FindLdrpInvertedFunctionTable FindLdrpInvertedFunctionTable64
|
||||
#else
|
||||
#define FindLdrpInvertedFunctionTable FindLdrpInvertedFunctionTable32
|
||||
#endif
|
||||
|
||||
BOOLEAN MmpBuildSectionName(_Out_ PUNICODE_STRING SectionName) {
|
||||
WCHAR buffer[128];
|
||||
|
||||
@@ -8,9 +16,176 @@ BOOLEAN MmpBuildSectionName(_Out_ PUNICODE_STRING SectionName) {
|
||||
return RtlCreateUnicodeString(SectionName, buffer);
|
||||
}
|
||||
|
||||
VOID InitializeLockHeld() {
|
||||
NTSTATUS status;
|
||||
HANDLE hSection;
|
||||
PRTL_RB_TREE FindLdrpModuleBaseAddressIndex() {
|
||||
PRTL_RB_TREE LdrpModuleBaseAddressIndex = nullptr;
|
||||
PLDR_DATA_TABLE_ENTRY_WIN10 nt10 = decltype(nt10)(MmpGlobalDataPtr->LdrpNtdllBase);
|
||||
PRTL_BALANCED_NODE node = nullptr;
|
||||
if (!nt10 || !RtlIsWindowsVersionOrGreater(6, 2, 0))return nullptr;
|
||||
node = &nt10->BaseAddressIndexNode;
|
||||
while (node->ParentValue & (~7)) node = decltype(node)(node->ParentValue & (~7));
|
||||
|
||||
if (!node->Red) {
|
||||
BYTE count = 0;
|
||||
PRTL_RB_TREE tmp = nullptr;
|
||||
SEARCH_CONTEXT SearchContext{};
|
||||
SearchContext.MemoryBuffer = &node;
|
||||
SearchContext.BufferLength = sizeof(size_t);
|
||||
while (NT_SUCCESS(RtlFindMemoryBlockFromModuleSection((HMODULE)nt10->DllBase, ".data", &SearchContext))) {
|
||||
if (count++)return nullptr;
|
||||
tmp = (decltype(tmp))SearchContext.MemoryBlockInSection;
|
||||
}
|
||||
if (count && tmp && tmp->Root && tmp->Min) {
|
||||
LdrpModuleBaseAddressIndex = tmp;
|
||||
}
|
||||
}
|
||||
|
||||
return LdrpModuleBaseAddressIndex;
|
||||
}
|
||||
|
||||
static __forceinline bool IsModuleUnloaded(PLDR_DATA_TABLE_ENTRY entry) {
|
||||
if (RtlIsWindowsVersionOrGreater(6, 2, 0)) {
|
||||
return PLDR_DATA_TABLE_ENTRY_WIN8(entry)->DdagNode->State == LdrModulesUnloaded;
|
||||
}
|
||||
else {
|
||||
return entry->DllBase == nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
PVOID FindLdrpInvertedFunctionTable32() {
|
||||
// _RTL_INVERTED_FUNCTION_TABLE x86
|
||||
// Count +0x0 ????????
|
||||
// MaxCount +0x4 0x00000200
|
||||
// Overflow +0x8 0x00000000(Win7) ????????(Win10)
|
||||
// NextEntrySEHandlerTableEncoded +0xc 0x00000000(Win10) ++++++++(Win7)
|
||||
// _RTL_INVERTED_FUNCTION_TABLE_ENTRY[0] +0x10 ntdll.dll(win10) or The smallest base module
|
||||
// ImageBase +0x10 ++++++++
|
||||
// ImageSize +0x14 ++++++++
|
||||
// SEHandlerCount +0x18 ++++++++
|
||||
// NextEntrySEHandlerTableEncoded +0x1c ++++++++(Win10) ????????(Win7)
|
||||
// _RTL_INVERTED_FUNCTION_TABLE_ENTRY[1] ... ...
|
||||
// ......
|
||||
HMODULE hModule = nullptr, hNtdll = GetModuleHandleW(L"ntdll.dll");
|
||||
PIMAGE_NT_HEADERS NtdllHeaders = RtlImageNtHeader(hNtdll), ModuleHeaders = nullptr;
|
||||
_RTL_INVERTED_FUNCTION_TABLE_ENTRY_WIN7_32 entry{};
|
||||
LPCSTR lpSectionName = ".data";
|
||||
SEARCH_CONTEXT SearchContext{ SearchContext.MemoryBuffer = &entry,SearchContext.BufferLength = sizeof(entry) };
|
||||
PLIST_ENTRY ListHead = &NtCurrentPeb()->Ldr->InMemoryOrderModuleList,
|
||||
ListEntry = ListHead->Flink;
|
||||
PLDR_DATA_TABLE_ENTRY CurEntry = nullptr;
|
||||
DWORD SEHTable, SEHCount;
|
||||
BYTE Offset = 0x20; //sizeof(_RTL_INVERTED_FUNCTION_TABLE_ENTRY)*2
|
||||
|
||||
if (RtlIsWindowsVersionOrGreater(6, 3, 0)) lpSectionName = ".mrdata";
|
||||
else if (!RtlIsWindowsVersionOrGreater(6, 2, 0)) Offset = 0xC;
|
||||
|
||||
while (ListEntry != ListHead) {
|
||||
CurEntry = CONTAINING_RECORD(ListEntry, LDR_DATA_TABLE_ENTRY, InMemoryOrderLinks);
|
||||
ListEntry = ListEntry->Flink;
|
||||
if (IsModuleUnloaded(CurEntry))continue; //skip unloaded module
|
||||
if (IsValidMemoryModuleHandle((HMEMORYMODULE)CurEntry->DllBase))continue; //skip our memory module.
|
||||
if (CurEntry->DllBase == hNtdll && Offset == 0x20)continue; //Win10 skip first entry, if the base of ntdll is smallest.
|
||||
hModule = (HMODULE)(hModule ? min(hModule, CurEntry->DllBase) : CurEntry->DllBase);
|
||||
}
|
||||
ModuleHeaders = RtlImageNtHeader(hModule);
|
||||
if (!hModule || !ModuleHeaders || !hNtdll || !NtdllHeaders)return nullptr;
|
||||
|
||||
RtlCaptureImageExceptionValues(hModule, &SEHTable, &SEHCount);
|
||||
entry = { RtlEncodeSystemPointer((PVOID)SEHTable),(DWORD)hModule,ModuleHeaders->OptionalHeader.SizeOfImage,(PVOID)SEHCount };
|
||||
|
||||
while (NT_SUCCESS(RtlFindMemoryBlockFromModuleSection(hNtdll, lpSectionName, &SearchContext))) {
|
||||
PRTL_INVERTED_FUNCTION_TABLE_WIN7_32 tab = decltype(tab)(SearchContext.OutBufferPtr - Offset);
|
||||
|
||||
//Note: Same memory layout for RTL_INVERTED_FUNCTION_TABLE_ENTRY in Windows 10 x86 and x64.
|
||||
if (RtlIsWindowsVersionOrGreater(6, 2, 0) && tab->MaxCount == 0x200 && !tab->NextEntrySEHandlerTableEncoded) return tab;
|
||||
else if (tab->MaxCount == 0x200 && !tab->Overflow) return tab;
|
||||
}
|
||||
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
PVOID FindLdrpInvertedFunctionTable64() {
|
||||
// _RTL_INVERTED_FUNCTION_TABLE x64
|
||||
// Count +0x0 ????????
|
||||
// MaxCount +0x4 0x00000200
|
||||
// Epoch +0x8 ????????
|
||||
// OverFlow +0xc 0x00000000
|
||||
// _RTL_INVERTED_FUNCTION_TABLE_ENTRY[0] +0x10 ntdll.dll(win10) or The smallest base module
|
||||
// ExceptionDirectory +0x10 ++++++++
|
||||
// ImageBase +0x18 ++++++++
|
||||
// ImageSize +0x20 ++++++++
|
||||
// ExceptionDirectorySize +0x24 ++++++++
|
||||
// _RTL_INVERTED_FUNCTION_TABLE_ENTRY[1] ... ...
|
||||
// ......
|
||||
HMODULE hModule = nullptr, hNtdll = GetModuleHandleW(L"ntdll.dll");
|
||||
PIMAGE_NT_HEADERS NtdllHeaders = RtlImageNtHeader(hNtdll), ModuleHeaders = nullptr;
|
||||
_RTL_INVERTED_FUNCTION_TABLE_ENTRY_64 entry{};
|
||||
LPCSTR lpSectionName = ".data";
|
||||
PIMAGE_DATA_DIRECTORY dir = nullptr;
|
||||
SEARCH_CONTEXT SearchContext{ SearchContext.MemoryBuffer = &entry,SearchContext.BufferLength = sizeof(entry) };
|
||||
|
||||
//Windows 8
|
||||
if (RtlVerifyVersion(6, 2, 0, RTL_VERIFY_FLAGS_MAJOR_VERSION | RTL_VERIFY_FLAGS_MINOR_VERSION)) {
|
||||
hModule = hNtdll;
|
||||
ModuleHeaders = NtdllHeaders;
|
||||
//lpSectionName = ".data";
|
||||
}
|
||||
//Windows 8.1 ~ Windows 10
|
||||
else if (RtlIsWindowsVersionOrGreater(6, 3, 0)) {
|
||||
hModule = hNtdll;
|
||||
ModuleHeaders = NtdllHeaders;
|
||||
lpSectionName = ".mrdata";
|
||||
}
|
||||
else {
|
||||
PLIST_ENTRY ListHead = &NtCurrentPeb()->Ldr->InLoadOrderModuleList,
|
||||
ListEntry = ListHead->Flink;
|
||||
PLDR_DATA_TABLE_ENTRY CurEntry = nullptr;
|
||||
while (ListEntry != ListHead) {
|
||||
CurEntry = CONTAINING_RECORD(ListEntry, LDR_DATA_TABLE_ENTRY, InLoadOrderLinks);
|
||||
ListEntry = ListEntry->Flink;
|
||||
//Make sure the smallest base address is not our memory module
|
||||
if (IsValidMemoryModuleHandle((HMEMORYMODULE)CurEntry->DllBase))continue;
|
||||
hModule = (HMODULE)(hModule ? min(hModule, CurEntry->DllBase) : CurEntry->DllBase);
|
||||
}
|
||||
ModuleHeaders = RtlImageNtHeader(hModule);
|
||||
}
|
||||
|
||||
if (!hModule || !ModuleHeaders || !hNtdll || !NtdllHeaders)return nullptr;
|
||||
dir = &ModuleHeaders->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_EXCEPTION];
|
||||
entry = {
|
||||
dir->Size ? decltype(entry.ExceptionDirectory)((size_t)hModule + dir->VirtualAddress) : nullptr ,
|
||||
(PVOID)hModule, ModuleHeaders->OptionalHeader.SizeOfImage,dir->Size
|
||||
};
|
||||
|
||||
while (NT_SUCCESS(RtlFindMemoryBlockFromModuleSection(hNtdll, lpSectionName, &SearchContext))) {
|
||||
PRTL_INVERTED_FUNCTION_TABLE_64 tab = decltype(tab)(SearchContext.OutBufferPtr - 0x10);
|
||||
if (RtlIsWindowsVersionOrGreater(6, 2, 0) && tab->MaxCount == 0x200 && !tab->Overflow) return tab;
|
||||
else if (tab->MaxCount == 0x200 && !tab->Epoch) return tab;
|
||||
}
|
||||
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
PLIST_ENTRY FindLdrpHashTable() {
|
||||
PLIST_ENTRY list = nullptr;
|
||||
PLIST_ENTRY head = &NtCurrentPeb()->Ldr->InInitializationOrderModuleList, entry = head->Flink;
|
||||
PLDR_DATA_TABLE_ENTRY CurEntry = nullptr;
|
||||
while (head != entry) {
|
||||
CurEntry = CONTAINING_RECORD(entry, LDR_DATA_TABLE_ENTRY, LDR_DATA_TABLE_ENTRY::InInitializationOrderLinks);
|
||||
entry = entry->Flink;
|
||||
if (CurEntry->HashLinks.Flink == &CurEntry->HashLinks)continue;
|
||||
list = CurEntry->HashLinks.Flink;
|
||||
if (list->Flink == &CurEntry->HashLinks) {
|
||||
list = (decltype(list))((size_t)CurEntry->HashLinks.Flink - LdrHashEntry(CurEntry->BaseDllName) * sizeof(_LIST_ENTRY));
|
||||
break;
|
||||
}
|
||||
list = nullptr;
|
||||
}
|
||||
return list;
|
||||
}
|
||||
|
||||
NTSTATUS InitializeLockHeld() {
|
||||
NTSTATUS status = STATUS_UNSUCCESSFUL;
|
||||
HANDLE hSection = nullptr;
|
||||
OBJECT_ATTRIBUTES oa;
|
||||
LARGE_INTEGER li;
|
||||
UNICODE_STRING us{};
|
||||
@@ -35,12 +210,26 @@ VOID InitializeLockHeld() {
|
||||
if (!NT_SUCCESS(status)) {
|
||||
if (status != STATUS_OBJECT_NAME_COLLISION) break;
|
||||
|
||||
HANDLE hSection2;
|
||||
status = NtOpenSection(
|
||||
&hSection,
|
||||
&hSection2,
|
||||
SECTION_ALL_ACCESS,
|
||||
&oa
|
||||
);
|
||||
if (!NT_SUCCESS(status))break;
|
||||
|
||||
SECTION_BASIC_INFORMATION sbi{};
|
||||
status = NtQuerySection(
|
||||
hSection2,
|
||||
SECTION_INFORMATION_CLASS::SectionBasicInformation,
|
||||
&sbi,
|
||||
sizeof(sbi),
|
||||
nullptr
|
||||
);
|
||||
|
||||
NtClose(hSection2);
|
||||
MmpGlobalDataPtr = (PMMP_GLOBAL_DATA)sbi.BaseAddress;
|
||||
break;
|
||||
}
|
||||
|
||||
PVOID BaseAddress = 0;
|
||||
@@ -57,8 +246,52 @@ VOID InitializeLockHeld() {
|
||||
0,
|
||||
PAGE_READWRITE
|
||||
);
|
||||
if (!NT_SUCCESS(status))break;
|
||||
|
||||
MmpGlobalDataPtr = (PMMP_GLOBAL_DATA)BaseAddress;
|
||||
|
||||
MmpGlobalDataPtr->MajorVersion = 1;
|
||||
MmpGlobalDataPtr->MinorVersion = 0;
|
||||
|
||||
MmpGlobalDataPtr->LdrpNtdllBase = RtlFindNtdllLdrEntry();
|
||||
MmpGlobalDataPtr->LdrpHashTable = FindLdrpHashTable();
|
||||
|
||||
MmpGlobalDataPtr->LdrpModuleBaseAddressIndex = FindLdrpModuleBaseAddressIndex();
|
||||
|
||||
MmpGlobalDataPtr->LdrpInvertedFunctionTable = FindLdrpInvertedFunctionTable();
|
||||
|
||||
MmpGlobalDataPtr->MmpFeatures = MEMORY_FEATURE_SUPPORT_VERSION | MEMORY_FEATURE_LDRP_HEAP | MEMORY_FEATURE_LDRP_HANDLE_TLS_DATA | MEMORY_FEATURE_LDRP_RELEASE_TLS_ENTRY;
|
||||
if (MmpGlobalDataPtr->LdrpModuleBaseAddressIndex)MmpGlobalDataPtr->MmpFeatures |= MEMORY_FEATURE_MODULE_BASEADDRESS_INDEX;
|
||||
if (MmpGlobalDataPtr->LdrpHashTable)MmpGlobalDataPtr->MmpFeatures |= MEMORY_FEATURE_LDRP_HASH_TABLE;
|
||||
if (MmpGlobalDataPtr->LdrpInvertedFunctionTable)MmpGlobalDataPtr->MmpFeatures |= MEMORY_FEATURE_INVERTED_FUNCTION_TABLE;
|
||||
|
||||
MmpTlsInitialize();
|
||||
|
||||
} while (false);
|
||||
|
||||
if (!NT_SUCCESS(status) && hSection)NtClose(hSection);
|
||||
RtlFreeUnicodeString(&us);
|
||||
return status;
|
||||
}
|
||||
|
||||
NTSTATUS NTAPI Initialize() {
|
||||
NTSTATUS status;
|
||||
|
||||
RtlAcquirePebLock();
|
||||
status = InitializeLockHeld();
|
||||
RtlReleasePebLock();
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
#ifdef _USRDLL
|
||||
BOOL APIENTRY DllMain(HMODULE hModule, DWORD ul_reason_for_call, LPVOID lpReserved) {
|
||||
if (ul_reason_for_call == DLL_PROCESS_ATTACH) {
|
||||
return NT_SUCCESS(Initialize());
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
#else
|
||||
const NTSTATUS Initializer = Initialize();
|
||||
#endif
|
||||
|
||||
@@ -1,16 +1,5 @@
|
||||
#include "stdafx.h"
|
||||
|
||||
int NTAPI RtlCaptureImageExceptionValues(PVOID BaseAddress, PDWORD SEHandlerTable, PDWORD SEHandlerCount);
|
||||
|
||||
static __forceinline bool NTAPI RtlIsModuleUnloaded(PLDR_DATA_TABLE_ENTRY entry) {
|
||||
if (RtlIsWindowsVersionOrGreater(6, 2, 0)) {
|
||||
return PLDR_DATA_TABLE_ENTRY_WIN8(entry)->DdagNode->State == LdrModulesUnloaded;
|
||||
}
|
||||
else {
|
||||
return entry->DllBase == nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
static VOID NTAPI RtlpInsertInvertedFunctionTable(IN PRTL_INVERTED_FUNCTION_TABLE InvertedTable, IN PVOID ImageBase, IN ULONG SizeOfImage) {
|
||||
#ifdef _WIN64
|
||||
ULONG CurrentSize;
|
||||
@@ -147,152 +136,6 @@ static VOID NTAPI RtlpRemoveInvertedFunctionTable(IN PRTL_INVERTED_FUNCTION_TABL
|
||||
return;
|
||||
}
|
||||
|
||||
int NTAPI RtlCaptureImageExceptionValues(PVOID BaseAddress, PDWORD SEHandlerTable, PDWORD SEHandlerCount) {
|
||||
PIMAGE_LOAD_CONFIG_DIRECTORY pLoadConfigDirectory;
|
||||
PIMAGE_COR20_HEADER pCor20;
|
||||
ULONG Size;
|
||||
|
||||
//check if no seh
|
||||
if (RtlImageNtHeader(BaseAddress)->OptionalHeader.DllCharacteristics & IMAGE_DLLCHARACTERISTICS_NO_SEH) {
|
||||
*SEHandlerTable = *SEHandlerCount = -1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
//get seh table and count
|
||||
pLoadConfigDirectory = (decltype(pLoadConfigDirectory))RtlImageDirectoryEntryToData(BaseAddress, TRUE, IMAGE_DIRECTORY_ENTRY_LOAD_CONFIG, &Size);
|
||||
if (pLoadConfigDirectory) {
|
||||
if (Size == 0x40 && pLoadConfigDirectory->Size >= 0x48u) {
|
||||
if (pLoadConfigDirectory->SEHandlerTable && pLoadConfigDirectory->SEHandlerCount) {
|
||||
*SEHandlerTable = pLoadConfigDirectory->SEHandlerTable;
|
||||
return *SEHandlerCount = pLoadConfigDirectory->SEHandlerCount;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//is .net core ?
|
||||
pCor20 = (decltype(pCor20))RtlImageDirectoryEntryToData(BaseAddress, TRUE, IMAGE_DIRECTORY_ENTRY_COM_DESCRIPTOR, &Size);
|
||||
*SEHandlerTable = *SEHandlerCount = ((pCor20 && pCor20->Flags & 1) ? -1 : 0);
|
||||
return 0;
|
||||
}
|
||||
|
||||
PVOID FindLdrpInvertedFunctionTable32() {
|
||||
// _RTL_INVERTED_FUNCTION_TABLE x86
|
||||
// Count +0x0 ????????
|
||||
// MaxCount +0x4 0x00000200
|
||||
// Overflow +0x8 0x00000000(Win7) ????????(Win10)
|
||||
// NextEntrySEHandlerTableEncoded +0xc 0x00000000(Win10) ++++++++(Win7)
|
||||
// _RTL_INVERTED_FUNCTION_TABLE_ENTRY[0] +0x10 ntdll.dll(win10) or The smallest base module
|
||||
// ImageBase +0x10 ++++++++
|
||||
// ImageSize +0x14 ++++++++
|
||||
// SEHandlerCount +0x18 ++++++++
|
||||
// NextEntrySEHandlerTableEncoded +0x1c ++++++++(Win10) ????????(Win7)
|
||||
// _RTL_INVERTED_FUNCTION_TABLE_ENTRY[1] ... ...
|
||||
// ......
|
||||
HMODULE hModule = nullptr, hNtdll = GetModuleHandleW(L"ntdll.dll");
|
||||
PIMAGE_NT_HEADERS NtdllHeaders = RtlImageNtHeader(hNtdll), ModuleHeaders = nullptr;
|
||||
_RTL_INVERTED_FUNCTION_TABLE_ENTRY_WIN7_32 entry{};
|
||||
LPCSTR lpSectionName = ".data";
|
||||
SEARCH_CONTEXT SearchContext{ SearchContext.MemoryBuffer = &entry,SearchContext.BufferLength = sizeof(entry) };
|
||||
PLIST_ENTRY ListHead = &NtCurrentPeb()->Ldr->InMemoryOrderModuleList,
|
||||
ListEntry = ListHead->Flink;
|
||||
PLDR_DATA_TABLE_ENTRY CurEntry = nullptr;
|
||||
DWORD SEHTable, SEHCount;
|
||||
BYTE Offset = 0x20; //sizeof(_RTL_INVERTED_FUNCTION_TABLE_ENTRY)*2
|
||||
|
||||
if (RtlIsWindowsVersionOrGreater(6, 3, 0)) lpSectionName = ".mrdata";
|
||||
else if (!RtlIsWindowsVersionOrGreater(6, 2, 0)) Offset = 0xC;
|
||||
|
||||
while (ListEntry != ListHead) {
|
||||
CurEntry = CONTAINING_RECORD(ListEntry, LDR_DATA_TABLE_ENTRY, InMemoryOrderLinks);
|
||||
ListEntry = ListEntry->Flink;
|
||||
if (RtlIsModuleUnloaded(CurEntry))continue; //skip unloaded module
|
||||
if (IsValidMemoryModuleHandle((HMEMORYMODULE)CurEntry->DllBase))continue; //skip our memory module.
|
||||
if (CurEntry->DllBase == hNtdll && Offset == 0x20)continue; //Win10 skip first entry, if the base of ntdll is smallest.
|
||||
hModule = (HMODULE)(hModule ? min(hModule, CurEntry->DllBase) : CurEntry->DllBase);
|
||||
}
|
||||
ModuleHeaders = RtlImageNtHeader(hModule);
|
||||
if (!hModule || !ModuleHeaders || !hNtdll || !NtdllHeaders)return nullptr;
|
||||
|
||||
RtlCaptureImageExceptionValues(hModule, &SEHTable, &SEHCount);
|
||||
entry = { RtlEncodeSystemPointer((PVOID)SEHTable),(DWORD)hModule,ModuleHeaders->OptionalHeader.SizeOfImage,(PVOID)SEHCount };
|
||||
|
||||
while (NT_SUCCESS(RtlFindMemoryBlockFromModuleSection(hNtdll, lpSectionName, &SearchContext))) {
|
||||
PRTL_INVERTED_FUNCTION_TABLE_WIN7_32 tab = decltype(tab)(SearchContext.OutBufferPtr - Offset);
|
||||
|
||||
//Note: Same memory layout for RTL_INVERTED_FUNCTION_TABLE_ENTRY in Windows 10 x86 and x64.
|
||||
if (RtlIsWindowsVersionOrGreater(6, 2, 0) && tab->MaxCount == 0x200 && !tab->NextEntrySEHandlerTableEncoded) return tab;
|
||||
else if (tab->MaxCount == 0x200 && !tab->Overflow) return tab;
|
||||
}
|
||||
|
||||
return nullptr;
|
||||
}
|
||||
PVOID FindLdrpInvertedFunctionTable64() {
|
||||
// _RTL_INVERTED_FUNCTION_TABLE x64
|
||||
// Count +0x0 ????????
|
||||
// MaxCount +0x4 0x00000200
|
||||
// Epoch +0x8 ????????
|
||||
// OverFlow +0xc 0x00000000
|
||||
// _RTL_INVERTED_FUNCTION_TABLE_ENTRY[0] +0x10 ntdll.dll(win10) or The smallest base module
|
||||
// ExceptionDirectory +0x10 ++++++++
|
||||
// ImageBase +0x18 ++++++++
|
||||
// ImageSize +0x20 ++++++++
|
||||
// ExceptionDirectorySize +0x24 ++++++++
|
||||
// _RTL_INVERTED_FUNCTION_TABLE_ENTRY[1] ... ...
|
||||
// ......
|
||||
HMODULE hModule = nullptr, hNtdll = GetModuleHandleW(L"ntdll.dll");
|
||||
PIMAGE_NT_HEADERS NtdllHeaders = RtlImageNtHeader(hNtdll), ModuleHeaders = nullptr;
|
||||
_RTL_INVERTED_FUNCTION_TABLE_ENTRY_64 entry{};
|
||||
LPCSTR lpSectionName = ".data";
|
||||
PIMAGE_DATA_DIRECTORY dir = nullptr;
|
||||
SEARCH_CONTEXT SearchContext{ SearchContext.MemoryBuffer = &entry,SearchContext.BufferLength = sizeof(entry) };
|
||||
|
||||
//Windows 8
|
||||
if (RtlVerifyVersion(6, 2, 0, RTL_VERIFY_FLAGS_MAJOR_VERSION | RTL_VERIFY_FLAGS_MINOR_VERSION)) {
|
||||
hModule = hNtdll;
|
||||
ModuleHeaders = NtdllHeaders;
|
||||
//lpSectionName = ".data";
|
||||
}
|
||||
//Windows 8.1 ~ Windows 10
|
||||
else if (RtlIsWindowsVersionOrGreater(6, 3, 0)) {
|
||||
hModule = hNtdll;
|
||||
ModuleHeaders = NtdllHeaders;
|
||||
lpSectionName = ".mrdata";
|
||||
}
|
||||
else {
|
||||
PLIST_ENTRY ListHead = &NtCurrentPeb()->Ldr->InLoadOrderModuleList,
|
||||
ListEntry = ListHead->Flink;
|
||||
PLDR_DATA_TABLE_ENTRY CurEntry = nullptr;
|
||||
while (ListEntry != ListHead) {
|
||||
CurEntry = CONTAINING_RECORD(ListEntry, LDR_DATA_TABLE_ENTRY, InLoadOrderLinks);
|
||||
ListEntry = ListEntry->Flink;
|
||||
//Make sure the smallest base address is not our memory module
|
||||
if (IsValidMemoryModuleHandle((HMEMORYMODULE)CurEntry->DllBase))continue;
|
||||
hModule = (HMODULE)(hModule ? min(hModule, CurEntry->DllBase) : CurEntry->DllBase);
|
||||
}
|
||||
ModuleHeaders = RtlImageNtHeader(hModule);
|
||||
}
|
||||
|
||||
if (!hModule || !ModuleHeaders || !hNtdll || !NtdllHeaders)return nullptr;
|
||||
dir = &ModuleHeaders->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_EXCEPTION];
|
||||
entry = {
|
||||
dir->Size ? decltype(entry.ExceptionDirectory)((size_t)hModule + dir->VirtualAddress) : nullptr ,
|
||||
(PVOID)hModule, ModuleHeaders->OptionalHeader.SizeOfImage,dir->Size
|
||||
};
|
||||
|
||||
while (NT_SUCCESS(RtlFindMemoryBlockFromModuleSection(hNtdll, lpSectionName, &SearchContext))) {
|
||||
PRTL_INVERTED_FUNCTION_TABLE_64 tab = decltype(tab)(SearchContext.OutBufferPtr - 0x10);
|
||||
if (RtlIsWindowsVersionOrGreater(6, 2, 0) && tab->MaxCount == 0x200 && !tab->Overflow) return tab;
|
||||
else if (tab->MaxCount == 0x200 && !tab->Epoch) return tab;
|
||||
}
|
||||
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
|
||||
PVOID NTAPI RtlFindLdrpInvertedFunctionTable() {
|
||||
static PVOID LdrpInvertedFunctionTable = FindLdrpInvertedFunctionTable();
|
||||
return LdrpInvertedFunctionTable;
|
||||
}
|
||||
static NTSTATUS NTAPI RtlProtectMrdata(IN SIZE_T Protect) {
|
||||
static PVOID MrdataBase = nullptr;
|
||||
static SIZE_T size = 0;
|
||||
@@ -303,7 +146,7 @@ static NTSTATUS NTAPI RtlProtectMrdata(IN SIZE_T Protect) {
|
||||
|
||||
if (!MrdataBase) {
|
||||
MEMORY_BASIC_INFORMATION mbi{};
|
||||
status = NtQueryVirtualMemory(GetCurrentProcess(), RtlFindLdrpInvertedFunctionTable(), MemoryBasicInformation, &mbi, sizeof(mbi), nullptr);
|
||||
status = NtQueryVirtualMemory(GetCurrentProcess(), MmpGlobalDataPtr->LdrpInvertedFunctionTable, MemoryBasicInformation, &mbi, sizeof(mbi), nullptr);
|
||||
if (!NT_SUCCESS(status))return status;
|
||||
MrdataBase = mbi.BaseAddress;
|
||||
size = mbi.RegionSize;
|
||||
@@ -315,7 +158,7 @@ static NTSTATUS NTAPI RtlProtectMrdata(IN SIZE_T Protect) {
|
||||
}
|
||||
|
||||
NTSTATUS NTAPI RtlInsertInvertedFunctionTable(IN PVOID BaseAddress, IN size_t ImageSize) {
|
||||
static auto table = PRTL_INVERTED_FUNCTION_TABLE(RtlFindLdrpInvertedFunctionTable());
|
||||
auto table = PRTL_INVERTED_FUNCTION_TABLE(MmpGlobalDataPtr->LdrpInvertedFunctionTable);
|
||||
if (!table)return STATUS_NOT_SUPPORTED;
|
||||
bool need_virtual_protect = RtlIsWindowsVersionOrGreater(6, 3, 0);
|
||||
NTSTATUS status;
|
||||
@@ -334,7 +177,7 @@ NTSTATUS NTAPI RtlInsertInvertedFunctionTable(IN PVOID BaseAddress, IN size_t Im
|
||||
}
|
||||
|
||||
NTSTATUS NTAPI RtlRemoveInvertedFunctionTable(IN PVOID ImageBase) {
|
||||
static auto table = PRTL_INVERTED_FUNCTION_TABLE(RtlFindLdrpInvertedFunctionTable());
|
||||
auto table = PRTL_INVERTED_FUNCTION_TABLE(MmpGlobalDataPtr->LdrpInvertedFunctionTable);
|
||||
bool need_virtual_protect = RtlIsWindowsVersionOrGreater(6, 3, 0);
|
||||
NTSTATUS status;
|
||||
|
||||
|
||||
@@ -52,14 +52,5 @@ typedef RTL_INVERTED_FUNCTION_TABLE_WIN7_32 _RTL_INVERTED_FUNCTION_TABLE, RTL_IN
|
||||
typedef _RTL_INVERTED_FUNCTION_TABLE_ENTRY_WIN7_32 _RTL_INVERTED_FUNCTION_TABLE_ENTRY, RTL_INVERTED_FUNCTION_TABLE_ENTRY, * PRTL_INVERTED_FUNCTION_TABLE_ENTRY;
|
||||
#endif
|
||||
|
||||
PVOID NTAPI RtlFindLdrpInvertedFunctionTable();
|
||||
|
||||
NTSTATUS NTAPI RtlInsertInvertedFunctionTable(IN PVOID BaseAddress, IN size_t ImageSize);
|
||||
NTSTATUS NTAPI RtlRemoveInvertedFunctionTable(IN PVOID ImageBase);
|
||||
|
||||
|
||||
#ifdef _WIN64
|
||||
#define FindLdrpInvertedFunctionTable FindLdrpInvertedFunctionTable64
|
||||
#else
|
||||
#define FindLdrpInvertedFunctionTable FindLdrpInvertedFunctionTable32
|
||||
#endif
|
||||
|
||||
@@ -254,7 +254,7 @@ NTSTATUS NTAPI RtlGetReferenceCount(IN PMEMORYMODULE pModule, OUT PULONG Count)
|
||||
|
||||
VOID NTAPI RtlInsertMemoryTableEntry(IN PLDR_DATA_TABLE_ENTRY LdrEntry) {
|
||||
PPEB_LDR_DATA PebData = NtCurrentPeb()->Ldr;
|
||||
PLIST_ENTRY LdrpHashTable = RtlFindLdrpHashTable();
|
||||
PLIST_ENTRY LdrpHashTable = MmpGlobalDataPtr->LdrpHashTable;
|
||||
ULONG i;
|
||||
|
||||
/* Insert into hash table */
|
||||
@@ -319,26 +319,6 @@ ULONG NTAPI LdrHashEntry(IN UNICODE_STRING& str, IN bool _xor) {
|
||||
return result;
|
||||
}
|
||||
|
||||
PLIST_ENTRY NTAPI RtlFindLdrpHashTable() {
|
||||
static PLIST_ENTRY list = nullptr;
|
||||
if (list) return list;
|
||||
|
||||
PLIST_ENTRY head = &NtCurrentPeb()->Ldr->InInitializationOrderModuleList, entry = head->Flink;
|
||||
PLDR_DATA_TABLE_ENTRY CurEntry = nullptr;
|
||||
while (head != entry) {
|
||||
CurEntry = CONTAINING_RECORD(entry, LDR_DATA_TABLE_ENTRY, LDR_DATA_TABLE_ENTRY::InInitializationOrderLinks);
|
||||
entry = entry->Flink;
|
||||
if (CurEntry->HashLinks.Flink == &CurEntry->HashLinks)continue;
|
||||
list = CurEntry->HashLinks.Flink;
|
||||
if (list->Flink == &CurEntry->HashLinks) {
|
||||
list = (decltype(list))((size_t)CurEntry->HashLinks.Flink - LdrHashEntry(CurEntry->BaseDllName) * sizeof(_LIST_ENTRY));
|
||||
break;
|
||||
}
|
||||
list = nullptr;
|
||||
}
|
||||
return list;
|
||||
}
|
||||
|
||||
size_t NTAPI LdrpDataTableEntrySize() {
|
||||
static size_t size = 0;
|
||||
if (size)return size;
|
||||
|
||||
@@ -334,8 +334,6 @@ typedef struct _LDR_DATA_TABLE_ENTRY_WIN10_2 {
|
||||
|
||||
ULONG NTAPI LdrHashEntry(IN UNICODE_STRING& str, IN bool _xor = true);
|
||||
|
||||
PLIST_ENTRY NTAPI RtlFindLdrpHashTable();
|
||||
|
||||
#define RtlInitializeListEntry(entry) ((entry)->Blink = (entry)->Flink = (entry))
|
||||
#define RtlInitializeSingleEntry(entry) ((entry->Next = (entry)))
|
||||
|
||||
|
||||
+2
-16
@@ -285,24 +285,10 @@ VOID NTAPI LdrUnloadDllMemoryAndExitThread(IN HMEMORYMODULE BaseAddress, IN DWOR
|
||||
RtlExitUserThread(dwExitCode);
|
||||
}
|
||||
|
||||
NTSTATUS NTAPI LdrQuerySystemMemoryModuleFeatures(OUT PDWORD pFeatures) {
|
||||
static DWORD features = 0;
|
||||
NTSTATUS NTAPI LdrQuerySystemMemoryModuleFeatures(_Out_ PDWORD pFeatures) {
|
||||
NTSTATUS status = STATUS_SUCCESS;
|
||||
PVOID pfn = nullptr;
|
||||
bool value = false;
|
||||
__try {
|
||||
if (features) {
|
||||
*pFeatures = features;
|
||||
return status;
|
||||
}
|
||||
|
||||
if (RtlFindLdrpModuleBaseAddressIndex())features |= MEMORY_FEATURE_MODULE_BASEADDRESS_INDEX;
|
||||
if (RtlFindLdrpHashTable())features |= MEMORY_FEATURE_LDRP_HASH_TABLE;
|
||||
if (RtlFindLdrpInvertedFunctionTable())features |= MEMORY_FEATURE_INVERTED_FUNCTION_TABLE;
|
||||
features |= MEMORY_FEATURE_LDRP_HEAP | MEMORY_FEATURE_LDRP_HANDLE_TLS_DATA | MEMORY_FEATURE_LDRP_RELEASE_TLS_ENTRY;
|
||||
|
||||
if (features)features |= MEMORY_FEATURE_SUPPORT_VERSION;
|
||||
*pFeatures = features;
|
||||
*pFeatures = MmpGlobalDataPtr->MmpFeatures;
|
||||
}
|
||||
__except (EXCEPTION_EXECUTE_HANDLER) {
|
||||
status = GetExceptionCode();
|
||||
|
||||
@@ -17,7 +17,7 @@ NTSTATUS NTAPI LdrLoadDllMemory(
|
||||
#define MEMORY_FEATURE_ALL 0x0000007f
|
||||
|
||||
//Get the implementation of the currently running operating system.
|
||||
NTSTATUS NTAPI LdrQuerySystemMemoryModuleFeatures(OUT PDWORD pFeatures);
|
||||
NTSTATUS NTAPI LdrQuerySystemMemoryModuleFeatures(_Out_ PDWORD pFeatures);
|
||||
|
||||
|
||||
/*
|
||||
@@ -78,6 +78,7 @@ NTSTATUS NTAPI LdrLoadDllMemoryExA(
|
||||
//Unload modules previously loaded from memory
|
||||
NTSTATUS NTAPI LdrUnloadDllMemory(IN HMEMORYMODULE BaseAddress);
|
||||
|
||||
#ifndef _USRDLL
|
||||
#ifdef _WIN64
|
||||
#pragma comment(linker,"/export:LdrUnloadDllMemoryAndExitThread")
|
||||
#pragma comment(linker,"/export:FreeLibraryMemoryAndExitThread=LdrUnloadDllMemoryAndExitThread")
|
||||
@@ -85,8 +86,8 @@ NTSTATUS NTAPI LdrUnloadDllMemory(IN HMEMORYMODULE BaseAddress);
|
||||
#pragma comment(linker,"/export:LdrUnloadDllMemoryAndExitThread=_LdrUnloadDllMemoryAndExitThread@8")
|
||||
#pragma comment(linker,"/export:FreeLibraryMemoryAndExitThread=_LdrUnloadDllMemoryAndExitThread@8")
|
||||
#endif
|
||||
//FreeLibraryMemoryAndExitThread = GetProcAddress(GetModuleHandleW(nullptr), "FreeLibraryMemoryAndExitThread");
|
||||
//FreeLibraryMemoryAndExitThread(hModule, 0);
|
||||
#endif
|
||||
|
||||
extern "C" {
|
||||
__declspec(noreturn) VOID NTAPI LdrUnloadDllMemoryAndExitThread(IN HMEMORYMODULE BaseAddress, IN DWORD dwExitCode);
|
||||
}
|
||||
|
||||
@@ -1,10 +1,26 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<Project DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||
<ItemGroup Label="ProjectConfigurations">
|
||||
<ProjectConfiguration Include="DebugDll|Win32">
|
||||
<Configuration>DebugDll</Configuration>
|
||||
<Platform>Win32</Platform>
|
||||
</ProjectConfiguration>
|
||||
<ProjectConfiguration Include="DebugDll|x64">
|
||||
<Configuration>DebugDll</Configuration>
|
||||
<Platform>x64</Platform>
|
||||
</ProjectConfiguration>
|
||||
<ProjectConfiguration Include="Debug|Win32">
|
||||
<Configuration>Debug</Configuration>
|
||||
<Platform>Win32</Platform>
|
||||
</ProjectConfiguration>
|
||||
<ProjectConfiguration Include="ReleaseDll|Win32">
|
||||
<Configuration>ReleaseDll</Configuration>
|
||||
<Platform>Win32</Platform>
|
||||
</ProjectConfiguration>
|
||||
<ProjectConfiguration Include="ReleaseDll|x64">
|
||||
<Configuration>ReleaseDll</Configuration>
|
||||
<Platform>x64</Platform>
|
||||
</ProjectConfiguration>
|
||||
<ProjectConfiguration Include="Release|Win32">
|
||||
<Configuration>Release</Configuration>
|
||||
<Platform>Win32</Platform>
|
||||
@@ -77,6 +93,7 @@
|
||||
<ClInclude Include="LoadDllMemoryApi.h" />
|
||||
<ClInclude Include="MemoryModule.h" />
|
||||
<ClInclude Include="MmpDotNet.h" />
|
||||
<ClInclude Include="MmpGlobalData.h" />
|
||||
<ClInclude Include="MmpTls.h" />
|
||||
<ClInclude Include="Loader.h" />
|
||||
<ClInclude Include="BaseAddressIndex.h" />
|
||||
@@ -87,6 +104,7 @@
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<None Include="..\README.md" />
|
||||
<None Include="MemoryModulePP.def" />
|
||||
</ItemGroup>
|
||||
<PropertyGroup Label="Globals">
|
||||
<VCProjectVersion>16.0</VCProjectVersion>
|
||||
@@ -103,6 +121,12 @@
|
||||
<PlatformToolset>v142</PlatformToolset>
|
||||
<CharacterSet>Unicode</CharacterSet>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='DebugDll|Win32'" Label="Configuration">
|
||||
<ConfigurationType>DynamicLibrary</ConfigurationType>
|
||||
<UseDebugLibraries>true</UseDebugLibraries>
|
||||
<PlatformToolset>v142</PlatformToolset>
|
||||
<CharacterSet>Unicode</CharacterSet>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
|
||||
<ConfigurationType>StaticLibrary</ConfigurationType>
|
||||
<UseDebugLibraries>false</UseDebugLibraries>
|
||||
@@ -110,6 +134,13 @@
|
||||
<WholeProgramOptimization>true</WholeProgramOptimization>
|
||||
<CharacterSet>Unicode</CharacterSet>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='ReleaseDll|Win32'" Label="Configuration">
|
||||
<ConfigurationType>DynamicLibrary</ConfigurationType>
|
||||
<UseDebugLibraries>false</UseDebugLibraries>
|
||||
<PlatformToolset>v142</PlatformToolset>
|
||||
<WholeProgramOptimization>true</WholeProgramOptimization>
|
||||
<CharacterSet>Unicode</CharacterSet>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">
|
||||
<ConfigurationType>StaticLibrary</ConfigurationType>
|
||||
<UseDebugLibraries>true</UseDebugLibraries>
|
||||
@@ -117,6 +148,13 @@
|
||||
<CharacterSet>Unicode</CharacterSet>
|
||||
<SpectreMitigation>false</SpectreMitigation>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='DebugDll|x64'" Label="Configuration">
|
||||
<ConfigurationType>DynamicLibrary</ConfigurationType>
|
||||
<UseDebugLibraries>true</UseDebugLibraries>
|
||||
<PlatformToolset>v142</PlatformToolset>
|
||||
<CharacterSet>Unicode</CharacterSet>
|
||||
<SpectreMitigation>false</SpectreMitigation>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
|
||||
<ConfigurationType>StaticLibrary</ConfigurationType>
|
||||
<UseDebugLibraries>false</UseDebugLibraries>
|
||||
@@ -124,6 +162,13 @@
|
||||
<WholeProgramOptimization>true</WholeProgramOptimization>
|
||||
<CharacterSet>Unicode</CharacterSet>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='ReleaseDll|x64'" Label="Configuration">
|
||||
<ConfigurationType>DynamicLibrary</ConfigurationType>
|
||||
<UseDebugLibraries>false</UseDebugLibraries>
|
||||
<PlatformToolset>v142</PlatformToolset>
|
||||
<WholeProgramOptimization>true</WholeProgramOptimization>
|
||||
<CharacterSet>Unicode</CharacterSet>
|
||||
</PropertyGroup>
|
||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
|
||||
<ImportGroup Label="ExtensionSettings">
|
||||
<Import Project="$(VCTargetsPath)\BuildCustomizations\masm.props" />
|
||||
@@ -133,32 +178,65 @@
|
||||
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
|
||||
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
|
||||
</ImportGroup>
|
||||
<ImportGroup Condition="'$(Configuration)|$(Platform)'=='DebugDll|Win32'" Label="PropertySheets">
|
||||
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
|
||||
</ImportGroup>
|
||||
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
|
||||
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
|
||||
</ImportGroup>
|
||||
<ImportGroup Condition="'$(Configuration)|$(Platform)'=='ReleaseDll|Win32'" Label="PropertySheets">
|
||||
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
|
||||
</ImportGroup>
|
||||
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
|
||||
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
|
||||
</ImportGroup>
|
||||
<ImportGroup Condition="'$(Configuration)|$(Platform)'=='DebugDll|x64'" Label="PropertySheets">
|
||||
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
|
||||
</ImportGroup>
|
||||
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
|
||||
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
|
||||
</ImportGroup>
|
||||
<ImportGroup Condition="'$(Configuration)|$(Platform)'=='ReleaseDll|x64'" Label="PropertySheets">
|
||||
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
|
||||
</ImportGroup>
|
||||
<PropertyGroup Label="UserMacros" />
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
|
||||
<LinkIncremental>true</LinkIncremental>
|
||||
<IncludePath>$(VC_IncludePath);$(WindowsSDK_IncludePath);$(SolutionDir);</IncludePath>
|
||||
<OutDir>$(SolutionDir)$(Configuration)\</OutDir>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='DebugDll|Win32'">
|
||||
<LinkIncremental>true</LinkIncremental>
|
||||
<IncludePath>$(VC_IncludePath);$(WindowsSDK_IncludePath);$(SolutionDir);</IncludePath>
|
||||
<OutDir>$(SolutionDir)Debug\</OutDir>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
|
||||
<LinkIncremental>true</LinkIncremental>
|
||||
<IncludePath>$(VC_IncludePath);$(WindowsSDK_IncludePath);$(SolutionDir);</IncludePath>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='DebugDll|x64'">
|
||||
<LinkIncremental>true</LinkIncremental>
|
||||
<IncludePath>$(VC_IncludePath);$(WindowsSDK_IncludePath);$(SolutionDir);</IncludePath>
|
||||
<OutDir>$(SolutionDir)$(Platform)\Debug\</OutDir>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
|
||||
<LinkIncremental>false</LinkIncremental>
|
||||
<IncludePath>$(VC_IncludePath);$(WindowsSDK_IncludePath);$(SolutionDir);</IncludePath>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='ReleaseDll|Win32'">
|
||||
<LinkIncremental>false</LinkIncremental>
|
||||
<IncludePath>$(VC_IncludePath);$(WindowsSDK_IncludePath);$(SolutionDir);</IncludePath>
|
||||
<OutDir>$(SolutionDir)Release\</OutDir>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
|
||||
<LinkIncremental>false</LinkIncremental>
|
||||
<IncludePath>$(VC_IncludePath);$(WindowsSDK_IncludePath);$(SolutionDir);</IncludePath>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='ReleaseDll|x64'">
|
||||
<LinkIncremental>false</LinkIncremental>
|
||||
<IncludePath>$(VC_IncludePath);$(WindowsSDK_IncludePath);$(SolutionDir);</IncludePath>
|
||||
<OutDir>$(SolutionDir)$(Platform)\Release\</OutDir>
|
||||
</PropertyGroup>
|
||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
|
||||
<ClCompile>
|
||||
<PrecompiledHeader>NotUsing</PrecompiledHeader>
|
||||
@@ -174,6 +252,26 @@
|
||||
<Link>
|
||||
<SubSystem>Windows</SubSystem>
|
||||
<GenerateDebugInformation>true</GenerateDebugInformation>
|
||||
<ModuleDefinitionFile>MemoryModulePP.def</ModuleDefinitionFile>
|
||||
</Link>
|
||||
</ItemDefinitionGroup>
|
||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='DebugDll|Win32'">
|
||||
<ClCompile>
|
||||
<PrecompiledHeader>NotUsing</PrecompiledHeader>
|
||||
<WarningLevel>Level3</WarningLevel>
|
||||
<SDLCheck>true</SDLCheck>
|
||||
<PreprocessorDefinitions>WIN32;_DEBUG;_USRDLL;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
<ConformanceMode>true</ConformanceMode>
|
||||
<PrecompiledHeaderFile>
|
||||
</PrecompiledHeaderFile>
|
||||
<PrecompiledHeaderOutputFile>
|
||||
</PrecompiledHeaderOutputFile>
|
||||
<RuntimeLibrary>MultiThreadedDebug</RuntimeLibrary>
|
||||
</ClCompile>
|
||||
<Link>
|
||||
<SubSystem>Windows</SubSystem>
|
||||
<GenerateDebugInformation>true</GenerateDebugInformation>
|
||||
<ModuleDefinitionFile>MemoryModulePP.def</ModuleDefinitionFile>
|
||||
</Link>
|
||||
</ItemDefinitionGroup>
|
||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
|
||||
@@ -191,6 +289,26 @@
|
||||
<Link>
|
||||
<SubSystem>Windows</SubSystem>
|
||||
<GenerateDebugInformation>true</GenerateDebugInformation>
|
||||
<ModuleDefinitionFile>MemoryModulePP.def</ModuleDefinitionFile>
|
||||
</Link>
|
||||
</ItemDefinitionGroup>
|
||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='DebugDll|x64'">
|
||||
<ClCompile>
|
||||
<PrecompiledHeader>NotUsing</PrecompiledHeader>
|
||||
<WarningLevel>Level3</WarningLevel>
|
||||
<SDLCheck>true</SDLCheck>
|
||||
<PreprocessorDefinitions>_DEBUG;_USRDLL;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
<ConformanceMode>true</ConformanceMode>
|
||||
<PrecompiledHeaderFile>
|
||||
</PrecompiledHeaderFile>
|
||||
<PrecompiledHeaderOutputFile>
|
||||
</PrecompiledHeaderOutputFile>
|
||||
<RuntimeLibrary>MultiThreadedDebug</RuntimeLibrary>
|
||||
</ClCompile>
|
||||
<Link>
|
||||
<SubSystem>Windows</SubSystem>
|
||||
<GenerateDebugInformation>true</GenerateDebugInformation>
|
||||
<ModuleDefinitionFile>MemoryModulePP.def</ModuleDefinitionFile>
|
||||
</Link>
|
||||
</ItemDefinitionGroup>
|
||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
|
||||
@@ -212,6 +330,30 @@
|
||||
<EnableCOMDATFolding>true</EnableCOMDATFolding>
|
||||
<OptimizeReferences>true</OptimizeReferences>
|
||||
<GenerateDebugInformation>true</GenerateDebugInformation>
|
||||
<ModuleDefinitionFile>MemoryModulePP.def</ModuleDefinitionFile>
|
||||
</Link>
|
||||
</ItemDefinitionGroup>
|
||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='ReleaseDll|Win32'">
|
||||
<ClCompile>
|
||||
<PrecompiledHeader>NotUsing</PrecompiledHeader>
|
||||
<WarningLevel>Level3</WarningLevel>
|
||||
<FunctionLevelLinking>true</FunctionLevelLinking>
|
||||
<IntrinsicFunctions>true</IntrinsicFunctions>
|
||||
<SDLCheck>true</SDLCheck>
|
||||
<PreprocessorDefinitions>WIN32;NDEBUG;_USRDLL;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
<ConformanceMode>true</ConformanceMode>
|
||||
<PrecompiledHeaderFile>
|
||||
</PrecompiledHeaderFile>
|
||||
<PrecompiledHeaderOutputFile>
|
||||
</PrecompiledHeaderOutputFile>
|
||||
<RuntimeLibrary>MultiThreaded</RuntimeLibrary>
|
||||
</ClCompile>
|
||||
<Link>
|
||||
<SubSystem>Windows</SubSystem>
|
||||
<EnableCOMDATFolding>true</EnableCOMDATFolding>
|
||||
<OptimizeReferences>true</OptimizeReferences>
|
||||
<GenerateDebugInformation>true</GenerateDebugInformation>
|
||||
<ModuleDefinitionFile>MemoryModulePP.def</ModuleDefinitionFile>
|
||||
</Link>
|
||||
</ItemDefinitionGroup>
|
||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
|
||||
@@ -233,6 +375,30 @@
|
||||
<EnableCOMDATFolding>true</EnableCOMDATFolding>
|
||||
<OptimizeReferences>true</OptimizeReferences>
|
||||
<GenerateDebugInformation>true</GenerateDebugInformation>
|
||||
<ModuleDefinitionFile>MemoryModulePP.def</ModuleDefinitionFile>
|
||||
</Link>
|
||||
</ItemDefinitionGroup>
|
||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='ReleaseDll|x64'">
|
||||
<ClCompile>
|
||||
<PrecompiledHeader>NotUsing</PrecompiledHeader>
|
||||
<WarningLevel>Level3</WarningLevel>
|
||||
<FunctionLevelLinking>true</FunctionLevelLinking>
|
||||
<IntrinsicFunctions>true</IntrinsicFunctions>
|
||||
<SDLCheck>true</SDLCheck>
|
||||
<PreprocessorDefinitions>NDEBUG;_USRDLL;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
<ConformanceMode>true</ConformanceMode>
|
||||
<PrecompiledHeaderFile>
|
||||
</PrecompiledHeaderFile>
|
||||
<PrecompiledHeaderOutputFile>
|
||||
</PrecompiledHeaderOutputFile>
|
||||
<RuntimeLibrary>MultiThreaded</RuntimeLibrary>
|
||||
</ClCompile>
|
||||
<Link>
|
||||
<SubSystem>Windows</SubSystem>
|
||||
<EnableCOMDATFolding>true</EnableCOMDATFolding>
|
||||
<OptimizeReferences>true</OptimizeReferences>
|
||||
<GenerateDebugInformation>true</GenerateDebugInformation>
|
||||
<ModuleDefinitionFile>MemoryModulePP.def</ModuleDefinitionFile>
|
||||
</Link>
|
||||
</ItemDefinitionGroup>
|
||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
|
||||
|
||||
@@ -221,10 +221,16 @@
|
||||
<ClInclude Include="..\3rdparty\phnt\include\winsta.h">
|
||||
<Filter>Header Files\3rdparty\phnt</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="MmpGlobalData.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<None Include="..\README.md">
|
||||
<Filter>Resource Files</Filter>
|
||||
</None>
|
||||
<None Include="MemoryModulePP.def">
|
||||
<Filter>Resource Files</Filter>
|
||||
</None>
|
||||
</ItemGroup>
|
||||
</Project>
|
||||
@@ -0,0 +1,13 @@
|
||||
LIBRARY
|
||||
EXPORTS
|
||||
LoadLibraryMemory
|
||||
LoadLibraryMemoryExA
|
||||
LoadLibraryMemoryExW
|
||||
FreeLibraryMemory
|
||||
|
||||
LdrLoadDllMemory
|
||||
LdrLoadDllMemoryExA
|
||||
LdrLoadDllMemoryExW
|
||||
LdrUnloadDllMemory
|
||||
LdrUnloadDllMemoryAndExitThread
|
||||
LdrQuerySystemMemoryModuleFeatures
|
||||
@@ -0,0 +1,29 @@
|
||||
#pragma once
|
||||
|
||||
typedef struct _MMP_GLOBAL_DATA {
|
||||
|
||||
WORD MajorVersion;
|
||||
WORD MinorVersion;
|
||||
|
||||
DWORD MmpFeatures;
|
||||
|
||||
//BaseAddressIndex.cpp
|
||||
PRTL_RB_TREE LdrpModuleBaseAddressIndex;
|
||||
|
||||
//InvertedFunctionTable.cpp
|
||||
PVOID LdrpInvertedFunctionTable;
|
||||
|
||||
//LdrEntry.cpp
|
||||
PLDR_DATA_TABLE_ENTRY LdrpNtdllBase;
|
||||
PLIST_ENTRY LdrpHashTable;
|
||||
|
||||
//MmpTls.cpp
|
||||
LIST_ENTRY MmpTlsList;
|
||||
RTL_BITMAP MmpTlsBitmap;
|
||||
SRWLOCK MmpTlsListLock;
|
||||
CRITICAL_SECTION MmpTlspLock;
|
||||
LIST_ENTRY MmpThreadLocalStoragePointer;
|
||||
DWORD MmpActiveThreadCount;
|
||||
}MMP_GLOBAL_DATA, * PMMP_GLOBAL_DATA;
|
||||
|
||||
extern PMMP_GLOBAL_DATA MmpGlobalDataPtr;
|
||||
+45
-59
@@ -42,11 +42,6 @@ typedef struct _TLS_ENTRY {
|
||||
PLDR_DATA_TABLE_ENTRY ModuleEntry;
|
||||
} TLS_ENTRY, * PTLS_ENTRY;
|
||||
|
||||
LIST_ENTRY MmpTlsList;
|
||||
RTL_BITMAP MmpTlsBitmap;
|
||||
SRWLOCK MmpTlsListLock;
|
||||
|
||||
|
||||
typedef struct _MMP_TLSP_RECORD {
|
||||
|
||||
LIST_ENTRY InMmpThreadLocalStoragePointer;
|
||||
@@ -60,11 +55,6 @@ typedef struct _MMP_TLSP_RECORD {
|
||||
PVOID* TlspMmpBlock;
|
||||
}MMP_TLSP_RECORD, * PMMP_TLSP_RECORD;
|
||||
|
||||
CRITICAL_SECTION MmpTlspLock;
|
||||
LIST_ENTRY MmpThreadLocalStoragePointer;
|
||||
DWORD MmpActiveThreadCount;
|
||||
|
||||
|
||||
decltype(&NtCreateThread) OriginNtCreateThread = NtCreateThread;
|
||||
decltype(&NtCreateThreadEx) OriginNtCreateThreadEx = NtCreateThreadEx;
|
||||
decltype(&NtSetInformationProcess) OriginNtSetInformationProcess = NtSetInformationProcess;
|
||||
@@ -169,7 +159,7 @@ DWORD NTAPI MmpUserThreadStart(LPVOID lpThreadParameter) {
|
||||
//
|
||||
// Allocate and replace ThreadLocalStoragePointer for new thread
|
||||
//
|
||||
EnterCriticalSection(&MmpTlspLock);
|
||||
EnterCriticalSection(&MmpGlobalDataPtr->MmpTlspLock);
|
||||
|
||||
record = PMMP_TLSP_RECORD(RtlAllocateHeap(RtlProcessHeap(), 0, sizeof(MMP_TLSP_RECORD)));
|
||||
if (record) {
|
||||
@@ -187,7 +177,7 @@ DWORD NTAPI MmpUserThreadStart(LPVOID lpThreadParameter) {
|
||||
|
||||
NtCurrentTeb()->ThreadLocalStoragePointer = record->TlspMmpBlock;
|
||||
|
||||
InsertTailList(&MmpThreadLocalStoragePointer, &record->InMmpThreadLocalStoragePointer);
|
||||
InsertTailList(&MmpGlobalDataPtr->MmpThreadLocalStoragePointer, &record->InMmpThreadLocalStoragePointer);
|
||||
success = true;
|
||||
}
|
||||
else {
|
||||
@@ -195,17 +185,17 @@ DWORD NTAPI MmpUserThreadStart(LPVOID lpThreadParameter) {
|
||||
}
|
||||
}
|
||||
|
||||
LeaveCriticalSection(&MmpTlspLock);
|
||||
LeaveCriticalSection(&MmpGlobalDataPtr->MmpTlspLock);
|
||||
|
||||
//
|
||||
// Handle MemoryModule Tls data
|
||||
//
|
||||
if (success) {
|
||||
RtlAcquireSRWLockShared(&MmpTlsListLock);
|
||||
RtlAcquireSRWLockShared(&MmpGlobalDataPtr->MmpTlsListLock);
|
||||
|
||||
auto ThreadLocalStoragePointer = (PVOID*)NtCurrentTeb()->ThreadLocalStoragePointer;
|
||||
PLIST_ENTRY entry = MmpTlsList.Flink;
|
||||
while (entry != &MmpTlsList) {
|
||||
PLIST_ENTRY entry = MmpGlobalDataPtr->MmpTlsList.Flink;
|
||||
while (entry != &MmpGlobalDataPtr->MmpTlsList) {
|
||||
|
||||
PTLS_ENTRY tls = CONTAINING_RECORD(entry, TLS_ENTRY, TlsEntryLinks);
|
||||
auto len = tls->TlsDirectory.EndAddressOfRawData - tls->TlsDirectory.StartAddressOfRawData;
|
||||
@@ -227,16 +217,16 @@ DWORD NTAPI MmpUserThreadStart(LPVOID lpThreadParameter) {
|
||||
entry = entry->Flink;
|
||||
}
|
||||
|
||||
RtlReleaseSRWLockShared(&MmpTlsListLock);
|
||||
RtlReleaseSRWLockShared(&MmpGlobalDataPtr->MmpTlsListLock);
|
||||
}
|
||||
|
||||
if (!success) {
|
||||
return ERROR_NOT_ENOUGH_MEMORY;
|
||||
}
|
||||
|
||||
EnterCriticalSection(&MmpTlspLock);
|
||||
++MmpActiveThreadCount;
|
||||
LeaveCriticalSection(&MmpTlspLock);
|
||||
EnterCriticalSection(&MmpGlobalDataPtr->MmpTlspLock);
|
||||
++MmpGlobalDataPtr->MmpActiveThreadCount;
|
||||
LeaveCriticalSection(&MmpGlobalDataPtr->MmpTlspLock);
|
||||
|
||||
__skip_tls:
|
||||
return Context.ThreadStartRoutine(Context.ThreadParameter);
|
||||
@@ -337,10 +327,10 @@ VOID NTAPI HookLdrShutdownThread(VOID) {
|
||||
//
|
||||
// Find our tlsp record
|
||||
//
|
||||
EnterCriticalSection(&MmpTlspLock);
|
||||
EnterCriticalSection(&MmpGlobalDataPtr->MmpTlspLock);
|
||||
|
||||
entry = MmpThreadLocalStoragePointer.Flink;
|
||||
while (entry != &MmpThreadLocalStoragePointer) {
|
||||
entry = MmpGlobalDataPtr->MmpThreadLocalStoragePointer.Flink;
|
||||
while (entry != &MmpGlobalDataPtr->MmpThreadLocalStoragePointer) {
|
||||
|
||||
auto p = CONTAINING_RECORD(entry, MMP_TLSP_RECORD, InMmpThreadLocalStoragePointer);
|
||||
if (p->UniqueThread == NtCurrentThreadId()) {
|
||||
@@ -359,19 +349,19 @@ VOID NTAPI HookLdrShutdownThread(VOID) {
|
||||
entry = entry->Flink;
|
||||
}
|
||||
|
||||
--MmpActiveThreadCount;
|
||||
--MmpGlobalDataPtr->MmpActiveThreadCount;
|
||||
|
||||
LeaveCriticalSection(&MmpTlspLock);
|
||||
LeaveCriticalSection(&MmpGlobalDataPtr->MmpTlspLock);
|
||||
|
||||
//
|
||||
// Free MemoryModule Tls data
|
||||
//
|
||||
RtlAcquireSRWLockExclusive(&MmpTlsListLock);
|
||||
RtlAcquireSRWLockExclusive(&MmpGlobalDataPtr->MmpTlsListLock);
|
||||
|
||||
if (record) {
|
||||
auto TlspMmpBlock = (PVOID*)record->TlspMmpBlock;
|
||||
entry = MmpTlsList.Flink;
|
||||
while (entry != &MmpTlsList) {
|
||||
entry = MmpGlobalDataPtr->MmpTlsList.Flink;
|
||||
while (entry != &MmpGlobalDataPtr->MmpTlsList) {
|
||||
|
||||
auto p = CONTAINING_RECORD(entry, TLS_ENTRY, TlsEntryLinks);
|
||||
RtlFreeHeap(RtlProcessHeap(), 0, TlspMmpBlock[p->TlsDirectory.Characteristics]);
|
||||
@@ -382,12 +372,12 @@ VOID NTAPI HookLdrShutdownThread(VOID) {
|
||||
RtlFreeHeap(RtlProcessHeap(), 0, TlspMmpBlock);
|
||||
}
|
||||
else {
|
||||
if (MmpTlsList.Flink != &MmpTlsList) {
|
||||
if (MmpGlobalDataPtr->MmpTlsList.Flink != &MmpGlobalDataPtr->MmpTlsList) {
|
||||
assert(false);
|
||||
}
|
||||
}
|
||||
|
||||
RtlReleaseSRWLockExclusive(&MmpTlsListLock);
|
||||
RtlReleaseSRWLockExclusive(&MmpGlobalDataPtr->MmpTlsListLock);
|
||||
|
||||
//
|
||||
// Call the original function
|
||||
@@ -443,7 +433,7 @@ BOOL NTAPI PreHookNtSetInformationProcess() {
|
||||
);
|
||||
|
||||
if (NT_SUCCESS(status)) {
|
||||
EnterCriticalSection(&MmpTlspLock);
|
||||
EnterCriticalSection(&MmpGlobalDataPtr->MmpTlspLock);
|
||||
for (DWORD i = 0; i < CurrentThreadCount; ++i) {
|
||||
auto const& LdrTls = ProcessTlsInformation->ThreadData[i];
|
||||
auto const& MmpTls = tmpTlsInformation->ThreadData[i];
|
||||
@@ -453,9 +443,9 @@ BOOL NTAPI PreHookNtSetInformationProcess() {
|
||||
record->TlspLdrBlock = LdrTls.TlsVector;
|
||||
record->TlspMmpBlock = MmpTls.TlsVector;
|
||||
record->UniqueThread = LdrTls.ThreadId;
|
||||
InsertTailList(&MmpThreadLocalStoragePointer, &record->InMmpThreadLocalStoragePointer);
|
||||
InsertTailList(&MmpGlobalDataPtr->MmpThreadLocalStoragePointer, &record->InMmpThreadLocalStoragePointer);
|
||||
}
|
||||
LeaveCriticalSection(&MmpTlspLock);
|
||||
LeaveCriticalSection(&MmpGlobalDataPtr->MmpTlspLock);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -557,14 +547,14 @@ NTSTATUS NTAPI HookNtSetInformationProcess(
|
||||
//
|
||||
// Modify our mapping
|
||||
//
|
||||
EnterCriticalSection(&MmpTlspLock);
|
||||
EnterCriticalSection(&MmpGlobalDataPtr->MmpTlspLock);
|
||||
for (auto i = 0; i < Tls->ThreadDataCount; ++i) {
|
||||
|
||||
bool found = false;
|
||||
PLIST_ENTRY entry = MmpThreadLocalStoragePointer.Flink;
|
||||
PLIST_ENTRY entry = MmpGlobalDataPtr->MmpThreadLocalStoragePointer.Flink;
|
||||
|
||||
// Find thread-spec tlsp
|
||||
while (entry != &MmpThreadLocalStoragePointer) {
|
||||
while (entry != &MmpGlobalDataPtr->MmpThreadLocalStoragePointer) {
|
||||
|
||||
PMMP_TLSP_RECORD j = CONTAINING_RECORD(entry, MMP_TLSP_RECORD, InMmpThreadLocalStoragePointer);
|
||||
|
||||
@@ -608,7 +598,7 @@ NTSTATUS NTAPI HookNtSetInformationProcess(
|
||||
ProcessTlsInformation->ThreadData[i].ThreadId = Tls->ThreadData[i].ThreadId;
|
||||
}
|
||||
}
|
||||
LeaveCriticalSection(&MmpTlspLock);
|
||||
LeaveCriticalSection(&MmpGlobalDataPtr->MmpTlspLock);
|
||||
|
||||
} while (false);
|
||||
|
||||
@@ -620,7 +610,7 @@ NTSTATUS NTAPI MmpAcquireTlsIndex(_Out_ PULONG TlsIndex) {
|
||||
|
||||
*TlsIndex = -1;
|
||||
|
||||
ULONG Index = RtlFindClearBitsAndSet(&MmpTlsBitmap, 1, 0);
|
||||
ULONG Index = RtlFindClearBitsAndSet(&MmpGlobalDataPtr->MmpTlsBitmap, 1, 0);
|
||||
if (Index != -1) {
|
||||
*TlsIndex = Index;
|
||||
return STATUS_SUCCESS;
|
||||
@@ -681,9 +671,9 @@ NTSTATUS NTAPI MmpAllocateTlsEntry(
|
||||
Entry->TlsDirectory.Characteristics =
|
||||
*PULONG(Entry->TlsDirectory.AddressOfIndex) = TlsIndex;
|
||||
|
||||
RtlAcquireSRWLockExclusive(&MmpTlsListLock);
|
||||
InsertTailList(&MmpTlsList, &Entry->TlsEntryLinks);
|
||||
RtlReleaseSRWLockExclusive(&MmpTlsListLock);
|
||||
RtlAcquireSRWLockExclusive(&MmpGlobalDataPtr->MmpTlsListLock);
|
||||
InsertTailList(&MmpGlobalDataPtr->MmpTlsList, &Entry->TlsEntryLinks);
|
||||
RtlReleaseSRWLockExclusive(&MmpGlobalDataPtr->MmpTlsListLock);
|
||||
|
||||
*lpTlsEntry = Entry;
|
||||
*lpTlsIndex = TlsIndex;
|
||||
@@ -692,20 +682,20 @@ NTSTATUS NTAPI MmpAllocateTlsEntry(
|
||||
|
||||
NTSTATUS NTAPI MmpReleaseTlsEntry(_In_ PLDR_DATA_TABLE_ENTRY lpModuleEntry) {
|
||||
|
||||
RtlAcquireSRWLockExclusive(&MmpTlsListLock);
|
||||
RtlAcquireSRWLockExclusive(&MmpGlobalDataPtr->MmpTlsListLock);
|
||||
|
||||
for (auto entry = MmpTlsList.Flink; entry != &MmpTlsList; entry = entry->Flink) {
|
||||
for (auto entry = MmpGlobalDataPtr->MmpTlsList.Flink; entry != &MmpGlobalDataPtr->MmpTlsList; entry = entry->Flink) {
|
||||
auto p = CONTAINING_RECORD(entry, TLS_ENTRY, TlsEntryLinks);
|
||||
if (p->ModuleEntry == lpModuleEntry) {
|
||||
RemoveEntryList(&p->TlsEntryLinks);
|
||||
RtlClearBit(&MmpTlsBitmap, p->TlsDirectory.Characteristics);
|
||||
RtlClearBit(&MmpGlobalDataPtr->MmpTlsBitmap, p->TlsDirectory.Characteristics);
|
||||
RtlFreeHeap(RtlProcessHeap(), 0, p);
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
RtlReleaseSRWLockExclusive(&MmpTlsListLock);
|
||||
RtlReleaseSRWLockExclusive(&MmpGlobalDataPtr->MmpTlsListLock);
|
||||
|
||||
return STATUS_SUCCESS;
|
||||
}
|
||||
@@ -738,7 +728,7 @@ NTSTATUS NTAPI MmpHandleTlsData(_In_ PLDR_DATA_TABLE_ENTRY lpModuleEntry) {
|
||||
return STATUS_INSUFFICIENT_RESOURCES;
|
||||
}
|
||||
|
||||
auto ThreadCount = MmpActiveThreadCount;
|
||||
auto ThreadCount = MmpGlobalDataPtr->MmpActiveThreadCount;
|
||||
auto success = true;
|
||||
auto Length = sizeof(PROCESS_TLS_INFORMATION) + (ThreadCount - 1) * sizeof(THREAD_TLS_INFORMATION);
|
||||
auto ProcessTlsInformation = PPROCESS_TLS_INFORMATION(RtlAllocateHeap(RtlProcessHeap(), HEAP_ZERO_MEMORY, Length));
|
||||
@@ -795,8 +785,7 @@ NTSTATUS NTAPI MmpHandleTlsData(_In_ PLDR_DATA_TABLE_ENTRY lpModuleEntry) {
|
||||
return status;
|
||||
}
|
||||
|
||||
|
||||
BOOL NTAPI MmpInitialize() {
|
||||
BOOL NTAPI MmpTlsInitialize() {
|
||||
|
||||
auto tls = CONTAINING_RECORD(NtCurrentTeb()->ThreadLocalStoragePointer, TLS_VECTOR, TLS_VECTOR::ModuleTlsData);
|
||||
if (tls && tls->Length > MMP_START_TLS_INDEX) {
|
||||
@@ -807,27 +796,26 @@ BOOL NTAPI MmpInitialize() {
|
||||
//
|
||||
// Capture thread count
|
||||
//
|
||||
MmpActiveThreadCount = MmpGetThreadCount();
|
||||
MmpGlobalDataPtr->MmpActiveThreadCount = MmpGetThreadCount();
|
||||
|
||||
//
|
||||
// Initialize tlsp
|
||||
//
|
||||
InitializeCriticalSection(&MmpTlspLock);
|
||||
InitializeListHead(&MmpThreadLocalStoragePointer);
|
||||
InitializeCriticalSection(&MmpGlobalDataPtr->MmpTlspLock);
|
||||
InitializeListHead(&MmpGlobalDataPtr->MmpThreadLocalStoragePointer);
|
||||
|
||||
//
|
||||
// Initialize tls list
|
||||
//
|
||||
InitializeListHead(&MmpTlsList);
|
||||
RtlInitializeSRWLock(&MmpTlsListLock);
|
||||
InitializeListHead(&MmpGlobalDataPtr->MmpTlsList);
|
||||
RtlInitializeSRWLock(&MmpGlobalDataPtr->MmpTlsListLock);
|
||||
|
||||
PULONG buffer = PULONG(RtlAllocateHeap(RtlProcessHeap(), HEAP_ZERO_MEMORY, MMP_TLSP_INDEX_BUFFER_SIZE));
|
||||
if (!buffer) {
|
||||
RtlRaiseStatus(STATUS_NO_MEMORY);
|
||||
}
|
||||
if (!buffer) RtlRaiseStatus(STATUS_NO_MEMORY);
|
||||
|
||||
|
||||
RtlFillMemory(buffer, MMP_START_TLS_INDEX / 8, -1);
|
||||
RtlInitializeBitMap(&MmpTlsBitmap, buffer, MMP_MAXIMUM_TLS_INDEX);
|
||||
RtlInitializeBitMap(&MmpGlobalDataPtr->MmpTlsBitmap, buffer, MMP_MAXIMUM_TLS_INDEX);
|
||||
|
||||
if (NtCurrentTeb()->ThreadLocalStoragePointer) {
|
||||
if (!PreHookNtSetInformationProcess()) {
|
||||
@@ -848,5 +836,3 @@ BOOL NTAPI MmpInitialize() {
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static const BOOL MmpStaticInitializer = MmpInitialize();
|
||||
|
||||
@@ -1,5 +1,7 @@
|
||||
#pragma once
|
||||
|
||||
BOOL NTAPI MmpTlsInitialize();
|
||||
|
||||
NTSTATUS NTAPI MmpReleaseTlsEntry(PLDR_DATA_TABLE_ENTRY lpModuleEntry);
|
||||
|
||||
NTSTATUS NTAPI MmpHandleTlsData(PLDR_DATA_TABLE_ENTRY lpModuleEntry);
|
||||
|
||||
@@ -408,3 +408,31 @@ WINDOWS_VERSION NTAPI NtWindowsVersion() {
|
||||
}
|
||||
return version = invalid;
|
||||
}
|
||||
|
||||
int NTAPI RtlCaptureImageExceptionValues(PVOID BaseAddress, PDWORD SEHandlerTable, PDWORD SEHandlerCount) {
|
||||
PIMAGE_LOAD_CONFIG_DIRECTORY pLoadConfigDirectory;
|
||||
PIMAGE_COR20_HEADER pCor20;
|
||||
ULONG Size;
|
||||
|
||||
//check if no seh
|
||||
if (RtlImageNtHeader(BaseAddress)->OptionalHeader.DllCharacteristics & IMAGE_DLLCHARACTERISTICS_NO_SEH) {
|
||||
*SEHandlerTable = *SEHandlerCount = -1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
//get seh table and count
|
||||
pLoadConfigDirectory = (decltype(pLoadConfigDirectory))RtlImageDirectoryEntryToData(BaseAddress, TRUE, IMAGE_DIRECTORY_ENTRY_LOAD_CONFIG, &Size);
|
||||
if (pLoadConfigDirectory) {
|
||||
if (Size == 0x40 && pLoadConfigDirectory->Size >= 0x48u) {
|
||||
if (pLoadConfigDirectory->SEHandlerTable && pLoadConfigDirectory->SEHandlerCount) {
|
||||
*SEHandlerTable = pLoadConfigDirectory->SEHandlerTable;
|
||||
return *SEHandlerCount = pLoadConfigDirectory->SEHandlerCount;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//is .net core ?
|
||||
pCor20 = (decltype(pCor20))RtlImageDirectoryEntryToData(BaseAddress, TRUE, IMAGE_DIRECTORY_ENTRY_COM_DESCRIPTOR, &Size);
|
||||
*SEHandlerTable = *SEHandlerCount = ((pCor20 && pCor20->Flags & 1) ? -1 : 0);
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -86,3 +86,5 @@ typedef enum _WINDOWS_VERSION {
|
||||
}WINDOWS_VERSION;
|
||||
|
||||
WINDOWS_VERSION NTAPI NtWindowsVersion();
|
||||
|
||||
int NTAPI RtlCaptureImageExceptionValues(PVOID BaseAddress, PDWORD SEHandlerTable, PDWORD SEHandlerCount);
|
||||
|
||||
@@ -34,3 +34,6 @@
|
||||
|
||||
//utils
|
||||
#include "Utils.h"
|
||||
|
||||
//global data
|
||||
#include "MmpGlobalData.h"
|
||||
Reference in New Issue
Block a user