kernel_physical_mapping_init()

pagetable_init() --> kernel_physical_mapping_init()

static void __init kernel_physical_mapping_init(pgd_t *pgd_base)
{
    unsigned long pfn;
    pgd_t *pgd;
    pmd_t *pmd;
    pte_t *pte;
    int pgd_idx, pmd_idx, pte_ofs;

定位主内核页全局目录(master kernel page global directory)的起始项pgd=768:
|--------------------------------------|
|   pgd_idx = pgd_index(PAGE_OFFSET);  |
|   pgd = pgd_base + pgd_idx;          |
|--------------------------------------|


物理地址从0x0000 0000开始,起始页框号(page frame number)为pfn;
|-----------------|
|   pfn = 0;      |
|-----------------|

    for (; pgd_idx < PTRS_PER_PGD; pgd++, pgd_idx++) {

直接返回pgd(pmd和pgd指向同一个页目录项)
|-------------------------------------|
|       pmd = one_md_table_init(pgd); |
|-------------------------------------|
 
        if (pfn >= max_low_pfn)
            continue;
        for (pmd_idx = 0; pmd_idx < PTRS_PER_PMD && pfn < max_low_pfn; pmd++, pmd_idx++) {

计算第pfn个页框对应的内核空间的线性地址:
|-----------------------------------------------------------------|
|           unsigned int address = pfn * PAGE_SIZE + PAGE_OFFSET; |
|-----------------------------------------------------------------|
            if (cpu_has_pse) {
                unsigned int address2 = (pfn + PTRS_PER_PTE - 1)
                                * PAGE_SIZE + PAGE_OFFSET + PAGE_SIZE-1;
                if (is_kernel_text(address) || is_kernel_text(address2))
                    set_pmd(pmd, pfn_pmd(pfn, PAGE_KERNEL_LARGE_EXEC));
                else
                    set_pmd(pmd, pfn_pmd(pfn, PAGE_KERNEL_LARGE));
                pfn += PTRS_PER_PTE;

填写一个页目录项pmd(pgd),并填写该目录项所对应的页表的所有项
为页目录项pmd分配页表pte,将该页表pte的物理地址写入pmd中,并初始化页表pte的每个页表项;
|--------------------------------------------------------------------------|
|           } else {                                                       |
|               pte = one_page_table_init(pmd);                            |
|               for (pte_ofs = 0;                                          |
|                    pte_ofs < PTRS_PER_PTE && pfn < max_low_pfn;          |
|                    pte++, pfn++, pte_ofs++) {                            |
|                       if ( is_kernel_text(address))                       |
|                           set_pte(pte, pfn_pte(pfn, PAGE_KERNEL_EXEC));  |
|                       else                                               |
|                           set_pte(pte, pfn_pte(pfn, PAGE_KERNEL));       |
|               }                                                          |
|           }                                                              |
|--------------------------------------------------------------------------|
        }
    }
}

