From c46cba8d3ac4e424daa9a79704f3aa38846428be Mon Sep 17 00:00:00 2001 From: cheat-engine Date: Tue, 16 Jul 2019 10:23:39 +0200 Subject: [PATCH] fix VM inside VM inside VM --- dbvm/Makefile | 4 +- dbvm/common/common.h | 1 + dbvm/vmm/common.c | 10 ++ dbvm/vmm/common.h | 5 + dbvm/vmm/epthandler.c | 1 + dbvm/vmm/main.c | 19 ++- dbvm/vmm/main.h | 2 + dbvm/vmm/vmeventhandler.c | 16 +- dbvm/vmm/vmma.asm | 41 +++++ dbvm/vmm/vmmhelper.c | 58 ++++++- dbvm/vmm/vmmhelper.h | 1 + dbvm/vmm/vmxcontrolstructures.h | 7 +- dbvm/vmm/vmxemu.c | 263 +++++++++++++++++++++++++++----- dbvm/vmm/vmxemu.h | 4 +- 14 files changed, 377 insertions(+), 55 deletions(-) diff --git a/dbvm/Makefile b/dbvm/Makefile index 3a9ba9e0..9b70e075 100755 --- a/dbvm/Makefile +++ b/dbvm/Makefile @@ -1,6 +1,6 @@ #SERIALPORT is the port to communicate with the debugger, usually 0x3f8, on db's system it's 0xef00 -SERIALPORT=0 #release/no serialport build -#SERIALPORT=0x3f8 #bochs (gigabyte test system) +#SERIALPORT=0 #release/no serialport build +SERIALPORT=0x3f8 #bochs (gigabyte test system) #SERIALPORT=0xbf00 #intel #SERIALPORT=0xec00 #amd #SERIALPORT=0xd010 #16 core test system diff --git a/dbvm/common/common.h b/dbvm/common/common.h index f7b4e73a..81569901 100755 --- a/dbvm/common/common.h +++ b/dbvm/common/common.h @@ -18,6 +18,7 @@ typedef struct _criticalSection int locked; int apicid; int lockcount; + } criticalSection, *PcriticalSection; extern int debugzeromem; diff --git a/dbvm/vmm/common.c b/dbvm/vmm/common.c index 4098189f..07b261b5 100755 --- a/dbvm/vmm/common.c +++ b/dbvm/vmm/common.c @@ -1026,6 +1026,11 @@ void mrewEndWrite(Pmultireadexclusivewritesychronizer MREW) void csEnter(PcriticalSection CS) { +#ifdef DEBUG + if (CS->ignorelock) + return; +#endif + int apicid=getAPICID()+1; //+1 so it never returns 0 if ((CS->locked) && (CS->apicid==apicid)) @@ -1046,6 +1051,11 @@ void csEnter(PcriticalSection CS) void csLeave(PcriticalSection CS) { +#ifdef DEBUG + if (CS->ignorelock) + return; +#endif + int apicid=getAPICID()+1; //+1 so it never returns 0 diff --git a/dbvm/vmm/common.h b/dbvm/vmm/common.h index 644b79f7..92bd7c97 100755 --- a/dbvm/vmm/common.h +++ b/dbvm/vmm/common.h @@ -12,11 +12,13 @@ #if (defined SERIALPORT) && (SERIALPORT != 0) #define DEBUG //comment for release #define DEBUGINTHANDLER //comment for release + #define CHECKAPICID #endif #if (DISPLAYDEBUG==1) #define DEBUG #define DEBUGINTHANDLER + #define CHECKAPICID #endif #define ULTIMAPDEBUG //for debugging ultimap (I seem to have misplaced my serial port...) @@ -80,6 +82,9 @@ typedef volatile struct _criticalSection volatile int locked; volatile int apicid; int lockcount; +#ifdef DEBUG + int ignorelock; +#endif } criticalSection, *PcriticalSection; diff --git a/dbvm/vmm/epthandler.c b/dbvm/vmm/epthandler.c index 2de8b602..e9b1782e 100644 --- a/dbvm/vmm/epthandler.c +++ b/dbvm/vmm/epthandler.c @@ -18,6 +18,7 @@ #include "vmcall.h" #include "maps.h" #include "list.h" +#include "vmeventhandler.h" QWORD EPTMapPhysicalMemory(pcpuinfo currentcpuinfo, QWORD physicalAddress, int forcesmallpage); diff --git a/dbvm/vmm/main.c b/dbvm/vmm/main.c index 11eef427..2c5d6d8c 100755 --- a/dbvm/vmm/main.c +++ b/dbvm/vmm/main.c @@ -117,6 +117,11 @@ int cinthandler(unsigned long long *stack, int intnr) //todo: move to it's own s DWORD thisAPICID; int cpunr=0; +#ifdef DEBUG + sendstringCS.ignorelock=1; + sendstringfCS.ignorelock=1; +#endif + if (readMSRSafe(IA32_FS_BASE_MSR)==0) { sendstringf("Invalid FS base during exception\n"); @@ -146,6 +151,18 @@ int cinthandler(unsigned long long *stack, int intnr) //todo: move to it's own s thisAPICID=getAPICID(); +#ifdef CHECKAPICID + if (thisAPICID!=cpuinfo->apicid) + { + sendstringCS.ignorelock=1; + sendstringfCS.ignorelock=1; + sendstringf("Interrupt %d. Invalid cpuinfo", intnr); + while(1); + } +#endif + + + sendstringCS.lockcount=0; sendstringCS.locked=0; sendstringfCS.lockcount=0; @@ -154,7 +171,7 @@ int cinthandler(unsigned long long *stack, int intnr) //todo: move to it's own s // sendstringf("interrupt fired : %d (%x)\n\r", intnr,intnr); - sendstringf("cpunr=%d\n\r",cpunr); + sendstringf("cpunr=%d (apicid=%d)\n\r",cpunr, thisAPICID); sendstringf("intnr=%d\n\r",intnr); sendstringf("rsp=%x\n\r",getRSP()); sendstringf("cr2=%6\n\r",getCR2()); diff --git a/dbvm/vmm/main.h b/dbvm/vmm/main.h index d1fab3ed..2747a5b1 100755 --- a/dbvm/vmm/main.h +++ b/dbvm/vmm/main.h @@ -71,7 +71,9 @@ extern ULONG setCR8(UINT64 newcr8); extern void _invlpg(UINT64 address); extern void _invpcid(int type, PINVPCIDDESCRIPTOR datablock); extern void _invept(int type, PINVEPTDESCRIPTOR datablock); +extern int _invept2(int type, PINVEPTDESCRIPTOR datablock); extern void _invvpid(int type, PINVVPIDDESCRIPTOR datablock); +extern int _invvpid2(int type, PINVVPIDDESCRIPTOR datablock); extern void _wbinvd(void); extern void _invd(void); diff --git a/dbvm/vmm/vmeventhandler.c b/dbvm/vmm/vmeventhandler.c index a4e0d4ff..545cfd7e 100755 --- a/dbvm/vmm/vmeventhandler.c +++ b/dbvm/vmm/vmeventhandler.c @@ -4198,7 +4198,9 @@ int handleVMEvent(pcpuinfo currentcpuinfo, VMRegisters *vmregisters, FXSAVE64 *f case 50: { sendstring("INVEPT\n\r"); - return 1; + return handleIntelVMXInstruction(currentcpuinfo, vmregisters); + + //return 1; } case 51: @@ -4239,15 +4241,23 @@ int handleVMEvent(pcpuinfo currentcpuinfo, VMRegisters *vmregisters, FXSAVE64 *f return 0; } - case 53: + case vm_exit_invvpid: { sendstring("INVVPID\n\r"); + return handleIntelVMXInstruction(currentcpuinfo, vmregisters); + #ifdef DEBUG while (1); #endif - return 1; + // return 1; } + case vm_exit_invpcid: + { + while(1); + return 1; + } + case 54: { sendstring("WBINVD\n\r"); diff --git a/dbvm/vmm/vmma.asm b/dbvm/vmm/vmma.asm index 0e830d02..186a2e84 100755 --- a/dbvm/vmm/vmma.asm +++ b/dbvm/vmm/vmma.asm @@ -1481,6 +1481,27 @@ invept rdi,[rsi] ret +global _invept2 +;---------------------------; +;_invept2(int type, 128data); type must be either 1(local for specific ept pointer) or 2(global for all vpids) +;---------------------------; +_invept2: +invept rdi,[rsi] +jc _invept2_err1 +jz _invept2_err2 +xor rax,rax +ret + +_invept2_err1: +mov eax,1 +ret + +_invept2_err2: +mov eax,2 +ret + + + global _invvpid ;--------------------------; ;_invvpid(int type, 128data); type must be either 0(specific linear address for specific vpid) 1(local for specific vpid) or 2(global for all vpids) @@ -1489,6 +1510,26 @@ _invvpid: invvpid rdi,[rsi] ret +global _invvpid2 +;----------------------------; +;_invvpid2(int type, 128data); type must be either 0(specific linear address for specific vpid) 1(local for specific vpid) or 2(global for all vpids) +;----------------------------; +_invvpid2: +invvpid rdi,[rsi] +jc _vmread2_err1 +jz _vmread2_err2 +xor rax,rax +ret + +_invvpid2_err1: +mov eax,1 +ret + +_invvpid2_err2: +mov eax,2 +ret + + global _invlpg diff --git a/dbvm/vmm/vmmhelper.c b/dbvm/vmm/vmmhelper.c index 4d28d134..8a619ae3 100755 --- a/dbvm/vmm/vmmhelper.c +++ b/dbvm/vmm/vmmhelper.c @@ -118,7 +118,7 @@ char * getVMExitReassonString(void) { case 0: return "Exception or NMI"; case 1: return "External interrupt"; - case 2: return "Tripple fault"; + case 2: return "Triple fault"; case 3: return "INIT Signal"; case 4: return "Start-up IPI (SIPI)"; case 5: return "SMI interrupt"; @@ -132,8 +132,10 @@ char * getVMExitReassonString(void) case 17: return "VMREAD"; case 18: return "VMCALL"; case 19: return "VMCLEAR"; + case 20: return "VMLAUNCH"; case 21: return "VMPTRLD"; case 23: return "VMREAD"; + case 24: return "VMRESUME"; case 25: return "VMWRITE"; case 27: return "VMXON"; //or: omg it's one bee case 28: return "Controlregister access"; @@ -145,8 +147,10 @@ char * getVMExitReassonString(void) case 37: return "Monitor trap flag"; case vm_exit_ept_violation: return "EPT Violation"; case vm_exit_ept_misconfiguration: return "EPT Misconfiguration"; + case 50: return "INVEPT"; case 51: return "RDTSCP"; case 52: return "Preemption timer"; + case 53: return "INVVPID"; case 55: return "XSETBV"; default :return "NYI"; } @@ -694,6 +698,9 @@ int vmexit_amd(pcpuinfo currentcpuinfo, UINT64 *registers, void *fxsave UNUSED) return result; } +int lastexits[10]; +int lastexitsindex=0; + #ifdef DEBUG QWORD lastbeat=0; @@ -752,8 +759,7 @@ int vmexit(pcpuinfo currentcpuinfo, UINT64 *registers, void *fxsave) int vmexit2(pcpuinfo currentcpuinfo, UINT64 *registers, void *fxsave) #else -int lastexits[10]; -int lastexitsindex=0; + int vmexit(pcpuinfo currentcpuinfo, UINT64 *registers, void *fxsave) #endif @@ -768,6 +774,25 @@ int vmexit(pcpuinfo currentcpuinfo, UINT64 *registers, void *fxsave) lastexitsindex++; lastexitsindex=lastexitsindex % 10; +#ifdef CHECKAPICID + if (currentcpuinfo) + { + if (getAPICID()!=currentcpuinfo->apicid) + { + sendstring("FUCK\n"); + while(1); + } + + + } + else + { + sendstring("WTFOMG\n"); + while (1); + } +#endif + + if (dbvm_plugin_exit_pre) { @@ -1050,9 +1075,13 @@ int vmexit(pcpuinfo currentcpuinfo, UINT64 *registers, void *fxsave) // skip=0; // break; // + case vm_exit_vmlaunch: + verbosity=10; + skip=0; + break; case vm_exit_vmresume: - //skip=1; + skip=currentcpuinfo->cpunr!=0; break; case vm_exit_vmcall: @@ -1062,7 +1091,11 @@ int vmexit(pcpuinfo currentcpuinfo, UINT64 *registers, void *fxsave) break; case vm_exit_vmread: - //skip=1; + skip=1; + break; + + case vm_exit_vmwrite: + skip=1; break; case vm_exit_vmptrld: @@ -1070,10 +1103,15 @@ int vmexit(pcpuinfo currentcpuinfo, UINT64 *registers, void *fxsave) break; - case vm_exit_vmwrite: - //skip=1; + case vm_exit_invept: + skip=1; break; + case vm_exit_invvpid: + skip=1; + break; + + case vm_exit_cpuid: skip=2; //REALLY verbose break; @@ -1177,6 +1215,7 @@ int vmexit(pcpuinfo currentcpuinfo, UINT64 *registers, void *fxsave) VMRegisters* r=(VMRegisters*)registers; switch (r->rcx) { + case 0x10: case 0x176: case 0x175: case 0x174: @@ -1195,6 +1234,7 @@ int vmexit(pcpuinfo currentcpuinfo, UINT64 *registers, void *fxsave) VMRegisters* r=(VMRegisters*)registers; switch (r->rcx) { + case 0x10: case 0x3a: case 0xc0000080: skip=1; @@ -1209,6 +1249,10 @@ int vmexit(pcpuinfo currentcpuinfo, UINT64 *registers, void *fxsave) skip=1; break; + case vm_exit_rdtsc: + skip=1; + break; + case vm_exit_invalid_guest_state: diff --git a/dbvm/vmm/vmmhelper.h b/dbvm/vmm/vmmhelper.h index fd802c11..1c593872 100755 --- a/dbvm/vmm/vmmhelper.h +++ b/dbvm/vmm/vmmhelper.h @@ -573,6 +573,7 @@ typedef volatile struct tcpuinfo int currenterrorcode; //if not 0, return this errorcode on vmread vmxhoststate originalhoststate; + vmxhoststate dbvmhoststate; int runningvmx; //1 if the previous call was a vmlaunch/vmresume and no vmexit happened yet } vmxdata; diff --git a/dbvm/vmm/vmxcontrolstructures.h b/dbvm/vmm/vmxcontrolstructures.h index 91f0d7be..3c28ee87 100755 --- a/dbvm/vmm/vmxcontrolstructures.h +++ b/dbvm/vmm/vmxcontrolstructures.h @@ -79,7 +79,9 @@ #define vm_exit_taskswitch 9 #define vm_exit_cpuid 10 #define vm_exit_invlpg 14 +#define vm_exit_rdtsc 16 #define vm_exit_vmcall 18 +#define vm_exit_vmlaunch 20 #define vm_exit_vmptrld 21 #define vm_exit_vmread 23 #define vm_exit_vmresume 24 @@ -91,8 +93,11 @@ #define vm_exit_monitor_trap_flag 37 #define vm_exit_ept_violation 48 #define vm_exit_ept_misconfiguration 49 +#define vm_exit_invept 50 #define vm_exit_vmx_preemptiontimer_reachedzero 52 -#define vm_exit_xsetbv 55 +#define vm_exit_invvpid 53 +#define vm_exit_xsetbv 55 +#define vm_exit_invpcid 58 #define vm_exit_invalid_guest_state 0x80000021 diff --git a/dbvm/vmm/vmxemu.c b/dbvm/vmm/vmxemu.c index 5503d832..1f5afc5d 100644 --- a/dbvm/vmm/vmxemu.c +++ b/dbvm/vmm/vmxemu.c @@ -21,7 +21,7 @@ int emulatevmx=1; -vmxhoststate *dbvm_originalhoststate; +//todo: vmcs link pointer implementation void setHostState(vmxhoststate *hoststate) @@ -585,6 +585,174 @@ int handle_vmresume(pcpuinfo currentcpuinfo, VMRegisters *vmregisters UNUSED) return 0xce01; //launch with the last entrystate and do a resume } +int handle_invept(pcpuinfo currentcpuinfo, VMRegisters *vmregisters) +{ + int vmcsinvepterror=0; + int vmcsinvepterrorcode=0; + + sendstringf("handle_invept\n"); + if (currentcpuinfo->vmxdata.insideVMXRootMode==0) + return raiseInvalidOpcodeException(currentcpuinfo); + + instruction_info_vm ii; + ii.instructioninfo=vmread(vm_instruction_information); //e.g: 7361d130 for invept rdi,[rsi] + /* 0111 0 0110 1 1000 011 1010 0 010 0110 0 00 + * + * scaling=00 (0) + * reserved=0 (0) + * reg1=0110 (6) + * addresSize=010 (2) + * usesreg = 0 (0) + * undefined =1010 + * segmentreg: 011 (3) + * indexreg: 1000 (10) + * indexreginvalid: 1 + * basereg: 0110 (6) + * basereginvalid: 0 + * reg2: 0111 (7) + * + *reg1=rsi + *basereg=rsi + *reg2=rdi + */ + int invepttype=regToVal(ii.reg2, vmregisters); + QWORD inveptdataaddress=getDestinationAddressFromInstructionInfo(vmregisters); + + //read the pointerinfo + int error; + QWORD pagefault; + + sendstringf("invept: Type=%d data=%6\n", invepttype, inveptdataaddress); + + + PINVEPTDESCRIPTOR inveptdescriptor=mapVMmemory(currentcpuinfo, inveptdataaddress, 16, &error, &pagefault); + if (error==2) + return raisePagefault(currentcpuinfo, pagefault); + + + + + if (vmptrld(currentcpuinfo->vmxdata.guest_activeVMCS)) + { + sendstringf("Failure to load guest active vmcs state"); + VMfailInvalid(); + unmapVMmemory(inveptdescriptor, 16); + return 0; + } + + //do the invept instruction + + vmcsinvepterror=_invept2(invepttype, inveptdescriptor); + if (vmcsinvepterror==2) //error happened and it had an errorcode + vmcsinvepterrorcode=vmread(vm_errorcode); + + //back to the original state + vmptrld(currentcpuinfo->vmcs_regionPA); + + unmapVMmemory(inveptdescriptor, 16); + + vmwrite(vm_guest_rip,vmread(vm_guest_rip)+vmread(vm_exit_instructionlength)); + + if (vmcsinvepterror) + { + if (vmcsinvepterror==1) + VMfailInvalid(); + else + VMfailValid(currentcpuinfo, vmcsinvepterrorcode); + } + else + vmsucceed(); + + return 0; +} + +int handle_invvpid(pcpuinfo currentcpuinfo, VMRegisters *vmregisters) +{ + int vmcsinvvpiderror=0; + int vmcsinvvpiderrorcode=0; + + sendstringf("handle_invept\n"); + if (currentcpuinfo->vmxdata.insideVMXRootMode==0) + return raiseInvalidOpcodeException(currentcpuinfo); + + instruction_info_vm ii; + ii.instructioninfo=vmread(vm_instruction_information); //e.g: 7361d130 for invept rdi,[rsi] + /* 0111 0 0110 1 1000 011 1010 0 010 0110 0 00 + * + * scaling=00 (0) + * reserved=0 (0) + * reg1=0110 (6) + * addresSize=010 (2) + * usesreg = 0 (0) + * undefined =1010 + * segmentreg: 011 (3) + * indexreg: 1000 (10) + * indexreginvalid: 1 + * basereg: 0110 (6) + * basereginvalid: 0 + * reg2: 0111 (7) + * + *reg1=rsi + *basereg=rsi + *reg2=rdi + */ + int invvpidtype=regToVal(ii.reg2, vmregisters); + QWORD invvpiddataaddress=getDestinationAddressFromInstructionInfo(vmregisters); + + //read the pointerinfo + int error; + QWORD pagefault; + + sendstringf("invvpid: Type=%d data=%6\n", invvpidtype, invvpiddataaddress); + + + PINVVPIDDESCRIPTOR invvpiddescriptor=mapVMmemory(currentcpuinfo, invvpiddataaddress, 16, &error, &pagefault); + if (error==2) + return raisePagefault(currentcpuinfo, pagefault); + + + + + if (vmptrld(currentcpuinfo->vmxdata.guest_activeVMCS)) + { + sendstringf("Failure to load guest active vmcs state"); + VMfailInvalid(); + unmapVMmemory(invvpiddescriptor, 16); + return 0; + } + + //do the invept instruction + + vmcsinvvpiderror=_invvpid2(invvpidtype, invvpiddescriptor); + if (vmcsinvvpiderror==2) //error happened and it had an errorcode + vmcsinvvpiderrorcode=vmread(vm_errorcode); + + //back to the original state + vmptrld(currentcpuinfo->vmcs_regionPA); + + unmapVMmemory(invvpiddescriptor, 16); + + vmwrite(vm_guest_rip,vmread(vm_guest_rip)+vmread(vm_exit_instructionlength)); + + if (vmcsinvvpiderror) + { + sendstringf("invept error"); + if (vmcsinvvpiderrorcode==1) + VMfailInvalid(); + else + { + VMfailValid(currentcpuinfo, vmcsinvvpiderrorcode); + sendstringf("%d", vmcsinvvpiderrorcode); + } + + sendstring("\n"); + } + else + vmsucceed(); + + return 0; +} + int handle_vmread(pcpuinfo currentcpuinfo, VMRegisters *vmregisters) @@ -953,14 +1121,8 @@ int handle_vmptrld(pcpuinfo currentcpuinfo, VMRegisters *vmregisters) unmapVMmemory(mapped, 8); - if (dbvm_originalhoststate==NULL) //one time init - { - sendstring("generating dbvm_originalhoststate\n"); - dbvm_originalhoststate=malloc2(sizeof(vmxhoststate)); //no free ever - getHostState(dbvm_originalhoststate); - - sendstringf("CR3=%6\n", dbvm_originalhoststate->CR3); - } + if (currentcpuinfo->vmxdata.dbvmhoststate.FS_BASE==0) //only needs one time init + getHostState((vmxhoststate *)¤tcpuinfo->vmxdata.dbvmhoststate); vmwrite(vm_guest_rip,vmread(vm_guest_rip)+vmread(vm_exit_instructionlength)); @@ -987,8 +1149,9 @@ int handle_vmptrld(pcpuinfo currentcpuinfo, VMRegisters *vmregisters) else { sendstringf("restore: vmptrld failed: %d (error=%d)\n", vmread(vm_errorcode)); - VMfailInvalid(); - return 0; + //VMfailInvalid(); + //return 0; + //it's a load, the old state could have been deleted } } @@ -1032,8 +1195,9 @@ int handle_vmptrld(pcpuinfo currentcpuinfo, VMRegisters *vmregisters) //change the hoststate so it exits on dbvm sendstring("Editing the guest vmcs state so it exits on this host\n"); - setHostState(dbvm_originalhoststate); + setHostState((vmxhoststate *)¤tcpuinfo->vmxdata.dbvmhoststate); + //debug code, can go vmxhoststate debugstate; getHostState(&debugstate); @@ -1143,49 +1307,70 @@ int handle_vmxoff(pcpuinfo currentcpuinfo, VMRegisters *vmregisters UNUSED) + int handleIntelVMXInstruction(pcpuinfo currentcpuinfo, VMRegisters *vmregisters) { - + int r; sendstringf("handleIntelVMXInstruction. emulatevmx=%d\n", emulatevmx); if (emulatevmx==0) return raiseInvalidOpcodeException(currentcpuinfo); else { //try to handle it + int exit_reason=currentcpuinfo->guest_error?currentcpuinfo->guest_error:vmread(vm_exit_reason) & 0x7fffffff; currentcpuinfo->guest_error=0; currentcpuinfo->vmxdata.currenterrorcode=0; - switch (exit_reason) + + + try { - /* -19 VMCLEAR. Guest software attempted to execute VMCLEAR. -20 VMLAUNCH. Guest software attempted to execute VMLAUNCH. -21 VMPTRLD. Guest software attempted to execute VMPTRLD. -22 VMPTRST. Guest software attempted to execute VMPTRST. -23 VMREAD. Guest software attempted to execute VMREAD. -24 VMRESUME. Guest software attempted to execute VMRESUME. -25 VMWRITE. Guest software attempted to execute VMWRITE. -26 VMXOFF. Guest software attempted to execute VMXOFF. -27 VMXON. Guest software attempted to execute VMXON. - */ - case 19: return handle_vmclear(currentcpuinfo, vmregisters); - case 20: return handle_vmlaunch(currentcpuinfo, vmregisters); - case 0xce00: return handle_vmlaunchFail(currentcpuinfo); - case 21: return handle_vmptrld(currentcpuinfo, vmregisters); - case 22: return handle_vmptrst(currentcpuinfo, vmregisters); - case 23: return handle_vmread(currentcpuinfo, vmregisters); - case 24: return handle_vmresume(currentcpuinfo, vmregisters); - case 0xce01: return handle_vmresumeFail(currentcpuinfo); - case 25: return handle_vmwrite(currentcpuinfo, vmregisters); - case 26: return handle_vmxoff(currentcpuinfo, vmregisters); - case 27: return handle_vmxon(currentcpuinfo, vmregisters); - default: + + switch (exit_reason) { - sendstringf("vmxemu.c: Invalid exit_reason: %d\n", exit_reason); - return 1; + /* + 19 VMCLEAR. Guest software attempted to execute VMCLEAR. + 20 VMLAUNCH. Guest software attempted to execute VMLAUNCH. + 21 VMPTRLD. Guest software attempted to execute VMPTRLD. + 22 VMPTRST. Guest software attempted to execute VMPTRST. + 23 VMREAD. Guest software attempted to execute VMREAD. + 24 VMRESUME. Guest software attempted to execute VMRESUME. + 25 VMWRITE. Guest software attempted to execute VMWRITE. + 26 VMXOFF. Guest software attempted to execute VMXOFF. + 27 VMXON. Guest software attempted to execute VMXON. + */ + case 19: r=handle_vmclear(currentcpuinfo, vmregisters); break; + case 20: r=handle_vmlaunch(currentcpuinfo, vmregisters); break; + case 0xce00: r=handle_vmlaunchFail(currentcpuinfo); break; + case 21: r=handle_vmptrld(currentcpuinfo, vmregisters); break; + case 22: r=handle_vmptrst(currentcpuinfo, vmregisters); break; + case 23: r=handle_vmread(currentcpuinfo, vmregisters); break; + case 24: r=handle_vmresume(currentcpuinfo, vmregisters); break; + case 0xce01: r=handle_vmresumeFail(currentcpuinfo); break; + case 25: r=handle_vmwrite(currentcpuinfo, vmregisters); break; + case 26: r=handle_vmxoff(currentcpuinfo, vmregisters); break; + case 27: r=handle_vmxon(currentcpuinfo, vmregisters); break; + case vm_exit_invept: r=handle_invept(currentcpuinfo, vmregisters); break; + case vm_exit_invvpid: r=handle_invvpid(currentcpuinfo, vmregisters); break; + default: + { + sendstringf("vmxemu.c: Invalid exit_reason: %d\n", exit_reason); + return 1; + } } } + except + { + int err=lastexception; + + sendstringf("Something shitty happened when emulating VMX (%6: %d)\n", ExceptionRIP, err); + + while (1); + } + tryend + + return r; } } diff --git a/dbvm/vmm/vmxemu.h b/dbvm/vmm/vmxemu.h index 1463bcd9..6b74c0f1 100644 --- a/dbvm/vmm/vmxemu.h +++ b/dbvm/vmm/vmxemu.h @@ -17,9 +17,9 @@ typedef struct _instruction_info_vm struct { unsigned scaling :2; //0-1 scaling unsigned reserved1 :1; //2 - unsigned reg1 :4; //3-6 + unsigned reg1 :4; //3-6 //invalid for INVEPT, INVPCID, and INVVPID unsigned addressSize:3; //7-9 - unsigned usesreg :1; //10 + unsigned usesreg :1; //10 //0 for INVEPT, INVPCID, and INVVPID unsigned undefined :4; //11-14 unsigned segmentReg :3; //15-17 unsigned indexReg :4; //18-21