diff --git a/MemoryModule/BaseAddressIndex.cpp b/MemoryModule/BaseAddressIndex.cpp index 5bacd47..70029e8 100644 --- a/MemoryModule/BaseAddressIndex.cpp +++ b/MemoryModule/BaseAddressIndex.cpp @@ -1,25 +1,43 @@ #include "stdafx.h" +VOID RtlRbInsertNodeEx( + _In_ PRTL_RB_TREE Tree, + _In_ PRTL_BALANCED_NODE Parent, + _In_ BOOLEAN Right, + _Out_ PRTL_BALANCED_NODE Node) { + RtlZeroMemory(Node, sizeof(*Node)); + + if (!MmpGlobalDataPtr->MmpBaseAddressIndex->_RtlRbInsertNodeEx)return; + return decltype(&RtlRbInsertNodeEx)(MmpGlobalDataPtr->MmpBaseAddressIndex->_RtlRbInsertNodeEx)(Tree, Parent, Right, Node); +} + +VOID RtlRbRemoveNode( + _In_ PRTL_RB_TREE Tree, + _In_ PRTL_BALANCED_NODE Node) { + if (!MmpGlobalDataPtr->MmpBaseAddressIndex->_RtlRbRemoveNode)return; + return decltype(&RtlRbRemoveNode)(MmpGlobalDataPtr->MmpBaseAddressIndex->_RtlRbRemoveNode)(Tree, Node); +} + NTSTATUS NTAPI RtlInsertModuleBaseAddressIndexNode( _In_ PLDR_DATA_TABLE_ENTRY DataTableEntry, _In_ PVOID BaseAddress) { auto LdrpModuleBaseAddressIndex = MmpGlobalDataPtr->MmpBaseAddressIndex->LdrpModuleBaseAddressIndex; if (!LdrpModuleBaseAddressIndex)return STATUS_UNSUCCESSFUL; - PLDR_DATA_TABLE_ENTRY_WIN8 LdrNode = decltype(LdrNode)((size_t)LdrpModuleBaseAddressIndex - offsetof(LDR_DATA_TABLE_ENTRY_WIN8, BaseAddressIndexNode)); + PLDR_DATA_TABLE_ENTRY_WIN8 LdrNode = CONTAINING_RECORD(LdrpModuleBaseAddressIndex, LDR_DATA_TABLE_ENTRY_WIN8, BaseAddressIndexNode); bool bRight = false; - const auto i = offsetof(LDR_DATA_TABLE_ENTRY_WIN8, BaseAddressIndexNode); + while (true) { if (BaseAddress < LdrNode->DllBase) { if (!LdrNode->BaseAddressIndexNode.Left)break; - LdrNode = decltype(LdrNode)((size_t)LdrNode->BaseAddressIndexNode.Left - offsetof(LDR_DATA_TABLE_ENTRY_WIN8, BaseAddressIndexNode)); + LdrNode = CONTAINING_RECORD(LdrNode->BaseAddressIndexNode.Left, LDR_DATA_TABLE_ENTRY_WIN8, BaseAddressIndexNode); } else if (BaseAddress > LdrNode->DllBase) { if (!LdrNode->BaseAddressIndexNode.Right) { bRight = true; break; } - LdrNode = decltype(LdrNode)((size_t)LdrNode->BaseAddressIndexNode.Right - offsetof(LDR_DATA_TABLE_ENTRY_WIN8, BaseAddressIndexNode)); + LdrNode = CONTAINING_RECORD(LdrNode->BaseAddressIndexNode.Right, LDR_DATA_TABLE_ENTRY_WIN8, BaseAddressIndexNode); } else { LdrNode->DdagNode->LoadCount++; diff --git a/MemoryModule/Initialize.cpp b/MemoryModule/Initialize.cpp index 2db1a65..edb3f9a 100644 --- a/MemoryModule/Initialize.cpp +++ b/MemoryModule/Initialize.cpp @@ -269,7 +269,7 @@ VOID InitializeWindowsVersion() { } } else { - // [13494, 15063) + // [14393, 15063) version = WINDOWS_VERSION::win10_1; LdrDataTableEntrySize = sizeof(LDR_DATA_TABLE_ENTRY_WIN10_1); } @@ -415,12 +415,11 @@ NTSTATUS InitializeLockHeld() { MmpGlobalDataPtr->MmpTls = (PMMP_TLS_DATA)((LPBYTE)MmpGlobalDataPtr->MmpLdrEntry + sizeof(MMP_LDR_ENTRY_DATA)); MmpGlobalDataPtr->MmpDotNet = (PMMP_DOT_NET_DATA)((LPBYTE)MmpGlobalDataPtr->MmpTls + sizeof(MMP_TLS_DATA)); - MmpGlobalDataPtr->MmpBaseAddressIndex->NtdllLdrEntry = RtlFindLdrTableEntryByBaseName(L"ntdll.dll"); + PLDR_DATA_TABLE_ENTRY pNtdllEntry = RtlFindLdrTableEntryByBaseName(L"ntdll.dll"); + MmpGlobalDataPtr->MmpBaseAddressIndex->NtdllLdrEntry = pNtdllEntry; 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->MmpBaseAddressIndex->_RtlRbInsertNodeEx = GetProcAddress((HMODULE)pNtdllEntry->DllBase, "RtlRbInsertNodeEx"); + MmpGlobalDataPtr->MmpBaseAddressIndex->_RtlRbRemoveNode = GetProcAddress((HMODULE)pNtdllEntry->DllBase, "RtlRbRemoveNode"); MmpGlobalDataPtr->MmpLdrEntry->LdrpHashTable = FindLdrpHashTable(); diff --git a/MemoryModule/LdrEntry.cpp b/MemoryModule/LdrEntry.cpp index 4d4928a..8a81c8a 100644 --- a/MemoryModule/LdrEntry.cpp +++ b/MemoryModule/LdrEntry.cpp @@ -281,24 +281,6 @@ VOID NTAPI RtlInsertMemoryTableEntry(_In_ PLDR_DATA_TABLE_ENTRY LdrEntry) { InsertTailList(&PebData->InInitializationOrderModuleList, &LdrEntry->InInitializationOrderLinks); } -VOID NTAPI RtlRbInsertNodeEx( - _In_ PRTL_RB_TREE Tree, - _In_ PRTL_BALANCED_NODE Parent, - _In_ BOOLEAN Right, - _Out_ PRTL_BALANCED_NODE Node) { - RtlZeroMemory(Node, sizeof(*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) { - if (!MmpGlobalDataPtr->MmpLdrEntry->_RtlRbRemoveNode)return; - return MmpGlobalDataPtr->MmpLdrEntry->_RtlRbRemoveNode(Tree, Node); -} - PLDR_DATA_TABLE_ENTRY NTAPI RtlFindLdrTableEntryByHandle(_In_ PVOID BaseAddress) { PLIST_ENTRY ListHead = &NtCurrentPeb()->Ldr->InLoadOrderModuleList, ListEntry = ListHead->Flink; PLDR_DATA_TABLE_ENTRY CurEntry; diff --git a/MemoryModule/LdrEntry.h b/MemoryModule/LdrEntry.h index 74c22fc..e0fb3a2 100644 --- a/MemoryModule/LdrEntry.h +++ b/MemoryModule/LdrEntry.h @@ -62,18 +62,6 @@ PLDR_DATA_TABLE_ENTRY NTAPI RtlFindLdrTableEntryByBaseName(_In_z_ PCWSTR BaseNam #define LDR_GET_HASH_ENTRY(x) (RtlUpcaseUnicodeChar((x)) & (LDR_HASH_TABLE_ENTRIES - 1)) #define LDR_HASH_TABLE_ENTRIES 32 -VOID NTAPI RtlRbInsertNodeEx( - _In_ PRTL_RB_TREE Tree, - _In_ PRTL_BALANCED_NODE Parent, - _In_ BOOLEAN Right, - _Out_ PRTL_BALANCED_NODE Node -); - -VOID NTAPI RtlRbRemoveNode( - _In_ PRTL_RB_TREE Tree, - _In_ PRTL_BALANCED_NODE Node -); - struct _LDR_DDAG_NODE_WIN8 { _LIST_ENTRY Modules; //0x0 _LDR_SERVICE_TAG_RECORD* ServiceTagList; //0x10 diff --git a/MemoryModule/MmpGlobalData.h b/MemoryModule/MmpGlobalData.h index 718a059..73de1b5 100644 --- a/MemoryModule/MmpGlobalData.h +++ b/MemoryModule/MmpGlobalData.h @@ -4,6 +4,9 @@ typedef struct _MMP_BASE_ADDRESS_INDEX_DATA { PRTL_RB_TREE LdrpModuleBaseAddressIndex; PLDR_DATA_TABLE_ENTRY NtdllLdrEntry; + + PVOID _RtlRbInsertNodeEx; + PVOID _RtlRbRemoveNode; }MMP_BASE_ADDRESS_INDEX_DATA, * PMMP_BASE_ADDRESS_INDEX_DATA; //InvertedFunctionTable.cpp @@ -14,9 +17,6 @@ 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 diff --git a/test/test.cpp b/test/test.cpp index e05b7e2..f44c2dc 100644 --- a/test/test.cpp +++ b/test/test.cpp @@ -19,52 +19,89 @@ static PVOID ReadDllFile(LPCSTR FileName) { } int test() { - HMODULE hModule; - NTSTATUS status; - PVOID buffer = ReadDllFile("a.dll"); - if (!buffer) return 0; + LPVOID buffer = ReadDllFile("a.dll"); - status = LdrLoadDllMemoryExW( - &hModule, // ModuleHandle - nullptr, // LdrEntry - 0, // Flags - buffer, // Buffer - 0, // Reserved - nullptr, // DllBaseName - nullptr // DllFullName - ); - if (NT_SUCCESS(status) && status != STATUS_IMAGE_MACHINE_TYPE_MISMATCH) { + HMEMORYMODULE m1 = nullptr, m2 = m1; + HMODULE hModule = nullptr; + FARPROC pfn = nullptr; + DWORD MemoryModuleFeatures = 0; - typedef int(__stdcall* func)(); - func test_user32 = (func)GetProcAddress(hModule, "test_user32"); - test_user32(); + typedef int(*_exception)(int code); + _exception exception = nullptr; + HRSRC hRsrc; + DWORD SizeofRes; + HGLOBAL gRes; + char str[10]; - // - // After calling MessageBox, we can't free it. - // - //LdrUnloadDllMemory(hModule); + LdrQuerySystemMemoryModuleFeatures(&MemoryModuleFeatures); + if (MemoryModuleFeatures != MEMORY_FEATURE_ALL) { + printf("not support all features on this version of windows.\n"); } + if (!NT_SUCCESS(LdrLoadDllMemoryExW(&m1, nullptr, 0, buffer, 0, L"kernel64", nullptr))) goto end; + LoadLibraryW(L"wininet.dll"); + if (!NT_SUCCESS(LdrLoadDllMemoryExW(&m2, nullptr, 0, buffer, 0, L"kernel128", nullptr))) goto end; + + //forward export + hModule = (HMODULE)m1; + pfn = (decltype(pfn))(GetProcAddress(hModule, "Socket")); //ws2_32.WSASocketW + pfn = (decltype(pfn))(GetProcAddress(hModule, "VerifyTruse")); //wintrust.WinVerifyTrust + hModule = (HMODULE)m2; + pfn = (decltype(pfn))(GetProcAddress(hModule, "Socket")); + pfn = (decltype(pfn))(GetProcAddress(hModule, "VerifyTruse")); + + //exception + hModule = (HMODULE)m1; + exception = (_exception)GetProcAddress(hModule, "exception"); + if (exception) { + for (int i = 0; i < 5; ++i)exception(i); + } + + //tls + pfn = GetProcAddress(hModule, "thread"); + if (pfn && pfn()) { + printf("thread test failed.\n"); + } + + //resource + if (!LoadStringA(hModule, 101, str, 10)) { + printf("load string failed.\n"); + } + else { + printf("%s\n", str); + } + if (!(hRsrc = FindResourceA(hModule, MAKEINTRESOURCEA(102), "BINARY"))) { + printf("find binary resource failed.\n"); + } + else { + if ((SizeofRes = SizeofResource(hModule, hRsrc)) != 0x10) { + printf("invalid res size.\n"); + } + else { + if (!(gRes = LoadResource(hModule, hRsrc))) { + printf("load res failed.\n"); + } + else { + if (!LockResource(gRes))printf("lock res failed.\n"); + else { + printf("resource test success.\n"); + } + } + } + } + +end: + delete[]buffer; + if (m1)LdrUnloadDllMemory(m1); + FreeLibrary(LoadLibraryW(L"wininet.dll")); + FreeLibrary(GetModuleHandleW(L"wininet.dll")); + if (m2)LdrUnloadDllMemory(m2); + return 0; } int main() { - 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; - } - } + test(); return 0; }