VT系列:退出事件系统构建(VMMEntryPoint)

[复制链接]

该用户从未签到

2380

主题

2433

帖子

9139

积分

管理员

Rank: 9Rank: 9Rank: 9

积分
9139
QQ
跳转到指定楼层
楼主
发表于 2018-7-15 15:38:33 | 只看该作者 |只看大图 回帖奖励 |倒序浏览 |阅读模式

想要查看内容赶紧注册登陆吧!

您需要 登录 才可以下载或查看,没有帐号?立即注册

x

VT执行流程:

产生退出事件 -> 根据退出事件指定特定的处理函数–> 决定自己处理还是交给CPU处理–> 完成了调用VmResume将控制权交给虚拟机.


而当发生退出事件时要调用的函数就是本章要讲的

VMCS位置:

HOST_RIP-->VMMEntryPoint(VM-Exit处理程序)


VM-Exit事件表:

#define EXIT_REASON_EXCEPTION_NMI       0                (EXCEPTION_BITMAP)//异常信息可以拦截int3等异常

#define EXIT_REASON_EXTERNAL_INTERRUPT  1

#define EXIT_REASON_TRIPLE_FAULT        2

#define EXIT_REASON_INIT                3

#define EXIT_REASON_SIPI                4

#define EXIT_REASON_IO_SMI              5

#define EXIT_REASON_OTHER_SMI           6

#define EXIT_REASON_PENDING_INTERRUPT   7

#define EXIT_REASON_TASK_SWITCH         9

#defineEXIT_REASON_CPUID               10 //必须处理的

#define EXIT_REASON_HLT                 12

#defineEXIT_REASON_INVD                13 //必须处理的

#define EXIT_REASON_INVLPG              14

#define EXIT_REASON_RDPMC               15

#define EXIT_REASON_RDTSC               16

#define EXIT_REASON_RSM                 17

#defineEXIT_REASON_VMCALL              18 //必须处理的因为可能存在多个VT

#define EXIT_REASON_VMCLEAR             19

#define EXIT_REASON_VMLAUNCH            20

#define EXIT_REASON_VMPTRLD             21

#define EXIT_REASON_VMPTRST             22

#define EXIT_REASON_VMREAD              23

#define EXIT_REASON_VMRESUME            24

#define EXIT_REASON_VMWRITE             25

#define EXIT_REASON_VMXOFF              26

#define EXIT_REASON_VMXON               27

#defineEXIT_REASON_CR_ACCESS            28 //必须处理的只要处理cr3寄存器

#defineEXIT_REASON_DR_ACCESS            29 //可以监控硬件断点

#defineEXIT_REASON_IO_INSTRUCTION       30 //可以监控键盘鼠标输入输出

#defineEXIT_REASON_MSR_READ            31 //必须处理的

#defineEXIT_REASON_MSR_WRITE           32 //必须处理的

#define EXIT_REASON_INVALID_GUEST_STATE 33

#define EXIT_REASON_MSR_LOADING         34

#define EXIT_REASON_MWAIT_INSTRUCTION   36

#define EXIT_REASON_MONITOR_INSTRUCTION 39

#define EXIT_REASON_PAUSE_INSTRUCTION   40

#define EXIT_REASON_MACHINE_CHECK       41

#define EXIT_REASON_TPR_BELOW_THRESHOLD 43


必须交由我们自己处理的VM-EXIT事件(即不在CPU_BASED_VM_EXEC_CONTROL或EXCEPTION_BITMAP控制内的):

事件

代号

对应汇编指令

Model Specific Register Read (MSR寄存器读操作)

EXIT_REASON_MSR_READ(0x1F)

rdmsr

Model Specific Register Read (MSR寄存器写操作)

EXIT_REASON_MSR_WRITE(0x20)

wrmsr

Control Register Access

(CR寄存器读/写操作)

EXIT_REASON_CR_ACCESS(0x1C)

mov crX,XXX

mov XXX,crX

Invd(高速缓存控制)

EXIT_REASON_INVD(0xD)

invd

CPUID

EXIT_REASON_CPUID(0xA)

cpuid

VmCall

EXIT_REASON_VMCALL(0x12)

