开启辅助访问 切换到宽版

精易论坛

 找回密码
 注册

QQ登录

只需一步,快速开始

用微信号发送消息登录论坛

新人指南 邀请好友注册 - 我关注人的新帖 教你赚取精币 - 每日签到


求职/招聘- 论坛接单- 开发者大厅

论坛版规 总版规 - 建议/投诉 - 应聘版主 - 精华帖总集 积分说明 - 禁言标准 - 有奖举报

查看: 982|回复: 9
收起左侧

[求助] 关于ZwMapViewOfSection在驱动中映射物理页的问题

[复制链接]
结帖率:100% (10/10)
发表于 2024-5-10 00:37:58 | 显示全部楼层 |阅读模式   湖北省襄阳市

我想在驱动里写一个线性地址转物理地址的例子,但是为了不同系统的兼容性,没有使用MmMapIoSpace(Ex)这种函数
最终还是打算用ZwMapViewOfSection来实现,但是遇到了一个很奇怪的问题

根据进程id取得CR3,再算出线性地址的 pml4 pdpte pde pte 的索引,然后开始映射

奇怪的地方来了,pml4和pdpte映射后的,和我手动解析后一样,但是从PDE这开始就不对了

Windbg调试后,发现 phy.QuadPart = (*pde & 0x000FFFFFFFFFF000) + pteIndex; 这个phy的物理地址和手动算的一样,但是映射的结果仍然为空,就很奇怪

麻烦各位大佬帮我看看是哪里的问题

代码:https://wwm.lanzoum.com/imPlZ1y8pz1a
映射问题.jpg
结帖率:100% (10/10)

签到天数: 3 天

 楼主| 发表于 2024-6-18 23:28:44 | 显示全部楼层   湖北省襄阳市
已自行解决,问题出在映射时索引和偏移上,而且少映射了一次,隔了一个多月再看自己代码,感觉自己写的就是一坨
回复 支持 反对

使用道具 举报

结帖率:100% (10/10)

签到天数: 3 天

 楼主| 发表于 2024-5-10 00:43:05 | 显示全部楼层   湖北省襄阳市
测试的环境是win7 x64
回复 支持 反对

使用道具 举报

签到天数: 5 天

发表于 2024-5-10 01:21:08 | 显示全部楼层   广东省清远市
[C++] 纯文本查看 复制代码
#include <ntifs.h>

HANDLE GetPhysicalHandle()
{
    static HANDLE hMemory = NULL;

    if (hMemory) return hMemory;

    UNICODE_STRING PhysicalMemoryString = { 0 };

    WCHAR PhysicalMemoryName[] = L"\\Device\\PhysicalMemory";
    RtlInitUnicodeString(&PhysicalMemoryString, PhysicalMemoryName);

    OBJECT_ATTRIBUTES obj;

    InitializeObjectAttributes(&obj, &PhysicalMemoryString, OBJ_CASE_INSENSITIVE, NULL, NULL);

    NTSTATUS status = ZwOpenSection(&hMemory, SECTION_MAP_READ | SECTION_MAP_WRITE, &obj);

    if (!NT_SUCCESS(status))
    {
        return NULL;
    }

    return hMemory;
}

