Intel 处理器虚拟化技术浅析3 四级页表

Intel 处理器虚拟化技术浅析3 四级页表我们假设电脑是运行在64位Windows系统,且CPU开户VM支持。在64位模式下,也可以叫做Long-mode或 IA-32epaging 模

大家好,欢迎来到IT知识分享网。

我们假设电脑是运行在64位Windows系统,且CPU开户VM支持。在64位模式下,也可以叫做Long-mode或 IA-32epaging 模式。在64位系统下使用4级的页转换表结构。最高线性地址为48位,在4K页面映射下被分成5部分:

Intel 处理器虚拟化技术浅析3 四级页表

以及2M和1G页面:

Intel 处理器虚拟化技术浅析3 四级页表

内核虚拟地址布局:

Intel 64位 CPU 仅支持 64 位虚拟地址中的48位,这48位虚拟地址被运行在该CPU上的软件使用。 对于用户模式地址,64位虚拟地址中的高16位总是被设置为0,对于内核模式地址,总是设置为 0Fh。

这有效地将64地址空间分开成2部分——用户模式地址的范围:00000000`00000000~0000FFFF`FFFFFFFFh;

内核模式地址的范围:0FFFF0000`00000000h~0FFFFFFFF`FFFFFFFFh。

此内核虚拟地址范围总计为 256 TB,用于 Windows 上可访问的全部内核虚拟地址空间。

如果我们按4K页表(2^12)来映射256TB的空间那么就需要:

512(pm4l)*512(pdpte)*512(pd)*512(pt)*8 = 512GB 内存空间,目前家用电脑还支持不了。

如果我们按2M页表(2^21)来映射256TB的空间那么就需要:

512(pm4l)*512(pdpte)*512(pd)*8 = 1G 还是太大,我们代码中申请1G的非分布内存很容易失败。

1G页表:我还不知道它的应用场景,超大软件?超占内存软件?

事实上虚拟系统只支持36位寻址(本人14年电脑目前是这种情况),也就是64GB,所以我们的电脑在测试虚拟机时最大物理内存不能超过64G。那么我们就以64GB物理内存来安排虚拟机页表时完全可以忽略PML4的9位地址。因为是36位物理地址所以PML4的值就一直为0,PML4指针表项里永远只能获取第一项8字节数据。但是即便不考虑pm4l也需要1GB的内存空间(512(pdpte)*512(pd)*512(pt)*8 = 1GB),还是太大。 所以我们在此使用2M页面,也就是PT的9位地址和offset的12位地址总共21位 2^21= 2M需要申请页表内存为(512(pdpte)*512(pd)*8 = 2M)2M内存申请很完美!

看到这里很多朋友都迷茫了:你说了那么多,可windows 64位系统 就是按照4级页表来映射256 TB物理内存的呀,也没见页表占用了多少物理内存。其实windows是“按需”映射的,它根据用户电脑里真实的物理内存,以及应用程序或驱动程序所需要的内存动态增删页表来控制页表的大小。

我们的虚拟软件不能像VMware 那样直接虚拟一个环境出来,然后在里面安装 操作系统,我们是让在 64位windows系统上运行的CPU进入一种虚拟状态,就是在虚拟状态下它还是运行在64位windows系统上。Windows系统的页表结构没有做任何改动。后续的代码里我们也不会更改cr3值。那么我们为什么还要建立一个新的页表项呢?这就是intel cpu虚拟系统的要求,软件运行在虚拟系统里它对内存的读写、执行最终都要在物理内存的层面体现出来。因为我们没有修改cr3所以虚拟系统里的软件也可以正常的寻址到真实的物理内存,但是当它寻址到这个物理地址时它不是直接去读取或者执行,它会把这个物理地址再当作一个虚拟地址再去用我们提供的页表项再去转换一次,然后获得的地址它才认为是真正的物理地址。这就相当于CPU给我们提供了一个HOOK页表的机会,那么余下的操作就可以自由发挥了,比如我们可以自定义某段内存的属性为只读,那么当软件写入数据时就可以断下来,我们可以定义它的执行权限,取消它的读权限,就可以定位到代码自校验。

我们现在要做的就是页表的操作了,虚拟系统获取的物理内存经过我们的一顿操作结果还是指向原来的物理内存,表面看起来什么都没做,但是我们修改了内存属性,好了我们的目的达到了。

_EPT_PML4E record _EPT_PML4E_Ignored3:12,_EPT_PML4E_Reserved2:4,_EPT_PML4E_PhysicalAddress:36,\ _EP T_PML4E_Ignored2:1,_EPT_PML4E_ExecuteForUserMode:1,_EPT_PML4E_Ignored1:1,\ _EPT_PML4E_Accessed:1,_EPT_PML4E_Reserved1_must_be_0:5,_EPT_PML4E_Execute:1,\ _EPT_PML4E_Write:1,_EPT_PML4E_Read:1 _EPT_PDPTE record _EPT_PDPTE_Ignored3:12,_EPT_PDPTE_Reserved2:4,\ _EPT_PDPTE_PhysicalAddress:36,_EPT_PDPTE_Ignored2:1,\ _EPT_PDPTE_ExecuteForUserMode:1,_EPT_PDPTE_Ignored1:1,\ _EPT_PDPTE_Accessed:1,_EPT_PDPTE_Reserved1:5,_EPT_PDPTE_Execute:1,\ _EPT_PDPTE_Write:1,_EPT_PDPTE_Read:1 _EPDE_2MB record _EPT_PDE_2M_SuppressVe:1,_EPT_PDE_2M_Reserved2:15,\ _EPT_PDE_2M_PhysicalAddress:27 ,_EPT_PDE_2M_Reserved1:10,\ _EPT_PDE_2M_ExecuteForUserMode:1,_EPT_PDE_2M_Dirty:1,\ _EPT_PDE_2M_Accessed:1,_EPT_PDE_2M_LargePage:1,\ _EPT_PDE_2M_IgnorePat:1,_EPT_PDE_2M_MemoryType:3,\ _EPT_PDE_2M_Execute:1,_EPT_PDE_2M_Write:1,_EPT_PDE_2M_Read:1 .DATA EPTP dq ?;hook入口 PML4E dq ? ;一个就够了 .code 分配PDPT 4K的连续非分页内存: PAGE_SIZE equ 4096 ;2^9*8 Invoke MmAllocateContiguousMemory,PAGE_SIZE,-1; .if rax== 0 ret .endif mov @pEPT_PDPT,rax invoke RtlZeroMemory,@pEPT_PDPT,PAGE_SIZE 分配PDE 2M的连续非分页内存: invoke MmAllocateContiguousMemory,512*512*8,-1;Allocate EPT Page-Table .if rax== 0 ret .endif mov @pEPDE_2MB,rax invoke RtlZeroMemory,@pEPDE_2MB,512*512*8 lea rdi,PML4E btr qword ptr[rdi],_EPT_PML4E_Accessed ;清对应的标志位 bts qword ptr[rdi],_EPT_PML4E_Execute ;内存可执行;置对应的标志位 btr qword ptr[rdi],_EPT_PML4E_ExecuteForUserMode btr qword ptr[rdi],_EPT_PML4E_Ignored1 btr qword ptr[rdi],_EPT_PML4E_Ignored2 btr qword ptr[rdi],_EPT_PML4E_Ignored3 bts qword ptr[rdi],_EPT_PML4E_Read内存可读 btr qword ptr[rdi],_EPT_PML4E_Reserved1 btr qword ptr[rdi],_EPT_PML4E_Reserved2 bts qword ptr[rdi],_EPT_PML4E_Write;内存可写 invoke MmGetPhysicalAddress,@pEPT_PDPT shr rax,0ch;除以4K ; 2^9*8 shl rax,_EPT_PML4E_PhysicalAddress;该字段所处的位置 or qword ptr[rdi],rax ;把PDPT的物理地址存入PML4E

我们看下intel 关于PML4E的定义:

Intel 处理器虚拟化技术浅析3 四级页表