vmcall

注:代号参考自Newbluepill


需要注意的是处理CR控制寄存器和MSR时的一些细节


l  CR Access:

         退出事件条件:

    ExitQualification= Vmx_VmRead(EXIT_QUALIFICATION);

    控制寄存器,我们只要处理CR3就可以了:

    movcrControlRegister= ( ExitQualification & 0x0000000F );

    操作类型,0为写入 1为读取

    movcrAccessType= ( ( ExitQualification & 0x00000030 )>> 4 );

    操作数类型,一般为0:

    movcrOperandType= ( ( ExitQualification & 0x00000040 )>> 6 );

    目的寄存器:

    movcrGeneralPurposeRegister= ( ( ExitQualification & 0x00000F00 )>> 8 );


    movcrControlRegister= 3 且movcrAccessType =0时为写入到CR3

    movcrControlRegister= 3 且movcrAccessType =1时为从CR3读出到寄存器

    movcrGeneralPurposeRegister

         0=eax 1=ecx 2=edx 3=edx 4=esp 5=ebp6=esi 7=edi


l  MSRAccess:

Read:ECX为MSR寄存器代号,EAX为返回值的低32位,EDX为返回值的高32位.

Write:ECX为MSR寄存器代号,EAX为写入值的低32位,EDX为写入值的高32位.

部分需要用VmRead和VmWrite来处理。



在产生退出事件的时需要保存虚拟机的寄存器信息

使用的数据结构如下:



  • typedef struct _GUEST_REGS



  • {



  •         ULONG eax;



  •         ULONG ecx;



  •         ULONG edx;



  •         ULONG ebx;



  •         ULONG esp;



  •         ULONG ebp;



  •         ULONG esi;



  •         ULONG edi;



  •         ULONG eip;



  •         ULONG cr3;



  • }GUEST_REGS,*PGUEST_REGS;