ULONG64 Va2Pa(ULONG64 VirtAddr, int processId)
{
    ULONG64 virtaddr = VirtAddr;
    PEPROCESS Process = NULL;
    PsLookupProcessByProcessId((HANDLE)processId, &Process);
    ULONG64 CR3 = *(PULONG64)((PUCHAR)Process + 0x28);
    CR3 &= ~0xFFF;

    ULONG64 pml4Index = ((virtaddr >> 39) & 0x1FF) * 8;
    ULONG64 pdpteIndex = ((virtaddr >> 30) & 0x1FF) * 8;
    ULONG64 pdeIndex = ((virtaddr >> 21) & 0x1FF) * 8;
    ULONG64 pteIndex = ((virtaddr >> 12) & 0x1FF) * 8;

    PHYSICAL_ADDRESS phy = { 0 };
    phy.QuadPart = CR3 + pml4Index;

    HANDLE pHandle = GetPhysicalHandle();

    if (!pHandle) return STATUS_UNSUCCESSFUL;

    NTSTATUS status;
    PULONG64 pml4 = NULL;
    SIZE_T map_size = 8;
    ULONG64 retaddress = 0;

    status = ZwMapViewOfSection(pHandle, NtCurrentProcess(), (PVOID*)&pml4, 0, 8, &phy, &map_size, ViewUnmap, MEM_TOP_DOWN, PAGE_READWRITE);
    if (!NT_SUCCESS(status) || !pml4)
    {
        return 0;
    }

    PULONG64 pdpte = NULL;
    phy.QuadPart = (*pml4 & 0x000FFFFFFFFFF000) + pdpteIndex;
    status = ZwMapViewOfSection(pHandle, NtCurrentProcess(), (PVOID*)&pdpte, 0, 8, &phy, &map_size, ViewUnmap, MEM_TOP_DOWN, PAGE_READWRITE);
    if (!NT_SUCCESS(status) || !pdpte)
    {
        ZwUnmapViewOfSection(NtCurrentProcess(), pml4);
        return 0;
    }

    PULONG64 pde = NULL;
    phy.QuadPart = (*pdpte & 0x000FFFFFFFFFF000) + pdeIndex;
    status = ZwMapViewOfSection(pHandle, NtCurrentProcess(), (PVOID*)&pde, 0, 8, &phy, &map_size, ViewUnmap, MEM_TOP_DOWN, PAGE_READWRITE);
    if (!NT_SUCCESS(status) || !pde)
    {
        ZwUnmapViewOfSection(NtCurrentProcess(), pdpte);
        ZwUnmapViewOfSection(NtCurrentProcess(), pml4);
        return 0;
    }

    PULONG64 pte = NULL;
    phy.QuadPart = (*pde & 0x000FFFFFFFFFF000) + pteIndex;
    status = ZwMapViewOfSection(pHandle, NtCurrentProcess(), (PVOID*)&pte, 0, 8, &phy, &map_size, ViewUnmap, MEM_TOP_DOWN, PAGE_READWRITE);
    if (!NT_SUCCESS(status) || !pte)
    {
        ZwUnmapViewOfSection(NtCurrentProcess(), pde);
        ZwUnmapViewOfSection(NtCurrentProcess(), pdpte);
        ZwUnmapViewOfSection(NtCurrentProcess(), pml4);
        return 0;
    }

    if (*pte & 0x1)
    {
        retaddress = (*pte & 0xFFFFFFFFFFFFF000) + (virtaddr & 0xFFF);
    }
    else
    {
        retaddress = (*pte & 0xFFFFFFFFFFFFF000) + (virtaddr & 0xFFF);
    }

    ZwUnmapViewOfSection(NtCurrentProcess(), pte);
    ZwUnmapViewOfSection(NtCurrentProcess(), pde);
    ZwUnmapViewOfSection(NtCurrentProcess(), pdpte);
    ZwUnmapViewOfSection(NtCurrentProcess(), pml4);

    return retaddress;
}

VOID DriverUnload(PDRIVER_OBJECT pDriver)
{

}

NTSTATUS DriverEntry(PDRIVER_OBJECT pDriver, PUNICODE_STRING pReg)
{
    ULONG64 ret = Va2Pa(0x00401F6A, 1996);
    
    DbgPrintEx(77, 0, "[=]:函数返回 : %llx\r\n", ret);

    pDriver->DriverUnload = DriverUnload;
    return STATUS_SUCCESS;
}


回复 支持 反对

使用道具 举报

结帖率:100% (10/10)

签到天数: 3 天

 楼主| 发表于 2024-5-10 01:54:37 | 显示全部楼层   湖北省襄阳市
oncall12 发表于 2024-5-10 01:21
[mw_shl_code=cpp,true]#include

HANDLE GetPhysicalHandle()

大佬,你这份代码和还是我那个一样,到PDE就错了
回复 支持 反对

使用道具 举报

结帖率:97% (29/30)

签到天数: 22 天

发表于 2024-5-10 02:32:33 | 显示全部楼层   广西壮族自治区柳州市
问错地方了,应该去看雪问
回复 支持 反对

使用道具 举报

发表于 2024-5-10 09:03:12 | 显示全部楼层   北京市北京市
用__invlpg刷掉TLB试试吧(注意用__invlpg要关中断或提IRQL)
回复 支持 反对

使用道具 举报