mov rbx,@pEPDE_2MB mov rdi,@pEPT_PDPT mov rsi,0 .while rsi { 512 btr qword ptr[rdi],_EPT_PDPTE_Accessed bts qword ptr[rdi],_EPT_PDPTE_Execute btr qword ptr[rdi],_EPT_PDPTE_ExecuteForUserMode btr qword ptr[rdi],_EPT_PDPTE_Ignored1 btr qword ptr[rdi],_EPT_PDPTE_Ignored2 btr qword ptr[rdi],_EPT_PDPTE_Ignored3 bts qword ptr[rdi],_EPT_PDPTE_Read btr qword ptr[rdi],_EPT_PDPTE_Reserved1 btr qword ptr[rdi],_EPT_PDPTE_Reserved2 bts qword ptr[rdi],_EPT_PDPTE_Write invoke MmGetPhysicalAddress,rbx shr rax,0ch;除以4K shl rax,_EPT_PDPTE_PhysicalAddress;该字段所处的位置 or qword ptr[rdi],rax ;把@pEPDE_2MB 分成的512份中的其中一份的地址存入 ;对应的PDPT里 add rdi,8 add rbx,512*8 ;每份大小4K inc rsi .endw 

下面我们填充@pEPDE_2MB里所代表的物理地址:

mov rdi,@pEPDE_2MB mov r13,0 .while r13 { 512 mov rbx,0 .while rbx { 512 bts qword ptr[rdi],_EPT_PDE_2M_Read bts qword ptr[rdi],_EPT_PDE_2M_Write bts qword ptr[rdi],_EPT_PDE_2M_Execute bts qword ptr[rdi],_EPT_PDE_2M_LargePage mov rax,r13 shl rax,9 ;*512 lea rax,[rax+rbx] ; shl rax,_EPT_PDE_2M_PhysicalAddress or [rdi],rax ;rax 这里代表物理地址,第一次时在这个循环里填充0-511 的 ;物理地址 mov @CandidateMemoryType,MTRR_TYPE_UC; mov rax,@CandidateMemoryType shl rax,_EPT_PDE_2M_MemoryType or [rdi],rax ADD RDI,8 inc rbx .endw inc r13 .endw

EPTP hook点填充:

先看下EPTP的结构定义:

_EPTP record _EPTP_Reserved2:16,_EPTP_PML4Address:36,_EPTP_Reserved1:5,\ _EPTP_DirtyAndAceessEnabled:1,_EPTP_PageWalkLength:3,\ _EPTP_MemoryType:3 _Ia32VmxEptVpidCapMsr record Msr_rev9:20,Msr_g_invvpid:1,Msr_all_invvpid:1,Msr_single_invvpid:1,\ Msr_address_invvpid:1,Msr_rev8:7,Msr_support_invvpid:1,Msr_rev7:5,\ Msr_all_invept:1,Msr_single_invept:1,\ Msr_rev6:3,Msr_accessed_and_dirty_flag:1,Msr_support_invept:1,Msr_rev5 :2,\ Msr_pdpte_1_gb_pages:1,Msr_pde_2mb_pages:1,Msr_rev4 :1,\ Msr_write_back_memory_type:1,Msr_rev3:5,Msr_uncacheble_memory_type:1,\ Msr_rev2 :1,Msr_page_walk_length4:1,Msr_rev1:5,Msr_execute_only_pages:1
lea rdi,EPTP mov rcx,MSR_IA32_VMX_EPT_VPID_CAP;ept扩展页表所支持的能力 rdmsr shl rdx,20h or rax,rdx mov rbx,rax mov rcx,mask Msr_page_walk_length4 and rax,rcx shr rax,Msr_page_walk_length4 .if rax {} 0 mov rax,3; // 4 (tables walked) - 1 = 3 ;最大支持4级查表 ;(1 less than the EPT page-walk length) must be 3, ;indicating an EPT page-walk length of 4 shl rax,_EPTP_PageWalkLength;该字段所处的位置 or qword ptr[rdi],rax .endif mov rax,rbx mov rcx,mask Msr_accessed_and_dirty_flag and rax,rcx shr rax,Msr_accessed_and_dirty_flag .if rax {} 0 bts qword ptr[rdi],_EPTP_DirtyAndAceessEnabled ;MSR_IA32_VMX_EPT_VPID_CAP .endif mov rax,rbx mov rcx,mask Msr_uncacheble_memory_type and rax,rcx shr rax,Msr_uncacheble_memory_type .if rax {} 0 mov rax,CACHE_TYPE_UC shl rax,_EPTP_MemoryType;该字段所处的位置 or qword ptr[rdi],rax .endif mov rax,rbx mov rcx,mask Msr_write_back_memory_type and rax,rcx shr rax,Msr_write_back_memory_type .if rax {} 0 mov rax,CACHE_TYPE_WB shl rax,_EPTP_MemoryType;该字段所处的位置 or qword ptr[rdi],rax .endif mov rax,rbx mov rcx,mask Msr_pde_2mb_pages and rax,rcx shr rax,Msr_pde_2mb_pages invoke MmGetPhysicalAddress,addr PML4E shr rax,0ch;除以4K shl rax,_EPTP_PML4Address;该字段所处的位置 or qword ptr[rdi],rax EPT_POINTER equ 8218 ;201ah mov rcx,EPT_POINTER mov rax,EPTP vmwrite rcx,rax ;;;;写入EPT_POINTER

至此, 页表初始化完毕。

免责声明:本站所有文章内容,图片,视频等均是来源于用户投稿和互联网及文摘转载整编而成,不代表本站观点,不承担相关法律责任。其著作权各归其原作者或其出版社所有。如发现本站有涉嫌抄袭侵权/违法违规的内容,侵犯到您的权益,请在线联系站长,一经查实,本站将立刻删除。 本文来自网络,若有侵权,请联系删除,如若转载,请注明出处:https://yundeesoft.com/50043.html

(0)

相关推荐

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注

关注微信