Skip to content

Commit 3468890

Browse files
committed
Refactored FindLdrpHashTable function, fixed crash when calling LdrUnloadDllMemory on Windows11
1 parent 06bb567 commit 3468890

4 files changed

Lines changed: 61 additions & 12 deletions

File tree

MemoryModule/Initialize.cpp

Lines changed: 42 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -158,22 +158,53 @@ PVOID FindLdrpInvertedFunctionTable64() {
158158
#define FindLdrpInvertedFunctionTable FindLdrpInvertedFunctionTable64
159159
#endif
160160

161+
BOOL IsValidLdrpHashTable(PLIST_ENTRY LdrpHashTable) {
162+
163+
//
164+
// Additional checks are performed to ensure that the LdrpHashTable is valid.
165+
//
166+
167+
__try {
168+
169+
for (ULONG i = 0; i < LDR_HASH_TABLE_ENTRIES; ++i) {
170+
PLIST_ENTRY head = &LdrpHashTable[i], entry = head->Flink;
171+
172+
while (head != entry) {
173+
PLDR_DATA_TABLE_ENTRY current = CONTAINING_RECORD(entry, LDR_DATA_TABLE_ENTRY, LDR_DATA_TABLE_ENTRY::HashLinks);
174+
175+
if (LdrHashEntry(current->BaseDllName) != i) {
176+
return FALSE;
177+
}
178+
179+
entry = entry->Flink;
180+
}
181+
}
182+
183+
return TRUE;
184+
}
185+
__except (EXCEPTION_EXECUTE_HANDLER) {
186+
return FALSE;
187+
}
188+
189+
}
190+
161191
PLIST_ENTRY FindLdrpHashTable() {
162-
PLIST_ENTRY list = nullptr;
163192
PLIST_ENTRY head = &NtCurrentPeb()->Ldr->InInitializationOrderModuleList, entry = head->Flink;
164-
PLDR_DATA_TABLE_ENTRY CurEntry = nullptr;
193+
165194
while (head != entry) {
166-
CurEntry = CONTAINING_RECORD(entry, LDR_DATA_TABLE_ENTRY, LDR_DATA_TABLE_ENTRY::InInitializationOrderLinks);
167-
entry = entry->Flink;
168-
if (CurEntry->HashLinks.Flink == &CurEntry->HashLinks)continue;
169-
list = CurEntry->HashLinks.Flink;
170-
if (list->Flink == &CurEntry->HashLinks) {
171-
list = (decltype(list))((size_t)CurEntry->HashLinks.Flink - LdrHashEntry(CurEntry->BaseDllName) * sizeof(_LIST_ENTRY));
172-
break;
195+
PLDR_DATA_TABLE_ENTRY current = CONTAINING_RECORD(entry, LDR_DATA_TABLE_ENTRY, LDR_DATA_TABLE_ENTRY::InInitializationOrderLinks);
196+
PLIST_ENTRY hashEntry = &current->HashLinks;
197+
198+
if (hashEntry->Flink != hashEntry && hashEntry->Flink->Flink == hashEntry) {
199+
PLIST_ENTRY table = &hashEntry->Flink[-(LONG)LdrHashEntry(current->BaseDllName)];
200+
201+
return IsValidLdrpHashTable(table) ? table : nullptr;
173202
}
174-
list = nullptr;
203+
204+
entry = entry->Flink;
175205
}
176-
return list;
206+
207+
return nullptr;
177208
}
178209

179210
VOID InitializeWindowsVersion() {

MemoryModule/LdrEntry.cpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -197,6 +197,7 @@ BOOL NTAPI RtlInitializeLdrDataTableEntry(
197197
BOOL NTAPI RtlFreeLdrDataTableEntry(_In_ PLDR_DATA_TABLE_ENTRY LdrEntry) {
198198
HANDLE heap = NtCurrentPeb()->ProcessHeap;
199199
switch (MmpGlobalDataPtr->WindowsVersion) {
200+
case WINDOWS_VERSION::win11:
200201
case WINDOWS_VERSION::win10:
201202
case WINDOWS_VERSION::win10_1:
202203
case WINDOWS_VERSION::win10_2:

MemoryModule/MmpGlobalData.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -77,7 +77,7 @@ typedef enum class _WINDOWS_VERSION :BYTE {
7777
}WINDOWS_VERSION;
7878

7979
#define MEMORY_MODULE_MAJOR_VERSION 1
80-
#define MEMORY_MODULE_MINOR_VERSION 0
80+
#define MEMORY_MODULE_MINOR_VERSION 1
8181

8282
typedef struct _MMP_GLOBAL_DATA {
8383

test/test.cpp

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,21 @@ static PVOID ReadDllFile(LPCSTR FileName) {
1818
return buffer;
1919
}
2020

21+
static void DisplayStatus() {
22+
printf(
23+
"MemoryModulePP [Version %d.%d]\n\n\tMmpFeatures = %08X\n\n\tLdrpModuleBaseAddressIndex = %p\n\tNtdllLdrEntry = %p\n\tRtlRbInsertNodeEx = %p\n\tRtlRbRemoveNode = %p\n\n\tLdrpInvertedFunctionTable = %p\n\n\tLdrpHashTable = %p\n\n",
24+
MmpGlobalDataPtr->MajorVersion,
25+
MmpGlobalDataPtr->MinorVersion,
26+
MmpGlobalDataPtr->MmpFeatures,
27+
MmpGlobalDataPtr->MmpBaseAddressIndex->LdrpModuleBaseAddressIndex,
28+
MmpGlobalDataPtr->MmpBaseAddressIndex->NtdllLdrEntry,
29+
MmpGlobalDataPtr->MmpBaseAddressIndex->_RtlRbInsertNodeEx,
30+
MmpGlobalDataPtr->MmpBaseAddressIndex->_RtlRbRemoveNode,
31+
MmpGlobalDataPtr->MmpInvertedFunctionTable->LdrpInvertedFunctionTable,
32+
MmpGlobalDataPtr->MmpLdrEntry->LdrpHashTable
33+
);
34+
}
35+
2136
int test() {
2237
LPVOID buffer = ReadDllFile("a.dll");
2338

@@ -101,6 +116,8 @@ int test() {
101116
}
102117

103118
int main() {
119+
DisplayStatus();
120+
104121
test();
105122

106123
return 0;

0 commit comments

Comments
 (0)