// Initializes GuardMon components _Use_decl_annotations_ NTSTATUS GMonInitialization() { PAGED_CODE(); GMonpDemoStl(); g_gmonp_ExAcquireResourceSharedLite = UtilGetSystemProcAddress(L"ExAcquireResourceSharedLite"); if (!g_gmonp_ExAcquireResourceSharedLite) { return STATUS_PROCEDURE_NOT_FOUND; } RTL_OSVERSIONINFOW os_version = {}; auto status = RtlGetVersion(&os_version); if (!NT_SUCCESS(status)) { return status; } if (os_version.dwMajorVersion == 10 && os_version.dwMinorVersion == 0) { g_pgmon_IsWindows10 = true; } return STATUS_SUCCESS; }
// Locates RtlPcToFileHeader _Use_decl_annotations_ static NTSTATUS MmonpInitializeRtlPcToFileHeader(PDRIVER_OBJECT driver_object) { PAGED_CODE(); if (kMmonpUseRtlPcToFileHeader) { const auto p_RtlPcToFileHeader = UtilGetSystemProcAddress(L"RtlPcToFileHeader"); if (p_RtlPcToFileHeader) { g_mmonp_RtlPcToFileHeader = reinterpret_cast<RtlPcToFileHeaderType *>(p_RtlPcToFileHeader); return STATUS_SUCCESS; } } #pragma warning(push) #pragma warning(disable : 28175) auto module = reinterpret_cast<LdrDataTableEntry *>(driver_object->DriverSection); #pragma warning(pop) g_mmonp_PsLoadedModuleList = module->in_load_order_links.Flink; g_mmonp_RtlPcToFileHeader = MmonpUnsafePcToFileHeader; return STATUS_SUCCESS; }
// Locate MmPfnDatabase _Use_decl_annotations_ static NTSTATUS MmonpInitializeMmPfnDatabase() { PAGED_CODE(); RTL_OSVERSIONINFOW os_version = {}; auto status = RtlGetVersion(&os_version); if (!NT_SUCCESS(status)) { return status; } // Set appropriate patterns and based on an OS version struct MmPfnDatabaseSearchPattern { const UCHAR *bytes; SIZE_T bytes_size; bool hard_coded; }; MmPfnDatabaseSearchPattern patterns[2] = {}; if (IsX64()) { // Win 10 build 14316 is the first version implements randomized page tables if (os_version.dwMajorVersion < 10 || os_version.dwBuildNumber < 14316) { // PFN database is at the constant location on older x64 Windows g_mmonp_MmPfnDatabase = reinterpret_cast<void *>(0xfffffa8000000000); return STATUS_SUCCESS; } // Windows 10 x64 Build 14332+ static const UCHAR kPatternWin10x64[] = { 0x48, 0x8B, 0xC1, // mov rax, rcx 0x48, 0xC1, 0xE8, 0x0C, // shr rax, 0Ch 0x48, 0x8D, 0x14, 0x40, // lea rdx, [rax + rax * 2] 0x48, 0x03, 0xD2, // add rdx, rdx 0x48, 0xB8, // mov rax, 0FFFFFA8000000008h }; patterns[0].bytes = kPatternWin10x64; patterns[0].bytes_size = sizeof(kPatternWin10x64); patterns[0].hard_coded = true; } else { // x86 if (os_version.dwMajorVersion == 6 && os_version.dwMinorVersion == 1) { // Windows 7 (No PAE) static const UCHAR kPatternWin7[] = { 0x6B, 0xC0, 0x18, // imul eax, 18h 0x8B, 0x0D, // mov ecx, ds:_MmPfnDatabase }; // Windows 7 (PAE) static const UCHAR kPatternWin7Pae[] = { 0x6B, 0xC0, 0x1C, // imul eax, 1Ch 0x8B, 0x0D, // mov ecx, ds:_MmPfnDatabase }; if (UtilIsX86Pae()) { patterns[0].bytes = kPatternWin7Pae; patterns[0].bytes_size = sizeof(kPatternWin7Pae); patterns[0].hard_coded = false; } else { patterns[0].bytes = kPatternWin7; patterns[0].bytes_size = sizeof(kPatternWin7); patterns[0].hard_coded = false; } } else if ((os_version.dwMajorVersion == 6 && os_version.dwMinorVersion == 3) || (os_version.dwMajorVersion == 10 && os_version.dwMinorVersion == 0)) { // Windows 8.1 and 10 static const UCHAR kPatternWin81And10_0[] = { 0xC1, 0xF8, 0x0C, // sar eax, 0Ch 0xA1, // mov eax, ds:_MmPfnDatabase }; static const UCHAR kPatternWin81And10_1[] = { 0xC1, 0xE8, 0x0C, // shr eax, 0Ch 0xA1, // mov eax, ds:_MmPfnDatabase }; patterns[0].bytes = kPatternWin81And10_0; patterns[0].bytes_size = sizeof(kPatternWin81And10_0); patterns[0].hard_coded = false; patterns[1].bytes = kPatternWin81And10_1; patterns[1].bytes_size = sizeof(kPatternWin81And10_1); patterns[1].hard_coded = false; } else { // Unknown x86 OS version return STATUS_UNSUCCESSFUL; } } // Search the patterns from MmGetVirtualForPhysical const auto p_MmGetVirtualForPhysical = reinterpret_cast<UCHAR *>( UtilGetSystemProcAddress(L"MmGetVirtualForPhysical")); if (!p_MmGetVirtualForPhysical) { return STATUS_PROCEDURE_NOT_FOUND; } for (const auto &pattern : patterns) { if (!pattern.bytes) { break; // no more patterns } auto found = reinterpret_cast<UCHAR *>(UtilMemMem( p_MmGetVirtualForPhysical, 0x20, pattern.bytes, pattern.bytes_size)); if (!found) { continue; } // Get an address of PFN database found += pattern.bytes_size; if (pattern.hard_coded) { HYPERPLATFORM_LOG_DEBUG("Found a hard coded PFN database address at %p", found); g_mmonp_MmPfnDatabase = *reinterpret_cast<void **>(found); } else { HYPERPLATFORM_LOG_DEBUG("Found a reference to MmPfnDatabase at %p", found); const auto mmpfn_address = *reinterpret_cast<ULONG_PTR *>(found); g_mmonp_MmPfnDatabase = *reinterpret_cast<void **>(mmpfn_address); } // On Windows 10 RS, a value has 0x8. Delete it. g_mmonp_MmPfnDatabase = PAGE_ALIGN(g_mmonp_MmPfnDatabase); break; } HYPERPLATFORM_LOG_DEBUG("MmPfnDatabase = %p", g_mmonp_MmPfnDatabase); if (!g_mmonp_MmPfnDatabase) { return STATUS_UNSUCCESSFUL; } return STATUS_SUCCESS; }
// Locate MmPfnDatabase _Use_decl_annotations_ static NTSTATUS MmonpInitializeMmPfnDatabase() { PAGED_CODE(); if (IsX64()) { g_mmonp_MmPfnDatabase = reinterpret_cast<void *>(0xfffffa8000000000); } else { const auto p_MmGetVirtualForPhysical = reinterpret_cast<UCHAR *>( UtilGetSystemProcAddress(L"MmGetVirtualForPhysical")); if (!p_MmGetVirtualForPhysical) { return STATUS_PROCEDURE_NOT_FOUND; } RTL_OSVERSIONINFOW os_version = {}; auto status = RtlGetVersion(&os_version); if (!NT_SUCCESS(status)) { return status; } if (os_version.dwMajorVersion == 6 && os_version.dwMinorVersion == 1) { // Windows 7 (No PAE) // 6B C0 18 imul eax, 18h // 8B 0D 14 28 56 00 mov ecx, ds:_MmPfnDatabase static const UCHAR kPatternWin7[] = { 0x6B, 0xC0, 0x18, 0x8B, 0x0D, }; // Windows 7 (PAE) // 6B C0 1C imul eax, 1Ch // 8B 0D 14 28 56 00 mov ecx, ds:_MmPfnDatabase static const UCHAR kPatternWin7Pae[] = { 0x6B, 0xC0, 0x1C, 0x8B, 0x0D, }; const auto is_pae_enabled = Cr4{__readcr4()}.fields.pae; const auto pattern = (is_pae_enabled) ? kPatternWin7Pae : kPatternWin7; const auto size = (is_pae_enabled) ? sizeof(kPatternWin7Pae) : sizeof(kPatternWin7); auto found = reinterpret_cast<UCHAR *>( UtilMemMem(p_MmGetVirtualForPhysical, 0x20, pattern, size)); if (found) { found += size; const auto address = *reinterpret_cast<ULONG_PTR *>(found); g_mmonp_MmPfnDatabase = *reinterpret_cast<void **>(address); } } else if ((os_version.dwMajorVersion == 6 && os_version.dwMinorVersion == 3) || (os_version.dwMajorVersion == 10 && os_version.dwMinorVersion == 0)) { // Windows 8.1 and 10 // C1 F8 0C sar eax, 0Ch // A1 08 B7 62 00 mov eax, ds:_MmPfnDatabase static const UCHAR kPatternWin81And10[] = { 0xC1, 0xF8, 0x0C, 0xA1, }; auto found = reinterpret_cast<UCHAR *>( UtilMemMem(p_MmGetVirtualForPhysical, 0x20, kPatternWin81And10, sizeof(kPatternWin81And10))); if (found) { found += sizeof(kPatternWin81And10); const auto address = *reinterpret_cast<ULONG_PTR *>(found); g_mmonp_MmPfnDatabase = *reinterpret_cast<void **>(address); } } } return (g_mmonp_MmPfnDatabase) ? STATUS_SUCCESS : STATUS_PROCEDURE_NOT_FOUND; }