Intel虚拟化技术浅析
本文仅讲解基于处理器的虚拟化,至于其它的PCI总线设备虚拟化以及基于网络的虚拟化不在我们的学习范围内。我们仅仅学习一下怎样虚拟一个运行环境,然后监控软件的运行。
假设我们64位的win10系统里有个你很在意的软件在运行(它可能是应用程序也可能是驱动程序,你怀疑它是个不友好的软件,你想删除它,你删不了,你想终止它,你终止不了。我们假设它很健壮不会自己产生异常导致自动退出。那么我们就可以通过虚拟化技术直接修改它的执行内存让它自动退出,或者让它去执行别的代码,即便它有所谓的内存保护也没用(仅针对应用程序)!
我们需要编写一个驱动程序才能实现虚拟化技术,应用程序权限太低了,vmlaunch这样的特权指令它运行不了。我们编写的驱动程序就叫做VMM(Virtual Machine Monitor) 虚拟机监管者,VMM准备一个运行环境,让需要监管的程序在里面运行就可以了。VMM准备的这个运行环境我们就叫做VMX(Virtual Machine Extensions)。我们用guest 代表需要监管的程序。
VMXON 区域: VMM需要一个物理地址区域去记录和维护一些工作,这个区域对我们来说是不透明的,但是准备运行环境时却是必须的。
VMCS 区域:为guest运行环境准备的物理地址区域,这个区域对我们来说是不透明的,并且需要用专用的指令vmwrite 去写入数据。(虽然你知道它的物理地址但是INTEL却不让你用mov指令去读写,你说气人不?)
VMXON 区域、 VMCS 区域的大小通过MSR寄存器获取:mov rcx,MSR_IA32_VMX_BASIC rdmsr shl rdx, 20h or rax, rdx
Rax 的值对应的数据如下:
IA32_VMX_BASIC_MSR record VMX_BASIC_MSR_Reserved3:8,VMX_BASIC_MSR_VmxCapabilityHint:1,VMX_BASIC_MSR_VmExitReport:1,VMX_BASIC_MSR_MemoryType:4,VMX_BASIC_MSR_SupportedDualMoniter:1,
VMX_BASIC_MSR_SupportedIA64:1,VMX_BASIC_MSR_Reserved2:3,VMX_BASIC_MSR_RegionClear:1,
VMX_BASIC_MSR_RegionSize:12,VMX_BASIC_MSR_Reserved1:1,VMX_BASIC_MSR_RevisionIdentifier:31
VMX_BASIC_MSR_RegionSize:12 代表VMXON或VMCS区域大小 12位数据 最大也就4K字节,事实上也就是4K大小,但是INTEL有个要求那就是我们申请的物理内存必须是4K边界对齐的。所以我们申请个8K的空间然后再4K对齐就OK了。
VMXON 区域 和VMCS 区域 虽然说是不透明的,但是INTEL却要求我们必须把前4个字节给填充为用MSR_IA32_VMX_BASIC 参数 调用rdmsr 获取的数据
我们分配个连续内存:invoke MmAllocateContiguousMemory,VMCS_SIZE*2+ALIGNMENT_PAGE_SIZE,-1mov @Contiguous_buffer,rax
再转换成物理内存:invoke MmGetPhysicalAddress,@Contiguous_buffer mov @PhysicalBuffer,rax
再来个4K对齐:mov rax,@PhysicalBuffer lea rax,[rax+ALIGNMENT_PAGE_SIZE-1] mov rcx,ALIGNMENT_PAGE_SIZE-1 not rcx and rax,rcx mov @alignedPhysicalBuffer_vmxon,rax mov rax,@Contiguous_buffer lea rax,[rax+ALIGNMENT_PAGE_SIZE-1] mov rcx,ALIGNMENT_PAGE_SIZE-1 not rcx and rax,rcx mov @alignedVirtualBuffer,rax
把MSR_IA32_VMX_BASIC 数据存入前4个字节:mov rcx,MSR_IA32_VMX_BASIC rdmsr
;MSR的高32位内容存放在EDX寄存器中,
;MSR的低32位内容存放在EAX寄存器中(在支持intel64架构的处理器中RDX和RAX的高32位忽略)。如果MSR中没有64位(有些位没有实现),则EDX:EAX中没有实现的位置则未定义。shl rdx, 20h or rax, rdx mov @IA32_VMX_BASIC_MSR.All,rax mov rcx,@alignedVirtualBuffer mov [rcx],eax
至此我们就可以调用vmxon 指令了(告诉CPU我们准备进入虚拟机模式了):Vmxon @alignedPhysicalBuffer_vmxon
同样的方法我们初始化VMCS 区域,然后调用vmptrld(告诉CPU我已经把你需要的VMCS 区域申请好了,你现在可以加载了。)vmclear qword ptr @alignedPhysicalBuffer_vmcs Vmptrld qword ptr @alignedPhysicalBuffer_vmcs
指令:Vmlaunch ;进入虚拟机吧!!!!
当然前提是我们必须把VMCS 区域按INTEL的要求给填充完整才可以。
VMCS区域:guest 区域,从真实系统进入虚拟系统时,CPU需要加载的数据,包括很多CPU内部的 寄存器,通用寄存器,控制寄存器,调试寄存器之类。host区域,就是从虚拟系统返回真实系统时CPU需要加载的寄存器。控制区域进入虚拟系统后,处理器的行为由这个区域的字段控制。虚拟机退出时的控制区域。控制怎样进入虚拟机。控制CPU以什么样的方式退出到真实系统。从虚拟机退出到真实系统时,虚拟系统退出的原因,或者失败时的错误代码。
前面提过VMCS区域需要专门的汇编指令才能读取,下面我们填充VMCS区域。
我们看下64位系统段选择子的描述:_SEGMENT_SELECTOR record Limit:32, SEGMENT_GPA:4,SEGMENT_attr_G:1,SEGMENT_attr_D_B:1,SEGMENT_attr_L:1, SEGMENT_attr_AVL:1,SEGMENT_attr_P:1, SEGMENT_attr_DPL:2,SEGMENT_attr_S:1,SEGMENT_attr_Type_code_or_data:1,SEGMENT_attr_Type_CRA:3,selector_index:13,selector_TI:1,selector_RPL:2
;selector_TI (Table Indicator)描述符表索引位,当TI=0时从GDT查找 =1时从LDT查找。RPL: 权限级别0-3
vmx_vmwrite_seg proc _value_HOST_XX_SELECTOR:qword,_SELECTOR_name:qword mov rax,_SELECTOR_name movzx eax,ax and eax,0f8h ;清低3位,RPL= 0 从GDT(全局描述符表)加载段描述符 cdqe mov rcx,_value_HOST_XX_SELECTOR vmwrite rcx, rax ret vmx_vmwrite_seg endp invoke vmx_vmwrite_seg,HOST_ES_SELECTOR,ES invoke vmx_vmwrite_seg,HOST_CS_SELECTOR,CS invoke vmx_vmwrite_seg,HOST_SS_SELECTOR,SS invoke vmx_vmwrite_seg,HOST_DS_SELECTOR,DS invoke vmx_vmwrite_seg,HOST_FS_SELECTOR,FS invoke vmx_vmwrite_seg,HOST_GS_SELECTOR,GS
任务寄存器需要单独操作:str rax invoke vmx_vmwrite_seg,HOST_TR_SELECTOR,RAX mov rcx,MSR_IA32_EFER
使能Extended Feature Enable Register;rdmsr shl rdx, 20h or rax, rdx mov rbx,rax invoke vmx_vmwrite,HOST_EFER,rbx
cr0 与cr4的固定位:
MSR_IA32_VMX_CR0_FIXED0、MSR_IA32_VMX_CR0_FIXED1 字段里规定了guest里cr0控制寄存器的数值要求。mov rcx,MSR_IA32_VMX_CR0_FIXED1 rdmsr shl rdx, 20h or rax, rdx mov rbx,cr0 and rbx,rax mov rcx,MSR_IA32_VMX_CR0_FIXED0 rdmsr shl rdx, 20h or rax, rdx or rbx,rax vmwrite,HOST_CR0, rbx vmwrite,HOST_CR3, cr3 mov rcx,MSR_IA32_VMX_CR4_FIXED1 rdmsr shl rdx, 20h or rax, rdx mov rbx,cr4 and rbx,rax mov rcx,MSR_IA32_VMX_CR4_FIXED0 rdmsr shl rdx, 20h or rax, rdx or rbx,rax vmwrite,HOST_CR3, rbx
从全局描述符表查找任务寄存器的基址:sgdt @gdtbase lea rdi,@gdtbase mov rbx,[rdi+2];路过Limit str rdx;tss invoke GetSegmentDescriptor,addr @_SEGMENT_SELECTOR,rdx,rbx vmwrite,HOST_TR_BASE, @_SEGMENT_SELECTOR.BASE
填充fs寄存器字段:(64位系统下fs基本是兼容32个应用程序而保留)mov ecx, MSR_FS_BASE rdmsr shl rdx, 20h or rax, rdx vmwrite,HOST_FS_BASE,rax
填充gs寄存器字段:(64位系统非常重要的寄存器,相当于32个系统里的fs寄存器)mov ecx, MSR_GS_BASE rdmsr shl rdx, 20h or rax, rdx vmwrite,HOST_GS_BASE, rax
填充全局描述符表字段:sgdt @gdtbase lea rdi,@gdtbase mov rbx,[rdi+2] vmwrite,HOST_GDTR_BASE,rbx
填充中断描述符表字段:sidt @idtbase lea rdi,@idtbase mov rbx,[rdi+2] vmwrite,HOST_IDTR_BASE,rbx vmwrite,VMCS_LINK_POINTER,-1;不启用SMM双重监控处理机制 vmwrite,EXCEPTION_BITMAP,0
填充guest 段选择子、段限、访问权限、段基址。sgdt tbyte ptr @gdtbase lea rdi,@gdtbase mov rbx,[rdi+2] invoke FillGuestSelectorData,rbx,0,es invoke FillGuestSelectorData,rbx,1,cs invoke FillGuestSelectorData,rbx,2,ss invoke FillGuestSelectorData,rbx,3,ds invoke FillGuestSelectorData,rbx,4,fs invoke FillGuestSelectorData,rbx,5,gs sldt rax invoke FillGuestSelectorData,rbx,6,rax str rax invoke FillGuestSelectorData,rbx,7,rax
填充fs寄存器字段:mov ecx, MSR_FS_BASE rdmsr shl rdx, 20h or rax, rdx vmwrite,GUEST_FS_BASE,rax
填充gs寄存器字段:mov ecx, MSR_GS_BASE rdmsr shl rdx, 20h or rax, rdx vmwrite,GUEST_GS_BASE,rax
填充控制字段:mov ecx, MSR_IA32_VMX_TRUE_PROCBASED_CTLS Rdmsr ;eax存入的是允许为零的位 "允许为零的位"已经被标0(其余的位必须为1)edx存入的是允 许为1的位"允许为1的位"已经被标1(其余的位必须为0) Mov ecx,CPU_BASED_ACTIVATE_MSR_BITMAP+ CPU_BASED_ACTIVATE_SECONDARY_CONTROLS mov rbx,rcx or ecx,eax and ecx,edx vmwrite,CPU_BASED_VM_EXEC_CONTROL,rcx mov ecx, MSR_IA32_VMX_PROCBASED_CTLS2 rdmsr mov rcx,CPU_BASED_CTL2_RDTSCP ; RDTSCP这个指令的用途,它是RDTSC的升级版,在一些比较新的处理器中用于获 ;得CPU时间计数器。 ;SECONDARY_EXEC_ENABLE_RDTSCP | SECONDARY_EXEC_ENABLE_INVPCID | ;SECONDARY_EXEC_XSAVES; ;如果不设置 rdtsc exiting 和 use tsc offsetting 的话,那么 rdtscp 会正常执行,因此这 ;里其实可以只设置 SECONDARY_EXEC_ENABLE_RDTSCP ,其他不设置。 ;这样的话 rdtscp 指令的执行并不会导致vm-exit事件的发生。这里我尝试了只将 ;SECONDARY_EXEC_ENABLE_RDTSCP 控制位置位,其他位不动,发现完全不会进入到 ;vm-exit事件中。 ;因此如果图省事的话其实可以只将 SECONDARY_EXEC_ENABLE_RDTSCP 置位,其他位不 ;进行操作即可。 or rcx,CPU_BASED_CTL2_ENABLE_INVPCID ;如果 invlpg exiting 没有被设置,那么也不会导致vm-exit事件的发生。因此这里其实 ;也可以只设置 SECONDARY_EXEC_ENABLE_INVPCID ,不设置 invlpg exiting 。这样可以 ;让其正常执行,不用在vm-exit处理函数中对其进行复杂的处理。 or rcx,CPU_BASED_CTL2_ENABLE_XSAVE_XRSTORS or rcx,CPU_BASED_CTL2_ENABLE_EPT or rcx,CPU_BASED_CTL2_ENABLE_VPID mov rbx,rcx or ecx,eax and ecx,edx and ebx,edx or ebx,eax vmwrite,SECONDARY_VM_EXEC_CONTROL,rcx vmwrite,PIN_BASED_VM_EXEC_CONTROL,0 mov ecx, MSR_IA32_VMX_TRUE_EXIT_CTLS Rdmsr mov rcx,VM_EXIT_IA32E_MODE + VM_EXIT_ACK_INTR_ON_EXIT ;On processors that support Intel 64 architecture, this control determines whether a logical ;processor is in 64-bit mode after the next VM exit. Its value is loaded into CS.L, and ecx,edx or ecx,eax vmwrite,VM_EXIT_CONTROLS,rcx mov ecx, MSR_IA32_VMX_TRUE_EXIT_CTLS rdmsr mov rcx,VM_EXIT_IA32E_MODE + VM_EXIT_ACK_INTR_ON_EXIT ;On processors that ;support Intel 64 architecture, this control determines whether a logical ;processor is in 64-bit mode after the next VM exit. Its value is loaded into CS.L, and ecx,edx or ecx,eax vmwrite,VM_EXIT_CONTROLS,rcx
;. 配置vm-entry控制域mov ecx, MSR_IA32_VMX_TRUE_ENTRY_CTLS rdmsr mov rcx,VM_ENTRY_IA32E_MODE ;64系统必须填, 参考【处理器虚拟化技术】(第212页) and ecx,edx or ecx,eax vmwrite,VM_ENTRY_CONTROLS,rcx ;
以下为填充guest区域和填充host区域基本相同mov rcx,MSR_IA32_EFER rdmsr shl rdx, 20h or rax, rdx mov rbx,rax vmwrite,GUEST_EFER,rbx mov rcx,MSR_IA32_VMX_CR0_FIXED1 rdmsr shl rdx, 20h or rax, rdx mov rbx,cr0 and rbx,rax mov rcx,MSR_IA32_VMX_CR0_FIXED0 rdmsr shl rdx, 20h or rax, rdx or rbx,rax vmwrite,GUEST_CR0,rbx mov rcx,MSR_IA32_VMX_CR4_FIXED1 rdmsr shl rdx, 20h or rax, rdx mov rbx,cr4 and rbx,rax mov rcx,MSR_IA32_VMX_CR4_FIXED0 rdmsr shl rdx, 20h or rax, rdx or rbx,rax vmwrite,GUEST_CR4,rbx vmwrite,GUEST_CR3,cr3 invoke vmx_vmwrite,GUEST_DR7, 0400h sgdt @gdtbase lea rdi,@gdtbase mov rbx,[rdi+2] vmwrite,GUEST_GDTR_BASE,rbx;Get_GDT_Base()); movzx eax, word ptr [rdi] vmwrite,GUEST_GDTR_LIMIT, rax;Get_GDT_Limit()); sidt @idtbase lea rdi,@idtbase mov rbx,[rdi+2] vmwrite,GUEST_IDTR_BASE,rbx;Get_IDT_Base()); movzx eax,word ptr [rdi] vmwrite,GUEST_IDTR_LIMIT,rax; Get_IDT_Limit()); pushfq pop rax vmwrite,GUEST_RFLAGS, rax; mov rsi,_current_vmState mov rdx,[rsi+VirtualMachineState.MSRBitMapPhysical] vmwrite,MSR_BITMAP, rdx;vmState->MSRBitMapPhysical);MSR Bitmap的某位为0时访问 ;该位所对应的MSR不会产生VM-exit vmwrite,GUEST_RSP, _GuestStack;(ULONG64)GuestStack); //setup guest sp mov rax,[rsi+VirtualMachineState.VmxGuestRip] vmwrite,GUEST_RIP, rax;addr VMXRestoreState; //setup guest ip mov rsi,_current_vmState mov rdx,[rsi+VirtualMachineState.VMM_Stack] mov rax,VMM_STACK_SIZE; add rdx,4000h;;堆栈向下增长,所以要增加,空间是0-VMM_STACK_SIZE 所以 要减1 vmwrite,HOST_RSP, rdx;((ULONG64)vmState->VMM_Stack + VMM_STACK_SIZE - 1)); ;host的rsp必须使用自己申请的一块内存。如果还是使用guest退出时的rsp,一定会 ;导致guest中堆栈被破坏从而导致不可预知的结果 lea rax,VMExitHandler vmwrite,HOST_RIP, rax;addr VMExitHandler
某些处理函数没有给出,会在最后的源码中展示。
来自网络的图片:
2022新生儿证件办理全攻略!!准爸妈必看产后71天分享2022新生儿证件办理指南!!新手爸妈收藏好正确办理顺序准生证出生证明户口本疫苗接种证新生儿社保卡身份证一定要按这个顺序来,能少跑好几趟!!准生证办理时间怀孕满3个月
如何预防心肌梗死?做好这4件事,和心梗说再见心脏是特别重要的器官,只有心脏正常的跳动并且保持健康的状态,身体各个器官组织才能够正常的运行。但由于压力的增加,许多人都忽略了心脏的健康,促使各种心脏疾病的发生几率有所提高,这其中
吃完抗抑郁药变得嗜睡昏沉,竟然是件好事?抑郁症一定会出现睡眠障碍吗?这个可是不一定的。只能说,大部分患者会出现不同程度的失眠多梦早醒症状。为了抑郁患者的情绪和睡眠,医生通常会选择具有镇静安定作用的抗抑郁药进行治疗。那问题
手凉脚凉看到请收好!下周就开始小雪,天气是越来越冷了,衣服还可以多穿,但晚上就不好了,即使裹上了厚被子,脚都是冷的,不能正常入睡。隔天大清早又被冷醒,盖着棉被蜷成一团,双脚依然冰凉!导致第二天睡眼惺忪
喝白酒的八大禁忌,千万不能犯万丈红尘一杯酒,一杯白酒承载了生活点滴,恰逢喜事偶有烦闷好友相聚独自小酌,都有白酒的见证。酒是我们生活的陪伴者情绪的见证者,是良师,也是益友。适当饮用白酒益处多多,但这白酒也不能乱
活雪尹涛晚上喝藏红花水好不好?藏红花非常名贵,但是吃法却比较简单,藏红花最主要的用法是直接泡水喝。藏红花泡水喝的时间并没有特别的要求,平时喝水的时候泡就可以了。很多朋友想知道晚上喝藏红花水好不好?当然是非常好的
缺什么严重掉发?这么做头发疯长缺什么最容易掉头发?好好看看这一篇就知道你该补什么了为了头发,记得多做这些事1缺锌元素锌元素能促进体内蛋白质核糖核酸脱氧核糖核酸的合成,这些都是头发生长必需的营养物质,不仅能强健发
安阳火灾生还者讲述逃生经历老板听到异样声音,喊快跑爬不上墙,急得给老公打电话求救作者丨陈龙编辑丨王晓根据应急管理部通报,安阳1121火灾事故中,有38人死亡,89人成功逃生。韦立峰的妻子刘芸就是89人中的一位。韦立峰夫妇50出头,没有固定工作。刘芸在安阳凯信达
经常胃胀,可不单单是脾胃不好,送你两味中药,疏肝解郁行气消胀经常胃胀,影响食欲?很多朋友都有胃胀,消化不良的毛病,很多时候并未进食难消化食物,但胃却很胀,不停地嗳气,放屁,胃里面顶得慌,吃不下,有时活动活动,排排气还能好点,有时胀的肚子鼓鼓
新手避坑为啥宝宝的血管瘤外敷很久还没效果?门诊有位家长说,对照我的文章给宝宝的血管瘤外敷了眼药水,每一步都认真操作了,但是过去两周了一点效果都没有,甚至有一点点发红担心要破溃了,为什么宝宝的血管瘤一点也没缓解?现在应该怎么
宝宝必须要一直穿着袜子吗?寒从脚起的说法是正确的吗虽然现在是冬天,但是北方的室内都是有暖气的,宝宝们在家总是喜欢偷偷把穿好的袜子拽掉,今天小欧育儿说的小编就来给大家说说关于宝宝穿袜子那些事吧。很多家长反映自己不管给宝宝穿了多少次袜