#include <ntifs.h> #include <ntddk.h> // 全局物理内存区段句柄 HANDLE g_phys_mem_handle = NULL; // 页表索引宏定义 #define PML4_INDEX(va) ((va >> 39) & 0x1FF) #define PDPT_INDEX(va) ((va >> 30) & 0x1FF) #define PD_INDEX(va) ((va >> 21) & 0x1FF) #define PT_INDEX(va) ((va >> 12) & 0x1FF) #define PAGE_OFFSET(va) (va & 0xFFF) // 初始化物理内存区段 NTSTATUS init_physical_memory_section() { OBJECT_ATTRIBUTES objAttr; UNICODE_STRING physMemName; RtlInitUnicodeString(&physMemName, L"\\Device\\PhysicalMemory"); InitializeObjectAttributes(&objAttr, &physMemName, OBJ_CASE_INSENSITIVE | OBJ_KERNEL_HANDLE, NULL, NULL); return ZwOpenSection(&g_phys_mem_handle, SECTION_MAP_READ | SECTION_MAP_WRITE, &objAttr); } // 映射物理页到虚拟地址 PVOID map_physical_page(ULONG64 physical_address) { if (!g_phys_mem_handle) return NULL; LARGE_INTEGER sectionOffset; sectionOffset.QuadPart = physical_address; PVOID baseAddress = NULL; SIZE_T viewSize = PAGE_SIZE; NTSTATUS status = ZwMapViewOfSection( g_phys_mem_handle, NtCurrentProcess(), &baseAddress, 0L, PAGE_SIZE, &sectionOffset, &viewSize, ViewShare, 0, PAGE_READWRITE ); return NT_SUCCESS(status) ? baseAddress : NULL; } // 取消映射 void unmap_physical_page(PVOID base_address) { if (base_address) { ZwUnmapViewOfSection(NtCurrentProcess(), base_address); } } // 获取进程的CR3值 ULONG64 get_process_cr3(HANDLE pid) { PEPROCESS process; if (NT_SUCCESS(PsLookupProcessByProcessId(pid, &process))) { // Windows 10 10240 EPROCESS中CR3的偏移为0x28 ULONG64 cr3 = *(ULONG64*)((PUCHAR)process + 0x28); ObDereferenceObject(process); return cr3; } return 0; } // 主函数:映射线性地址到物理空间 PVOID get_pyse_map_space(HANDLE pid, ULONG64 linear_address) { // 1. 获取目标进程CR3 ULONG64 cr3 = get_process_cr3(pid); if (!cr3) return NULL; // 2. 计算页表索引 ULONG64 pml4_index = PML4_INDEX(linear_address); ULONG64 pdpt_index = PDPT_INDEX(linear_address); ULONG64 pd_index = PD_INDEX(linear_address); ULONG64 pt_index = PT_INDEX(linear_address); ULONG64 offset = PAGE_OFFSET(linear_address); // 3. 递归查询页表 ULONG64 current_phys = cr3 & ~0xFFF; // 清除低12位标志 // PML4 -> PDPT PVOID mapped_page = map_physical_page(current_phys); if (!mapped_page) return NULL; ULONG64* pml4_entry = (ULONG64*)mapped_page + pml4_index; if (!(*pml4_entry & 1)) { // 检查有效位 unmap_physical_page(mapped_page); return NULL; } current_phys = *pml4_entry & 0x000FFFFFFFFFF000; unmap_physical_page(mapped_page); // PDPT -> PD mapped_page = map_physical_page(current_phys); if (!mapped_page) return NULL; ULONG64* pdpt_entry = (ULONG64*)mapped_page + pdpt_index; if (!(*pdpt_entry & 1)) { unmap_physical_page(mapped_page); return NULL; } // 检查2MB大页 if (*pdpt_entry & 0x80) { ULONG64 large_page_base = *pdpt_entry & 0x000FFFFFFFFFF000; unmap_physical_page(mapped_page); return (PVOID)((ULONG64)map_physical_page(large_page_base) + offset); } current_phys = *pdpt_entry & 0x000FFFFFFFFFF000; unmap_physical_page(mapped_page); // PD -> PT mapped_page = map_physical_page(current_phys); if (!mapped_page) return NULL; ULONG64* pd_entry = (ULONG64*)mapped_page + pd_index; if (!(*pd_entry & 1)) { unmap_physical_page(mapped_page); return NULL; } // 检查1GB大页 if (*pd_entry & 0x80) { ULONG64 large_page_base = *pd_entry & 0x000FFFFFFFFFF000; unmap_physical_page(mapped_page); return (PVOID)((ULONG64)map_physical_page(large_page_base) + offset); } current_phys = *pd_entry & 0x000FFFFFFFFFF000; unmap_physical_page(mapped_page); // PT -> 物理页 mapped_page = map_physical_page(current_phys); if (!mapped_page) return NULL; ULONG64* pt_entry = (ULONG64*)mapped_page + pt_index; if (!(*pt_entry & 1)) { unmap_physical_page(mapped_page); return NULL; } ULONG64 target_phys = *pt_entry & 0x000FFFFFFFFFF000; unmap_physical_page(mapped_page); // 4. 映射目标物理页 PVOID result = map_physical_page(target_phys); return result ? (PVOID)((ULONG64)result + offset) : NULL; } // 驱动卸载清理 VOID DriverUnload(PDRIVER_OBJECT DriverObject) { if (g_phys_mem_handle) { ZwClose(g_phys_mem_handle); g_phys_mem_handle = NULL; } } // 驱动入口 extern "C" NTSTATUS DriverEntry(PDRIVER_OBJECT DriverObject, PUNICODE_STRING RegistryPath) { DriverObject->DriverUnload = DriverUnload; NTSTATUS status = init_physical_memory_section(); if (!NT_SUCCESS(status)) { KdPrint(("Failed to open physical memory section: 0x%X\n", status)); return status; } HANDLE pid = 0; ULONG64 linear_addr = 0; PVOID mapped_addr = get_pyse_map_space(pid, linear_addr); return STATUS_SUCCESS; } 这代码映射物理地址到虚拟地址?什么流程?是获取到物理地址然后给自己的进程空间的虚拟地址替换物理页?指定了哪个虚拟地址吗?
最新发布
07-22
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值