diff --git a/test/testdrv1/main.cpp b/test/testdrv1/main.cpp index 93b984b..f0102e3 100644 --- a/test/testdrv1/main.cpp +++ b/test/testdrv1/main.cpp @@ -1,6 +1,8 @@ #include #include +#include +#include DECLSPEC_NOINLINE EXTERN_C @@ -55,15 +57,228 @@ KCETBSOD() #endif } +uintptr_t +search_pattern(void *module_handle, const char *signature_value) +{ + static auto in_range = [](auto x, auto a, auto b) { return (x >= a && x <= b); }; + static auto get_bits = [](auto x) { + return ( + in_range((x & (~0x20)), 'A', 'F') ? ((x & (~0x20)) - 'A' + 0xa) : (in_range(x, '0', '9') ? x - '0' : 0)); + }; + static auto get_byte = [](auto x) { return (get_bits(x[0]) << 4 | get_bits(x[1])); }; + + const auto dos_headers = reinterpret_cast(module_handle); + const auto nt_headers = + reinterpret_cast(reinterpret_cast(module_handle) + dos_headers->e_lfanew); + + const auto range_start = reinterpret_cast(module_handle); + const auto range_end = range_start + nt_headers->OptionalHeader.SizeOfImage; + + auto first_match = 0ui64; + auto pat = signature_value; + + for (uintptr_t cur = range_start; cur < range_end; cur++) + { + if (*pat == '\0') + { + return first_match; + } + if (*(uint8_t *)pat == '\?' || *reinterpret_cast(cur) == get_byte(pat)) + { + if (!first_match) + first_match = cur; + + if (!pat[2]) + return first_match; + + if (*(uint16_t *)pat == 16191 || *(uint8_t *)pat != '\?') + { + pat += 3; + } + else + { + pat += 2; + } + } + else + { + pat = signature_value; + first_match = 0; + } + } + return 0u; +} + +uintptr_t +get_kernel_base() +{ +#ifndef _ARM64_ + const auto idtbase = *reinterpret_cast(__readgsqword(0x18) + 0x38); + const auto descriptor_0 = *reinterpret_cast(idtbase); + const auto descriptor_1 = *reinterpret_cast(idtbase + 8); + const auto isr_base = ((descriptor_0 >> 32) & 0xFFFF0000) + (descriptor_0 & 0xFFFF) + (descriptor_1 << 32); + auto align_base = isr_base & 0xFFFFFFFFFFFFF000; + + for (;; align_base -= 0x1000) + { + for (auto *search_base = reinterpret_cast(align_base); + search_base < reinterpret_cast(align_base) + 0xFF9; + search_base++) + { + if (search_base[0] == 0x48 && search_base[1] == 0x8D && search_base[2] == 0x1D && search_base[6] == 0xFF) + { + const auto relative_offset = *reinterpret_cast(&search_base[3]); + const auto address = reinterpret_cast(search_base + relative_offset + 7); + if ((address & 0xFFF) == 0) + { + if (*reinterpret_cast(address) == 0x5A4D) + { + return address; + } + } + } + } + } +#endif + return 0; +} + +uintptr_t +search_pattern(void *module_handle, const char *section, const char *signature_value) +{ + static auto in_range = [](auto x, auto a, auto b) { return (x >= a && x <= b); }; + static auto get_bits = [](auto x) { + return ( + in_range((x & (~0x20)), 'A', 'F') ? ((x & (~0x20)) - 'A' + 0xa) : (in_range(x, '0', '9') ? x - '0' : 0)); + }; + static auto get_byte = [](auto x) { return (get_bits(x[0]) << 4 | get_bits(x[1])); }; + + const auto dos_headers = reinterpret_cast(module_handle); + const auto nt_headers = + reinterpret_cast(reinterpret_cast(module_handle) + dos_headers->e_lfanew); + const auto section_headers = reinterpret_cast(nt_headers + 1); + + auto range_start = 0ui64; + auto range_end = 0ui64; + for (auto cur_section = section_headers; cur_section < section_headers + nt_headers->FileHeader.NumberOfSections; + cur_section++) + { + if (strcmp(reinterpret_cast(cur_section->Name), section) == 0) + { + range_start = reinterpret_cast(module_handle) + cur_section->VirtualAddress; + range_end = range_start + cur_section->Misc.VirtualSize; + } + } + + if (range_start == 0) + return 0u; + + auto first_match = 0ui64; + auto pat = signature_value; + for (uintptr_t cur = range_start; cur < range_end; cur++) + { + if (*pat == '\0') + { + return first_match; + } + if (*(uint8_t *)pat == '\?' || *reinterpret_cast(cur) == get_byte(pat)) + { + if (!first_match) + first_match = cur; + + if (!pat[2]) + return first_match; + + if (*(uint16_t *)pat == 16191 || *(uint8_t *)pat != '\?') + { + pat += 3; + } + else + { + pat += 2; + } + } + else + { + pat = signature_value; + first_match = 0; + } + } + return 0u; +} + +static uint64_t mm_pfn_database = 0; + +uintptr_t +init_mmpfn_database() +{ + auto search = search_pattern( + reinterpret_cast(get_kernel_base()), ".text", "B9 ? ? ? ? 48 8B 05 ? ? ? ? 48 89 43 18") + + 5; + auto resolved_base = search + *reinterpret_cast(search + 3) + 7; + mm_pfn_database = *reinterpret_cast(resolved_base); + printf("mm_pfn_database=%p\n", mm_pfn_database); + return mm_pfn_database; +} + +#pragma warning(push) +#pragma warning(disable : 4201) +struct _MMPFN +{ + uintptr_t flags; + uintptr_t pte_address; + uintptr_t Unused_1; + uintptr_t Unused_2; + uintptr_t Unused_3; + uintptr_t Unused_4; +}; +static_assert(sizeof(_MMPFN) == 0x30); + +EXTERN_C +NTSYSAPI CHAR * +PsGetProcessImageFileName(__in uintptr_t Process); + +typedef struct _PAGE_ENTRY +{ + union + { + UINT64 Flags; + + struct + { + UINT64 Present : 1; + UINT64 Write : 1; + UINT64 Supervisor : 1; + UINT64 PageLevelWriteThrough : 1; + UINT64 PageLevelCacheDisable : 1; + UINT64 Accessed : 1; + UINT64 Dirty : 1; + UINT64 LargePage : 1; + UINT64 Global : 1; + UINT64 Ignored1 : 3; + UINT64 PageFrameNumber : 36; + UINT64 Reserved1 : 4; + UINT64 Ignored2 : 7; + UINT64 ProtectionKey : 4; + UINT64 ExecuteDisable : 1; + }; + }; +} PAGE_ENTRY, *PPAGE_ENTRY; + DECLSPEC_NOINLINE EXTERN_C void InitPageTable() { #ifndef _ARM64_ + + // Copy from https://github.com/Rythorndoran/enum_real_dirbase/blob/master/enum_real_dirbase/main.cpp + init_mmpfn_database(); + PHYSICAL_ADDRESS PA = {0}; ULONG64 CurCr3 = (ULONG64)PAGE_ALIGN(__readcr3()); PA.QuadPart = CurCr3; + printf("CurCr3 pa=%p\n", PA.QuadPart); PVOID MapAddress = MmGetVirtualForPhysical(PA); if (MapAddress) { @@ -81,6 +296,48 @@ InitPageTable() printf("PdeBase=%p\n", PdeBase); printf("PpeBase=%p\n", PpeBase); printf("PxeBase=%p\n", PxeBase); + + auto mem_range = MmGetPhysicalMemoryRanges(); + auto mem_range_count = 0; + PPAGE_ENTRY cr3_ptebase = (PPAGE_ENTRY)(SelfMapIndex * 8 + PxeBase); + printf("cr3_ptebase=%p\n", cr3_ptebase); + + auto CR3PF = cr3_ptebase->PageFrameNumber << 12; + printf("CR3PF=%p\n", CR3PF); + + for (mem_range_count = 0; mem_range_count < 200; mem_range_count++) + { + if (mem_range[mem_range_count].BaseAddress.QuadPart == 0 && + mem_range[mem_range_count].NumberOfBytes.QuadPart == 0) + break; + + auto start_pfn = mem_range[mem_range_count].BaseAddress.QuadPart >> 12; + auto end_pfn = start_pfn + (mem_range[mem_range_count].NumberOfBytes.QuadPart >> 12); + + for (auto i = start_pfn; i < end_pfn; i++) + { + auto cur_mmpfn = reinterpret_cast<_MMPFN *>(mm_pfn_database + 0x30 * i); + if (cur_mmpfn->flags) + { + if (cur_mmpfn->flags == 1) + continue; + if (cur_mmpfn->pte_address != (ULONG64)cr3_ptebase) + continue; + auto decrypted_eprocess = + ((cur_mmpfn->flags | 0xF000000000000000) >> 0xd) | 0xFFFF000000000000; + auto dirbase = i << 12; + if (MmIsAddressValid(reinterpret_cast(decrypted_eprocess))) + { + printf( + "Process -> 0x%llx\nProcessName -> %s\nDirBase -> 0x%llx\n\n", + decrypted_eprocess, + PsGetProcessImageFileName(decrypted_eprocess), + dirbase); + } + } + } + } + break; } } @@ -105,7 +362,7 @@ LibWinDrvDriverEntry(__in DRIVER_OBJECT *DriverObject, __in UNICODE_STRING *Regi printf("hello world2\n");*/ // KCETBSOD(); main2(); - InitPageTable(); + // InitPageTable(); return STATUS_SUCCESS; }