发表于 2024-5-10 09:27:06 | 显示全部楼层   美国
你确定这个东西在这里能找到答案?
这个页表结构有点花眼睛,当时我下载了一份写的很乱的代码优化了一个星期才搞清楚。

        PTE_HOOK::PageTable         PTE_HOOK:: GetPageTableStruct(ULONG64 Address)//表项
        {
                PTE_HOOK::PageTable res = { 0 };
                ULONG64 vcr3 = reinterpret_cast <ULONG64>(PTE_HOOK::GetVirtualAddressByPhysical(__readcr3() & (~(PAGE_SIZE - 1))));
                if (!MmIsAddressValid(reinterpret_cast<PVOID>(vcr3)))                 return res;

                ULONG64 address = Address & (~0xfff);

                ULONG pml4eIndex = (address & (((ULONG64)1 << 48) - 1)) >> 39;
                ULONG ppeIndex = (address & (((ULONG64)1 << 39) - 1)) >> 30;
                ULONG pdeIndex = (address & (((ULONG64)1 << 30) - 1)) >> 21;
                ULONG pteIndex = (address & (((ULONG64)1 << 21) - 1)) >> 12;

                res.PML4E = reinterpret_cast <PHardwarePml4e>(vcr3 + pml4eIndex * 8);

                if (!MmIsAddressValid(res.PML4E))                   return res;

                ULONG64    p = reinterpret_cast <ULONG64>(PTE_HOOK::GetVirtualAddressByPhysical(res.PML4E->PageFrameNumber << PAGE_SHIFT));

                if (!p)
                {
                        return res;
                }


                res.PPE = reinterpret_cast <PHardwarePdpte>(p + ppeIndex * 8);

                if (!MmIsAddressValid(res.PPE))                  return res;
                p = reinterpret_cast <ULONG64>(PTE_HOOK::GetVirtualAddressByPhysical(res.PPE->PageFrameNumber << PAGE_SHIFT));

                if (!p)
                {
                        return res;
                }



                res.PDE = reinterpret_cast <PHardwarePde>(p + pdeIndex * 8);

                if (!MmIsAddressValid(res.PDE))                  return res;
                p = reinterpret_cast <ULONG64>(PTE_HOOK::GetVirtualAddressByPhysical(res.PDE->PageFrameNumber << PAGE_SHIFT));

                if (p)
                {
                        res.PTE = reinterpret_cast <PHardwarePte>(p + pteIndex * 8);
                }


                return res;

        }
计算出 pte后 将你需要映射地址的pte中的PageFrameNumber 修改为线性地址的PageFrameNumber 即便完成映射,并且要注意 有些时候pte和pde存在大页的情况,映射完成后刷一下tlb
回复 支持 反对

使用道具 举报

结帖率:100% (10/10)

签到天数: 3 天

 楼主| 发表于 2024-5-10 17:00:18 | 显示全部楼层   湖北省襄阳市
我的小拇指啊 发表于 2024-5-10 02:32
问错地方了,应该去看雪问

问了,看雪那边没人理我
回复 支持 反对

使用道具 举报

结帖率:100% (10/10)

签到天数: 3 天

 楼主| 发表于 2024-5-10 17:00:37 | 显示全部楼层   湖北省襄阳市
ANormalUser 发表于 2024-5-10 09:03
用__invlpg刷掉TLB试试吧(注意用__invlpg要关中断或提IRQL)

试了,还是不行
回复 支持 反对

使用道具 举报

  高级模式
B Color Image Link Quote Code Smilies |上传

本版积分规则 致发广告者

发布主题 收藏帖子 返回列表

sitemap| 易语言源码| 易语言教程| 易语言论坛| 易语言模块| 手机版| 广告投放| 精易论坛
拒绝任何人以任何形式在本论坛发表与中华人民共和国法律相抵触的言论,本站内容均为会员发表,并不代表精易立场!
论坛帖子内容仅用于技术交流学习和研究的目的,严禁用于非法目的,否则造成一切后果自负!如帖子内容侵害到你的权益,请联系我们!
防范网络诈骗,远离网络犯罪 违法和不良信息举报电话0663-3422125,QQ: 793400750,邮箱:wp@125.la
Powered by Discuz! X3.4 揭阳市揭东区精易科技有限公司 ( 粤ICP备12094385号-1) 粤公网安备 44522102000125 增值电信业务经营许可证 粤B2-20192173

快速回复 返回顶部 返回列表