在处理函数中需要用到的一些定义



  • /* VMCS Encordings */



  • enum



  • {



  •         VIRTUAL_PROCESSOR_ID = 0x00000000,



  •         POSTED_INTR_NV = 0x00000002,



  •         GUEST_ES_SELECTOR = 0x00000800,



  •         GUEST_CS_SELECTOR = 0x00000802,



  •         GUEST_SS_SELECTOR = 0x00000804,



  •         GUEST_DS_SELECTOR = 0x00000806,



  •         GUEST_FS_SELECTOR = 0x00000808,



  •         GUEST_GS_SELECTOR = 0x0000080a,



  •         GUEST_LDTR_SELECTOR = 0x0000080c,



  •         GUEST_TR_SELECTOR = 0x0000080e,



  •         GUEST_INTR_STATUS = 0x00000810,



  •         HOST_ES_SELECTOR = 0x00000c00,



  •         HOST_CS_SELECTOR = 0x00000c02,



  •         HOST_SS_SELECTOR = 0x00000c04,



  •         HOST_DS_SELECTOR = 0x00000c06,



  •         HOST_FS_SELECTOR = 0x00000c08,



  •         HOST_GS_SELECTOR = 0x00000c0a,



  •         HOST_TR_SELECTOR = 0x00000c0c,



  •         IO_BITMAP_A = 0x00002000,



  •         IO_BITMAP_A_HIGH = 0x00002001,



  •         IO_BITMAP_B = 0x00002002,



  •         IO_BITMAP_B_HIGH = 0x00002003,



  •         MSR_BITMAP = 0x00002004,



  •         MSR_BITMAP_HIGH = 0x00002005,



  •         VM_EXIT_MSR_STORE_ADDR = 0x00002006,



  •         VM_EXIT_MSR_STORE_ADDR_HIGH = 0x00002007,



  •         VM_EXIT_MSR_LOAD_ADDR = 0x00002008,



  •         VM_EXIT_MSR_LOAD_ADDR_HIGH = 0x00002009,



  •         VM_ENTRY_MSR_LOAD_ADDR = 0x0000200a,



  •         VM_ENTRY_MSR_LOAD_ADDR_HIGH = 0x0000200b,



  •         TSC_OFFSET = 0x00002010,



  •         TSC_OFFSET_HIGH = 0x00002011,



  •         VIRTUAL_APIC_PAGE_ADDR = 0x00002012,



  •         VIRTUAL_APIC_PAGE_ADDR_HIGH = 0x00002013,



  •         APIC_ACCESS_ADDR = 0x00002014,



  •         APIC_ACCESS_ADDR_HIGH = 0x00002015,



  •         POSTED_INTR_DESC_ADDR = 0x00002016,



  •         POSTED_INTR_DESC_ADDR_HIGH = 0x00002017,



  •         EPT_POINTER = 0x0000201a,



  •         EPT_POINTER_HIGH = 0x0000201b,



  •         EOI_EXIT_BITMAP0 = 0x0000201c,



  •         EOI_EXIT_BITMAP0_HIGH = 0x0000201d,



  •         EOI_EXIT_BITMAP1 = 0x0000201e,



  •         EOI_EXIT_BITMAP1_HIGH = 0x0000201f,



  •         EOI_EXIT_BITMAP2 = 0x00002020,



  •         EOI_EXIT_BITMAP2_HIGH = 0x00002021,



  •         EOI_EXIT_BITMAP3 = 0x00002022,



  •         EOI_EXIT_BITMAP3_HIGH = 0x00002023,



  •         VMREAD_BITMAP = 0x00002026,



  •         VMWRITE_BITMAP = 0x00002028,



  •         XSS_EXIT_BITMAP = 0x0000202C,



  •         XSS_EXIT_BITMAP_HIGH = 0x0000202D,



  •         GUEST_PHYSICAL_ADDRESS = 0x00002400,



  •         GUEST_PHYSICAL_ADDRESS_HIGH = 0x00002401,



  •         VMCS_LINK_POINTER = 0x00002800,



  •         VMCS_LINK_POINTER_HIGH = 0x00002801,



  •         GUEST_IA32_DEBUGCTL = 0x00002802,



  •         GUEST_IA32_DEBUGCTL_HIGH = 0x00002803,



  •         GUEST_IA32_PAT = 0x00002804,



  •         GUEST_IA32_PAT_HIGH = 0x00002805,



  •         GUEST_IA32_EFER = 0x00002806,



  •         GUEST_IA32_EFER_HIGH = 0x00002807,



  •         GUEST_IA32_PERF_GLOBAL_CTRL = 0x00002808,



  •         GUEST_IA32_PERF_GLOBAL_CTRL_HIGH = 0x00002809,



  •         GUEST_PDPTR0 = 0x0000280a,



  •         GUEST_PDPTR0_HIGH = 0x0000280b,



  •         GUEST_PDPTR1 = 0x0000280c,



  •         GUEST_PDPTR1_HIGH = 0x0000280d,



  •         GUEST_PDPTR2 = 0x0000280e,



  •         GUEST_PDPTR2_HIGH = 0x0000280f,



  •         GUEST_PDPTR3 = 0x00002810,



  •         GUEST_PDPTR3_HIGH = 0x00002811,



  •         GUEST_BNDCFGS = 0x00002812,



  •         GUEST_BNDCFGS_HIGH = 0x00002813,



  •         HOST_IA32_PAT = 0x00002c00,



  •         HOST_IA32_PAT_HIGH = 0x00002c01,



  •         HOST_IA32_EFER = 0x00002c02,



  •         HOST_IA32_EFER_HIGH = 0x00002c03,



  •         HOST_IA32_PERF_GLOBAL_CTRL = 0x00002c04,



  •         HOST_IA32_PERF_GLOBAL_CTRL_HIGH = 0x00002c05,



  •         PIN_BASED_VM_EXEC_CONTROL = 0x00004000,



  •         CPU_BASED_VM_EXEC_CONTROL = 0x00004002,



  •         EXCEPTION_BITMAP = 0x00004004,



  •         PAGE_FAULT_ERROR_CODE_MASK = 0x00004006,



  •         PAGE_FAULT_ERROR_CODE_MATCH = 0x00004008,



  •         CR3_TARGET_COUNT = 0x0000400a,



  •         VM_EXIT_CONTROLS = 0x0000400c,



  •         VM_EXIT_MSR_STORE_COUNT = 0x0000400e,



  •         VM_EXIT_MSR_LOAD_COUNT = 0x00004010,



  •         VM_ENTRY_CONTROLS = 0x00004012,



  •         VM_ENTRY_MSR_LOAD_COUNT = 0x00004014,



  •         VM_ENTRY_INTR_INFO_FIELD = 0x00004016,



  •         VM_ENTRY_EXCEPTION_ERROR_CODE = 0x00004018,



  •         VM_ENTRY_INSTRUCTION_LEN = 0x0000401a,



  •         TPR_THRESHOLD = 0x0000401c,



  •         SECONDARY_VM_EXEC_CONTROL = 0x0000401e,



  •         PLE_GAP = 0x00004020,



  •         PLE_WINDOW = 0x00004022,



  •         VM_INSTRUCTION_ERROR = 0x00004400,



  •         VM_EXIT_REASON = 0x00004402,



  •         VM_EXIT_INTR_INFO = 0x00004404,



  •         VM_EXIT_INTR_ERROR_CODE = 0x00004406,



  •         IDT_VECTORING_INFO_FIELD = 0x00004408,



  •         IDT_VECTORING_ERROR_CODE = 0x0000440a,



  •         VM_EXIT_INSTRUCTION_LEN = 0x0000440c,



  •         VMX_INSTRUCTION_INFO = 0x0000440e,



  •         GUEST_ES_LIMIT = 0x00004800,



  •         GUEST_CS_LIMIT = 0x00004802,



  •         GUEST_SS_LIMIT = 0x00004804,



  •         GUEST_DS_LIMIT = 0x00004806,



  •         GUEST_FS_LIMIT = 0x00004808,



  •         GUEST_GS_LIMIT = 0x0000480a,



  •         GUEST_LDTR_LIMIT = 0x0000480c,



  •         GUEST_TR_LIMIT = 0x0000480e,



  •         GUEST_GDTR_LIMIT = 0x00004810,



  •         GUEST_IDTR_LIMIT = 0x00004812,



  •         GUEST_ES_AR_BYTES = 0x00004814,



  •         GUEST_CS_AR_BYTES = 0x00004816,



  •         GUEST_SS_AR_BYTES = 0x00004818,



  •         GUEST_DS_AR_BYTES = 0x0000481a,



  •         GUEST_FS_AR_BYTES = 0x0000481c,



  •         GUEST_GS_AR_BYTES = 0x0000481e,



  •         GUEST_LDTR_AR_BYTES = 0x00004820,



  •         GUEST_TR_AR_BYTES = 0x00004822,



  •         GUEST_INTERRUPTIBILITY_INFO = 0x00004824,



  •         GUEST_ACTIVITY_STATE = 0X00004826,



  •         GUEST_SYSENTER_CS = 0x0000482A,



  •         VMX_PREEMPTION_TIMER_VALUE = 0x0000482E,



  •         HOST_IA32_SYSENTER_CS = 0x00004c00,



  •         CR0_GUEST_HOST_MASK = 0x00006000,



  •         CR4_GUEST_HOST_MASK = 0x00006002,



  •         CR0_READ_SHADOW = 0x00006004,



  •         CR4_READ_SHADOW = 0x00006006,



  •         CR3_TARGET_VALUE0 = 0x00006008,



  •         CR3_TARGET_VALUE1 = 0x0000600a,



  •         CR3_TARGET_VALUE2 = 0x0000600c,



  •         CR3_TARGET_VALUE3 = 0x0000600e,



  •         EXIT_QUALIFICATION = 0x00006400,



  •         GUEST_LINEAR_ADDRESS = 0x0000640a,



  •         GUEST_CR0 = 0x00006800,



  •         GUEST_CR3 = 0x00006802,



  •         GUEST_CR4 = 0x00006804,



  •         GUEST_ES_BASE = 0x00006806,



  •         GUEST_CS_BASE = 0x00006808,



  •         GUEST_SS_BASE = 0x0000680a,



  •         GUEST_DS_BASE = 0x0000680c,



  •         GUEST_FS_BASE = 0x0000680e,



  •         GUEST_GS_BASE = 0x00006810,



  •         GUEST_LDTR_BASE = 0x00006812,



  •         GUEST_TR_BASE = 0x00006814,



  •         GUEST_GDTR_BASE = 0x00006816,



  •         GUEST_IDTR_BASE = 0x00006818,



  •         GUEST_DR7 = 0x0000681a,



  •         GUEST_RSP = 0x0000681c,



  •         GUEST_RIP = 0x0000681e,



  •         GUEST_RFLAGS = 0x00006820,



  •         GUEST_PENDING_DBG_EXCEPTIONS = 0x00006822,



  •         GUEST_SYSENTER_ESP = 0x00006824,



  •         GUEST_SYSENTER_EIP = 0x00006826,



  •         HOST_CR0 = 0x00006c00,



  •         HOST_CR3 = 0x00006c02,



  •         HOST_CR4 = 0x00006c04,



  •         HOST_FS_BASE = 0x00006c06,



  •         HOST_GS_BASE = 0x00006c08,



  •         HOST_TR_BASE = 0x00006c0a,



  •         HOST_GDTR_BASE = 0x00006c0c,



  •         HOST_IDTR_BASE = 0x00006c0e,



  •         HOST_IA32_SYSENTER_ESP = 0x00006c10,



  •         HOST_IA32_SYSENTER_EIP = 0x00006c12,



  •         HOST_RSP = 0x00006c14,



  •         HOST_RIP = 0x00006c16,



  • };



由于汇编里面不能直接引用cpp全局变量

这里需要一个函数得到保存虚拟机退出时的寄存器信息的地址

定义的保存寄存器信息的变量为GUEST_REGS g_GuestRegs;

在cpp代码中添加:




  • extern "C" ULONG GetGuestRegsAddress()



  • {



  •          return(ULONG)&g_GuestRegs;



  • }



然后在asm文件中添加


GetGuestRegsAddress Proto


例子:




  • .686p



  • .model flat, stdcall



  • option casemap:none







  • GetGuestRegsAddress Proto :在这里添加



  • VMMEntryPoint Proto







  • .data



  • .code







  • …..




这里我们要实现一个汇编函数 功能是

1.push 原始寄存器

2.保存寄存器信息到全局变量g_GuestRegs;中

3.call cpp代码中的退出事件分发函数

4.pop 原始寄存器

5.恢复原始寄存器



代码如下:

其中需要注意的是这里esp不是虚拟机的esp,是HOST机的这里需要在cpp(VMMEntryPoint的cpp)代码中重新获取

最后不是写ret 而是vmresume



  • Asm_VMMEntryPoint Proc



  •         cli



  •         push eax



  •         push ecx



  •         push edx



  •         push ebx



  •         push esp     ;HOST_RSP



  •         push ebp



  •         push edi



  •         push esi







  •         mov [esp-1280h],eax



  •         mov [esp-1284h],ebx



  •         call GetGuestRegsAddress



  •         mov [eax+4h],ecx



  •         mov [eax+8h],edx



  •         mov [eax+0Ch],ebx



  •         mov [eax+10h],esp



  •         mov [eax+14h],ebp



  •         mov [eax+18h],esi



  •         mov [eax+1Ch],edi



  •         mov ebx,[esp-1280h]



  •         mov [eax],ebx



  •         mov eax,[esp-1280h]



  •         mov ebx,[esp-1284h]







  •         call VMMEntryPoint







  •         pop esi



  •         pop edi



  •         pop ebp



  •         pop esp



  •         pop ebx



  •         pop edx



  •         pop ecx



  •         pop eax







  •         call GetGuestRegsAddress



  •         mov ecx,[eax+4h]



  •         mov edx,[eax+8h]



  •         mov ebx,[eax+0Ch]



  •         mov esp,[eax+10h]



  •         mov ebp,[eax+14h]



  •         mov esi,[eax+18h]



  •         mov edi,[eax+1Ch]



  •         mov eax,[eax]



  •         sti



  •         vmresume



  • Asm_VMMEntryPoint Endp



