This commit is contained in:
Boring
2022-10-01 12:51:58 +08:00
parent 0c4f334418
commit d6f0715c49
20 changed files with 550 additions and 383 deletions
+2 -30
View File
@@ -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;
-2
View File
@@ -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
View File
@@ -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
+3 -160
View File
@@ -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;
-9
View File
@@ -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
+1 -21
View File
@@ -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;
-2
View File
@@ -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
View File
@@ -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();
+4 -3
View File
@@ -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);
}
+166
View File
@@ -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>
+13
View File
@@ -0,0 +1,13 @@
LIBRARY
EXPORTS
LoadLibraryMemory
LoadLibraryMemoryExA
LoadLibraryMemoryExW
FreeLibraryMemory
LdrLoadDllMemory
LdrLoadDllMemoryExA
LdrLoadDllMemoryExW
LdrUnloadDllMemory
LdrUnloadDllMemoryAndExitThread
LdrQuerySystemMemoryModuleFeatures
+29
View File
@@ -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
View File
@@ -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();
+2
View File
@@ -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);
+28
View File
@@ -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;
}
+2
View File
@@ -86,3 +86,5 @@ typedef enum _WINDOWS_VERSION {
}WINDOWS_VERSION;
WINDOWS_VERSION NTAPI NtWindowsVersion();
int NTAPI RtlCaptureImageExceptionValues(PVOID BaseAddress, PDWORD SEHandlerTable, PDWORD SEHandlerCount);
+3
View File
@@ -34,3 +34,6 @@
//utils
#include "Utils.h"
//global data
#include "MmpGlobalData.h"