diff --git a/3rdparty/phnt/include/ntldr.h b/3rdparty/phnt/include/ntldr.h index bae8336..e4cc4f6 100644 --- a/3rdparty/phnt/include/ntldr.h +++ b/3rdparty/phnt/include/ntldr.h @@ -130,12 +130,6 @@ typedef enum _LDR_HOT_PATCH_STATE #define LDRP_REDIRECTED 0x10000000 #define LDRP_COMPAT_DATABASE_PROCESSED 0x80000000 -#define LDR_DATA_TABLE_ENTRY_SIZE_WINXP FIELD_OFFSET(LDR_DATA_TABLE_ENTRY, DdagNode) -#define LDR_DATA_TABLE_ENTRY_SIZE_WIN7 FIELD_OFFSET(LDR_DATA_TABLE_ENTRY, BaseNameHashValue) -#define LDR_DATA_TABLE_ENTRY_SIZE_WIN8 FIELD_OFFSET(LDR_DATA_TABLE_ENTRY, ImplicitPathOptions) -#define LDR_DATA_TABLE_ENTRY_SIZE_WIN10 FIELD_OFFSET(LDR_DATA_TABLE_ENTRY, SigningLevel) -#define LDR_DATA_TABLE_ENTRY_SIZE_WIN11 sizeof(LDR_DATA_TABLE_ENTRY) - // symbols typedef struct _LDR_DATA_TABLE_ENTRY { diff --git a/3rdparty/phnt/include/ntwow64.h b/3rdparty/phnt/include/ntwow64.h index d713e38..f8f55c6 100644 --- a/3rdparty/phnt/include/ntwow64.h +++ b/3rdparty/phnt/include/ntwow64.h @@ -100,10 +100,6 @@ typedef struct _LDR_DDAG_NODE32 ULONG PreorderNumber; } LDR_DDAG_NODE32, *PLDR_DDAG_NODE32; -#define LDR_DATA_TABLE_ENTRY_SIZE_WINXP_32 FIELD_OFFSET(LDR_DATA_TABLE_ENTRY32, DdagNode) -#define LDR_DATA_TABLE_ENTRY_SIZE_WIN7_32 FIELD_OFFSET(LDR_DATA_TABLE_ENTRY32, BaseNameHashValue) -#define LDR_DATA_TABLE_ENTRY_SIZE_WIN8_32 FIELD_OFFSET(LDR_DATA_TABLE_ENTRY32, ImplicitPathOptions) - typedef struct _LDR_DATA_TABLE_ENTRY32 { LIST_ENTRY32 InLoadOrderLinks; diff --git a/MemoryModule/BaseAddressIndex.cpp b/MemoryModule/BaseAddressIndex.cpp index 5b6f180..5bacd47 100644 --- a/MemoryModule/BaseAddressIndex.cpp +++ b/MemoryModule/BaseAddressIndex.cpp @@ -3,7 +3,7 @@ NTSTATUS NTAPI RtlInsertModuleBaseAddressIndexNode( _In_ PLDR_DATA_TABLE_ENTRY DataTableEntry, _In_ PVOID BaseAddress) { - auto LdrpModuleBaseAddressIndex = MmpGlobalDataPtr->MmpBaseAddressIndex.LdrpModuleBaseAddressIndex; + 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)); @@ -35,7 +35,7 @@ NTSTATUS NTAPI RtlInsertModuleBaseAddressIndexNode( } NTSTATUS NTAPI RtlRemoveModuleBaseAddressIndexNode(_In_ PLDR_DATA_TABLE_ENTRY DataTableEntry) { - static auto tree{ MmpGlobalDataPtr->MmpBaseAddressIndex.LdrpModuleBaseAddressIndex }; + static auto tree{ MmpGlobalDataPtr->MmpBaseAddressIndex->LdrpModuleBaseAddressIndex }; if (!tree->Root)return STATUS_UNSUCCESSFUL; RtlRbRemoveNode(tree, &PLDR_DATA_TABLE_ENTRY_WIN8(DataTableEntry)->BaseAddressIndexNode); return STATUS_SUCCESS; diff --git a/MemoryModule/Initialize.cpp b/MemoryModule/Initialize.cpp index 6fc0e90..2db1a65 100644 --- a/MemoryModule/Initialize.cpp +++ b/MemoryModule/Initialize.cpp @@ -12,7 +12,7 @@ BOOLEAN MmpBuildSectionName(_Out_ PUNICODE_STRING SectionName) { PRTL_RB_TREE FindLdrpModuleBaseAddressIndex() { PRTL_RB_TREE LdrpModuleBaseAddressIndex = nullptr; - PLDR_DATA_TABLE_ENTRY_WIN10 nt10 = decltype(nt10)(MmpGlobalDataPtr->MmpBaseAddressIndex.NtdllLdrEntry); + PLDR_DATA_TABLE_ENTRY_WIN10 nt10 = decltype(nt10)(MmpGlobalDataPtr->MmpBaseAddressIndex->NtdllLdrEntry); PRTL_BALANCED_NODE node = nullptr; if (!nt10 || !RtlIsWindowsVersionOrGreater(6, 2, 0))return nullptr; node = &nt10->BaseAddressIndexNode; @@ -186,55 +186,64 @@ PLIST_ENTRY FindLdrpHashTable() { VOID InitializeWindowsVersion() { WINDOWS_VERSION version = WINDOWS_VERSION::invalid; + DWORD MajorVersion, MinorVersion, BuildNumber, LdrDataTableEntrySize; - switch (MmpGlobalDataPtr->NtVersions.MajorVersion) { + RtlGetNtVersionNumbers( + &MajorVersion, + &MinorVersion, + &BuildNumber + ); + if (BuildNumber & 0xf0000000)BuildNumber &= 0xffff; + + switch (MajorVersion) { case 5: { - switch (MmpGlobalDataPtr->NtVersions.MinorVersion) { - case 1: - if (MmpGlobalDataPtr->NtVersions.BuildNumber == 2600) - version = WINDOWS_VERSION::xp; - break; - - case 2: - if (MmpGlobalDataPtr->NtVersions.BuildNumber == 3790) - version = WINDOWS_VERSION::xp; - break; + if ((MinorVersion == 1 && BuildNumber == 2600) || + (MinorVersion == 2 && BuildNumber == 3790)) { + version = WINDOWS_VERSION::xp; + LdrDataTableEntrySize = sizeof(LDR_DATA_TABLE_ENTRY_XP); } + break; } case 6: { - switch (MmpGlobalDataPtr->NtVersions.MinorVersion) { + switch (MinorVersion) { case 0: { - switch (MmpGlobalDataPtr->NtVersions.BuildNumber) { + switch (BuildNumber) { case 6000: case 6001: case 6002: version = WINDOWS_VERSION::vista; + LdrDataTableEntrySize = sizeof(LDR_DATA_TABLE_ENTRY_VISTA); break; } break; } case 1: { - switch (MmpGlobalDataPtr->NtVersions.BuildNumber) { + switch (BuildNumber) { case 7600: case 7601: version = WINDOWS_VERSION::win7; + LdrDataTableEntrySize = sizeof(LDR_DATA_TABLE_ENTRY_WIN7); break; } break; } case 2: { - if (MmpGlobalDataPtr->NtVersions.BuildNumber == 9200) + if (BuildNumber == 9200) { version = WINDOWS_VERSION::win8; + LdrDataTableEntrySize = sizeof(LDR_DATA_TABLE_ENTRY_WIN8); + } break; } case 3: { - if (MmpGlobalDataPtr->NtVersions.BuildNumber == 9600) + if (BuildNumber == 9600) { version = WINDOWS_VERSION::winBlue; + LdrDataTableEntrySize = sizeof(LDR_DATA_TABLE_ENTRY_WINBLUE); + } break; } @@ -243,29 +252,32 @@ VOID InitializeWindowsVersion() { } case 10: { - if (MmpGlobalDataPtr->NtVersions.MinorVersion)break; + if (MinorVersion)break; - DWORD BuildNumber = MmpGlobalDataPtr->NtVersions.BuildNumber; if (BuildNumber >= 10240) { if (BuildNumber >= 14393) { if (BuildNumber >= 15063) { if (BuildNumber >= 22000) { // [22000, ?) version = WINDOWS_VERSION::win11; + LdrDataTableEntrySize = sizeof(LDR_DATA_TABLE_ENTRY_WIN11); } else { // [15063, 22000) version = WINDOWS_VERSION::win10_2; + LdrDataTableEntrySize = sizeof(LDR_DATA_TABLE_ENTRY_WIN10_2); } } else { // [13494, 15063) version = WINDOWS_VERSION::win10_1; + LdrDataTableEntrySize = sizeof(LDR_DATA_TABLE_ENTRY_WIN10_1); } } else { // [10240, 14393) version = WINDOWS_VERSION::win10; + LdrDataTableEntrySize = sizeof(LDR_DATA_TABLE_ENTRY_WIN10); } } @@ -275,158 +287,156 @@ VOID InitializeWindowsVersion() { } MmpGlobalDataPtr->WindowsVersion = version; + if (version != WINDOWS_VERSION::invalid) { + MmpGlobalDataPtr->NtVersions.MajorVersion = MajorVersion; + MmpGlobalDataPtr->NtVersions.MinorVersion = MinorVersion; + MmpGlobalDataPtr->NtVersions.BuildNumber = BuildNumber; + MmpGlobalDataPtr->LdrDataTableEntrySize = (WORD)LdrDataTableEntrySize; + } + +} + +NTSTATUS MmpAllocateGlobalData() { + NTSTATUS status = STATUS_UNSUCCESSFUL; + HANDLE hSection = nullptr; + OBJECT_ATTRIBUTES oa; + LARGE_INTEGER li; + UNICODE_STRING us{}; + + li.QuadPart = 0x1000; + + do { + + if (!MmpBuildSectionName(&us))break; + + 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)) { + if (status != STATUS_OBJECT_NAME_COLLISION) break; + + HANDLE hSection2; + status = NtOpenSection( + &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; + SIZE_T ViewSize = 0; + status = NtMapViewOfSection( + hSection, + NtCurrentProcess(), + &BaseAddress, + 0, + 0, + nullptr, + &ViewSize, + ViewUnmap, + 0, + PAGE_READWRITE + ); + if (!NT_SUCCESS(status))break; + + MmpGlobalDataPtr = (PMMP_GLOBAL_DATA)BaseAddress; + + } while (false); + + RtlFreeUnicodeString(&us); + + if (NT_SUCCESS(status)) { + status = hSection ? status : STATUS_ALREADY_INITIALIZED; + } + else { + if (hSection)NtClose(hSection); + } + + return status; } NTSTATUS InitializeLockHeld() { - NTSTATUS status = STATUS_UNSUCCESSFUL; - HANDLE hSection = nullptr; - OBJECT_ATTRIBUTES oa; - LARGE_INTEGER li; - UNICODE_STRING us{}; - - li.QuadPart = 0x1000; + NTSTATUS status; do { - if (!MmpBuildSectionName(&us))break; + status = MmpAllocateGlobalData(); + if (!NT_SUCCESS(status)) { + if (status == STATUS_ALREADY_INITIALIZED) { + if ((MmpGlobalDataPtr->MajorVersion < MEMORY_MODULE_MAJOR_VERSION) || + (MmpGlobalDataPtr->MajorVersion == MEMORY_MODULE_MAJOR_VERSION && MmpGlobalDataPtr->MinorVersion < MEMORY_MODULE_MINOR_VERSION)) { + status = STATUS_NOT_SUPPORTED; + } + else { + status = STATUS_SUCCESS; + } + } - InitializeObjectAttributes(&oa, &us, 0, nullptr, nullptr); + break; + } - status = NtCreateSection( - &hSection, - SECTION_ALL_ACCESS, - &oa, - &li, - PAGE_READWRITE, - SEC_COMMIT | SEC_BASED, - nullptr - ); - if (!NT_SUCCESS(status)) { - if (status != STATUS_OBJECT_NAME_COLLISION) break; - - HANDLE hSection2; - status = NtOpenSection( - &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; - SIZE_T ViewSize = 0; - status = NtMapViewOfSection( - hSection, - NtCurrentProcess(), - &BaseAddress, - 0, - 0, - nullptr, - &ViewSize, - ViewUnmap, - 0, - PAGE_READWRITE - ); - if (!NT_SUCCESS(status))break; - - MmpGlobalDataPtr = (PMMP_GLOBAL_DATA)BaseAddress; - - MmpGlobalDataPtr->MajorVersion = 1; - MmpGlobalDataPtr->MinorVersion = 0; + MmpGlobalDataPtr->MajorVersion = MEMORY_MODULE_MAJOR_VERSION; + MmpGlobalDataPtr->MinorVersion = MEMORY_MODULE_MINOR_VERSION; GetSystemInfo(&MmpGlobalDataPtr->SystemInfo); - RtlGetNtVersionNumbers( - &MmpGlobalDataPtr->NtVersions.MajorVersion, - &MmpGlobalDataPtr->NtVersions.MinorVersion, - &MmpGlobalDataPtr->NtVersions.BuildNumber - ); - if (MmpGlobalDataPtr->NtVersions.BuildNumber & 0xf0000000)MmpGlobalDataPtr->NtVersions.BuildNumber &= 0xffff; - InitializeWindowsVersion(); - - switch (MmpGlobalDataPtr->WindowsVersion) { - case WINDOWS_VERSION::xp: - MmpGlobalDataPtr->LdrDataTableEntrySize = sizeof(LDR_DATA_TABLE_ENTRY_XP); - break; - - case WINDOWS_VERSION::vista: - MmpGlobalDataPtr->LdrDataTableEntrySize = sizeof(LDR_DATA_TABLE_ENTRY_VISTA); - break; - - case WINDOWS_VERSION::win7: - MmpGlobalDataPtr->LdrDataTableEntrySize = sizeof(LDR_DATA_TABLE_ENTRY_WIN7); - break; - - case WINDOWS_VERSION::win8: - MmpGlobalDataPtr->LdrDataTableEntrySize = sizeof(LDR_DATA_TABLE_ENTRY_WIN8); - break; - - case WINDOWS_VERSION::winBlue: - MmpGlobalDataPtr->LdrDataTableEntrySize = sizeof(LDR_DATA_TABLE_ENTRY_WINBLUE); - break; - - case WINDOWS_VERSION::win10: - MmpGlobalDataPtr->LdrDataTableEntrySize = sizeof(LDR_DATA_TABLE_ENTRY_WIN10); - break; - - case WINDOWS_VERSION::win10_1: - MmpGlobalDataPtr->LdrDataTableEntrySize = sizeof(LDR_DATA_TABLE_ENTRY_WIN10_1); - break; - - case WINDOWS_VERSION::win10_2: - MmpGlobalDataPtr->LdrDataTableEntrySize = sizeof(LDR_DATA_TABLE_ENTRY_WIN10_2); - break; - - case WINDOWS_VERSION::win11: - MmpGlobalDataPtr->LdrDataTableEntrySize = sizeof(LDR_DATA_TABLE_ENTRY_WIN11); - break; - - default: - NtUnmapViewOfSection(NtCurrentProcess(), BaseAddress); + if (MmpGlobalDataPtr->WindowsVersion == WINDOWS_VERSION::invalid) { + NtUnmapViewOfSection(NtCurrentProcess(), MmpGlobalDataPtr); status = STATUS_NOT_SUPPORTED; break; } - if (!NT_SUCCESS(status))break; + MmpGlobalDataPtr->MmpBaseAddressIndex = (PMMP_BASE_ADDRESS_INDEX_DATA)((LPBYTE)MmpGlobalDataPtr + sizeof(MMP_GLOBAL_DATA)); + MmpGlobalDataPtr->MmpInvertedFunctionTable = (PMMP_INVERTED_FUNCTION_TABLE_DATA)((LPBYTE)MmpGlobalDataPtr->MmpBaseAddressIndex + sizeof(MMP_BASE_ADDRESS_INDEX_DATA)); + MmpGlobalDataPtr->MmpLdrEntry = (PMMP_LDR_ENTRY_DATA)((LPBYTE)MmpGlobalDataPtr->MmpInvertedFunctionTable + sizeof(MMP_INVERTED_FUNCTION_TABLE_DATA)); + 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"); - MmpGlobalDataPtr->MmpBaseAddressIndex.LdrpModuleBaseAddressIndex = FindLdrpModuleBaseAddressIndex(); + 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")); + 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->MmpLdrEntry->LdrpHashTable = FindLdrpHashTable(); - MmpGlobalDataPtr->MmpInvertedFunctionTable.LdrpInvertedFunctionTable = FindLdrpInvertedFunctionTable(); + MmpGlobalDataPtr->MmpInvertedFunctionTable->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->MmpBaseAddressIndex.LdrpModuleBaseAddressIndex)MmpGlobalDataPtr->MmpFeatures |= MEMORY_FEATURE_MODULE_BASEADDRESS_INDEX; - if (MmpGlobalDataPtr->MmpLdrEntry.LdrpHashTable)MmpGlobalDataPtr->MmpFeatures |= MEMORY_FEATURE_LDRP_HASH_TABLE; - if (MmpGlobalDataPtr->MmpInvertedFunctionTable.LdrpInvertedFunctionTable)MmpGlobalDataPtr->MmpFeatures |= MEMORY_FEATURE_INVERTED_FUNCTION_TABLE; + if (MmpGlobalDataPtr->MmpBaseAddressIndex->LdrpModuleBaseAddressIndex)MmpGlobalDataPtr->MmpFeatures |= MEMORY_FEATURE_MODULE_BASEADDRESS_INDEX; + if (MmpGlobalDataPtr->MmpLdrEntry->LdrpHashTable)MmpGlobalDataPtr->MmpFeatures |= MEMORY_FEATURE_LDRP_HASH_TABLE; + if (MmpGlobalDataPtr->MmpInvertedFunctionTable->LdrpInvertedFunctionTable)MmpGlobalDataPtr->MmpFeatures |= MEMORY_FEATURE_INVERTED_FUNCTION_TABLE; MmpTlsInitialize(); - MmpGlobalDataPtr->MmpDotNet.Initialized = MmpGlobalDataPtr->MmpDotNet.PreHooked = FALSE; + MmpGlobalDataPtr->MmpDotNet->Initialized = MmpGlobalDataPtr->MmpDotNet->PreHooked = FALSE; } while (false); - if (!NT_SUCCESS(status) && hSection)NtClose(hSection); - RtlFreeUnicodeString(&us); return status; } diff --git a/MemoryModule/InvertedFunctionTable.cpp b/MemoryModule/InvertedFunctionTable.cpp index 572a410..3830a48 100644 --- a/MemoryModule/InvertedFunctionTable.cpp +++ b/MemoryModule/InvertedFunctionTable.cpp @@ -151,7 +151,7 @@ static NTSTATUS RtlProtectMrdata(_In_ ULONG Protect) { if (!MrdataBase) { MEMORY_BASIC_INFORMATION mbi{}; - status = NtQueryVirtualMemory(GetCurrentProcess(), MmpGlobalDataPtr->MmpInvertedFunctionTable.LdrpInvertedFunctionTable, MemoryBasicInformation, &mbi, sizeof(mbi), nullptr); + status = NtQueryVirtualMemory(GetCurrentProcess(), MmpGlobalDataPtr->MmpInvertedFunctionTable->LdrpInvertedFunctionTable, MemoryBasicInformation, &mbi, sizeof(mbi), nullptr); if (!NT_SUCCESS(status))return status; MrdataBase = mbi.BaseAddress; size = mbi.RegionSize; @@ -165,7 +165,7 @@ static NTSTATUS RtlProtectMrdata(_In_ ULONG Protect) { NTSTATUS NTAPI RtlInsertInvertedFunctionTable( _In_ PVOID BaseAddress, _In_ ULONG ImageSize) { - auto table = PRTL_INVERTED_FUNCTION_TABLE(MmpGlobalDataPtr->MmpInvertedFunctionTable.LdrpInvertedFunctionTable); + auto table = PRTL_INVERTED_FUNCTION_TABLE(MmpGlobalDataPtr->MmpInvertedFunctionTable->LdrpInvertedFunctionTable); if (!table)return STATUS_NOT_SUPPORTED; bool need_virtual_protect = RtlIsWindowsVersionOrGreater(6, 3, 0); NTSTATUS status; @@ -184,7 +184,7 @@ NTSTATUS NTAPI RtlInsertInvertedFunctionTable( } NTSTATUS NTAPI RtlRemoveInvertedFunctionTable(_In_ PVOID ImageBase) { - auto table = PRTL_INVERTED_FUNCTION_TABLE(MmpGlobalDataPtr->MmpInvertedFunctionTable.LdrpInvertedFunctionTable); + auto table = PRTL_INVERTED_FUNCTION_TABLE(MmpGlobalDataPtr->MmpInvertedFunctionTable->LdrpInvertedFunctionTable); bool need_virtual_protect = RtlIsWindowsVersionOrGreater(6, 3, 0); NTSTATUS status; diff --git a/MemoryModule/LdrEntry.cpp b/MemoryModule/LdrEntry.cpp index d510e40..4d4928a 100644 --- a/MemoryModule/LdrEntry.cpp +++ b/MemoryModule/LdrEntry.cpp @@ -240,10 +240,19 @@ NTSTATUS NTAPI RtlUpdateReferenceCount( _In_ DWORD Flags) { if (Flags != FLAG_REFERENCE && Flags != FLAG_DEREFERENCE)return STATUS_INVALID_PARAMETER_2; - if (Flags == FLAG_REFERENCE && pModule->dwReferenceCount != 0xffffffff) + if (pModule->dwReferenceCount == 0xffffffff)return STATUS_SUCCESS; + + if (PLDR_DATA_TABLE_ENTRY(pModule->LdrEntry)->ObsoleteLoadCount == 0xffff) { + pModule->dwReferenceCount = 0xffffffff; + return STATUS_SUCCESS; + } + + if (Flags == FLAG_REFERENCE) { ++pModule->dwReferenceCount; - if (Flags == FLAG_DEREFERENCE && pModule->dwReferenceCount) - --pModule->dwReferenceCount; + } + else { + if (pModule->dwReferenceCount)--pModule->dwReferenceCount; + } return STATUS_SUCCESS; } @@ -259,7 +268,7 @@ NTSTATUS NTAPI RtlGetReferenceCount( VOID NTAPI RtlInsertMemoryTableEntry(_In_ PLDR_DATA_TABLE_ENTRY LdrEntry) { PPEB_LDR_DATA PebData = NtCurrentPeb()->Ldr; - PLIST_ENTRY LdrpHashTable = MmpGlobalDataPtr->MmpLdrEntry.LdrpHashTable; + PLIST_ENTRY LdrpHashTable = MmpGlobalDataPtr->MmpLdrEntry->LdrpHashTable; ULONG i; /* Insert into hash table */ @@ -279,15 +288,15 @@ VOID NTAPI RtlRbInsertNodeEx( _Out_ PRTL_BALANCED_NODE Node) { RtlZeroMemory(Node, sizeof(*Node)); - if (!MmpGlobalDataPtr->MmpLdrEntry._RtlRbInsertNodeEx)return; - return MmpGlobalDataPtr->MmpLdrEntry._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) { - if (!MmpGlobalDataPtr->MmpLdrEntry._RtlRbRemoveNode)return; - return MmpGlobalDataPtr->MmpLdrEntry._RtlRbRemoveNode(Tree, Node); + if (!MmpGlobalDataPtr->MmpLdrEntry->_RtlRbRemoveNode)return; + return MmpGlobalDataPtr->MmpLdrEntry->_RtlRbRemoveNode(Tree, Node); } PLDR_DATA_TABLE_ENTRY NTAPI RtlFindLdrTableEntryByHandle(_In_ PVOID BaseAddress) { diff --git a/MemoryModule/Loader.cpp b/MemoryModule/Loader.cpp index 2289044..a4e2f81 100644 --- a/MemoryModule/Loader.cpp +++ b/MemoryModule/Loader.cpp @@ -110,7 +110,7 @@ NTSTATUS NTAPI LdrLoadDllMemoryExW( ExitProcess(STATUS_INVALID_ADDRESS); TerminateProcess(NtCurrentProcess(), STATUS_INVALID_ADDRESS); } - module->loadFromNtLoadDllMemory = true; + module->loadFromLdrLoadDllMemory = true; headers = RtlImageNtHeader(*BaseAddress); if (headers->OptionalHeader.DllCharacteristics & IMAGE_DLLCHARACTERISTICS_NO_SEH)dwFlags |= LOAD_FLAGS_NOT_ADD_INVERTED_FUNCTION; @@ -144,6 +144,7 @@ NTSTATUS NTAPI LdrLoadDllMemoryExW( if (!NT_SUCCESS(status))break; module->MappedDll = true; + module->LdrEntry = ModuleEntry; status = MemoryResolveImportTable(LPBYTE(*BaseAddress), headers, module); if (!NT_SUCCESS(status))break; @@ -225,65 +226,69 @@ NTSTATUS NTAPI LdrLoadDllMemoryExA( } NTSTATUS NTAPI LdrUnloadDllMemory(_In_ HMEMORYMODULE BaseAddress) { - __try { - ProbeForRead(BaseAddress, sizeof(size_t)); - } - __except (EXCEPTION_EXECUTE_HANDLER) { - return GetExceptionCode(); - } - PLDR_DATA_TABLE_ENTRY CurEntry; ULONG count = 0; NTSTATUS status = STATUS_SUCCESS; PMEMORYMODULE module = MapMemoryModuleHandle(BaseAddress); + PIMAGE_NT_HEADERS headers = RtlImageNtHeader(BaseAddress); - //Not a memory module loaded via LdrLoadDllMemory - if (!module || !module->loadFromNtLoadDllMemory)return STATUS_INVALID_HANDLE; + do { - //Mapping dll failed - if (module->loadFromNtLoadDllMemory && !module->MappedDll) { - module->underUnload = true; - return MemoryFreeLibrary(BaseAddress) ? STATUS_SUCCESS : STATUS_UNSUCCESSFUL; - } - - if (CurEntry = RtlFindLdrTableEntryByHandle(BaseAddress)) { - PIMAGE_NT_HEADERS headers = RtlImageNtHeader(BaseAddress); - if (headers->OptionalHeader.SizeOfImage == CurEntry->SizeOfImage) { - if (module->UseReferenceCount) { - status = RtlGetReferenceCount(module, &count); - if (!NT_SUCCESS(status))return status; - } - if (!(count & ~1)) { - module->underUnload = true; - if (module->initialized) { - PLDR_INIT_ROUTINE((LPVOID)(module->codeBase + headers->OptionalHeader.AddressOfEntryPoint))( - (HINSTANCE)module->codeBase, - DLL_PROCESS_DETACH, - 0 - ); - } - if (module->MappedDll) { - if (module->InsertInvertedFunctionTableEntry) { - status = RtlRemoveInvertedFunctionTable(BaseAddress); - if (!NT_SUCCESS(status))__fastfail(FAST_FAIL_CORRUPT_LIST_ENTRY); - } - if (module->TlsHandled) { - - status = MmpReleaseTlsEntry(CurEntry); - if (!NT_SUCCESS(status)) __fastfail(FAST_FAIL_FATAL_APP_EXIT); - } - if (!RtlFreeLdrDataTableEntry(CurEntry))__fastfail(FAST_FAIL_FATAL_APP_EXIT); - } - if (!MemoryFreeLibrary(BaseAddress))__fastfail(FAST_FAIL_FATAL_APP_EXIT); - return STATUS_SUCCESS; - } - else { - return RtlUpdateReferenceCount(module, FLAG_DEREFERENCE); - } + //Not a memory module loaded via LdrLoadDllMemory + if (!module || !module->loadFromLdrLoadDllMemory) { + status = STATUS_INVALID_HANDLE; + break; } - } - return STATUS_INVALID_HANDLE; + //Mapping dll failed + if (!module->MappedDll) { + module->underUnload = true; + status = (MemoryFreeLibrary(BaseAddress) ? STATUS_SUCCESS : STATUS_UNSUCCESSFUL); + break; + } + + CurEntry = (PLDR_DATA_TABLE_ENTRY)module->LdrEntry; + + if (headers->OptionalHeader.SizeOfImage != CurEntry->SizeOfImage) __fastfail(FAST_FAIL_FATAL_APP_EXIT); + + if (module->UseReferenceCount) { + status = RtlGetReferenceCount(module, &count); + if (!NT_SUCCESS(status)) break; + } + + if (count & ~1) { + status = RtlUpdateReferenceCount(module, FLAG_DEREFERENCE); + break; + } + + module->underUnload = true; + if (module->initialized) { + PLDR_INIT_ROUTINE((LPVOID)(module->codeBase + headers->OptionalHeader.AddressOfEntryPoint))( + (HINSTANCE)module->codeBase, + DLL_PROCESS_DETACH, + 0 + ); + } + + if (module->MappedDll) { + if (module->InsertInvertedFunctionTableEntry) { + status = RtlRemoveInvertedFunctionTable(BaseAddress); + if (!NT_SUCCESS(status)) __fastfail(FAST_FAIL_CORRUPT_LIST_ENTRY); + } + + if (module->TlsHandled) { + status = MmpReleaseTlsEntry(CurEntry); + if (!NT_SUCCESS(status)) __fastfail(FAST_FAIL_FATAL_APP_EXIT); + } + + if (!RtlFreeLdrDataTableEntry(CurEntry)) __fastfail(FAST_FAIL_FATAL_APP_EXIT); + } + + if (!MemoryFreeLibrary(BaseAddress)) __fastfail(FAST_FAIL_FATAL_APP_EXIT); + + } while (false); + + return status; } __declspec(noreturn) diff --git a/MemoryModule/MemoryModule.cpp b/MemoryModule/MemoryModule.cpp index 5474069..fbcd85d 100644 --- a/MemoryModule/MemoryModule.cpp +++ b/MemoryModule/MemoryModule.cpp @@ -407,7 +407,7 @@ BOOL MemoryFreeLibrary(HMEMORYMODULE mod) { PIMAGE_NT_HEADERS headers = RtlImageNtHeader(mod); if (!module) return FALSE; - if (module->loadFromNtLoadDllMemory && !module->underUnload)return FALSE; + if (module->loadFromLdrLoadDllMemory && !module->underUnload)return FALSE; if (module->hModulesList) { for (DWORD i = 0; i < module->dwModulesCount; ++i) { if (module->hModulesList[i]) { diff --git a/MemoryModule/MemoryModule.h b/MemoryModule/MemoryModule.h index db1bf2e..702734f 100644 --- a/MemoryModule/MemoryModule.h +++ b/MemoryModule/MemoryModule.h @@ -27,7 +27,7 @@ typedef struct _MEMORYMODULE { struct { //Status Flags BYTE initialized : 1; - BYTE loadFromNtLoadDllMemory : 1; + BYTE loadFromLdrLoadDllMemory : 1; BYTE underUnload : 1; BYTE reservedStatusFlags : 5; @@ -52,7 +52,9 @@ typedef struct _MEMORYMODULE { DWORD dwReferenceCount; DWORD dwImageFileSize; - //DWORD headers_align; //headers_align == OptionalHeaders.BaseOfCode; + DWORD dwReserved; + + PVOID LdrEntry; } MEMORYMODULE, * PMEMORYMODULE; diff --git a/MemoryModule/MmpDotNet.cpp b/MemoryModule/MmpDotNet.cpp index 242b8bd..5f5e958 100644 --- a/MemoryModule/MmpDotNet.cpp +++ b/MemoryModule/MmpDotNet.cpp @@ -59,17 +59,17 @@ VOID MmpInsertHandleEntry( entry->value = value; entry->bImageMapping = bImageMapping; - EnterCriticalSection(&MmpGlobalDataPtr->MmpDotNet.MmpFakeHandleListLock); - InsertTailList(&MmpGlobalDataPtr->MmpDotNet.MmpFakeHandleListHead, &entry->InMmpFakeHandleList); - LeaveCriticalSection(&MmpGlobalDataPtr->MmpDotNet.MmpFakeHandleListLock); + EnterCriticalSection(&MmpGlobalDataPtr->MmpDotNet->MmpFakeHandleListLock); + InsertTailList(&MmpGlobalDataPtr->MmpDotNet->MmpFakeHandleListHead, &entry->InMmpFakeHandleList); + LeaveCriticalSection(&MmpGlobalDataPtr->MmpDotNet->MmpFakeHandleListLock); } PMMP_FAKE_HANDLE_LIST_ENTRY MmpFindHandleEntry(HANDLE hObject) { PMMP_FAKE_HANDLE_LIST_ENTRY result = nullptr; - EnterCriticalSection(&MmpGlobalDataPtr->MmpDotNet.MmpFakeHandleListLock); + EnterCriticalSection(&MmpGlobalDataPtr->MmpDotNet->MmpFakeHandleListLock); - for (auto entry = MmpGlobalDataPtr->MmpDotNet.MmpFakeHandleListHead.Flink; entry != &MmpGlobalDataPtr->MmpDotNet.MmpFakeHandleListHead; entry = entry->Flink) { + for (auto entry = MmpGlobalDataPtr->MmpDotNet->MmpFakeHandleListHead.Flink; entry != &MmpGlobalDataPtr->MmpDotNet->MmpFakeHandleListHead; entry = entry->Flink) { auto CurEntry = CONTAINING_RECORD(entry, MMP_FAKE_HANDLE_LIST_ENTRY, MMP_FAKE_HANDLE_LIST_ENTRY::InMmpFakeHandleList); if (CurEntry->hObject == hObject) { @@ -79,15 +79,15 @@ PMMP_FAKE_HANDLE_LIST_ENTRY MmpFindHandleEntry(HANDLE hObject) { } - LeaveCriticalSection(&MmpGlobalDataPtr->MmpDotNet.MmpFakeHandleListLock); + LeaveCriticalSection(&MmpGlobalDataPtr->MmpDotNet->MmpFakeHandleListLock); return result; } VOID MmpFreeHandleEntry(PMMP_FAKE_HANDLE_LIST_ENTRY lpHandleEntry) { - EnterCriticalSection(&MmpGlobalDataPtr->MmpDotNet.MmpFakeHandleListLock); + EnterCriticalSection(&MmpGlobalDataPtr->MmpDotNet->MmpFakeHandleListLock); RemoveEntryList(&lpHandleEntry->InMmpFakeHandleList); RtlFreeHeap(RtlProcessHeap(), 0, lpHandleEntry); - LeaveCriticalSection(&MmpGlobalDataPtr->MmpDotNet.MmpFakeHandleListLock); + LeaveCriticalSection(&MmpGlobalDataPtr->MmpDotNet->MmpFakeHandleListLock); } HANDLE WINAPI HookCreateFileW( @@ -107,7 +107,7 @@ HANDLE WINAPI HookCreateFileW( return hEvent; } - return MmpGlobalDataPtr->MmpDotNet.Hooks.OriginCreateFileW( + return MmpGlobalDataPtr->MmpDotNet->Hooks.OriginCreateFileW( lpFileName, dwDesiredAccess, dwShareMode, @@ -128,13 +128,13 @@ BOOL WINAPI HookGetFileInformationByHandle( auto entry = (PLDR_DATA_TABLE_ENTRY)iter->value; auto module = MapMemoryModuleHandle((HMEMORYMODULE)entry->DllBase); - lpFileInformation->ftCreationTime = lpFileInformation->ftLastAccessTime = lpFileInformation->ftLastWriteTime = MmpGlobalDataPtr->MmpDotNet.AssemblyTimes; + lpFileInformation->ftCreationTime = lpFileInformation->ftLastAccessTime = lpFileInformation->ftLastWriteTime = MmpGlobalDataPtr->MmpDotNet->AssemblyTimes; lpFileInformation->nFileSizeLow = module->dwImageFileSize; return TRUE; } else { - return MmpGlobalDataPtr->MmpDotNet.Hooks.OriginGetFileInformationByHandle( + return MmpGlobalDataPtr->MmpDotNet->Hooks.OriginGetFileInformationByHandle( hFile, lpFileInformation ); @@ -157,7 +157,7 @@ BOOL WINAPI HookGetFileAttributesExW( LPWIN32_FILE_ATTRIBUTE_DATA data = (LPWIN32_FILE_ATTRIBUTE_DATA)lpFileInformation; auto module = MapMemoryModuleHandle((HMEMORYMODULE)entry->DllBase); - data->ftCreationTime = data->ftLastAccessTime = data->ftLastWriteTime = MmpGlobalDataPtr->MmpDotNet.AssemblyTimes; + data->ftCreationTime = data->ftLastAccessTime = data->ftLastWriteTime = MmpGlobalDataPtr->MmpDotNet->AssemblyTimes; data->nFileSizeLow = module->dwImageFileSize; return TRUE; } @@ -166,7 +166,7 @@ BOOL WINAPI HookGetFileAttributesExW( } } - return MmpGlobalDataPtr->MmpDotNet.Hooks.OriginGetFileAttributesExW( + return MmpGlobalDataPtr->MmpDotNet->Hooks.OriginGetFileAttributesExW( lpFileName, fInfoLevelId, lpFileInformation @@ -187,7 +187,7 @@ DWORD WINAPI HookGetFileSize( return module->dwImageFileSize; } else { - return MmpGlobalDataPtr->MmpDotNet.Hooks.OriginGetFileSize( + return MmpGlobalDataPtr->MmpDotNet->Hooks.OriginGetFileSize( hFile, lpFileSizeHigh ); @@ -208,7 +208,7 @@ BOOL WINAPI HookGetFileSizeEx( return TRUE; } else { - return MmpGlobalDataPtr->MmpDotNet.Hooks.OriginGetFileSizeEx( + return MmpGlobalDataPtr->MmpDotNet->Hooks.OriginGetFileSizeEx( hFile, lpFileSize ); @@ -232,7 +232,7 @@ HANDLE WINAPI HookCreateFileMappingW( return hEvent; } - return MmpGlobalDataPtr->MmpDotNet.Hooks.OriginCreateFileMappingW( + return MmpGlobalDataPtr->MmpDotNet->Hooks.OriginCreateFileMappingW( hFile, lpFileMappingAttributes, flProtect, @@ -268,7 +268,7 @@ LPVOID WINAPI HookMapViewOfFileEx( return hModule; } - return MmpGlobalDataPtr->MmpDotNet.Hooks.OriginMapViewOfFileEx( + return MmpGlobalDataPtr->MmpDotNet->Hooks.OriginMapViewOfFileEx( hFileMappingObject, dwDesiredAccess, dwFileOffsetHigh, @@ -304,14 +304,14 @@ BOOL WINAPI HookUnmapViewOfFile(_In_ LPCVOID lpBaseAddress) { return TRUE; } - return MmpGlobalDataPtr->MmpDotNet.Hooks.OriginUnmapViewOfFile(lpBaseAddress); + return MmpGlobalDataPtr->MmpDotNet->Hooks.OriginUnmapViewOfFile(lpBaseAddress); } BOOL WINAPI HookCloseHandle(_In_ _Post_ptr_invalid_ HANDLE hObject) { auto iter = MmpFindHandleEntry(hObject); if (iter)MmpFreeHandleEntry(iter); - return MmpGlobalDataPtr->MmpDotNet.Hooks.OriginCloseHandle(hObject); + return MmpGlobalDataPtr->MmpDotNet->Hooks.OriginCloseHandle(hObject); } HRESULT WINAPI HookGetFileVersion( @@ -354,7 +354,7 @@ HRESULT WINAPI HookGetFileVersion( } - return MmpGlobalDataPtr->MmpDotNet.Hooks.OriginGetFileVersion1( + return MmpGlobalDataPtr->MmpDotNet->Hooks.OriginGetFileVersion1( szFilename, szBuffer, cchBuffer, @@ -366,74 +366,74 @@ BOOL WINAPI MmpPreInitializeHooksForDotNet() { EnterCriticalSection(NtCurrentPeb()->FastPebLock); - if (!MmpGlobalDataPtr->MmpDotNet.PreHooked) { + if (!MmpGlobalDataPtr->MmpDotNet->PreHooked) { HMODULE hModule = LoadLibraryW(L"mscoree.dll"); if (hModule) { - MmpGlobalDataPtr->MmpDotNet.Hooks.OriginGetFileVersion2 = (GetFileVersion_T)GetProcAddress(hModule, "GetFileVersion"); - if (MmpGlobalDataPtr->MmpDotNet.Hooks.OriginGetFileVersion2) { + MmpGlobalDataPtr->MmpDotNet->Hooks.OriginGetFileVersion2 = (GetFileVersion_T)GetProcAddress(hModule, "GetFileVersion"); + if (MmpGlobalDataPtr->MmpDotNet->Hooks.OriginGetFileVersion2) { - GetSystemTimeAsFileTime(&MmpGlobalDataPtr->MmpDotNet.AssemblyTimes); + GetSystemTimeAsFileTime(&MmpGlobalDataPtr->MmpDotNet->AssemblyTimes); - InitializeCriticalSection(&MmpGlobalDataPtr->MmpDotNet.MmpFakeHandleListLock); - InitializeListHead(&MmpGlobalDataPtr->MmpDotNet.MmpFakeHandleListHead); + InitializeCriticalSection(&MmpGlobalDataPtr->MmpDotNet->MmpFakeHandleListLock); + InitializeListHead(&MmpGlobalDataPtr->MmpDotNet->MmpFakeHandleListHead); - MmpGlobalDataPtr->MmpDotNet.Hooks.OriginCreateFileW = CreateFileW; - MmpGlobalDataPtr->MmpDotNet.Hooks.OriginGetFileInformationByHandle = GetFileInformationByHandle; - MmpGlobalDataPtr->MmpDotNet.Hooks.OriginGetFileAttributesExW = GetFileAttributesExW; - MmpGlobalDataPtr->MmpDotNet.Hooks.OriginGetFileSize = GetFileSize; - MmpGlobalDataPtr->MmpDotNet.Hooks.OriginGetFileSizeEx = GetFileSizeEx; - MmpGlobalDataPtr->MmpDotNet.Hooks.OriginCreateFileMappingW = CreateFileMappingW; - MmpGlobalDataPtr->MmpDotNet.Hooks.OriginMapViewOfFileEx = MapViewOfFileEx; - MmpGlobalDataPtr->MmpDotNet.Hooks.OriginMapViewOfFile = MapViewOfFile; - MmpGlobalDataPtr->MmpDotNet.Hooks.OriginUnmapViewOfFile = UnmapViewOfFile; - MmpGlobalDataPtr->MmpDotNet.Hooks.OriginCloseHandle = CloseHandle; + MmpGlobalDataPtr->MmpDotNet->Hooks.OriginCreateFileW = CreateFileW; + MmpGlobalDataPtr->MmpDotNet->Hooks.OriginGetFileInformationByHandle = GetFileInformationByHandle; + MmpGlobalDataPtr->MmpDotNet->Hooks.OriginGetFileAttributesExW = GetFileAttributesExW; + MmpGlobalDataPtr->MmpDotNet->Hooks.OriginGetFileSize = GetFileSize; + MmpGlobalDataPtr->MmpDotNet->Hooks.OriginGetFileSizeEx = GetFileSizeEx; + MmpGlobalDataPtr->MmpDotNet->Hooks.OriginCreateFileMappingW = CreateFileMappingW; + MmpGlobalDataPtr->MmpDotNet->Hooks.OriginMapViewOfFileEx = MapViewOfFileEx; + MmpGlobalDataPtr->MmpDotNet->Hooks.OriginMapViewOfFile = MapViewOfFile; + MmpGlobalDataPtr->MmpDotNet->Hooks.OriginUnmapViewOfFile = UnmapViewOfFile; + MmpGlobalDataPtr->MmpDotNet->Hooks.OriginCloseHandle = CloseHandle; DetourTransactionBegin(); DetourUpdateThread(NtCurrentThread()); - DetourAttach((PVOID*)&MmpGlobalDataPtr->MmpDotNet.Hooks.OriginCreateFileW, HookCreateFileW); - DetourAttach((PVOID*)&MmpGlobalDataPtr->MmpDotNet.Hooks.OriginGetFileInformationByHandle, HookGetFileInformationByHandle); - DetourAttach((PVOID*)&MmpGlobalDataPtr->MmpDotNet.Hooks.OriginGetFileAttributesExW, HookGetFileAttributesExW); - DetourAttach((PVOID*)&MmpGlobalDataPtr->MmpDotNet.Hooks.OriginGetFileSize, HookGetFileSize); - DetourAttach((PVOID*)&MmpGlobalDataPtr->MmpDotNet.Hooks.OriginGetFileSizeEx, HookGetFileSizeEx); - DetourAttach((PVOID*)&MmpGlobalDataPtr->MmpDotNet.Hooks.OriginCreateFileMappingW, HookCreateFileMappingW); - DetourAttach((PVOID*)&MmpGlobalDataPtr->MmpDotNet.Hooks.OriginMapViewOfFileEx, HookMapViewOfFileEx); - DetourAttach((PVOID*)&MmpGlobalDataPtr->MmpDotNet.Hooks.OriginMapViewOfFile, HookMapViewOfFile); - DetourAttach((PVOID*)&MmpGlobalDataPtr->MmpDotNet.Hooks.OriginUnmapViewOfFile, HookUnmapViewOfFile); - DetourAttach((PVOID*)&MmpGlobalDataPtr->MmpDotNet.Hooks.OriginCloseHandle, HookCloseHandle); - DetourAttach((PVOID*)&MmpGlobalDataPtr->MmpDotNet.Hooks.OriginGetFileVersion2, HookGetFileVersion); + DetourAttach((PVOID*)&MmpGlobalDataPtr->MmpDotNet->Hooks.OriginCreateFileW, HookCreateFileW); + DetourAttach((PVOID*)&MmpGlobalDataPtr->MmpDotNet->Hooks.OriginGetFileInformationByHandle, HookGetFileInformationByHandle); + DetourAttach((PVOID*)&MmpGlobalDataPtr->MmpDotNet->Hooks.OriginGetFileAttributesExW, HookGetFileAttributesExW); + DetourAttach((PVOID*)&MmpGlobalDataPtr->MmpDotNet->Hooks.OriginGetFileSize, HookGetFileSize); + DetourAttach((PVOID*)&MmpGlobalDataPtr->MmpDotNet->Hooks.OriginGetFileSizeEx, HookGetFileSizeEx); + DetourAttach((PVOID*)&MmpGlobalDataPtr->MmpDotNet->Hooks.OriginCreateFileMappingW, HookCreateFileMappingW); + DetourAttach((PVOID*)&MmpGlobalDataPtr->MmpDotNet->Hooks.OriginMapViewOfFileEx, HookMapViewOfFileEx); + DetourAttach((PVOID*)&MmpGlobalDataPtr->MmpDotNet->Hooks.OriginMapViewOfFile, HookMapViewOfFile); + DetourAttach((PVOID*)&MmpGlobalDataPtr->MmpDotNet->Hooks.OriginUnmapViewOfFile, HookUnmapViewOfFile); + DetourAttach((PVOID*)&MmpGlobalDataPtr->MmpDotNet->Hooks.OriginCloseHandle, HookCloseHandle); + DetourAttach((PVOID*)&MmpGlobalDataPtr->MmpDotNet->Hooks.OriginGetFileVersion2, HookGetFileVersion); DetourTransactionCommit(); - MmpGlobalDataPtr->MmpDotNet.PreHooked = TRUE; + MmpGlobalDataPtr->MmpDotNet->PreHooked = TRUE; } } } LeaveCriticalSection(NtCurrentPeb()->FastPebLock); - return MmpGlobalDataPtr->MmpDotNet.PreHooked; + return MmpGlobalDataPtr->MmpDotNet->PreHooked; } BOOL WINAPI MmpInitializeHooksForDotNet() { HMODULE hModule = GetModuleHandleW(L"mscoreei.dll"); if (hModule) { - MmpGlobalDataPtr->MmpDotNet.Hooks.OriginGetFileVersion1 = (GetFileVersion_T)GetProcAddress(hModule, "GetFileVersion"); - if (MmpGlobalDataPtr->MmpDotNet.Hooks.OriginGetFileVersion1) { + MmpGlobalDataPtr->MmpDotNet->Hooks.OriginGetFileVersion1 = (GetFileVersion_T)GetProcAddress(hModule, "GetFileVersion"); + if (MmpGlobalDataPtr->MmpDotNet->Hooks.OriginGetFileVersion1) { EnterCriticalSection(NtCurrentPeb()->FastPebLock); - if (!MmpGlobalDataPtr->MmpDotNet.PreHooked) { + if (!MmpGlobalDataPtr->MmpDotNet->PreHooked) { LeaveCriticalSection(NtCurrentPeb()->FastPebLock); return FALSE; } - if (!MmpGlobalDataPtr->MmpDotNet.Initialized) { + if (!MmpGlobalDataPtr->MmpDotNet->Initialized) { DetourTransactionBegin(); DetourUpdateThread(NtCurrentThread()); - DetourAttach((PVOID*)&MmpGlobalDataPtr->MmpDotNet.Hooks.OriginGetFileVersion1, HookGetFileVersion); + DetourAttach((PVOID*)&MmpGlobalDataPtr->MmpDotNet->Hooks.OriginGetFileVersion1, HookGetFileVersion); DetourTransactionCommit(); - MmpGlobalDataPtr->MmpDotNet.Initialized = TRUE; + MmpGlobalDataPtr->MmpDotNet->Initialized = TRUE; } LeaveCriticalSection(NtCurrentPeb()->FastPebLock); diff --git a/MemoryModule/MmpGlobalData.h b/MemoryModule/MmpGlobalData.h index 8870f43..718a059 100644 --- a/MemoryModule/MmpGlobalData.h +++ b/MemoryModule/MmpGlobalData.h @@ -76,6 +76,9 @@ typedef enum class _WINDOWS_VERSION :BYTE { invalid }WINDOWS_VERSION; +#define MEMORY_MODULE_MAJOR_VERSION 1 +#define MEMORY_MODULE_MINOR_VERSION 0 + typedef struct _MMP_GLOBAL_DATA { WORD MajorVersion; @@ -95,16 +98,25 @@ typedef struct _MMP_GLOBAL_DATA { SYSTEM_INFO SystemInfo; - MMP_BASE_ADDRESS_INDEX_DATA MmpBaseAddressIndex; + PMMP_BASE_ADDRESS_INDEX_DATA MmpBaseAddressIndex; - MMP_INVERTED_FUNCTION_TABLE_DATA MmpInvertedFunctionTable; + PMMP_INVERTED_FUNCTION_TABLE_DATA MmpInvertedFunctionTable; - MMP_LDR_ENTRY_DATA MmpLdrEntry; + PMMP_LDR_ENTRY_DATA MmpLdrEntry; - MMP_TLS_DATA MmpTls; + PMMP_TLS_DATA MmpTls; - MMP_DOT_NET_DATA MmpDotNet; + PMMP_DOT_NET_DATA MmpDotNet; }MMP_GLOBAL_DATA, * PMMP_GLOBAL_DATA; +#define MMP_GLOBAL_DATA_SIZE (\ + sizeof(MMP_GLOBAL_DATA) + \ + sizeof(MMP_BASE_ADDRESS_INDEX_DATA) + \ + sizeof(MMP_INVERTED_FUNCTION_TABLE_DATA) + \ + sizeof(MMP_LDR_ENTRY_DATA) + \ + sizeof(MMP_TLS_DATA) + \ + sizeof(MMP_DOT_NET_DATA)\ +) + extern PMMP_GLOBAL_DATA MmpGlobalDataPtr; diff --git a/MemoryModule/MmpTls.cpp b/MemoryModule/MmpTls.cpp index 61842d0..1876d06 100644 --- a/MemoryModule/MmpTls.cpp +++ b/MemoryModule/MmpTls.cpp @@ -154,7 +154,7 @@ DWORD NTAPI MmpUserThreadStart(LPVOID lpThreadParameter) { // // Allocate and replace ThreadLocalStoragePointer for new thread // - EnterCriticalSection(&MmpGlobalDataPtr->MmpTls.MmpTlspLock); + EnterCriticalSection(&MmpGlobalDataPtr->MmpTls->MmpTlspLock); record = PMMP_TLSP_RECORD(RtlAllocateHeap(RtlProcessHeap(), 0, sizeof(MMP_TLSP_RECORD))); if (record) { @@ -172,7 +172,7 @@ DWORD NTAPI MmpUserThreadStart(LPVOID lpThreadParameter) { NtCurrentTeb()->ThreadLocalStoragePointer = record->TlspMmpBlock; - InsertTailList(&MmpGlobalDataPtr->MmpTls.MmpThreadLocalStoragePointer, &record->InMmpThreadLocalStoragePointer); + InsertTailList(&MmpGlobalDataPtr->MmpTls->MmpThreadLocalStoragePointer, &record->InMmpThreadLocalStoragePointer); success = true; } else { @@ -180,17 +180,17 @@ DWORD NTAPI MmpUserThreadStart(LPVOID lpThreadParameter) { } } - LeaveCriticalSection(&MmpGlobalDataPtr->MmpTls.MmpTlspLock); + LeaveCriticalSection(&MmpGlobalDataPtr->MmpTls->MmpTlspLock); // // Handle MemoryModule Tls data // if (success) { - RtlAcquireSRWLockShared(&MmpGlobalDataPtr->MmpTls.MmpTlsListLock); + RtlAcquireSRWLockShared(&MmpGlobalDataPtr->MmpTls->MmpTlsListLock); auto ThreadLocalStoragePointer = (PVOID*)NtCurrentTeb()->ThreadLocalStoragePointer; - PLIST_ENTRY entry = MmpGlobalDataPtr->MmpTls.MmpTlsList.Flink; - while (entry != &MmpGlobalDataPtr->MmpTls.MmpTlsList) { + PLIST_ENTRY entry = MmpGlobalDataPtr->MmpTls->MmpTlsList.Flink; + while (entry != &MmpGlobalDataPtr->MmpTls->MmpTlsList) { PTLS_ENTRY tls = CONTAINING_RECORD(entry, TLS_ENTRY, TlsEntryLinks); auto len = tls->TlsDirectory.EndAddressOfRawData - tls->TlsDirectory.StartAddressOfRawData; @@ -212,16 +212,16 @@ DWORD NTAPI MmpUserThreadStart(LPVOID lpThreadParameter) { entry = entry->Flink; } - RtlReleaseSRWLockShared(&MmpGlobalDataPtr->MmpTls.MmpTlsListLock); + RtlReleaseSRWLockShared(&MmpGlobalDataPtr->MmpTls->MmpTlsListLock); } if (!success) { return ERROR_NOT_ENOUGH_MEMORY; } - EnterCriticalSection(&MmpGlobalDataPtr->MmpTls.MmpTlspLock); - ++MmpGlobalDataPtr->MmpTls.MmpActiveThreadCount; - LeaveCriticalSection(&MmpGlobalDataPtr->MmpTls.MmpTlspLock); + EnterCriticalSection(&MmpGlobalDataPtr->MmpTls->MmpTlspLock); + ++MmpGlobalDataPtr->MmpTls->MmpActiveThreadCount; + LeaveCriticalSection(&MmpGlobalDataPtr->MmpTls->MmpTlspLock); __skip_tls: return Context.ThreadStartRoutine(Context.ThreadParameter); @@ -257,7 +257,7 @@ NTSTATUS NTAPI HookNtCreateThread( Context.Rdx = ULONG64(_Context); #endif - status = MmpGlobalDataPtr->MmpTls.Hooks.OriginNtCreateThread( + status = MmpGlobalDataPtr->MmpTls->Hooks.OriginNtCreateThread( ThreadHandle, DesiredAccess, ObjectAttributes, @@ -294,7 +294,7 @@ NTSTATUS NTAPI HookNtCreateThreadEx( Context->ThreadStartRoutine = PTHREAD_START_ROUTINE(StartRoutine); Context->ThreadParameter = Argument; - NTSTATUS status = MmpGlobalDataPtr->MmpTls.Hooks.OriginNtCreateThreadEx( + NTSTATUS status = MmpGlobalDataPtr->MmpTls->Hooks.OriginNtCreateThreadEx( ThreadHandle, DesiredAccess, ObjectAttributes, @@ -322,10 +322,10 @@ VOID NTAPI HookLdrShutdownThread(VOID) { // // Find our tlsp record // - EnterCriticalSection(&MmpGlobalDataPtr->MmpTls.MmpTlspLock); + EnterCriticalSection(&MmpGlobalDataPtr->MmpTls->MmpTlspLock); - entry = MmpGlobalDataPtr->MmpTls.MmpThreadLocalStoragePointer.Flink; - while (entry != &MmpGlobalDataPtr->MmpTls.MmpThreadLocalStoragePointer) { + entry = MmpGlobalDataPtr->MmpTls->MmpThreadLocalStoragePointer.Flink; + while (entry != &MmpGlobalDataPtr->MmpTls->MmpThreadLocalStoragePointer) { auto p = CONTAINING_RECORD(entry, MMP_TLSP_RECORD, InMmpThreadLocalStoragePointer); if (p->UniqueThread == NtCurrentThreadId()) { @@ -344,19 +344,19 @@ VOID NTAPI HookLdrShutdownThread(VOID) { entry = entry->Flink; } - --MmpGlobalDataPtr->MmpTls.MmpActiveThreadCount; + --MmpGlobalDataPtr->MmpTls->MmpActiveThreadCount; - LeaveCriticalSection(&MmpGlobalDataPtr->MmpTls.MmpTlspLock); + LeaveCriticalSection(&MmpGlobalDataPtr->MmpTls->MmpTlspLock); // // Free MemoryModule Tls data // - RtlAcquireSRWLockExclusive(&MmpGlobalDataPtr->MmpTls.MmpTlsListLock); + RtlAcquireSRWLockExclusive(&MmpGlobalDataPtr->MmpTls->MmpTlsListLock); if (record) { auto TlspMmpBlock = (PVOID*)record->TlspMmpBlock; - entry = MmpGlobalDataPtr->MmpTls.MmpTlsList.Flink; - while (entry != &MmpGlobalDataPtr->MmpTls.MmpTlsList) { + entry = MmpGlobalDataPtr->MmpTls->MmpTlsList.Flink; + while (entry != &MmpGlobalDataPtr->MmpTls->MmpTlsList) { auto p = CONTAINING_RECORD(entry, TLS_ENTRY, TlsEntryLinks); RtlFreeHeap(RtlProcessHeap(), 0, TlspMmpBlock[p->TlsDirectory.Characteristics]); @@ -367,17 +367,17 @@ VOID NTAPI HookLdrShutdownThread(VOID) { RtlFreeHeap(RtlProcessHeap(), 0, TlspMmpBlock); } else { - if (MmpGlobalDataPtr->MmpTls.MmpTlsList.Flink != &MmpGlobalDataPtr->MmpTls.MmpTlsList) { + if (MmpGlobalDataPtr->MmpTls->MmpTlsList.Flink != &MmpGlobalDataPtr->MmpTls->MmpTlsList) { assert(false); } } - RtlReleaseSRWLockExclusive(&MmpGlobalDataPtr->MmpTls.MmpTlsListLock); + RtlReleaseSRWLockExclusive(&MmpGlobalDataPtr->MmpTls->MmpTlsListLock); // // Call the original function // - MmpGlobalDataPtr->MmpTls.Hooks.OriginLdrShutdownThread(); + MmpGlobalDataPtr->MmpTls->Hooks.OriginLdrShutdownThread(); } BOOL NTAPI PreHookNtSetInformationProcess() { @@ -428,7 +428,7 @@ BOOL NTAPI PreHookNtSetInformationProcess() { ); if (NT_SUCCESS(status)) { - EnterCriticalSection(&MmpGlobalDataPtr->MmpTls.MmpTlspLock); + EnterCriticalSection(&MmpGlobalDataPtr->MmpTls->MmpTlspLock); for (DWORD i = 0; i < CurrentThreadCount; ++i) { auto const& LdrTls = ProcessTlsInformation->ThreadData[i]; auto const& MmpTls = tmpTlsInformation->ThreadData[i]; @@ -438,9 +438,9 @@ BOOL NTAPI PreHookNtSetInformationProcess() { record->TlspLdrBlock = LdrTls.TlsVector; record->TlspMmpBlock = MmpTls.TlsVector; record->UniqueThread = LdrTls.ThreadId; - InsertTailList(&MmpGlobalDataPtr->MmpTls.MmpThreadLocalStoragePointer, &record->InMmpThreadLocalStoragePointer); + InsertTailList(&MmpGlobalDataPtr->MmpTls->MmpThreadLocalStoragePointer, &record->InMmpThreadLocalStoragePointer); } - LeaveCriticalSection(&MmpGlobalDataPtr->MmpTls.MmpTlspLock); + LeaveCriticalSection(&MmpGlobalDataPtr->MmpTls->MmpTlspLock); } } @@ -458,7 +458,7 @@ NTSTATUS NTAPI HookNtSetInformationProcess( _In_ ULONG ProcessInformationLength) { if (ProcessInformationClass != ProcessTlsInformation) { - return MmpGlobalDataPtr->MmpTls.Hooks.OriginNtSetInformationProcess( + return MmpGlobalDataPtr->MmpTls->Hooks.OriginNtSetInformationProcess( ProcessHandle, ProcessInformationClass, ProcessInformation, @@ -532,7 +532,7 @@ NTSTATUS NTAPI HookNtSetInformationProcess( } } - status = MmpGlobalDataPtr->MmpTls.Hooks.OriginNtSetInformationProcess( + status = MmpGlobalDataPtr->MmpTls->Hooks.OriginNtSetInformationProcess( hProcess, ProcessInformationClass, Tls, @@ -542,14 +542,14 @@ NTSTATUS NTAPI HookNtSetInformationProcess( // // Modify our mapping // - EnterCriticalSection(&MmpGlobalDataPtr->MmpTls.MmpTlspLock); + EnterCriticalSection(&MmpGlobalDataPtr->MmpTls->MmpTlspLock); for (ULONG i = 0; i < Tls->ThreadDataCount; ++i) { bool found = false; - PLIST_ENTRY entry = MmpGlobalDataPtr->MmpTls.MmpThreadLocalStoragePointer.Flink; + PLIST_ENTRY entry = MmpGlobalDataPtr->MmpTls->MmpThreadLocalStoragePointer.Flink; // Find thread-spec tlsp - while (entry != &MmpGlobalDataPtr->MmpTls.MmpThreadLocalStoragePointer) { + while (entry != &MmpGlobalDataPtr->MmpTls->MmpThreadLocalStoragePointer) { PMMP_TLSP_RECORD j = CONTAINING_RECORD(entry, MMP_TLSP_RECORD, InMmpThreadLocalStoragePointer); @@ -593,7 +593,7 @@ NTSTATUS NTAPI HookNtSetInformationProcess( ProcessTlsInformation->ThreadData[i].ThreadId = Tls->ThreadData[i].ThreadId; } } - LeaveCriticalSection(&MmpGlobalDataPtr->MmpTls.MmpTlspLock); + LeaveCriticalSection(&MmpGlobalDataPtr->MmpTls->MmpTlspLock); } while (false); @@ -605,7 +605,7 @@ NTSTATUS NTAPI MmpAcquireTlsIndex(_Out_ PULONG TlsIndex) { *TlsIndex = -1; - ULONG Index = RtlFindClearBitsAndSet(&MmpGlobalDataPtr->MmpTls.MmpTlsBitmap, 1, 0); + ULONG Index = RtlFindClearBitsAndSet(&MmpGlobalDataPtr->MmpTls->MmpTlsBitmap, 1, 0); if (Index != -1) { *TlsIndex = Index; return STATUS_SUCCESS; @@ -666,9 +666,9 @@ NTSTATUS NTAPI MmpAllocateTlsEntry( Entry->TlsDirectory.Characteristics = *PULONG(Entry->TlsDirectory.AddressOfIndex) = TlsIndex; - RtlAcquireSRWLockExclusive(&MmpGlobalDataPtr->MmpTls.MmpTlsListLock); - InsertTailList(&MmpGlobalDataPtr->MmpTls.MmpTlsList, &Entry->TlsEntryLinks); - RtlReleaseSRWLockExclusive(&MmpGlobalDataPtr->MmpTls.MmpTlsListLock); + RtlAcquireSRWLockExclusive(&MmpGlobalDataPtr->MmpTls->MmpTlsListLock); + InsertTailList(&MmpGlobalDataPtr->MmpTls->MmpTlsList, &Entry->TlsEntryLinks); + RtlReleaseSRWLockExclusive(&MmpGlobalDataPtr->MmpTls->MmpTlsListLock); *lpTlsEntry = Entry; *lpTlsIndex = TlsIndex; @@ -677,20 +677,20 @@ NTSTATUS NTAPI MmpAllocateTlsEntry( NTSTATUS NTAPI MmpReleaseTlsEntry(_In_ PLDR_DATA_TABLE_ENTRY lpModuleEntry) { - RtlAcquireSRWLockExclusive(&MmpGlobalDataPtr->MmpTls.MmpTlsListLock); + RtlAcquireSRWLockExclusive(&MmpGlobalDataPtr->MmpTls->MmpTlsListLock); - for (auto entry = MmpGlobalDataPtr->MmpTls.MmpTlsList.Flink; entry != &MmpGlobalDataPtr->MmpTls.MmpTlsList; entry = entry->Flink) { + for (auto entry = MmpGlobalDataPtr->MmpTls->MmpTlsList.Flink; entry != &MmpGlobalDataPtr->MmpTls->MmpTlsList; entry = entry->Flink) { auto p = CONTAINING_RECORD(entry, TLS_ENTRY, TlsEntryLinks); if (p->ModuleEntry == lpModuleEntry) { RemoveEntryList(&p->TlsEntryLinks); - RtlClearBit(&MmpGlobalDataPtr->MmpTls.MmpTlsBitmap, p->TlsDirectory.Characteristics); + RtlClearBit(&MmpGlobalDataPtr->MmpTls->MmpTlsBitmap, p->TlsDirectory.Characteristics); RtlFreeHeap(RtlProcessHeap(), 0, p); break; } } - RtlReleaseSRWLockExclusive(&MmpGlobalDataPtr->MmpTls.MmpTlsListLock); + RtlReleaseSRWLockExclusive(&MmpGlobalDataPtr->MmpTls->MmpTlsListLock); return STATUS_SUCCESS; } @@ -723,7 +723,7 @@ NTSTATUS NTAPI MmpHandleTlsData(_In_ PLDR_DATA_TABLE_ENTRY lpModuleEntry) { return STATUS_INSUFFICIENT_RESOURCES; } - auto ThreadCount = MmpGlobalDataPtr->MmpTls.MmpActiveThreadCount; + auto ThreadCount = MmpGlobalDataPtr->MmpTls->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)); @@ -791,26 +791,26 @@ BOOL NTAPI MmpTlsInitialize() { // // Capture thread count // - MmpGlobalDataPtr->MmpTls.MmpActiveThreadCount = MmpGetThreadCount(); + MmpGlobalDataPtr->MmpTls->MmpActiveThreadCount = MmpGetThreadCount(); // // Initialize tlsp // - InitializeCriticalSection(&MmpGlobalDataPtr->MmpTls.MmpTlspLock); - InitializeListHead(&MmpGlobalDataPtr->MmpTls.MmpThreadLocalStoragePointer); + InitializeCriticalSection(&MmpGlobalDataPtr->MmpTls->MmpTlspLock); + InitializeListHead(&MmpGlobalDataPtr->MmpTls->MmpThreadLocalStoragePointer); // // Initialize tls list // - InitializeListHead(&MmpGlobalDataPtr->MmpTls.MmpTlsList); - RtlInitializeSRWLock(&MmpGlobalDataPtr->MmpTls.MmpTlsListLock); + InitializeListHead(&MmpGlobalDataPtr->MmpTls->MmpTlsList); + RtlInitializeSRWLock(&MmpGlobalDataPtr->MmpTls->MmpTlsListLock); PULONG buffer = PULONG(RtlAllocateHeap(RtlProcessHeap(), HEAP_ZERO_MEMORY, MMP_TLSP_INDEX_BUFFER_SIZE)); if (!buffer) RtlRaiseStatus(STATUS_NO_MEMORY); RtlFillMemory(buffer, MMP_START_TLS_INDEX / 8, -1); - RtlInitializeBitMap(&MmpGlobalDataPtr->MmpTls.MmpTlsBitmap, buffer, MMP_MAXIMUM_TLS_INDEX); + RtlInitializeBitMap(&MmpGlobalDataPtr->MmpTls->MmpTlsBitmap, buffer, MMP_MAXIMUM_TLS_INDEX); if (NtCurrentTeb()->ThreadLocalStoragePointer) { if (!PreHookNtSetInformationProcess()) { @@ -822,17 +822,17 @@ BOOL NTAPI MmpTlsInitialize() { // Hook functions // - MmpGlobalDataPtr->MmpTls.Hooks.OriginNtCreateThread = NtCreateThread; - MmpGlobalDataPtr->MmpTls.Hooks.OriginNtCreateThreadEx = NtCreateThreadEx; - MmpGlobalDataPtr->MmpTls.Hooks.OriginLdrShutdownThread = LdrShutdownThread; - MmpGlobalDataPtr->MmpTls.Hooks.OriginNtSetInformationProcess = NtSetInformationProcess; + MmpGlobalDataPtr->MmpTls->Hooks.OriginNtCreateThread = NtCreateThread; + MmpGlobalDataPtr->MmpTls->Hooks.OriginNtCreateThreadEx = NtCreateThreadEx; + MmpGlobalDataPtr->MmpTls->Hooks.OriginLdrShutdownThread = LdrShutdownThread; + MmpGlobalDataPtr->MmpTls->Hooks.OriginNtSetInformationProcess = NtSetInformationProcess; DetourTransactionBegin(); DetourUpdateThread(NtCurrentThread()); - DetourAttach((PVOID*)&MmpGlobalDataPtr->MmpTls.Hooks.OriginNtCreateThread, HookNtCreateThread); - DetourAttach((PVOID*)&MmpGlobalDataPtr->MmpTls.Hooks.OriginNtCreateThreadEx, HookNtCreateThreadEx); - DetourAttach((PVOID*)&MmpGlobalDataPtr->MmpTls.Hooks.OriginLdrShutdownThread, HookLdrShutdownThread); - DetourAttach((PVOID*)&MmpGlobalDataPtr->MmpTls.Hooks.OriginNtSetInformationProcess, HookNtSetInformationProcess); + DetourAttach((PVOID*)&MmpGlobalDataPtr->MmpTls->Hooks.OriginNtCreateThread, HookNtCreateThread); + DetourAttach((PVOID*)&MmpGlobalDataPtr->MmpTls->Hooks.OriginNtCreateThreadEx, HookNtCreateThreadEx); + DetourAttach((PVOID*)&MmpGlobalDataPtr->MmpTls->Hooks.OriginLdrShutdownThread, HookLdrShutdownThread); + DetourAttach((PVOID*)&MmpGlobalDataPtr->MmpTls->Hooks.OriginNtSetInformationProcess, HookNtSetInformationProcess); DetourTransactionCommit(); return TRUE; diff --git a/test/Header.h b/test/Header.h deleted file mode 100644 index 92cb518..0000000 --- a/test/Header.h +++ /dev/null @@ -1,553 +0,0 @@ -//#include -//#include "../MemoryModule/NativeFunctionsInternal.h" -// -//typedef struct _THREAD_TLS_INFORMATION { -// ULONG Flags; -// union { -// PVOID* TlsVector; -// PVOID TlsModulePointer; -// }; -// HANDLE ThreadId; -//} THREAD_TLS_INFORMATION, * PTHREAD_TLS_INFORMATION; -// -//typedef enum _PROCESS_TLS_INFORMATION_TYPE { -// ProcessTlsReplaceIndex, -// ProcessTlsReplaceVector, -// MaxProcessTlsOperation -//} PROCESS_TLS_INFORMATION_TYPE, * PPROCESS_TLS_INFORMATION_TYPE; -// -//typedef struct _PROCESS_TLS_INFORMATION { -// ULONG Reserved; // Reserved bitmask -// ULONG OperationType; -// ULONG ThreadDataCount; -// union { -// ULONG TlsIndex; -// ULONG TlsVectorLength; -// }; -// THREAD_TLS_INFORMATION ThreadData[ANYSIZE_ARRAY]; -//} PROCESS_TLS_INFORMATION, * PPROCESS_TLS_INFORMATION; -// -//// Need struct name -//typedef struct _TLS_VECTOR { -// union { -// ULONG Length; -// HANDLE ThreadId; -// }; -// -// struct _TLS_VECTOR* PreviousDeferredTlsVector; -// PVOID ModuleTlsData[ANYSIZE_ARRAY]; -//} TLS_VECTOR, * PTLS_VECTOR; -// -//// Need struct name -//typedef struct _TLS_RECLAIM_TABLE_ENTRY { -// PTLS_VECTOR TlsVector; -// RTL_SRWLOCK Lock; -//} TLS_RECLAIM_TABLE_ENTRY, * PTLS_RECLAIM_TABLE_ENTRY; -// -//// Need struct name -//typedef struct _TLS_ENTRY { -// LIST_ENTRY TlsEntryLinks; -// IMAGE_TLS_DIRECTORY TlsDirectory; -// PLDR_DATA_TABLE_ENTRY ModuleEntry; -//} TLS_ENTRY, * PTLS_ENTRY; -// -////0x10 bytes (sizeof) -//typedef struct _RTL_BITMAP { -// ULONG SizeOfBitMap; //0x0 -// ULONG* Buffer; //0x8 -//}RTL_BITMAP, * PRTL_BITMAP; -// -//VOID RtlClearBit( -// PRTL_BITMAP BitMapHeader, -// ULONG BitNumber -//); -// -//VOID RtlInitializeBitMap( -// PRTL_BITMAP BitMapHeader, -// PULONG BitMapBuffer, -// ULONG SizeOfBitMap -//); -// -//ULONG RtlFindClearBitsAndSet( -// PRTL_BITMAP BitMapHeader, -// ULONG NumberToFind, -// ULONG HintIndex -//); -// -//VOID RtlClearBits( -// PRTL_BITMAP BitMapHeader, -// ULONG StartingIndex, -// ULONG NumberToClear -//); -// -//VOID RtlSetBit( -// PRTL_BITMAP BitMapHeader, -// ULONG BitNumber -//); -// -//BOOLEAN RemoveEntryList( -// PLIST_ENTRY Entry -//); -// -//VOID NTAPI RtlAcquireSRWLockExclusive(IN OUT PRTL_SRWLOCK SRWLock); -//VOID NTAPI RtlReleaseSRWLockExclusive(IN OUT PRTL_SRWLOCK SRWLock); -// -//NTSTATUS NTAPI NtSetInformationProcess( -// IN HANDLE ProcessHandle, -// IN ULONG ProcessInformationClass, -// IN PVOID ProcessInformation, -// IN ULONG ProcessInformationLength); -// -//#define ProcessTlsInformation ProcessResourceManagement -// -//PUCHAR NtdllBaseTag = 0; -//ULONG LdrpActiveThreadCount = 0; -//ULONG LdrpPotentialTlsLeaks = 0; -//RTL_BITMAP LdrpTlsBitmap; -//LIST_ENTRY LdrpTlsList; -// -//TLS_RECLAIM_TABLE_ENTRY LdrpDelayedTlsReclaimTable[16]; -// -//ULONG LdrpStaticTlsBitmapVector[4]; -//ULONG LdrpActualBitmapSize = 0; -// -// -//VOID LdrpInit() { -// RtlCopyMemory(&LdrpTlsBitmap, NtCurrentPeb()->TlsBitmap, sizeof(RTL_BITMAP)); -// PROCESS_TLS_INFORMATION pti; -// -//} -// -//VOID LdrpReleaseTlsIndex(ULONG TlsIndex) { -// RtlClearBit(&LdrpTlsBitmap, TlsIndex); -//} -// -//#define LDRP_BITMAP_INCREMENT (0x27 - sizeof( PVOID )) -// -//NTSTATUS LdrpAcquireTlsIndex(PULONG TlsIndex, PBOOLEAN AllocatedBitmap) { -// ULONG Length; -// ULONG Index; -// PULONG NewBitmapBuffer; -// -// Length = LdrpTlsBitmap.SizeOfBitMap; -// -// if (Length == 0) { -// // -// // If we're the first caller, then we shall need to be initializing the -// // bitmap. -// // -// // This implies that we don't need to expand as by definition, there -// // shall exist space for ourselves at the start of the bitmap now. -// // -// RtlInitializeBitMap(&LdrpTlsBitmap, LdrpStaticTlsBitmapVector, 4); -// LdrpActualBitmapSize = 1; -// } -// else { -// Index = RtlFindClearBitsAndSet(&LdrpTlsBitmap, 1, 0); -// -// // -// // If we found space in the existing bitmap then there is no reason to -// // expand buffers, so we'll just return with the existing data. -// // -// if (Index != 0xFFFFFFFF) { -// *TlsIndex = Index; -// *AllocatedBitmap = FALSE; -// return STATUS_SUCCESS; -// } -// -// // -// // Check if we need to grow the bitmap itself or if the bitmap still -// // has space. -// // -// if (((LdrpTlsBitmap.SizeOfBitMap + LDRP_BITMAP_INCREMENT) >> 5) > LdrpActualBitmapSize) { -// // -// // We'll need to grow it. Let's go do so now. -// // -// -// // -// // BUG: We set the new size before checking the allocation. If we -// // fail, then we leave the TLS variables in an inconsistant state. -// // -// LdrpActualBitmapSize = (Length + LDRP_BITMAP_INCREMENT) >> 5; -// NewBitmapBuffer = (PULONG)RtlAllocateHeap(GetProcessHeap(), (ULONG_PTR)((PUCHAR)NtdllBaseTag + 0x000C0000), LdrpActualBitmapSize); -// if (!NewBitmapBuffer) return STATUS_NO_MEMORY; -// -// // -// // Copy the contents of the previous buffer into the new one. -// // -// RtlCopyMemory(NewBitmapBuffer, LdrpTlsBitmap.Buffer, Length + 7); -// -// // -// // Free the old buffer if it wasn't the initial static buffer. -// // -// if (LdrpTlsBitmap.Buffer != LdrpStaticTlsBitmapVector) { -// RtlFreeHeap(GetProcessHeap(), 0, LdrpTlsBitmap.Buffer); -// } -// -// // -// // Reinitialize the bitmap as we've changed the buffer pointer. -// // -// RtlInitializeBitMap(&LdrpTlsBitmap, NewBitmapBuffer, Length + 4); -// } -// else { -// LdrpTlsBitmap.SizeOfBitMap += 4; -// } -// } -// -// RtlClearBits(&LdrpTlsBitmap, Length + 1, 3); -// RtlSetBit(&LdrpTlsBitmap, Length); -// -// *TlsIndex = Index; -// *AllocatedBitmap = TRUE; -// -// return STATUS_SUCCESS; -//} -// -//NTSTATUS LdrpAllocateTlsEntry(PIMAGE_TLS_DIRECTORY TlsDirectory, PLDR_DATA_TABLE_ENTRY ModuleEntry, PULONG TlsIndex, PBOOLEAN AllocatedBitmap, PTLS_ENTRY* TlsEntry) { -// -// PTLS_ENTRY Entry = nullptr; -// NTSTATUS Status; -// -// __try { -// Entry = (PTLS_ENTRY)RtlAllocateHeap(GetProcessHeap(), (ULONG_PTR)((PUCHAR)NtdllBaseTag + 0x000C0000), sizeof(TLS_ENTRY)); -// if (!Entry) return STATUS_NO_MEMORY; -// Status = STATUS_SUCCESS; -// RtlCopyMemory(&Entry->TlsDirectory, TlsDirectory, sizeof(IMAGE_TLS_DIRECTORY)); -// } -// __except (EXCEPTION_EXECUTE_HANDLER) { -// // -// // Also print string and complain. -// // -// Status = GetExceptionCode(); -// } -// -// if (!NT_SUCCESS(Status)) { -// RtlFreeHeap(GetProcessHeap(), 0, Entry); -// return Status; -// } -// -// // -// // Validate that the TLS directory entry is sane. -// // -// if (Entry->TlsDirectory.StartAddressOfRawData < Entry->TlsDirectory.EndAddressOfRawData) { -// RtlFreeHeap(GetProcessHeap(), 0, Entry); -// return STATUS_INVALID_IMAGE_FORMAT; -// } -// Entry->ModuleEntry = ModuleEntry; -// -// // -// // Insert the entry into our list. -// // -// -// InsertTailList(&LdrpTlsList, &Entry->TlsEntryLinks); -// if (AllocatedBitmap) { -// Status = LdrpAcquireTlsIndex(TlsIndex, AllocatedBitmap); -// if (!NT_SUCCESS(Status)) { -// // -// // BUG: We don't remove the entry from LdrpTlsList -// // -// RtlFreeHeap(GetProcessHeap(), 0, Entry); -// return Status; -// } -// } -// else { -// *TlsIndex += 1; -// } -// -// // -// // We reuse the 'Characteristics' field for the real TLS index. -// // -// Entry->TlsDirectory.Characteristics = *TlsIndex; -// __try { -// *(PULONG)Entry->TlsDirectory.AddressOfIndex = *TlsIndex; -// } -// __except (EXCEPTION_EXECUTE_HANDLER) { -// Status = GetExceptionCode(); -// } -// if (!NT_SUCCESS(Status)) { -// if (AllocatedBitmap) { -// LdrpReleaseTlsIndex(*TlsIndex); -// if (*AllocatedBitmap) LdrpTlsBitmap.SizeOfBitMap -= 4; -// } -// -// // -// // BUG: We don't remove the entry from LdrpTlsList -// // -// RtlFreeHeap(GetProcessHeap(), 0, Entry); -// return Status; -// } -// -// if (TlsEntry) *TlsEntry = Entry; -// return STATUS_SUCCESS; -//} -// -//PTLS_ENTRY __fastcall LdrpFindTlsEntry(PLDR_DATA_TABLE_ENTRY ModuleEntry) { -// PTLS_ENTRY TlsEntry; -// PLIST_ENTRY ListHead; -// -// ListHead = &LdrpTlsList; -// -// for (TlsEntry = CONTAINING_RECORD(LdrpTlsList.Flink, TLS_ENTRY, TlsEntryLinks); -// &TlsEntry->TlsEntryLinks != ListHead; -// TlsEntry = CONTAINING_RECORD(TlsEntry->TlsEntryLinks.Flink, TLS_ENTRY, TlsEntryLinks)) { -// -// if (TlsEntry->ModuleEntry == ModuleEntry) return TlsEntry; -// } -// -// return 0; -//} -// -//NTSTATUS LdrpReleaseTlsEntry(PLDR_DATA_TABLE_ENTRY ModuleEntry) { -// PTLS_ENTRY TlsEntry; -// -// // -// // Find the corresponding TLS_ENTRY for this module entry. -// // -// TlsEntry = LdrpFindTlsEntry(ModuleEntry); -// if (!TlsEntry) return STATUS_NOT_FOUND; -// -// // -// // Remove it from the global list of outstanding TLS entries. -// // -// RemoveEntryList(&TlsEntry->TlsEntryLinks); -// -// // -// // Deallocate the TLS index. -// // -// LdrpReleaseTlsIndex(TlsEntry->TlsDirectory.Characteristics); -// -// // -// // Deallocate the TLS_ENTRY object itself. -// // -// RtlFreeHeap(GetProcessHeap(), 0, TlsEntry); -// -// // -// // We're done. -// // -// return STATUS_SUCCESS; -//} -// -//PVOID* __fastcall LdrpGetNewTlsVector(ULONG TlsBitmapLength) { -// PTLS_VECTOR TlsVector; -// -// TlsVector = (PTLS_VECTOR)RtlAllocateHeap(GetProcessHeap(), (ULONG_PTR)((PUCHAR)NtdllBaseTag + 0x000C0000), -// sizeof(TLS_VECTOR) + (sizeof(PVOID) * TlsBitmapLength) - sizeof(PVOID)); -// if (!TlsVector) return 0; -// TlsVector->Length = TlsBitmapLength; -// RtlZeroMemory(TlsVector->ModuleTlsData, TlsBitmapLength * sizeof(PVOID)); -// return TlsVector->ModuleTlsData; -//} -// -//VOID LdrpQueueDeferredTlsData(PVOID TlsVector, PVOID ThreadId) { -// PTLS_VECTOR RealTlsVector; -// PTLS_RECLAIM_TABLE_ENTRY ReclaimEntry; -// -// RealTlsVector = CONTAINING_RECORD(TlsVector, TLS_VECTOR, ModuleTlsData); -// -// RealTlsVector->ThreadId = ThreadId; -// -// ReclaimEntry = &LdrpDelayedTlsReclaimTable[((ULONG_PTR)(ThreadId) >> 2) & 0xF]; -// -// RtlAcquireSRWLockExclusive(&ReclaimEntry->Lock); -// -// RealTlsVector->PreviousDeferredTlsVector = ReclaimEntry->TlsVector; -// ReclaimEntry->TlsVector = RealTlsVector; -// -// RtlReleaseSRWLockExclusive(&ReclaimEntry->Lock); -//} -// -//#define SIZEOF_TLS_INFO(_ThreadCount_) (_ThreadCount_==0)?sizeof(PROCESS_TLS_INFORMATION)-sizeof(THREAD_TLS_INFORMATION):(_ThreadCount_-1)*sizeof(THREAD_TLS_INFORMATION)+sizeof(PROCESS_TLS_INFORMATION) -//NTSTATUS LdrpHandleTlsData(PLDR_DATA_TABLE_ENTRY ModuleEntry) { -// PIMAGE_TLS_DIRECTORY TlsDirectory; -// ULONG DirectorySize; -// ULONG TlsIndex; -// HANDLE Heap; -// PPROCESS_TLS_INFORMATION TlsInfo; -// PROCESS_TLS_INFORMATION OneThreadTlsInfo; -// NTSTATUS Status; -// BOOLEAN AllocatedBitmap; -// PTLS_ENTRY TlsEntry; -// ULONG TlsBitmapLength; -// SIZE_T TlsRawDataLength; -// ULONG ThreadIndex; -// PVOID TlsData = nullptr; -// PVOID* TlsVector; -// PTHREAD_TLS_INFORMATION ThreadTlsData; -// ULONG ThreadsCleanedUp; -// -// if (LdrpActiveThreadCount == 0) return STATUS_SUCCESS; -// TlsDirectory = (PIMAGE_TLS_DIRECTORY)RtlImageDirectoryEntryToData(ModuleEntry->DllBase, TRUE, IMAGE_DIRECTORY_ENTRY_TLS, &DirectorySize); -// if (!TlsDirectory) return STATUS_SUCCESS; -// Heap = NtCurrentPeb()->ProcessHeap; -// -// TlsInfo = LdrpActiveThreadCount == 1 ? &OneThreadTlsInfo : -// (decltype(TlsInfo))RtlAllocateHeap(Heap, (ULONG)NtdllBaseTag + 0x000C0000, SIZEOF_TLS_INFO(LdrpActiveThreadCount)); -// if (!TlsInfo) return STATUS_NO_MEMORY; -// -// do { -// TlsBitmapLength = LdrpTlsBitmap.SizeOfBitMap; -// Status = LdrpAllocateTlsEntry(TlsDirectory, ModuleEntry, &TlsIndex, &AllocatedBitmap, &TlsEntry); -// if (!NT_SUCCESS(Status)) break; -// TlsInfo->ThreadDataCount = LdrpActiveThreadCount; -// if (AllocatedBitmap) { -// TlsInfo->OperationType = ProcessTlsReplaceVector; -// TlsInfo->TlsVectorLength = TlsBitmapLength; -// TlsBitmapLength = LdrpTlsBitmap.SizeOfBitMap; -// } -// else { -// TlsInfo->OperationType = ProcessTlsReplaceIndex; -// TlsInfo->TlsIndex = TlsIndex; -// } -// Status = STATUS_SUCCESS; -// ThreadsCleanedUp = 0; -// -// // -// // Calculate the size of the raw TLS data for this module. -// // -// TlsRawDataLength = TlsEntry->TlsDirectory.EndAddressOfRawData - TlsEntry->TlsDirectory.StartAddressOfRawData; -// -// // -// // Prepare data for each running thread. -// // -// for (ThreadIndex = 0; ThreadIndex < TlsInfo->ThreadDataCount; ++ThreadIndex) { -// TlsData = RtlAllocateHeap(Heap, (ULONG_PTR)((PUCHAR)NtdllBaseTag + 0x000C0000), TlsRawDataLength); -// if (!TlsData) { -// Status = STATUS_NO_MEMORY; -// break; -// } -// __try { -// RtlCopyMemory(TlsData, (PVOID)TlsEntry->TlsDirectory.StartAddressOfRawData, TlsRawDataLength); -// } -// __except (EXCEPTION_EXECUTE_HANDLER) { -// Status = GetExceptionCode(); -// } -// if (!NT_SUCCESS(Status)) { -// RtlFreeHeap(Heap, 0, TlsData); -// break; -// } -// -// if (AllocatedBitmap) { -// TlsVector = LdrpGetNewTlsVector(TlsBitmapLength); -// if (!TlsVector) { -// RtlFreeHeap(Heap, 0, TlsData); -// break; -// } -// TlsVector[TlsIndex] = TlsData; -// TlsInfo->ThreadData[ThreadIndex].TlsVector = TlsVector; -// } -// else { -// TlsInfo->ThreadData[ThreadIndex].TlsModulePointer = TlsData; -// } -// -// TlsInfo->ThreadData[ThreadIndex].Flags = 0; -// } -// -// // -// // This is awkward; all the 'break' above really are either goto or -// // __leave, but we aren't using those. This is really supposed to -// // just happen on normal for loop exit. -// // -// if (ThreadIndex == TlsInfo->ThreadDataCount) { -// TlsInfo->Reserved = 0; -// Status = NtSetInformationProcess(GetCurrentProcess(), ProcessTlsInformation, TlsInfo, -// TlsInfo->ThreadDataCount * sizeof(THREAD_TLS_INFORMATION) + sizeof(PROCESS_TLS_INFORMATION) - sizeof(THREAD_TLS_INFORMATION)); -// } -// -// // -// // Let's handle each thread that we replaced, as the -// // ProcessTlsInformation call fills our buffer with the old data -// // after performing a swap. -// // -// for (ThreadTlsData = &TlsInfo->ThreadData[ThreadIndex]; ThreadIndex > 0;) { -// ThreadIndex -= 1; -// ThreadTlsData -= 1; -// -// if (ThreadTlsData->Flags & 0x2) { -// if (!ThreadTlsData->TlsVector) continue; -// -// if (!AllocatedBitmap) { -// RtlFreeHeap(Heap, 0, ThreadTlsData->TlsVector); -// continue; -// } -// else { -// LdrpQueueDeferredTlsData(ThreadTlsData->TlsVector, ThreadTlsData->ThreadId); -// continue; -// } -// } -// else { -// if (ThreadTlsData->Flags & 0x1) { -// ++LdrpPotentialTlsLeaks; -// continue; -// } -// else { -// ++ThreadsCleanedUp; -// if (AllocatedBitmap) { -// TlsData = ThreadTlsData->TlsVector[TlsIndex]; -// RtlFreeHeap(Heap, 0, CONTAINING_RECORD(ThreadTlsData->TlsVector, TLS_VECTOR, ModuleTlsData)); -// } -// RtlFreeHeap(Heap, 0, TlsData); -// continue; -// } -// } -// } -// -// if (!NT_SUCCESS(Status)) { -// LdrpReleaseTlsEntry(ModuleEntry); -// if (AllocatedBitmap) LdrpTlsBitmap.SizeOfBitMap -= 4; -// } -// else if (ThreadsCleanedUp > 0) { -// LdrpActiveThreadCount -= ThreadsCleanedUp; -// } -// } while (0); -// -// if (TlsInfo != &OneThreadTlsInfo) RtlFreeHeap(Heap, 0, TlsInfo); -// if (!NT_SUCCESS(Status)) return Status; -// ModuleEntry->TlsIndex = 0xFFFF; -// return STATUS_SUCCESS; -//} -// -////struct UNKNOWN { -//// PVOID unknown1; //+0x0 -//// PVOID unknown2; //+0x8 -//// PVOID unknown3; //+0x10 -//// struct { -//// DWORD dwFlags; //+0x14 -//// DWORD unknown4; //+0x18 -//// }; -//// PWSTR DllName; //+0x20 -//// PVOID unknown[11]; -////}; -//// -//////#include "../MemoryModule/Native.h" -//// -//////size = 0xC0 + DllName->Length + sizeof(wchar_t) -////typedef struct _ALLOCATE_ENTRY_PARAMETER { -//// UNICODE_STRING DllName; //+0x0 -//// UNKNOWN* unknown_structure; //+0x10 -//// PVOID reserved1; //+0x18 -//// struct { -//// DWORD ProcessStatus; //+0x20 -//// DWORD reserved2; //+0x24 -//// }; -//// PVOID reserved3; //+0x28 -//// PVOID reserved4; //+0x30 -//// PVOID LdrEntry; //+0x38 -//// PVOID reserved[16]; //+0x40 -//// BYTE UnicodeStringBuffer[1]; //+0xC0 -////}ALLOCATE_ENTRY_PARAMETER, * PALLOCATE_ENTRY_PARAMETER; -// - - -typedef struct _RTL_INVERTED_FUNCTION_TABLE_ENTRY_WIN7_32 { - PVOID ImageBase; - ULONG ImageSize; - ULONG SEHandlerCount; - PVOID NextEntrySEHandlerTableEncoded; -} RTL_INVERTED_FUNCTION_TABLE_ENTRY_WIN7_32, * PRTL_INVERTED_FUNCTION_TABLE_ENTRY_WIN7_32; -typedef struct _RTL_INVERTED_FUNCTION_TABLE { - ULONG Count; - ULONG MaxCount; - ULONG Overflow; - ULONG NextEntrySEHandlerTableEncoded; - RTL_INVERTED_FUNCTION_TABLE_ENTRY_WIN7_32 Entries[0x200]; -} RTL_INVERTED_FUNCTION_TABLE, * PRTL_INVERTED_FUNCTION_TABLE; diff --git a/test/test.vcxproj b/test/test.vcxproj index 2d10375..e0883c9 100644 --- a/test/test.vcxproj +++ b/test/test.vcxproj @@ -169,9 +169,6 @@ {5b1f46db-036e-4a50-af5f-f5d6584d42c6} - - - diff --git a/test/test.vcxproj.filters b/test/test.vcxproj.filters index 7d6d192..0fccb83 100644 --- a/test/test.vcxproj.filters +++ b/test/test.vcxproj.filters @@ -19,9 +19,4 @@ Source Files - - - Header Files - - \ No newline at end of file