VMMEntryPoint 的Cpp代码实现(也就是汇编代码里call的那个):



  • extern "C" void VMMEntryPoint()



  • {



  •         ULONG ExitReason;                                        //退出事件类型



  •         ULONG ExitInstructionLength;                //退出事件时的代码的长度 用于后面恢复时跳过



  •         ULONG GuestResumeEIP;                        //虚拟机恢复时的EIP







  •         ExitReason = Vmx_VmRead(VM_EXIT_REASON);  //通过Vmx_VmRead(VM_EXIT_REASON)得到退出事件类型



  •         ExitInstructionLength = Vmx_VmRead(VM_EXIT_INSTRUCTION_LEN); //得到产生退出事件时代码的长度 用于恢复







  •         g_GuestRegs.esp = Vmx_VmRead(GUEST_RSP); //前面说过esp要重新获取



  •         g_GuestRegs.eip = Vmx_VmRead(GUEST_RIP); //得到产生退出事件时的EIP



  •         g_GuestRegs.cr3 = Vmx_VmRead(GUEST_CR3); //得到产生退出事件时的CR3 用于处理CR ACCESS(必须处理的)







  •         switch(ExitReason)



  •         {



  •         case EXIT_REASON_CPUID: //如果是调用了CPUID



  •                 {



  •                         HandleCPUID();



  •                         break;



  •                 }



  •         case EXIT_REASON_INVD://如果是INVD 不知道干什么的 但必须处理



  •                 {



  •                         HandleInvd();



  •                         break;



  •                 }



  •         case EXIT_REASON_VMCALL: //处理VMCALL 可能存在多个VT 关闭虚拟机



  •                 {



  •                         HandleVmCall();



  •                         break;



  •                 }



  •         case EXIT_REASON_MSR_READ: //MSR READ



  •                 {



  •                         HandleMsrRead();



  •                         break;



  •                 }



  •         case EXIT_REASON_MSR_WRITE: // MSR WRITR



  •                 {



  •                         HandleMsrWrite();



  •                         break;



  •                 }



  •         case EXIT_REASON_CR_ACCESS: //CR_ACCESS



  •                 {



  •                         HandleCrAccess();



  •                         break;



  •                 }



  •         default:



  •                 break;



  •         }







  • //如果不是上面的就恢复



  • Resume:



  •         GuestResumeEIP = g_GuestRegs.eip+ExitInstructionLength;



  •         Vmx_VmWrite(GUEST_RIP,GuestResumeEIP);



  •         Vmx_VmWrite(GUEST_RSP,g_GuestRegs.esp);



  • }



