[原创]Windows 10 (14393) VT虚拟化与CPU时间计数器
2016-9-16 21:55
20228
[原创]Windows 10 (14393) VT虚拟化与CPU时间计数器
声明:本文及代码仅供学习交流,转载请保留原作者信息。
首先要感谢下坛友的支持,以及各路大牛对小弟我的指导。
第一次在看雪发文章,有疏漏错误之处还望指出。
大家应该知道巨硬对Windows 10 的架构做了极大的更新。同时也增加了一些新的汇编指令。
那CPU时间计数器和VT加载有何关系呢?
这要从我前几天准备在Win10上加载VT开始。
Win10下自带Hyper-V,先把它关掉。
本来抱着直接把MiniVT重新用WDK 10编译就好的心态运行虚拟机,然后加载。
结果是,蓝屏。
这份VT代码在Win7 x64上跑得好好的,怎么到Win10就不行了?
于是我在VMM(EXIT事件接口函数下断点),一切正常,没有出现什么寄存器被篡改、事件没处理等问题。
奇怪?难不成Win10不允许第三方加载VT?
后面我查看了下蓝屏信息(虚拟机和真实机都是同一个蓝屏代码):CRITICAL_PROCESS_DIED
它的意思是:系统关键进程终止(DIED)。
奇怪,难道是System进程出问题了?
后面我在Windbg里看到,不是System进程出问题,是services.exe和svhosts.exe进程出了问题。
*** Unhandled exception 0xc000001d, hit in C:\Windows\system32\svchost.exe -k netsvcs:
*** enter .exr 0000001C05B7E670 for the exception record
*** enter .cxr 0000001C05B7E180 for the context
*** then kb to get the faulting stack
Break instruction exception - code 80000003 (first chance)
0033:00007ff9`2cf1212a cc
这个是应用层异常,因为是svhosts.exe进程,牵连了内核层一起崩溃了。
异常代号是0xc000001d,居然是个非法指令异常。
kd> .exr 0000001C05B7E670
ExceptionAddress: 00007ff92cec4a3a
ExceptionCode: c000001d [B]([U]Illegal instruction[/U][/B])
ExceptionFlags: 00000000
NumberParameters: 0
继续查看异常发生地址,是这个"RDTSCP"指令出现了非法指令异常。
kd> u 00007ff92cec4a3a
00007ff9`2cec4a3a 0f01f9 rdtscp
00007ff9`2cec4a3d 33c0 xor eax,eax
00007ff9`2cec4a3f 8ac1 mov al,cl
00007ff9`2cec4a41 c3 ret
00007ff9`2cec4a42 b853000000 mov eax,53h
00007ff9`2cec4a47 0f03c0 lsl eax,eax
00007ff9`2cec4a4a 7504 jne 00007ff9`2cec4a50
00007ff9`2cec4a4c c1e80e shr eax,0Eh
嗯哼?Windbg都能识别出是RDTSCP指令,为什么还会非法指令异常?
于是我搜索了下RDTSCP这个指令的用途,它是RDTSC的升级版,在一些比较新的处理器中用于获得CPU时间计数器。
到这里我就没头绪了,RDTSCP这个指令怎么和VT相冲突了?
然后,我又查看了Intel手册关于RDTSCP的处理。
在Intel手册附录C我找到了这个RDTSCP指令的VMEXIT处理。
51 当客户机软件运行 RDTSCP 并且 "enable RDTSCP" 、 "RDTSC exiting" 标识位在虚拟机运行控制域中置为1时触发。
按照注释说的,应该是开启了这两个标识位才会产生这个exit事件才对啊。
不管了,为了验证必须处理RDTSCP指令EXIT事件,我参考了newbluepill开启了那两个标识并且在exithandler里模拟执行了RDTSCP(注意:开启了RDTSCP指令的监视后,还必须要处理RDTSC指令的EXIT事件)。
模拟执行RDTSCP,只要像处理RDTSC一样就可以了,即调用RDTSC汇编指令后,把edx:eax赋值给客户机即可完成处理。
果然,处理了这个事件后,VT开启成功了。的确是我们缺少了必要的处理,导致了系统关键进程发生非法指令异常,关键进程异常退出,并最终导致系统蓝屏。
附上最终效果(多核+真实机)
(注:TestVT是通过调用CPUID指令来检查VT是否开启成功的。成功则修改ebx,ecx,edx为指定的数值)
总结:
Windows 7为了兼容一些老的处理器,并没有使用Intel给出的一些新指令。所以,在Win7下开启VT,并不需要对RDTSC和RDTSCP做出必要处理。当然,并不排除某些CPU计时软件会用到这些指令。
因为Windows 10 新增了这些指令,所以要求开发者进行单独处理。
其实,你如果做出一个完整VT系统,可以完全忽略以上问题。
不管怎么样,我们在Win10加载VT(最小化),还是成功了的。于是,我们现在可以在Win10下干点......
附上对RDTSC和RDTSCP的处理代码(部分)
exithandler.h
void HandleRDTSC()
{
ULONG uCPUID;
uCPUID = KeGetCurrentProcessorNumber();
Asm_Rdtsc(&g_GuestRegs[uCPUID].rax, &g_GuestRegs[uCPUID].rdx);
}
// Work for Windows 10
void HandleRDTSCP()
{
ULONG uCPUID;
uCPUID = KeGetCurrentProcessorNumber();
g_GuestRegs[uCPUID].rax = (Asm_GetTSC() & 0xFFFFFFFF);
g_GuestRegs[uCPUID].rdx = (Asm_GetTSC() >> 32);
}
extern "C" void VMMEntryPoint()
{
ULONG64 ExitReason;
ULONG64 ExitInstructionLength;
ULONG64 GuestResumeEIP;
ULONG64 uCPUID;
uCPUID = KeGetCurrentProcessorNumber();
ExitReason = Vmx_VmRead(VM_EXIT_REASON);
ExitInstructionLength = Vmx_VmRead(VM_EXIT_INSTRUCTION_LEN);
g_GuestRegs[uCPUID].rsp = Vmx_VmRead(GUEST_RSP);
g_GuestRegs[uCPUID].rip = Vmx_VmRead(GUEST_RIP);
g_GuestRegs[uCPUID].cr3 = Vmx_VmRead(GUEST_CR3);
switch(ExitReason)
{
case EXIT_REASON_CPUID:
{
HandleCPUID();
break;
}
case EXIT_REASON_INVD:
{
HandleInvd();
break;
}
case EXIT_REASON_VMCALL:
{
HandleVmCall();
break;
}
case EXIT_REASON_MSR_READ:
{
HandleMsrRead();
break;
}
case EXIT_REASON_MSR_WRITE:
{
HandleMsrWrite();
break;
}
case EXIT_REASON_CR_ACCESS:
{
HandleCrAccess();
break;
}
case EXIT_REASON_RDTSC: // 16
{
HandleRDTSC();
break;
}
case EXIT_REASON_RDTSCP: // 51
{
HandleRDTSCP();
break;
}
default:
break;
}
GuestResumeEIP = g_GuestRegs[uCPUID].rip+ExitInstructionLength;
Vmx_VmWrite(GUEST_RIP,GuestResumeEIP);
Vmx_VmWrite(GUEST_RSP,g_GuestRegs[uCPUID].rsp);
}
vtasm.asm
Asm_Rdtsc Proc
mov rbx,rcx
mov rsi,rdx
xor rax,rax
xor rdx,rdx
rdtsc
mov [rbx],rax
mov [rsi],rdx
ret
Asm_Rdtsc Endp
Asm_GetTSC PROC
;Copy from newbluepill
rdtsc
shl rdx, 32
or rax, rdx
ret
Asm_GetTSC ENDP
vtsystem.cpp
extern "C" void SetupVMCS()
{
// ......
// 下面的代码开启RDTSC事件
uCPUBase = VmxAdjustControls(0,MSR_IA32_VMX_PROCBASED_CTLS);
uCPUBase |= CPU_BASED_RDTSC_EXITING;
uCPUBase |= CPU_BASED_ACTIVATE_SECONDARY_CONTROLS;
Vmx_VmWrite(CPU_BASED_VM_EXEC_CONTROL,uCPUBase);
uTemp64 = 0;
uTemp64 |= SECONDARY_EXEC_RDTSCP; // enable RDTSCP
Vmx_VmWrite(SECONDARY_VM_EXEC_CONTROL, uTemp64);
// ......
}
驱动文件,Win10 x64(测试签名)
MiniVT_Win10.rar
[培训]《安卓高级研修班(网课)》月薪三万计划,掌
握调试、分析还原ollvm、vmp的方法,定制art虚拟机自动化脱壳的方法
上传的附件: