首页 > 其他 > 详细

06_基本框架_VMCS_GuestArea

时间:2019-10-27 11:30:40      阅读:99      评论:0      收藏:0      [点我收藏+]

1 Guest-State Area

1.1 References

技术分享图片

注释:

其实 内容很多 一般是不背 的;需要的时候来查就行;但是要大致知道是做啥的。

代码

》 设置 Guest Area

// 设置GUEST
// 当尝试执行 VM_Guest 出错的时候,会调用VM_Exit.
Vmx_VmWrite(GUEST_CR0, Asm_GetCr0());
Vmx_VmWrite(GUEST_CR3, Asm_GetCr3());
Vmx_VmWrite(GUEST_CR4, Asm_GetCr4());
?
Vmx_VmWrite(GUEST_DR7, 0x400);
Vmx_VmWrite(GUEST_RFLAGS, Asm_GetEflags() & ~0x200);//cli
?
Vmx_VmWrite(GUEST_ES_SELECTOR, Asm_GetEs() & 0xFFF8);
Vmx_VmWrite(GUEST_CS_SELECTOR, Asm_GetCs() & 0xFFF8);
Vmx_VmWrite(GUEST_DS_SELECTOR, Asm_GetDs() & 0xFFF8);
Vmx_VmWrite(GUEST_FS_SELECTOR, Asm_GetFs() & 0xFFF8);
Vmx_VmWrite(GUEST_GS_SELECTOR, Asm_GetGs() & 0xFFF8);
Vmx_VmWrite(GUEST_SS_SELECTOR, Asm_GetSs() & 0xFFF8);
Vmx_VmWrite(GUEST_TR_SELECTOR, Asm_GetTr() & 0xFFF8);
?
Vmx_VmWrite(GUEST_ES_AR_BYTES,      0x10000);// 设置成不可用;然后进入GuestEntry 刷新
Vmx_VmWrite(GUEST_FS_AR_BYTES,      0x10000);
Vmx_VmWrite(GUEST_DS_AR_BYTES,      0x10000);
Vmx_VmWrite(GUEST_SS_AR_BYTES,      0x10000);
Vmx_VmWrite(GUEST_GS_AR_BYTES,      0x10000);
Vmx_VmWrite(GUEST_LDTR_AR_BYTES,    0x10000);
?
Vmx_VmWrite(GUEST_CS_AR_BYTES0xc09b);// CS 和 TR 不能 像 前面一样设置成不可用,然后进入GuestEntry 刷新;因为GuestEntry以来CS和TR
Vmx_VmWrite(GUEST_CS_BASE,      0); // 所以需要手动设置。
Vmx_VmWrite(GUEST_CS_LIMIT,     0xffffffff);
?
Vmx_VmWrite(GUEST_TR_AR_BYTES0x008b);
Vmx_VmWrite(GUEST_TR_BASE,      0x80042000);
Vmx_VmWrite(GUEST_TR_LIMIT,     0x20ab);
?
?
Vmx_VmWrite(GUEST_GDTR_BASE,    GdtBase);
Vmx_VmWrite(GUEST_GDTR_LIMIT,   Asm_GetGdtLimit());
Vmx_VmWrite(GUEST_IDTR_BASE,    IdtBase);
Vmx_VmWrite(GUEST_IDTR_LIMIT,   Asm_GetIdtLimit());
?
Vmx_VmWrite(GUEST_IA32_DEBUGCTL,        Asm_ReadMsr(MSR_IA32_DEBUGCTL)&0xFFFFFFFF);
Vmx_VmWrite(GUEST_IA32_DEBUGCTL_HIGH,   Asm_ReadMsr(MSR_IA32_DEBUGCTL)>>32);
?
Vmx_VmWrite(GUEST_SYSENTER_CS,          Asm_ReadMsr(MSR_IA32_SYSENTER_CS)&0xFFFFFFFF);
Vmx_VmWrite(GUEST_SYSENTER_ESP,         Asm_ReadMsr(MSR_IA32_SYSENTER_ESP)&0xFFFFFFFF);
Vmx_VmWrite(GUEST_SYSENTER_EIP,         Asm_ReadMsr(MSR_IA32_SYSENTER_EIP)&0xFFFFFFFF); // KiFastCallEntry
?
Vmx_VmWrite(GUEST_RSP, ((ULONG)g_VMXCPU.pStack) + 0x1000);     //Guest 临时栈
Vmx_VmWrite(GUEST_RIP, (ULONG)GuestEntry);                     // 客户机的入口点
?
Vmx_VmWrite(VMCS_LINK_POINTER, 0xffffffff);// referrence volume 3. 24.10
Vmx_VmWrite(VMCS_LINK_POINTER_HIGH, 0xffffffff);

》 设置 入口函数(例程)

void _declspec(naked) GuestEntry(void)
{
__asm{
mov ax, es// 刷新VM 的selector 背后的数据
mov es, ax
?
mov ax, ds
mov ds, ax
?
mov ax, fs
mov fs, ax
?
mov ax, gs
mov gs, ax
?
mov ax, ss
mov ss, ax
?
//int 3;   WARNING!!! HERE CAN‘T USE INT3!!
}
Vmx_VmCall();
__asm{
//jmp g_exit
}
}

》修改 EXIT 函数以 便于查看 EXIT信息

static void VMMEntryPointEbd(void)
{
ULONG ExitReason;
ExitReason = Vmx_VmRead(VM_EXIT_REASON);
g_GuestRegs.esp = Vmx_VmRead(GUEST_RSP);
g_GuestRegs.eip = Vmx_VmRead(GUEST_RIP);
Log("g_GuestRegs.eip:",g_GuestRegs.eip);
__asm int 3;// Interrupt Here;Give the chance to view the Info
}
?
void __declspec(naked) VMMEntryPoint(void)
// 注意:1. 裸函数里面不要用局部变量;因为使用到ebp;而裸函数不维护,如果手动维护,那么和普通函数有什么却别;
//       2. 裸函数 是为了我们更好的控制进来那一刻 寄存器等的 获取、设置
// 3. 裸函数 最好不要太冗余;所以 有很多操作的话,最好 另外封装一个函数,在裸函数中调用即可。(这里封装了VMMEntryPointEbd()函数)
{
// Refresh selector -- >underneath part-- gdtinfo;
//do Exchange itself can refresh the VM TLB when selector right ;
__asm{
mov ax,fs;
mov fs,ax;

mov ax,gs;
mov gs,ax;

}
?
// Call the Func to show the ExitReason and regs!
VMMEntryPointEbd();
?
}

从开始 到现在所实现的阶段性代码 我放在了github 上面有需要的可以参考这里的代码:https://github.com/leibso/VT-learning/tree/05_Fields_Area(环境 vs 2010),

测试代码:

技术分享图片


06_基本框架_VMCS_GuestArea

原文:https://www.cnblogs.com/leibso-cy/p/11746977.html

(0)
(0)
   
举报
评论 一句话评论(0
关于我们 - 联系我们 - 留言反馈 - 联系我们:wmxa8@hotmail.com
© 2014 bubuko.com 版权所有
打开技术之扣,分享程序人生!