Windows内存机制

Windows内存机制

在这里插入图片描述

1 基本原理

Cr3寄存器

描述:

在所有的寄存器中,只有Cr3存储的是物理地址,其它寄存器存的都是线性地址
Cr3所存储的物理地址指向了一个页目录表(PDT-Page Directory Table)
在Windows中,一个页的大小通常为4KB,即一个页可以存储1024个页目录表项(PDE)

PD/PDE(Page Directory Table/Entry 页目录表/项)

描述:

页目录表(PDT)的每一项元素称为页目录表项(PDE)
每个页目录表项指向一个页表(PTT)
每个页表的大小为4KB,即一个页表可以存储1024个页表项(PTE)

PT/PTE(Page Table/Entry 页表/项)

描述:

页表(PTT)的每一个元素称为页表项(PTE)
页表项(PTE)所指向的才是真正的物理页

PDP (Page Directory Pointer)

PAE中增加了Page Directory Pointer Table这一级:

PAE

PAE 就是物理地址扩展。我们常规的寻址方式是之前的将虚拟地址化为10 10 12的方式来寻址页目录,页表,页偏移,但是在开始PAE之后的寻址方式发生了改变,将32位的虚拟地址转化成 2 9 9 12的方式来寻址。

高2位指向Page Directory Pointer Table
次高9位指向页目录 共512项 每项64位8字节,4K(正好一页,与未启用PAE一致)
次次高9位指向页表 共512项 每项64位8字节,4K(正好一页,与未启用PAE一致)
低12位作4K的页内偏移。

2 X64特性

在这里插入图片描述

PML4

x64的分页使用4个级别的表,将物理页面映射到虚拟页面,它们分别是PML4(也就是PXE)、PDPT、PD和PT。

控制寄存器CR3包含当前进程PML4表的(物理)内存基地址。

示例-虚拟地址转化为物理地址

在这里插入图片描述

图为x64系统中,从虚拟地址到物理地址遍历过程的概览

在这里,假设我们需要遍历虚拟地址0x71000000000的分页表。

首先,我们对其进行分解:

地址结构

在这里插入图片描述

虚拟地址最低的12位是页偏移量,接下来的9位是PT索引,后面的9位是PD索引,再然后的9位是PDPT索引,最后的9位是PML4索引这里可以看到64位的电脑,实际地址为48位。

我会使用下面的结构来完成这项工作:

typedef
struct VirtualAddressFields
{
    ULONG64 
offset : 12;
    ULONG64 
pt_index : 9;
    ULONG64 
pd_index : 9;
    ULONG64
pdpt_index : 9;
    ULONG64
pml4_index : 9;
    VirtualAddressFields(ULONG64
value)
    {
        *(ULONG64
*)this = 0;
        offset
= value & 0xfff;
        pt_index
= (value >> 12) & 0x1ff;
        pd_index
= (value >> 21) & 0x1ff;
        pdpt_index
= (value >> 30) & 0x1ff;
        pml4_index
= (value >> 39) & 0x1ff;
    }
    ULONG64
getVA()
    {
        ULONG64
res = *(ULONG64 *)this;
        return
res;
    }
}
VirtualAddressFields;

举例来说:

VirtualAddressFields
ADDR1a = 0x71000000000;
0:
kd> dt ADDR1a
Local
var @ 0x1de4d8 Type VirtualAddressFields
   +0x000
offset     : 0y000000000000 (0)
   +0x000
pt_index   : 0y000000000 (0)
   +0x000
pd_index   : 0y000000000 (0)
   +0x000
pdpt_index : 0y001000000 (0x40)
   +0x000
pml4_index : 0y000001110 (0xe)

针对这个例子(VA:0x71000000000),我们得到了PML4_index = 0x0E,PDPT_index = 0x40,PD_index = 0,PT_index = 0,Offset = 0。

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-9Za0y1eR-1592483115485)(window内存机制.assets/t01e5729edede706c9d.jpg)]

现在,我们就得到了虚拟地址的PML4条目:38a0000040653867

这实际上是一个被称为MMPTE的8字节结构,我们需要从中提取页帧号(Page Frame Number):

在这里插入图片描述

现在我们将PFN(0x40653),乘以页大小(0x1000),其得到的结果(0x40653000)作为下一个分页表(PDPT)的基地址。并且,PDPT_index(0x40)将作为该分页表的索引:

在这里插入图片描述

在这里插入图片描述

然后,再将下一个PFN(0x41cd7),乘以页大小(0x1000),其得到的结果(0x41cd7000)作为下一个分页表(PD)的基地址。并且,PD_index(0x00)将作为该分页表的索引:

在这里插入图片描述

在这里插入图片描述

同样,对于最后一级的PFN(0x3e7d8),乘以页大小(0x1000),其得到的结果(0x3e7d8000)作为下一个分页表(PT)的基地址。并且PT_index(0x00)作为该表的索引:

在这里插入图片描述

在这里插入图片描述

最后剩下需要做的,就是把这个PFN(0x3d7d9)乘以页大小(0x1000),再加上page_offset(0x000)。

现在,我们就知道了,虚拟地址0x71000000000实际上是映射物理地址0x3d7d9000。

漏洞

漏洞-自引用

​ X64由于48位物理地址的限制,实际上有效的虚拟地址属于下面这两个范围:0至7FFF’FFFFFFFF(512GB256)或FFFF8000’00000000至FFFFFFFF’FFFFFFFF(512GB256)。微软采取了一种称为self-ref entry(自引用条目)的技术,在最高级别的页表中有一个条目指向自己。在64位系统中,任意自引用条目使用的物理地址应该指向PML4基地址的物理地址,与CR3寄存器所指向的地址相同。

​ 例如,如果我们在PML4表中创建一个索引0x100处的新条目,并且该条目指向PML4表的物理地址,那么我们就有所谓的“自引用条目”。

​ 那么为什么会有人这样做呢?这实际上给了我们一组虚拟地址,我们可以在虚拟地址空间中引用和修改任何页表。

​ 例如,如果我们想要为我们的过程修改PML4表,我们可以简单地引用虚拟地址0x804020100000,该虚拟地址转换为:

0b 1000 0000 0 — 100 0000 00 — 10 0000 000 — 1 0000 0000 — 0000 0000 0000

  • PML4索引0x100 - PML4的物理地址
  • PDPT索引0x100 - 同样是PML4的物理地址
  • PD索引0x100 - 同样是PML4的物理地址
  • PT索引0x100 - 再次… PML4的物理地址

它最终会返回PML4的内存。

修补

​ 微软已经在Anniversary Update中针对该方法推出了缓解机制。这并不意味着Windows 10不再依赖自引用,Windows只是随机化处理了PML4中自引用条目的索引,这样最终导致PML4及PET虚拟地址的随机化。

  • 4
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Windows操作系统中,内存分页机制是一种虚拟内存管理技术,用于将物理内存与进程的虚拟地址空间进行映射和管理。内存分页机制的核心概念是将进程的虚拟地址空间划分为固定大小的页面(通常为4KB),并将其映射到物理内存上。 Windows使用了两级的页表结构来实现内存分页机制: 1. 页面目录表(Page Directory Table):页面目录表是一个固定大小的数据结构,用于存储指向页面表的指针。每个页面目录表项(Page Directory Entry)对应着一个页面表。页面目录表通常在系统启动时创建,并且对于每个进程都有一个独立的页面目录表。 2. 页面表(Page Table):页面表是一个固定大小的数据结构,用于将虚拟地址映射到物理地址。每个页面表项(Page Table Entry)包含了虚拟地址与物理地址的对应关系。页面表通常在进程创建时动态生成,并且只包含当前进程所需的页面映射。 通过这两级的页表结构,Windows可以实现虚拟地址到物理地址的映射。当进程访问虚拟地址时,操作系统会根据页表将其转换为物理地址,并进行相应的读取或写入操作。如果所需的页面不在物理内存中,则会触发页面错误(Page Fault),操作系统会将页面从磁盘加载到物理内存中,并更新页表的映射关系。 内存分页机制的好处是可以实现虚拟内存的管理和保护。每个进程都有独立的虚拟地址空间,使得进程之间的内存不会相互干扰,同时允许操作系统灵活地分配和回收物理内存。此外,内存分页机制还支持内存权限控制、页面共享和延迟加载等功能,提高了系统的安全性和性能。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值