Blue Pill源代码分析(4)

发布时间:2014-10-25 2:20:30
来源:分享查询网

HvmInit分别用AMD65和IA32的实现对当前CPU平台进行识别,并确认是否支持VT技术。HvmSwallowBluepill函数则对当前物理CPU上的所有逻辑CPU,进行虚拟设置,反转到虚拟机的运行状态。CmDeliverToProcessor 函数调用KeSetSystemAffinityThread将当前线程调度到指定的CPU cProcessorNumber,并将IRQL提升到Dpc Level,调用回调函数CallbackProc,回调返回之后将IRQL降低并调度回原来的CPU。NTSTATUS NTAPI CmDeliverToProcessor (  CCHAR cProcessorNumber,  PCALLBACK_PROC CallbackProc,  PVOID CallbackParam,  PNTSTATUS pCallbackStatus)HvmSwallowBluepill在调用CmDeliverToProcessor的时候使用了回调函数CmSubvert,该函数使用汇编代码编写。CmSubvert函数首先保存8个通用寄存器到栈中,接着传递当前栈指针调用HvmSubvertCpu。 NTSTATUS NTAPI HvmSubvertCpu (  PVOID GuestRsp) HvmSubvertCpu 函数再次确认当前CPU实现了VT。紧接着为该CPU在宿主机运行分配栈空间,大小为HOST_STACK_SIZE_IN_PAGES=16 Pages。 在栈底部保留一个结构体struct CPU,保存当前CPU的全局描述符表和中断描述符表等信息。整个栈布局如下:; Stack layout for vmxVmrun() call:;; ^                              ^; |                              |; | lots of pages for host stack |; |                              |; |------------------------------|   <- HostStackBottom(rcx) points here; |         struct CPU           |; --------------------------------栈和CPU信息块准备好了之后,调用平台相关函数ArchRegisterTraps注册一些导致客户机陷入宿主机的陷阱处理函数,这个函数具体实现在vmxtraps.c或svmtraps.c。调用ArchInitialize (Cpu, CmSlipIntoMatrix, GuestRsp)初始化客户机的RIP和RSP。在不同的平台具体函数如下:static NTSTATUS NTAPI VmxInitialize (  PCPU Cpu,  PVOID GuestRip,  PVOID GuestRsp) static NTSTATUS NTAPI SvmInitialize (  PCPU Cpu,  PVOID GuestRip,  PVOID GuestRsp) 而CmSlipIntoMatrix则是客户机运行的入口点,该函数是CmSubvert的逆向操作,具体如下//x86; CmSubvert (PVOID  GuestRsp);CmSubvert PROC StdCall _GuestRsp  CM_SAVE_ALL_NOSEGREGS  mov eax,esp push eax        ;setup esp to argv[0] call HvmSubvertCpu@4 ;注意这里是不会返回的 ret CmSubvert ENDP ; CmSlipIntoMatrix (PVOID  GuestRsp);CmSlipIntoMatrix PROC StdCall _GuestRsp pop ebp  call   HvmResumeGuest@0 ;这个函数不进行任何操作,除了log CM_RESTORE_ALL_NOSEGREGS  ret CmSlipIntoMatrix ENDP //x64CmSubvert PROC  push rax push rcx push rdx push rbx push rbp push rsi push rdi push r8 push r9 push r10 push r11 push r12 push r13 push r14 push r15  sub rsp, 28h  mov rcx, rsp call HvmSubvertCpu ;这个函数不返回 CmSubvert ENDP CmSlipIntoMatrix PROC  call HvmResumeGuest ;空函数  add rsp, 28h pop r15 pop r14 pop r13 pop r12 pop r11 pop r10 pop r9 pop r8 pop rdi pop rsi pop rbp pop rbx pop rdx pop rcx pop rax retCmSlipIntoMatrix ENDP 最终调用ArchVirtualize()之后,内部分别运行VmxLaunch和SvmVmrun(AMD的x86不支持,直接返回了),这样客户机在虚拟运行模式下从CmSlipIntoMatrix 开始运行了,esp还是原先传入CmSlipIntoMatrix 的esp(rsp),又回到了CmDeliverToProcessor->HvmSwallowBluepill。static NTSTATUS NTAPI VmxVirtualize (  PCPU Cpu) static NTSTATUS NTAPI SvmVirtualize (  PCPU Cpu) 当所有的CPU都运行在虚拟模式下之后,设置驱动的Unload例程,DriverEntry成功返回。当然这中间如果失败就进行善后处理。所有的CPU都运行在虚拟模式下之后,BP接下来就有的忙了,要处理很多来自客户机的陷阱处理。这后面具体分析,待续...............

返回顶部
查看电脑版