diff --git a/MemoryModule/Initialize.cpp b/MemoryModule/Initialize.cpp index da27d02..6fc0e90 100644 --- a/MemoryModule/Initialize.cpp +++ b/MemoryModule/Initialize.cpp @@ -191,11 +191,13 @@ VOID InitializeWindowsVersion() { case 5: { switch (MmpGlobalDataPtr->NtVersions.MinorVersion) { case 1: - version = MmpGlobalDataPtr->NtVersions.BuildNumber == 2600 ? WINDOWS_VERSION::xp : WINDOWS_VERSION::invalid; + if (MmpGlobalDataPtr->NtVersions.BuildNumber == 2600) + version = WINDOWS_VERSION::xp; break; case 2: - version = MmpGlobalDataPtr->NtVersions.BuildNumber == 3790 ? WINDOWS_VERSION::xp : WINDOWS_VERSION::invalid; + if (MmpGlobalDataPtr->NtVersions.BuildNumber == 3790) + version = WINDOWS_VERSION::xp; break; } break; @@ -225,12 +227,14 @@ VOID InitializeWindowsVersion() { } case 2: { - if (MmpGlobalDataPtr->NtVersions.BuildNumber == 9200) version = WINDOWS_VERSION::win8; + if (MmpGlobalDataPtr->NtVersions.BuildNumber == 9200) + version = WINDOWS_VERSION::win8; break; } case 3: { - if (MmpGlobalDataPtr->NtVersions.BuildNumber == 9600) version = WINDOWS_VERSION::win8_1; + if (MmpGlobalDataPtr->NtVersions.BuildNumber == 9600) + version = WINDOWS_VERSION::winBlue; break; } @@ -240,27 +244,29 @@ VOID InitializeWindowsVersion() { case 10: { if (MmpGlobalDataPtr->NtVersions.MinorVersion)break; - switch (MmpGlobalDataPtr->NtVersions.BuildNumber) { - case 10240: - case 10586: - version = WINDOWS_VERSION::win10; - break; - case 14393: - version = WINDOWS_VERSION::win10_1; - break; - - case 15063: - case 16299: - case 17134: - case 17763: - case 18362: - version = WINDOWS_VERSION::win10_2; - break; - - default: - if (RtlIsWindowsVersionOrGreater(MmpGlobalDataPtr->NtVersions.MajorVersion, MmpGlobalDataPtr->NtVersions.MinorVersion, 15063)) version = WINDOWS_VERSION::win10_2; - break; + DWORD BuildNumber = MmpGlobalDataPtr->NtVersions.BuildNumber; + if (BuildNumber >= 10240) { + if (BuildNumber >= 14393) { + if (BuildNumber >= 15063) { + if (BuildNumber >= 22000) { + // [22000, ?) + version = WINDOWS_VERSION::win11; + } + else { + // [15063, 22000) + version = WINDOWS_VERSION::win10_2; + } + } + else { + // [13494, 15063) + version = WINDOWS_VERSION::win10_1; + } + } + else { + // [10240, 14393) + version = WINDOWS_VERSION::win10; + } } break; @@ -369,8 +375,8 @@ NTSTATUS InitializeLockHeld() { MmpGlobalDataPtr->LdrDataTableEntrySize = sizeof(LDR_DATA_TABLE_ENTRY_WIN8); break; - case WINDOWS_VERSION::win8_1: - MmpGlobalDataPtr->LdrDataTableEntrySize = sizeof(LDR_DATA_TABLE_ENTRY_WIN8_1); + case WINDOWS_VERSION::winBlue: + MmpGlobalDataPtr->LdrDataTableEntrySize = sizeof(LDR_DATA_TABLE_ENTRY_WINBLUE); break; case WINDOWS_VERSION::win10: @@ -385,14 +391,25 @@ NTSTATUS InitializeLockHeld() { MmpGlobalDataPtr->LdrDataTableEntrySize = sizeof(LDR_DATA_TABLE_ENTRY_WIN10_2); break; + case WINDOWS_VERSION::win11: + MmpGlobalDataPtr->LdrDataTableEntrySize = sizeof(LDR_DATA_TABLE_ENTRY_WIN11); + break; + default: - MmpGlobalDataPtr->LdrDataTableEntrySize = sizeof(LDR_DATA_TABLE_ENTRY_WIN10_2); + NtUnmapViewOfSection(NtCurrentProcess(), BaseAddress); + status = STATUS_NOT_SUPPORTED; break; } + if (!NT_SUCCESS(status))break; + MmpGlobalDataPtr->MmpBaseAddressIndex.NtdllLdrEntry = RtlFindLdrTableEntryByBaseName(L"ntdll.dll"); MmpGlobalDataPtr->MmpBaseAddressIndex.LdrpModuleBaseAddressIndex = FindLdrpModuleBaseAddressIndex(); + HMODULE hNtdll = (HMODULE)MmpGlobalDataPtr->MmpBaseAddressIndex.NtdllLdrEntry->DllBase; + MmpGlobalDataPtr->MmpLdrEntry._RtlRbInsertNodeEx = decltype(&RtlRbInsertNodeEx)(GetProcAddress(hNtdll, "RtlRbInsertNodeEx")); + MmpGlobalDataPtr->MmpLdrEntry._RtlRbRemoveNode = decltype(&RtlRbRemoveNode)(GetProcAddress(hNtdll, "RtlRbRemoveNode")); + MmpGlobalDataPtr->MmpLdrEntry.LdrpHashTable = FindLdrpHashTable(); MmpGlobalDataPtr->MmpInvertedFunctionTable.LdrpInvertedFunctionTable = FindLdrpInvertedFunctionTable(); diff --git a/MemoryModule/LdrEntry.cpp b/MemoryModule/LdrEntry.cpp index d35db8a..d510e40 100644 --- a/MemoryModule/LdrEntry.cpp +++ b/MemoryModule/LdrEntry.cpp @@ -120,6 +120,11 @@ BOOL NTAPI RtlInitializeLdrDataTableEntry( } switch (MmpGlobalDataPtr->WindowsVersion) { + case WINDOWS_VERSION::win11: { + auto entry = (PLDR_DATA_TABLE_ENTRY_WIN11)LdrEntry; + entry->CheckSum = headers->OptionalHeader.CheckSum; + } + case WINDOWS_VERSION::win10: case WINDOWS_VERSION::win10_1: case WINDOWS_VERSION::win10_2: { @@ -127,7 +132,7 @@ BOOL NTAPI RtlInitializeLdrDataTableEntry( entry->ReferenceCount = 1; } case WINDOWS_VERSION::win8: - case WINDOWS_VERSION::win8_1: { + case WINDOWS_VERSION::winBlue: { auto entry = (PLDR_DATA_TABLE_ENTRY_WIN8)LdrEntry; const static bool IsWin8 = RtlIsWindowsVersionInScope(6, 2, 0, 6, 3, -1); NtQuerySystemTime(&entry->LoadTime); @@ -137,9 +142,7 @@ BOOL NTAPI RtlInitializeLdrDataTableEntry( if (!NT_SUCCESS(RtlInsertModuleBaseAddressIndexNode(LdrEntry, BaseAddress)))return FALSE; if (!(entry->DdagNode = (decltype(entry->DdagNode)) RtlAllocateHeap(heap, HEAP_ZERO_MEMORY, IsWin8 ? sizeof(_LDR_DDAG_NODE_WIN8) : sizeof(_LDR_DDAG_NODE))))return FALSE; - //RtlInitializeListEntry(&entry->NodeModuleLink); - //RtlInitializeListEntry(&entry->DdagNode->Modules); - //RtlInitializeSingleEntry(&entry->DdagNode->CondenseLink); + entry->NodeModuleLink.Flink = &entry->DdagNode->Modules; entry->NodeModuleLink.Blink = &entry->DdagNode->Modules; entry->DdagNode->Modules.Flink = &entry->NodeModuleLink; @@ -198,7 +201,7 @@ BOOL NTAPI RtlFreeLdrDataTableEntry(_In_ PLDR_DATA_TABLE_ENTRY LdrEntry) { case WINDOWS_VERSION::win10_1: case WINDOWS_VERSION::win10_2: case WINDOWS_VERSION::win8: - case WINDOWS_VERSION::win8_1: { + case WINDOWS_VERSION::winBlue: { auto entry = (PLDR_DATA_TABLE_ENTRY_WIN10)LdrEntry; RtlFreeDependencies(entry); RtlFreeHeap(heap, 0, entry->DdagNode); @@ -274,20 +277,17 @@ VOID NTAPI RtlRbInsertNodeEx( _In_ PRTL_BALANCED_NODE Parent, _In_ BOOLEAN Right, _Out_ PRTL_BALANCED_NODE Node) { - static decltype(&RtlRbInsertNodeEx)_RtlRbInsertNodeEx = decltype(_RtlRbInsertNodeEx)(RtlGetNtProcAddress("RtlRbInsertNodeEx")); - RtlZeroMemory(Node, sizeof(*Node)); - if (!_RtlRbInsertNodeEx)return; - return _RtlRbInsertNodeEx(Tree, Parent, Right, Node); + if (!MmpGlobalDataPtr->MmpLdrEntry._RtlRbInsertNodeEx)return; + return MmpGlobalDataPtr->MmpLdrEntry._RtlRbInsertNodeEx(Tree, Parent, Right, Node); } VOID NTAPI RtlRbRemoveNode( _In_ PRTL_RB_TREE Tree, _In_ PRTL_BALANCED_NODE Node) { - static decltype(&RtlRbRemoveNode)_RtlRbRemoveNode = decltype(_RtlRbRemoveNode)(RtlGetNtProcAddress("RtlRbRemoveNode")); - if (!_RtlRbRemoveNode)return; - return _RtlRbRemoveNode(Tree, Node); + if (!MmpGlobalDataPtr->MmpLdrEntry._RtlRbRemoveNode)return; + return MmpGlobalDataPtr->MmpLdrEntry._RtlRbRemoveNode(Tree, Node); } PLDR_DATA_TABLE_ENTRY NTAPI RtlFindLdrTableEntryByHandle(_In_ PVOID BaseAddress) { @@ -317,15 +317,15 @@ PLDR_DATA_TABLE_ENTRY NTAPI RtlFindLdrTableEntryByBaseName(_In_z_ PCWSTR BaseNam return nullptr; } -ULONG NTAPI LdrHashEntry(_In_ UNICODE_STRING& str, _In_ BOOL _xor) { +ULONG NTAPI LdrHashEntry(_In_ UNICODE_STRING& DllBaseName, _In_ BOOL ToIndex) { ULONG result = 0; if (RtlIsWindowsVersionOrGreater(6, 2, 0)) { - RtlHashUnicodeString(&str, TRUE, HASH_STRING_ALGORITHM_DEFAULT, &result); + RtlHashUnicodeString(&DllBaseName, TRUE, HASH_STRING_ALGORITHM_DEFAULT, &result); } else { - for (USHORT i = 0; i < (str.Length / sizeof(wchar_t)); ++i) - result += 0x1003F * RtlUpcaseUnicodeChar(str.Buffer[i]); + for (USHORT i = 0; i < (DllBaseName.Length / sizeof(wchar_t)); ++i) + result += 0x1003F * RtlUpcaseUnicodeChar(DllBaseName.Buffer[i]); } - if (_xor)result &= (LDR_HASH_TABLE_ENTRIES - 1); + if (ToIndex)result &= (LDR_HASH_TABLE_ENTRIES - 1); return result; } diff --git a/MemoryModule/LdrEntry.h b/MemoryModule/LdrEntry.h index bd760fa..74c22fc 100644 --- a/MemoryModule/LdrEntry.h +++ b/MemoryModule/LdrEntry.h @@ -199,9 +199,9 @@ typedef struct _LDR_DATA_TABLE_ENTRY_WIN8 { }LDR_DATA_TABLE_ENTRY_WIN8, * PLDR_DATA_TABLE_ENTRY_WIN8; //6.3.9600 Windows 8.1 | 2012R2 RTM | 2012R2 Update 1 -typedef struct _LDR_DATA_TABLE_ENTRY_WIN8_1 :public _LDR_DATA_TABLE_ENTRY_WIN8 { +typedef struct _LDR_DATA_TABLE_ENTRY_WINBLUE :public _LDR_DATA_TABLE_ENTRY_WIN8 { ULONG ImplicitPathOptions; -}LDR_DATA_TABLE_ENTRY_WIN8_1, * PLDR_DATA_TABLE_ENTRY_WIN8_1; +}LDR_DATA_TABLE_ENTRY_WINBLUE, * PLDR_DATA_TABLE_ENTRY_WINBLUE; //10.0.10240 Windows 10 | 2016 1507 Threshold 1 //10.0.10586 Windows 10 | 2016 1511 Threshold 2 @@ -280,69 +280,18 @@ typedef struct _LDR_DATA_TABLE_ENTRY_WIN10_1 :public _LDR_DATA_TABLE_ENTRY_WIN10 //10.0.18362 Windows 10 | 2016 1903 19H1 (May 2019 Update) | 2016 1909 19H2 (November 2019 Update) //10.0.19041 Windows 10 | 2016 2004 20H1 (May 2020 Update) //10.0.19042 Windows 10 | 2016 2009 20H2 (October 2020 Update) -typedef struct _LDR_DATA_TABLE_ENTRY_WIN10_2 { - _LIST_ENTRY InLoadOrderLinks; //0x0 - _LIST_ENTRY InMemoryOrderLinks; //0x10 - _LIST_ENTRY InInitializationOrderLinks; //0x20 - VOID* DllBase; //0x30 - VOID* EntryPoint; //0x38 - ULONG SizeOfImage; //0x40 - _UNICODE_STRING FullDllName; //0x48 - _UNICODE_STRING BaseDllName; //0x58 - union { - UCHAR FlagGroup[4]; //0x68 - ULONG Flags; //0x68 - struct { - ULONG PackagedBinary : 1; //0x68 - ULONG MarkedForRemoval : 1; //0x68 - ULONG ImageDll : 1; //0x68 - ULONG LoadNotificationsSent : 1; //0x68 - ULONG TelemetryEntryProcessed : 1; //0x68 - ULONG ProcessStaticImport : 1; //0x68 - ULONG InLegacyLists : 1; //0x68 - ULONG InIndexes : 1; //0x68 - ULONG ShimDll : 1; //0x68 - ULONG InExceptionTable : 1; //0x68 - ULONG ReservedFlags1 : 2; //0x68 - ULONG LoadInProgress : 1; //0x68 - ULONG LoadConfigProcessed : 1; //0x68 - ULONG EntryProcessed : 1; //0x68 - ULONG ProtectDelayLoad : 1; //0x68 - ULONG ReservedFlags3 : 2; //0x68 - ULONG DontCallForThreads : 1; //0x68 - ULONG ProcessAttachCalled : 1; //0x68 - ULONG ProcessAttachFailed : 1; //0x68 - ULONG CorDeferredValidate : 1; //0x68 - ULONG CorImage : 1; //0x68 - ULONG DontRelocate : 1; //0x68 - ULONG CorILOnly : 1; //0x68 - ULONG ReservedFlags5 : 3; //0x68 - ULONG Redirected : 1; //0x68 - ULONG ReservedFlags6 : 2; //0x68 - ULONG CompatDatabaseProcessed : 1; //0x68 - }; - }; - USHORT ObsoleteLoadCount; //0x6c - USHORT TlsIndex; //0x6e - _LIST_ENTRY HashLinks; //0x70 - ULONG TimeDateStamp; //0x80 - _ACTIVATION_CONTEXT* EntryPointActivationContext; //0x88 - VOID* Lock; //0x90 - _LDR_DDAG_NODE* DdagNode; //0x98 - _LIST_ENTRY NodeModuleLink; //0xa0 - VOID* LoadContext; //0xb0 - VOID* ParentDllBase; //0xb8 - VOID* SwitchBackContext; //0xc0 - _RTL_BALANCED_NODE BaseAddressIndexNode; //0xc8 - _RTL_BALANCED_NODE MappingInfoIndexNode; //0xe0 - ULONGLONG OriginalBase; //0xf8 - _LARGE_INTEGER LoadTime; //0x100 - ULONG BaseNameHashValue; //0x108 - _LDR_DLL_LOAD_REASON LoadReason; //0x10c - ULONG ImplicitPathOptions; //0x110 - ULONG ReferenceCount; //0x114 +typedef struct _LDR_DATA_TABLE_ENTRY_WIN10_2 :LDR_DATA_TABLE_ENTRY_WIN10 { ULONG DependentLoadFlags; //0x118 UCHAR SigningLevel; //0x11c }LDR_DATA_TABLE_ENTRY_WIN10_2, * PLDR_DATA_TABLE_ENTRY_WIN10_2; -ULONG NTAPI LdrHashEntry(_In_ UNICODE_STRING& str, _In_ BOOL _xor = TRUE); +//10.0.22000 Windows 11 Insider Preview (Jun 2021) +//10.0.22000 Windows 11 21H2 (RTM) +//10.0.22621 Windows 11 22H2 (2022 Update) +typedef struct _LDR_DATA_TABLE_ENTRY_WIN11 :LDR_DATA_TABLE_ENTRY_WIN10_2 { + ULONG CheckSum; //0x120 + VOID* ActivePatchImageBase; //0x128 + LDR_HOT_PATCH_STATE HotPatchState; //0x130 +}LDR_DATA_TABLE_ENTRY_WIN11, * PLDR_DATA_TABLE_ENTRY_WIN11; + +ULONG NTAPI LdrHashEntry(_In_ UNICODE_STRING& DllBaseName, _In_ BOOL ToIndex = TRUE); diff --git a/MemoryModule/Loader.cpp b/MemoryModule/Loader.cpp index eb95b89..2289044 100644 --- a/MemoryModule/Loader.cpp +++ b/MemoryModule/Loader.cpp @@ -256,7 +256,7 @@ NTSTATUS NTAPI LdrUnloadDllMemory(_In_ HMEMORYMODULE BaseAddress) { if (!(count & ~1)) { module->underUnload = true; if (module->initialized) { - PDLL_STARTUP_ROUTINE((LPVOID)(module->codeBase + headers->OptionalHeader.AddressOfEntryPoint))( + PLDR_INIT_ROUTINE((LPVOID)(module->codeBase + headers->OptionalHeader.AddressOfEntryPoint))( (HINSTANCE)module->codeBase, DLL_PROCESS_DETACH, 0 diff --git a/MemoryModule/MmpGlobalData.h b/MemoryModule/MmpGlobalData.h index 42d8b08..8870f43 100644 --- a/MemoryModule/MmpGlobalData.h +++ b/MemoryModule/MmpGlobalData.h @@ -14,6 +14,9 @@ typedef struct _MMP_INVERTED_FUNCTION_TABLE_DATA { //LdrEntry.cpp typedef struct _MMP_LDR_ENTRY_DATA { PLIST_ENTRY LdrpHashTable; + + decltype(&RtlRbInsertNodeEx)_RtlRbInsertNodeEx; + decltype(&RtlRbRemoveNode)_RtlRbRemoveNode; }MMP_LDR_ENTRY_DATA, * PMMP_LDR_ENTRY_DATA; //MmpTls.cpp @@ -65,10 +68,11 @@ typedef enum class _WINDOWS_VERSION :BYTE { vista, win7, win8, - win8_1, + winBlue, win10, win10_1, win10_2, + win11, invalid }WINDOWS_VERSION; diff --git a/MemoryModule/Utils.cpp b/MemoryModule/Utils.cpp index aa58470..1b2c756 100644 --- a/MemoryModule/Utils.cpp +++ b/MemoryModule/Utils.cpp @@ -138,7 +138,7 @@ BOOL NTAPI LdrpCallInitializers(PMEMORYMODULE module, DWORD dwReason) { if (headers->OptionalHeader.AddressOfEntryPoint) { __try { // notify library about attaching to process - if (((PDLL_STARTUP_ROUTINE)(module->codeBase + headers->OptionalHeader.AddressOfEntryPoint))((HINSTANCE)module->codeBase, dwReason, 0)) { + if (((PLDR_INIT_ROUTINE)(module->codeBase + headers->OptionalHeader.AddressOfEntryPoint))((HINSTANCE)module->codeBase, dwReason, 0)) { module->initialized = TRUE; return TRUE; } @@ -311,10 +311,6 @@ BOOLEAN NTAPI RtlIsValidImageBuffer( return result; } -FARPROC NTAPI RtlGetNtProcAddress(LPCSTR func_name) { - return GetProcAddress(GetModuleHandleA("ntdll.dll"), func_name); -} - BOOLEAN NTAPI VirtualAccessCheckNoException(LPCVOID pBuffer, size_t size, ACCESS_MASK protect) { if (size) { MEMORY_BASIC_INFORMATION mbi{}; diff --git a/MemoryModule/Utils.h b/MemoryModule/Utils.h index 8d945fd..21f4b0d 100644 --- a/MemoryModule/Utils.h +++ b/MemoryModule/Utils.h @@ -26,8 +26,6 @@ NTSTATUS NTAPI RtlFindMemoryBlockFromModuleSection( _Inout_ PSEARCH_CONTEXT SearchContext ); -typedef BOOL(WINAPI* PDLL_STARTUP_ROUTINE)(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpReserved); - NTSTATUS NTAPI RtlResolveDllNameUnicodeString( _In_opt_ PCWSTR DllName, _In_opt_ PCWSTR DllFullName, @@ -44,8 +42,6 @@ BOOLEAN NTAPI RtlIsValidImageBuffer( _Out_opt_ size_t* Size ); -FARPROC NTAPI RtlGetNtProcAddress(LPCSTR func_name); - BOOLEAN NTAPI VirtualAccessCheck(LPCVOID pBuffer, size_t size, ACCESS_MASK protect); BOOLEAN NTAPI VirtualAccessCheckNoException(LPCVOID pBuffer, size_t size, ACCESS_MASK protect); #define ProbeForRead(pBuffer, size) VirtualAccessCheck(pBuffer, size, PAGE_READONLY | PAGE_READWRITE | PAGE_EXECUTE_READ | PAGE_EXECUTE_READWRITE) diff --git a/test/test.cpp b/test/test.cpp index 701ac74..e05b7e2 100644 --- a/test/test.cpp +++ b/test/test.cpp @@ -49,6 +49,22 @@ int test() { } int main() { - test(); + if (MmpGlobalDataPtr->WindowsVersion == WINDOWS_VERSION::win11) { + auto head = &NtCurrentPeb()->Ldr->InLoadOrderModuleList; + auto entry = head->Flink; + while (entry != head) { + PLDR_DATA_TABLE_ENTRY_WIN11 __entry = CONTAINING_RECORD(entry, LDR_DATA_TABLE_ENTRY_WIN11, InLoadOrderLinks); + wprintf(L"%s\t0x%08X, 0x%08X, 0x%p, %d\n", + __entry->BaseDllName.Buffer, + __entry->CheckSum, + RtlImageNtHeader(__entry->DllBase)->OptionalHeader.CheckSum, + __entry->ActivePatchImageBase, + __entry->HotPatchState + ); + + entry = entry->Flink; + } + } + return 0; }