diff --git a/MemoryModule/BaseAddressIndex.cpp b/MemoryModule/BaseAddressIndex.cpp index f261ae7..4fc1db5 100644 --- a/MemoryModule/BaseAddressIndex.cpp +++ b/MemoryModule/BaseAddressIndex.cpp @@ -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; diff --git a/MemoryModule/BaseAddressIndex.h b/MemoryModule/BaseAddressIndex.h index 3cb8064..c19ff53 100644 --- a/MemoryModule/BaseAddressIndex.h +++ b/MemoryModule/BaseAddressIndex.h @@ -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); diff --git a/MemoryModule/Initialize.cpp b/MemoryModule/Initialize.cpp index d013211..bb5bc25 100644 --- a/MemoryModule/Initialize.cpp +++ b/MemoryModule/Initialize.cpp @@ -1,6 +1,14 @@ #include "stdafx.h" #include +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 diff --git a/MemoryModule/InvertedFunctionTable.cpp b/MemoryModule/InvertedFunctionTable.cpp index 0e53510..20a59b5 100644 --- a/MemoryModule/InvertedFunctionTable.cpp +++ b/MemoryModule/InvertedFunctionTable.cpp @@ -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; diff --git a/MemoryModule/InvertedFunctionTable.h b/MemoryModule/InvertedFunctionTable.h index 1b43fbf..979a3e6 100644 --- a/MemoryModule/InvertedFunctionTable.h +++ b/MemoryModule/InvertedFunctionTable.h @@ -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 diff --git a/MemoryModule/LdrEntry.cpp b/MemoryModule/LdrEntry.cpp index 30e02fd..6d62fbd 100644 --- a/MemoryModule/LdrEntry.cpp +++ b/MemoryModule/LdrEntry.cpp @@ -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; diff --git a/MemoryModule/LdrEntry.h b/MemoryModule/LdrEntry.h index 56a6b19..8a41694 100644 --- a/MemoryModule/LdrEntry.h +++ b/MemoryModule/LdrEntry.h @@ -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))) diff --git a/MemoryModule/Loader.cpp b/MemoryModule/Loader.cpp index 9a4f64d..5dbf836 100644 --- a/MemoryModule/Loader.cpp +++ b/MemoryModule/Loader.cpp @@ -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(); diff --git a/MemoryModule/Loader.h b/MemoryModule/Loader.h index b171318..9217b12 100644 --- a/MemoryModule/Loader.h +++ b/MemoryModule/Loader.h @@ -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); } diff --git a/MemoryModule/MemoryModule.vcxproj b/MemoryModule/MemoryModule.vcxproj index 8df50e5..526246d 100644 --- a/MemoryModule/MemoryModule.vcxproj +++ b/MemoryModule/MemoryModule.vcxproj @@ -1,10 +1,26 @@ + + DebugDll + Win32 + + + DebugDll + x64 + Debug Win32 + + ReleaseDll + Win32 + + + ReleaseDll + x64 + Release Win32 @@ -77,6 +93,7 @@ + @@ -87,6 +104,7 @@ + 16.0 @@ -103,6 +121,12 @@ v142 Unicode + + DynamicLibrary + true + v142 + Unicode + StaticLibrary false @@ -110,6 +134,13 @@ true Unicode + + DynamicLibrary + false + v142 + true + Unicode + StaticLibrary true @@ -117,6 +148,13 @@ Unicode false + + DynamicLibrary + true + v142 + Unicode + false + StaticLibrary false @@ -124,6 +162,13 @@ true Unicode + + DynamicLibrary + false + v142 + true + Unicode + @@ -133,32 +178,65 @@ + + + + + + + + + + + + true $(VC_IncludePath);$(WindowsSDK_IncludePath);$(SolutionDir); + $(SolutionDir)$(Configuration)\ + + + true + $(VC_IncludePath);$(WindowsSDK_IncludePath);$(SolutionDir); + $(SolutionDir)Debug\ true $(VC_IncludePath);$(WindowsSDK_IncludePath);$(SolutionDir); + + true + $(VC_IncludePath);$(WindowsSDK_IncludePath);$(SolutionDir); + $(SolutionDir)$(Platform)\Debug\ + false $(VC_IncludePath);$(WindowsSDK_IncludePath);$(SolutionDir); + + false + $(VC_IncludePath);$(WindowsSDK_IncludePath);$(SolutionDir); + $(SolutionDir)Release\ + false $(VC_IncludePath);$(WindowsSDK_IncludePath);$(SolutionDir); + + false + $(VC_IncludePath);$(WindowsSDK_IncludePath);$(SolutionDir); + $(SolutionDir)$(Platform)\Release\ + NotUsing @@ -174,6 +252,26 @@ Windows true + MemoryModulePP.def + + + + + NotUsing + Level3 + true + WIN32;_DEBUG;_USRDLL;%(PreprocessorDefinitions) + true + + + + + MultiThreadedDebug + + + Windows + true + MemoryModulePP.def @@ -191,6 +289,26 @@ Windows true + MemoryModulePP.def + + + + + NotUsing + Level3 + true + _DEBUG;_USRDLL;%(PreprocessorDefinitions) + true + + + + + MultiThreadedDebug + + + Windows + true + MemoryModulePP.def @@ -212,6 +330,30 @@ true true true + MemoryModulePP.def + + + + + NotUsing + Level3 + true + true + true + WIN32;NDEBUG;_USRDLL;%(PreprocessorDefinitions) + true + + + + + MultiThreaded + + + Windows + true + true + true + MemoryModulePP.def @@ -233,6 +375,30 @@ true true true + MemoryModulePP.def + + + + + NotUsing + Level3 + true + true + true + NDEBUG;_USRDLL;%(PreprocessorDefinitions) + true + + + + + MultiThreaded + + + Windows + true + true + true + MemoryModulePP.def diff --git a/MemoryModule/MemoryModule.vcxproj.filters b/MemoryModule/MemoryModule.vcxproj.filters index e32c49b..2aa9155 100644 --- a/MemoryModule/MemoryModule.vcxproj.filters +++ b/MemoryModule/MemoryModule.vcxproj.filters @@ -221,10 +221,16 @@ Header Files\3rdparty\phnt + + Header Files + Resource Files + + Resource Files + \ No newline at end of file diff --git a/MemoryModule/MemoryModulePP.def b/MemoryModule/MemoryModulePP.def new file mode 100644 index 0000000..90108a6 --- /dev/null +++ b/MemoryModule/MemoryModulePP.def @@ -0,0 +1,13 @@ +LIBRARY +EXPORTS +LoadLibraryMemory +LoadLibraryMemoryExA +LoadLibraryMemoryExW +FreeLibraryMemory + +LdrLoadDllMemory +LdrLoadDllMemoryExA +LdrLoadDllMemoryExW +LdrUnloadDllMemory +LdrUnloadDllMemoryAndExitThread +LdrQuerySystemMemoryModuleFeatures \ No newline at end of file diff --git a/MemoryModule/MmpGlobalData.h b/MemoryModule/MmpGlobalData.h new file mode 100644 index 0000000..3470c18 --- /dev/null +++ b/MemoryModule/MmpGlobalData.h @@ -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; \ No newline at end of file diff --git a/MemoryModule/MmpTls.cpp b/MemoryModule/MmpTls.cpp index 0d45cfd..aa3e65b 100644 --- a/MemoryModule/MmpTls.cpp +++ b/MemoryModule/MmpTls.cpp @@ -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(); diff --git a/MemoryModule/MmpTls.h b/MemoryModule/MmpTls.h index f6c4950..ebcc64a 100644 --- a/MemoryModule/MmpTls.h +++ b/MemoryModule/MmpTls.h @@ -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); diff --git a/MemoryModule/Utils.cpp b/MemoryModule/Utils.cpp index 155b6ba..3fe4e27 100644 --- a/MemoryModule/Utils.cpp +++ b/MemoryModule/Utils.cpp @@ -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; +} diff --git a/MemoryModule/Utils.h b/MemoryModule/Utils.h index d5183e4..afe375d 100644 --- a/MemoryModule/Utils.h +++ b/MemoryModule/Utils.h @@ -86,3 +86,5 @@ typedef enum _WINDOWS_VERSION { }WINDOWS_VERSION; WINDOWS_VERSION NTAPI NtWindowsVersion(); + +int NTAPI RtlCaptureImageExceptionValues(PVOID BaseAddress, PDWORD SEHandlerTable, PDWORD SEHandlerCount); diff --git a/MemoryModule/stdafx.h b/MemoryModule/stdafx.h index 226baf3..0affb02 100644 --- a/MemoryModule/stdafx.h +++ b/MemoryModule/stdafx.h @@ -34,3 +34,6 @@ //utils #include "Utils.h" + +//global data +#include "MmpGlobalData.h" \ No newline at end of file diff --git a/MemoryModulePP.sln b/MemoryModulePP.sln index 0b985a5..77f852f 100644 --- a/MemoryModulePP.sln +++ b/MemoryModulePP.sln @@ -19,12 +19,12 @@ Global GlobalSection(ProjectConfigurationPlatforms) = postSolution {5B1F46DB-036E-4A50-AF5F-F5D6584D42C6}.Debug|x64.ActiveCfg = Debug|x64 {5B1F46DB-036E-4A50-AF5F-F5D6584D42C6}.Debug|x64.Build.0 = Debug|x64 - {5B1F46DB-036E-4A50-AF5F-F5D6584D42C6}.Debug|x86.ActiveCfg = Debug|Win32 - {5B1F46DB-036E-4A50-AF5F-F5D6584D42C6}.Debug|x86.Build.0 = Debug|Win32 - {5B1F46DB-036E-4A50-AF5F-F5D6584D42C6}.Release|x64.ActiveCfg = Release|x64 - {5B1F46DB-036E-4A50-AF5F-F5D6584D42C6}.Release|x64.Build.0 = Release|x64 - {5B1F46DB-036E-4A50-AF5F-F5D6584D42C6}.Release|x86.ActiveCfg = Release|Win32 - {5B1F46DB-036E-4A50-AF5F-F5D6584D42C6}.Release|x86.Build.0 = Release|Win32 + {5B1F46DB-036E-4A50-AF5F-F5D6584D42C6}.Debug|x86.ActiveCfg = DebugDll|Win32 + {5B1F46DB-036E-4A50-AF5F-F5D6584D42C6}.Debug|x86.Build.0 = DebugDll|Win32 + {5B1F46DB-036E-4A50-AF5F-F5D6584D42C6}.Release|x64.ActiveCfg = ReleaseDll|x64 + {5B1F46DB-036E-4A50-AF5F-F5D6584D42C6}.Release|x64.Build.0 = ReleaseDll|x64 + {5B1F46DB-036E-4A50-AF5F-F5D6584D42C6}.Release|x86.ActiveCfg = ReleaseDll|Win32 + {5B1F46DB-036E-4A50-AF5F-F5D6584D42C6}.Release|x86.Build.0 = ReleaseDll|Win32 {5B3131BA-178A-4A28-BD54-315A45C97ED1}.Debug|x64.ActiveCfg = Debug|x64 {5B3131BA-178A-4A28-BD54-315A45C97ED1}.Debug|x64.Build.0 = Debug|x64 {5B3131BA-178A-4A28-BD54-315A45C97ED1}.Debug|x64.Deploy.0 = Debug|x64 diff --git a/test/test.cpp b/test/test.cpp index 4e376c4..29a047a 100644 --- a/test/test.cpp +++ b/test/test.cpp @@ -132,77 +132,7 @@ int test_user32() { return 0; } -void test() { - - NTSTATUS status; - HANDLE hSection; - OBJECT_ATTRIBUTES oa; - LARGE_INTEGER li; - UNICODE_STRING us; - SECTION_BASIC_INFORMATION sbi; - PVOID BaseAddress = 0; - SIZE_T ViewSize = 0; - - li.QuadPart = 0x1000; - - RtlInitUnicodeString(&us, L"\\Sessions\\2\\BaseNamedObjects\\SectionTest"); - - InitializeObjectAttributes(&oa, &us, 0, nullptr, nullptr); - - status = NtCreateSection( - &hSection, - SECTION_ALL_ACCESS, - &oa, - &li, - PAGE_READWRITE, - SEC_COMMIT | SEC_BASED, - nullptr - ); - - if (NT_SUCCESS(status)) { - - status = NtQuerySection( - hSection, - SECTION_INFORMATION_CLASS::SectionBasicInformation, - &sbi, - sizeof(sbi), - nullptr - ); - - status = NtMapViewOfSection( - hSection, - NtCurrentProcess(), - &BaseAddress, - 0, - 0, - nullptr, - &ViewSize, - ViewUnmap, - 0, - PAGE_READWRITE - ); - if (NT_SUCCESS(status)) { - - status = NtQuerySection( - hSection, - SECTION_INFORMATION_CLASS::SectionBasicInformation, - &sbi, - sizeof(sbi), - nullptr - ); - - status = NtUnmapViewOfSection( - NtCurrentProcess(), - BaseAddress - ); - } - - NtClose(hSection); - } - -} - int main() { - test(); + test_a_dll(); return 0; }