11#include " stdafx.h"
22#include < wchar.h>
33
4+ PMMP_GLOBAL_DATA MmpGlobalDataPtr;
5+
6+ #ifdef _WIN64
7+ #define FindLdrpInvertedFunctionTable FindLdrpInvertedFunctionTable64
8+ #else
9+ #define FindLdrpInvertedFunctionTable FindLdrpInvertedFunctionTable32
10+ #endif
11+
412BOOLEAN MmpBuildSectionName (_Out_ PUNICODE_STRING SectionName) {
513 WCHAR buffer[128 ];
614
715 wsprintfW (buffer, L" \\ Sessions\\ %d\\ BaseNamedObjects\\ MMPP%d" , NtCurrentPeb ()->SessionId , (unsigned int )NtCurrentProcessId ());
816 return RtlCreateUnicodeString (SectionName, buffer);
917}
1018
11- VOID InitializeLockHeld () {
12- NTSTATUS status;
13- HANDLE hSection;
19+ PRTL_RB_TREE FindLdrpModuleBaseAddressIndex () {
20+ PRTL_RB_TREE LdrpModuleBaseAddressIndex = nullptr ;
21+ PLDR_DATA_TABLE_ENTRY_WIN10 nt10 = decltype (nt10)(MmpGlobalDataPtr->LdrpNtdllBase );
22+ PRTL_BALANCED_NODE node = nullptr ;
23+ if (!nt10 || !RtlIsWindowsVersionOrGreater (6 , 2 , 0 ))return nullptr ;
24+ node = &nt10->BaseAddressIndexNode ;
25+ while (node->ParentValue & (~7 )) node = decltype (node)(node->ParentValue & (~7 ));
26+
27+ if (!node->Red ) {
28+ BYTE count = 0 ;
29+ PRTL_RB_TREE tmp = nullptr ;
30+ SEARCH_CONTEXT SearchContext{};
31+ SearchContext.MemoryBuffer = &node;
32+ SearchContext.BufferLength = sizeof (size_t );
33+ while (NT_SUCCESS (RtlFindMemoryBlockFromModuleSection ((HMODULE)nt10->DllBase , " .data" , &SearchContext))) {
34+ if (count++)return nullptr ;
35+ tmp = (decltype (tmp))SearchContext.MemoryBlockInSection ;
36+ }
37+ if (count && tmp && tmp->Root && tmp->Min ) {
38+ LdrpModuleBaseAddressIndex = tmp;
39+ }
40+ }
41+
42+ return LdrpModuleBaseAddressIndex;
43+ }
44+
45+ static __forceinline bool IsModuleUnloaded (PLDR_DATA_TABLE_ENTRY entry) {
46+ if (RtlIsWindowsVersionOrGreater (6 , 2 , 0 )) {
47+ return PLDR_DATA_TABLE_ENTRY_WIN8 (entry)->DdagNode ->State == LdrModulesUnloaded;
48+ }
49+ else {
50+ return entry->DllBase == nullptr ;
51+ }
52+ }
53+
54+ PVOID FindLdrpInvertedFunctionTable32 () {
55+ // _RTL_INVERTED_FUNCTION_TABLE x86
56+ // Count +0x0 ????????
57+ // MaxCount +0x4 0x00000200
58+ // Overflow +0x8 0x00000000(Win7) ????????(Win10)
59+ // NextEntrySEHandlerTableEncoded +0xc 0x00000000(Win10) ++++++++(Win7)
60+ // _RTL_INVERTED_FUNCTION_TABLE_ENTRY[0] +0x10 ntdll.dll(win10) or The smallest base module
61+ // ImageBase +0x10 ++++++++
62+ // ImageSize +0x14 ++++++++
63+ // SEHandlerCount +0x18 ++++++++
64+ // NextEntrySEHandlerTableEncoded +0x1c ++++++++(Win10) ????????(Win7)
65+ // _RTL_INVERTED_FUNCTION_TABLE_ENTRY[1] ... ...
66+ // ......
67+ HMODULE hModule = nullptr , hNtdll = GetModuleHandleW (L" ntdll.dll" );
68+ PIMAGE_NT_HEADERS NtdllHeaders = RtlImageNtHeader (hNtdll), ModuleHeaders = nullptr ;
69+ _RTL_INVERTED_FUNCTION_TABLE_ENTRY_WIN7_32 entry{};
70+ LPCSTR lpSectionName = " .data" ;
71+ SEARCH_CONTEXT SearchContext{ SearchContext.MemoryBuffer = &entry,SearchContext.BufferLength = sizeof (entry) };
72+ PLIST_ENTRY ListHead = &NtCurrentPeb ()->Ldr ->InMemoryOrderModuleList ,
73+ ListEntry = ListHead->Flink ;
74+ PLDR_DATA_TABLE_ENTRY CurEntry = nullptr ;
75+ DWORD SEHTable, SEHCount;
76+ BYTE Offset = 0x20 ; // sizeof(_RTL_INVERTED_FUNCTION_TABLE_ENTRY)*2
77+
78+ if (RtlIsWindowsVersionOrGreater (6 , 3 , 0 )) lpSectionName = " .mrdata" ;
79+ else if (!RtlIsWindowsVersionOrGreater (6 , 2 , 0 )) Offset = 0xC ;
80+
81+ while (ListEntry != ListHead) {
82+ CurEntry = CONTAINING_RECORD (ListEntry, LDR_DATA_TABLE_ENTRY, InMemoryOrderLinks);
83+ ListEntry = ListEntry->Flink ;
84+ if (IsModuleUnloaded (CurEntry))continue ; // skip unloaded module
85+ if (IsValidMemoryModuleHandle ((HMEMORYMODULE)CurEntry->DllBase ))continue ; // skip our memory module.
86+ if (CurEntry->DllBase == hNtdll && Offset == 0x20 )continue ; // Win10 skip first entry, if the base of ntdll is smallest.
87+ hModule = (HMODULE)(hModule ? min (hModule, CurEntry->DllBase ) : CurEntry->DllBase );
88+ }
89+ ModuleHeaders = RtlImageNtHeader (hModule);
90+ if (!hModule || !ModuleHeaders || !hNtdll || !NtdllHeaders)return nullptr ;
91+
92+ RtlCaptureImageExceptionValues (hModule, &SEHTable, &SEHCount);
93+ entry = { RtlEncodeSystemPointer ((PVOID)SEHTable),(DWORD)hModule,ModuleHeaders->OptionalHeader .SizeOfImage ,(PVOID)SEHCount };
94+
95+ while (NT_SUCCESS (RtlFindMemoryBlockFromModuleSection (hNtdll, lpSectionName, &SearchContext))) {
96+ PRTL_INVERTED_FUNCTION_TABLE_WIN7_32 tab = decltype (tab)(SearchContext.OutBufferPtr - Offset);
97+
98+ // Note: Same memory layout for RTL_INVERTED_FUNCTION_TABLE_ENTRY in Windows 10 x86 and x64.
99+ if (RtlIsWindowsVersionOrGreater (6 , 2 , 0 ) && tab->MaxCount == 0x200 && !tab->NextEntrySEHandlerTableEncoded ) return tab;
100+ else if (tab->MaxCount == 0x200 && !tab->Overflow ) return tab;
101+ }
102+
103+ return nullptr ;
104+ }
105+
106+ PVOID FindLdrpInvertedFunctionTable64 () {
107+ // _RTL_INVERTED_FUNCTION_TABLE x64
108+ // Count +0x0 ????????
109+ // MaxCount +0x4 0x00000200
110+ // Epoch +0x8 ????????
111+ // OverFlow +0xc 0x00000000
112+ // _RTL_INVERTED_FUNCTION_TABLE_ENTRY[0] +0x10 ntdll.dll(win10) or The smallest base module
113+ // ExceptionDirectory +0x10 ++++++++
114+ // ImageBase +0x18 ++++++++
115+ // ImageSize +0x20 ++++++++
116+ // ExceptionDirectorySize +0x24 ++++++++
117+ // _RTL_INVERTED_FUNCTION_TABLE_ENTRY[1] ... ...
118+ // ......
119+ HMODULE hModule = nullptr , hNtdll = GetModuleHandleW (L" ntdll.dll" );
120+ PIMAGE_NT_HEADERS NtdllHeaders = RtlImageNtHeader (hNtdll), ModuleHeaders = nullptr ;
121+ _RTL_INVERTED_FUNCTION_TABLE_ENTRY_64 entry{};
122+ LPCSTR lpSectionName = " .data" ;
123+ PIMAGE_DATA_DIRECTORY dir = nullptr ;
124+ SEARCH_CONTEXT SearchContext{ SearchContext.MemoryBuffer = &entry,SearchContext.BufferLength = sizeof (entry) };
125+
126+ // Windows 8
127+ if (RtlVerifyVersion (6 , 2 , 0 , RTL_VERIFY_FLAGS_MAJOR_VERSION | RTL_VERIFY_FLAGS_MINOR_VERSION)) {
128+ hModule = hNtdll;
129+ ModuleHeaders = NtdllHeaders;
130+ // lpSectionName = ".data";
131+ }
132+ // Windows 8.1 ~ Windows 10
133+ else if (RtlIsWindowsVersionOrGreater (6 , 3 , 0 )) {
134+ hModule = hNtdll;
135+ ModuleHeaders = NtdllHeaders;
136+ lpSectionName = " .mrdata" ;
137+ }
138+ else {
139+ PLIST_ENTRY ListHead = &NtCurrentPeb ()->Ldr ->InLoadOrderModuleList ,
140+ ListEntry = ListHead->Flink ;
141+ PLDR_DATA_TABLE_ENTRY CurEntry = nullptr ;
142+ while (ListEntry != ListHead) {
143+ CurEntry = CONTAINING_RECORD (ListEntry, LDR_DATA_TABLE_ENTRY, InLoadOrderLinks);
144+ ListEntry = ListEntry->Flink ;
145+ // Make sure the smallest base address is not our memory module
146+ if (IsValidMemoryModuleHandle ((HMEMORYMODULE)CurEntry->DllBase ))continue ;
147+ hModule = (HMODULE)(hModule ? min (hModule, CurEntry->DllBase ) : CurEntry->DllBase );
148+ }
149+ ModuleHeaders = RtlImageNtHeader (hModule);
150+ }
151+
152+ if (!hModule || !ModuleHeaders || !hNtdll || !NtdllHeaders)return nullptr ;
153+ dir = &ModuleHeaders->OptionalHeader .DataDirectory [IMAGE_DIRECTORY_ENTRY_EXCEPTION];
154+ entry = {
155+ dir->Size ? decltype (entry.ExceptionDirectory )((size_t )hModule + dir->VirtualAddress ) : nullptr ,
156+ (PVOID)hModule, ModuleHeaders->OptionalHeader .SizeOfImage ,dir->Size
157+ };
158+
159+ while (NT_SUCCESS (RtlFindMemoryBlockFromModuleSection (hNtdll, lpSectionName, &SearchContext))) {
160+ PRTL_INVERTED_FUNCTION_TABLE_64 tab = decltype (tab)(SearchContext.OutBufferPtr - 0x10 );
161+ if (RtlIsWindowsVersionOrGreater (6 , 2 , 0 ) && tab->MaxCount == 0x200 && !tab->Overflow ) return tab;
162+ else if (tab->MaxCount == 0x200 && !tab->Epoch ) return tab;
163+ }
164+
165+ return nullptr ;
166+ }
167+
168+ PLIST_ENTRY FindLdrpHashTable () {
169+ PLIST_ENTRY list = nullptr ;
170+ PLIST_ENTRY head = &NtCurrentPeb ()->Ldr ->InInitializationOrderModuleList , entry = head->Flink ;
171+ PLDR_DATA_TABLE_ENTRY CurEntry = nullptr ;
172+ while (head != entry) {
173+ CurEntry = CONTAINING_RECORD (entry, LDR_DATA_TABLE_ENTRY, LDR_DATA_TABLE_ENTRY::InInitializationOrderLinks);
174+ entry = entry->Flink ;
175+ if (CurEntry->HashLinks .Flink == &CurEntry->HashLinks )continue ;
176+ list = CurEntry->HashLinks .Flink ;
177+ if (list->Flink == &CurEntry->HashLinks ) {
178+ list = (decltype (list))((size_t )CurEntry->HashLinks .Flink - LdrHashEntry (CurEntry->BaseDllName ) * sizeof (_LIST_ENTRY));
179+ break ;
180+ }
181+ list = nullptr ;
182+ }
183+ return list;
184+ }
185+
186+ NTSTATUS InitializeLockHeld () {
187+ NTSTATUS status = STATUS_UNSUCCESSFUL;
188+ HANDLE hSection = nullptr ;
14189 OBJECT_ATTRIBUTES oa;
15190 LARGE_INTEGER li;
16191 UNICODE_STRING us{};
@@ -35,12 +210,26 @@ VOID InitializeLockHeld() {
35210 if (!NT_SUCCESS (status)) {
36211 if (status != STATUS_OBJECT_NAME_COLLISION) break ;
37212
213+ HANDLE hSection2;
38214 status = NtOpenSection (
39- &hSection ,
215+ &hSection2 ,
40216 SECTION_ALL_ACCESS,
41217 &oa
42218 );
43219 if (!NT_SUCCESS (status))break ;
220+
221+ SECTION_BASIC_INFORMATION sbi{};
222+ status = NtQuerySection (
223+ hSection2,
224+ SECTION_INFORMATION_CLASS::SectionBasicInformation,
225+ &sbi,
226+ sizeof (sbi),
227+ nullptr
228+ );
229+
230+ NtClose (hSection2);
231+ MmpGlobalDataPtr = (PMMP_GLOBAL_DATA)sbi.BaseAddress ;
232+ break ;
44233 }
45234
46235 PVOID BaseAddress = 0 ;
@@ -57,8 +246,52 @@ VOID InitializeLockHeld() {
57246 0 ,
58247 PAGE_READWRITE
59248 );
249+ if (!NT_SUCCESS (status))break ;
250+
251+ MmpGlobalDataPtr = (PMMP_GLOBAL_DATA)BaseAddress;
252+
253+ MmpGlobalDataPtr->MajorVersion = 1 ;
254+ MmpGlobalDataPtr->MinorVersion = 0 ;
255+
256+ MmpGlobalDataPtr->LdrpNtdllBase = RtlFindNtdllLdrEntry ();
257+ MmpGlobalDataPtr->LdrpHashTable = FindLdrpHashTable ();
258+
259+ MmpGlobalDataPtr->LdrpModuleBaseAddressIndex = FindLdrpModuleBaseAddressIndex ();
260+
261+ MmpGlobalDataPtr->LdrpInvertedFunctionTable = FindLdrpInvertedFunctionTable ();
262+
263+ MmpGlobalDataPtr->MmpFeatures = MEMORY_FEATURE_SUPPORT_VERSION | MEMORY_FEATURE_LDRP_HEAP | MEMORY_FEATURE_LDRP_HANDLE_TLS_DATA | MEMORY_FEATURE_LDRP_RELEASE_TLS_ENTRY;
264+ if (MmpGlobalDataPtr->LdrpModuleBaseAddressIndex )MmpGlobalDataPtr->MmpFeatures |= MEMORY_FEATURE_MODULE_BASEADDRESS_INDEX;
265+ if (MmpGlobalDataPtr->LdrpHashTable )MmpGlobalDataPtr->MmpFeatures |= MEMORY_FEATURE_LDRP_HASH_TABLE;
266+ if (MmpGlobalDataPtr->LdrpInvertedFunctionTable )MmpGlobalDataPtr->MmpFeatures |= MEMORY_FEATURE_INVERTED_FUNCTION_TABLE;
267+
268+ MmpTlsInitialize ();
60269
61270 } while (false );
62271
272+ if (!NT_SUCCESS (status) && hSection)NtClose (hSection);
63273 RtlFreeUnicodeString (&us);
274+ return status;
275+ }
276+
277+ NTSTATUS NTAPI Initialize () {
278+ NTSTATUS status;
279+
280+ RtlAcquirePebLock ();
281+ status = InitializeLockHeld ();
282+ RtlReleasePebLock ();
283+
284+ return status;
285+ }
286+
287+ #ifdef _USRDLL
288+ BOOL APIENTRY DllMain (HMODULE hModule, DWORD ul_reason_for_call, LPVOID lpReserved) {
289+ if (ul_reason_for_call == DLL_PROCESS_ATTACH) {
290+ return NT_SUCCESS (Initialize ());
291+ }
292+
293+ return TRUE ;
64294}
295+ #else
296+ const NTSTATUS Initializer = Initialize();
297+ #endif
0 commit comments