各个处理函数的实现 :这里只实现必须要处理的 其它请自己研究



  • //CPUID的处理函数



  • void HandleCPUID()



  • {



  • //如果是我们的



  •         if (g_GuestRegs.eax == 'Mini')



  •         {



  •                 g_GuestRegs.ebx = 0x88888888;



  •                 g_GuestRegs.ecx = 0x11111111;



  •                 g_GuestRegs.edx = 0x12345678;



  •         }//不是我们的就让CPU模拟执行后返回 x86下 nfn保存在eax中



  •         else Asm_CPUID(g_GuestRegs.eax,&g_GuestRegs.eax,&g_GuestRegs.ebx,&g_GuestRegs.ecx,&g_GuestRegs.edx);



  • }







  • // Invd处理函数



  • void HandleInvd()



  • {



  •         Asm_Invd();



  • }







  • //VMCall处理函数 未写完待续



  • void HandleVmCall()



  • {



  •         if (g_GuestRegs.eax == 'SVT')



  •         {



  •                 Vmx_VmxOff();







  •                 // ......



  •         }



  • }







  • //MSR Read 必须处理三个 MSR_IA32_SYSENTER_CS: MSR_IA32_SYSENTER_ESP: MSR_IA32_SYSENTER_EIP;



  • 其中有意思的是MSR_IA32_SYSENTER_EIP 这个就是x86下KiFastCallEntry 看雪开学的一份OD插件中就是修改了此处



  • void HandleMsrRead()



  • {



  •         switch(g_GuestRegs.ecx)



  •         {



  •         case MSR_IA32_SYSENTER_CS:



  •                 {



  •                         g_GuestRegs.eax = Vmx_VmRead(GUEST_SYSENTER_CS);



  •                         break;



  •                 }



  •         case MSR_IA32_SYSENTER_ESP:



  •                 {



  •                         g_GuestRegs.eax = Vmx_VmRead(GUEST_SYSENTER_ESP);



  •                         break;



  •                 }



  •         case MSR_IA32_SYSENTER_EIP:        // KiFastCallEntry



  •                 {



  •                         g_GuestRegs.eax = Vmx_VmRead(GUEST_SYSENTER_EIP);



  •                         break;



  •                 }



  •         default:



  •                 g_GuestRegs.eax = Asm_ReadMsr(g_GuestRegs.ecx);



  •         }







  • }







  • //Msr Write 也必须处理三个 可能有误



  • void HandleMsrWrite()



  • {



  •         switch(g_GuestRegs.ecx)



  •         {



  •         case MSR_IA32_SYSENTER_CS:



  •                 {



  •                         Vmx_VmWrite(GUEST_SYSENTER_CS,g_GuestRegs.eax);



  •                         break;



  •                 }



  •         case MSR_IA32_SYSENTER_ESP:



  •                 {



  •                         Vmx_VmWrite(GUEST_SYSENTER_ESP,g_GuestRegs.eax);



  •                         break;



  •                 }



  •         case MSR_IA32_SYSENTER_EIP:        // KiFastCallEntry



  •                 {



  •                         Vmx_VmWrite(GUEST_SYSENTER_EIP,g_GuestRegs.eax);



  •                         break;



  •                 }



  •         default:



  •                 Asm_WriteMsr(g_GuestRegs.ecx,g_GuestRegs.eax,g_GuestRegs.edx);



  •         }



  • }







  • /*



  •         CR Access:



  •         退出事件条件:



  •         ExitQualification = Vmx_VmRead(EXIT_QUALIFICATION) ;



  •         控制寄存器,我们只要处理CR3就可以了:



  •         movcrControlRegister = ( ExitQualification & 0x0000000F );



  •         操作类型,0为写入 1为读取



  •         movcrAccessType = ( ( ExitQualification & 0x00000030 ) >> 4 );



  •         操作数类型,一般为0:



  •         movcrOperandType = ( ( ExitQualification & 0x00000040 ) >> 6 );



  •         目的寄存器:



  •         movcrGeneralPurposeRegister = ( ( ExitQualification & 0x00000F00 ) >> 8 );







  •         movcrControlRegister= 3 且movcrAccessType = 0时为写入到CR3



  •         movcrControlRegister= 3 且movcrAccessType = 1时为从CR3读出到寄存器







  •         movcrGeneralPurposeRegister



  •         0=eax 1=ecx 2=edx 3=edx 4=esp 5=ebp 6=esi 7=edi







  • */



  • void HandleCrAccess()



  • {



  •         ULONG                movcrControlRegister;



  •         ULONG                movcrAccessType;



  •         ULONG                movcrOperandType;



  •         ULONG                movcrGeneralPurposeRegister;



  •         ULONG                movcrLMSWSourceData;



  •         ULONG                ExitQualification;







  •         ExitQualification = Vmx_VmRead(EXIT_QUALIFICATION) ;



  •         movcrControlRegister = ( ExitQualification & 0x0000000F );



  •         movcrAccessType = ( ( ExitQualification & 0x00000030 ) >> 4 );



  •         movcrOperandType = ( ( ExitQualification & 0x00000040 ) >> 6 );



  •         movcrGeneralPurposeRegister = ( ( ExitQualification & 0x00000F00 ) >> 8 );







  •         //        Control Register Access (CR3 <-- reg32)



  •         //



  •         if( movcrControlRegister == 3 && movcrAccessType == 0 && movcrOperandType == 0 && movcrGeneralPurposeRegister == 0 )



  •         {



  •                 Vmx_VmWrite( GUEST_CR3, g_GuestRegs.eax );



  •         }



  •         if( movcrControlRegister == 3 && movcrAccessType == 0 && movcrOperandType == 0 && movcrGeneralPurposeRegister == 1 )



  •         {



  •                 Vmx_VmWrite( GUEST_CR3, g_GuestRegs.ecx );



  •         }



  •         if( movcrControlRegister == 3 && movcrAccessType == 0 && movcrOperandType == 0 && movcrGeneralPurposeRegister == 2 )



  •         {



  •                 Vmx_VmWrite( GUEST_CR3, g_GuestRegs.edx );



  •         }



  •         if( movcrControlRegister == 3 && movcrAccessType == 0 && movcrOperandType == 0 && movcrGeneralPurposeRegister == 3 )



  •         {



  •                 Vmx_VmWrite( GUEST_CR3, g_GuestRegs.ebx );



  •         }



  •         if( movcrControlRegister == 3 && movcrAccessType == 0 && movcrOperandType == 0 && movcrGeneralPurposeRegister == 4 )



  •         {



  •                 Vmx_VmWrite( GUEST_CR3, g_GuestRegs.esp );



  •         }



  •         if( movcrControlRegister == 3 && movcrAccessType == 0 && movcrOperandType == 0 && movcrGeneralPurposeRegister == 5 )



  •         {



  •                 Vmx_VmWrite( GUEST_CR3, g_GuestRegs.ebp );



  •         }



  •         if( movcrControlRegister == 3 && movcrAccessType == 0 && movcrOperandType == 0 && movcrGeneralPurposeRegister == 6 )



  •         {



  •                 Vmx_VmWrite( GUEST_CR3, g_GuestRegs.esi );



  •         }



  •         if( movcrControlRegister == 3 && movcrAccessType == 0 && movcrOperandType == 0 && movcrGeneralPurposeRegister == 7 )



  •         {



  •                 Vmx_VmWrite( GUEST_CR3, g_GuestRegs.edi );



  •         }



  •         //        Control Register Access (reg32 <-- CR3)



  •         //



  •         if( movcrControlRegister == 3 && movcrAccessType == 1 && movcrOperandType == 0 && movcrGeneralPurposeRegister == 0 )



  •         {



  •                 g_GuestRegs.eax = g_GuestRegs.cr3;



  •         }



  •         if( movcrControlRegister == 3 && movcrAccessType == 1 && movcrOperandType == 0 && movcrGeneralPurposeRegister == 1 )



  •         {



  •                 g_GuestRegs.ecx = g_GuestRegs.cr3;



  •         }



  •         if( movcrControlRegister == 3 && movcrAccessType == 1 && movcrOperandType == 0 && movcrGeneralPurposeRegister == 2 )



  •         {



  •                 g_GuestRegs.edx = g_GuestRegs.cr3;



  •         }



  •         if( movcrControlRegister == 3 && movcrAccessType == 1 && movcrOperandType == 0 && movcrGeneralPurposeRegister == 3 )



  •         {



  •                 g_GuestRegs.ebx = g_GuestRegs.cr3;



  •         }



  •         if( movcrControlRegister == 3 && movcrAccessType == 1 && movcrOperandType == 0 && movcrGeneralPurposeRegister == 4 )



  •         {



  •                 g_GuestRegs.esp = g_GuestRegs.cr3;



  •         }



  •         if( movcrControlRegister == 3 && movcrAccessType == 1 && movcrOperandType == 0 && movcrGeneralPurposeRegister == 5 )



  •         {



  •                 g_GuestRegs.ebp = g_GuestRegs.cr3;



  •         }



  •         if( movcrControlRegister == 3 && movcrAccessType == 1 && movcrOperandType == 0 && movcrGeneralPurposeRegister == 6 )



  •         {



  •                 g_GuestRegs.esi = g_GuestRegs.cr3;



  •         }



  •         if( movcrControlRegister == 3 && movcrAccessType == 1 && movcrOperandType == 0 && movcrGeneralPurposeRegister == 7 )



  •         {



  •                 g_GuestRegs.edi = g_GuestRegs.cr3;



  •         }  



  • }



下一章将讲VMCS表填写
分享到:  QQ好友和群QQ好友和群
收藏收藏
回复

使用道具 举报

快速回复高级模式
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

快速回复 返回顶部 返回列表