fix VM inside VM inside VM
This commit is contained in:
parent
735da7d8dd
commit
c46cba8d3a
@ -1,6 +1,6 @@
|
|||||||
#SERIALPORT is the port to communicate with the debugger, usually 0x3f8, on db's system it's 0xef00
|
#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=0 #release/no serialport build
|
||||||
#SERIALPORT=0x3f8 #bochs (gigabyte test system)
|
SERIALPORT=0x3f8 #bochs (gigabyte test system)
|
||||||
#SERIALPORT=0xbf00 #intel
|
#SERIALPORT=0xbf00 #intel
|
||||||
#SERIALPORT=0xec00 #amd
|
#SERIALPORT=0xec00 #amd
|
||||||
#SERIALPORT=0xd010 #16 core test system
|
#SERIALPORT=0xd010 #16 core test system
|
||||||
|
@ -18,6 +18,7 @@ typedef struct _criticalSection
|
|||||||
int locked;
|
int locked;
|
||||||
int apicid;
|
int apicid;
|
||||||
int lockcount;
|
int lockcount;
|
||||||
|
|
||||||
} criticalSection, *PcriticalSection;
|
} criticalSection, *PcriticalSection;
|
||||||
|
|
||||||
extern int debugzeromem;
|
extern int debugzeromem;
|
||||||
|
@ -1026,6 +1026,11 @@ void mrewEndWrite(Pmultireadexclusivewritesychronizer MREW)
|
|||||||
|
|
||||||
void csEnter(PcriticalSection CS)
|
void csEnter(PcriticalSection CS)
|
||||||
{
|
{
|
||||||
|
#ifdef DEBUG
|
||||||
|
if (CS->ignorelock)
|
||||||
|
return;
|
||||||
|
#endif
|
||||||
|
|
||||||
int apicid=getAPICID()+1; //+1 so it never returns 0
|
int apicid=getAPICID()+1; //+1 so it never returns 0
|
||||||
|
|
||||||
if ((CS->locked) && (CS->apicid==apicid))
|
if ((CS->locked) && (CS->apicid==apicid))
|
||||||
@ -1046,6 +1051,11 @@ void csEnter(PcriticalSection CS)
|
|||||||
|
|
||||||
void csLeave(PcriticalSection CS)
|
void csLeave(PcriticalSection CS)
|
||||||
{
|
{
|
||||||
|
#ifdef DEBUG
|
||||||
|
if (CS->ignorelock)
|
||||||
|
return;
|
||||||
|
#endif
|
||||||
|
|
||||||
int apicid=getAPICID()+1; //+1 so it never returns 0
|
int apicid=getAPICID()+1; //+1 so it never returns 0
|
||||||
|
|
||||||
|
|
||||||
|
@ -12,11 +12,13 @@
|
|||||||
#if (defined SERIALPORT) && (SERIALPORT != 0)
|
#if (defined SERIALPORT) && (SERIALPORT != 0)
|
||||||
#define DEBUG //comment for release
|
#define DEBUG //comment for release
|
||||||
#define DEBUGINTHANDLER //comment for release
|
#define DEBUGINTHANDLER //comment for release
|
||||||
|
#define CHECKAPICID
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if (DISPLAYDEBUG==1)
|
#if (DISPLAYDEBUG==1)
|
||||||
#define DEBUG
|
#define DEBUG
|
||||||
#define DEBUGINTHANDLER
|
#define DEBUGINTHANDLER
|
||||||
|
#define CHECKAPICID
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#define ULTIMAPDEBUG //for debugging ultimap (I seem to have misplaced my serial port...)
|
#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 locked;
|
||||||
volatile int apicid;
|
volatile int apicid;
|
||||||
int lockcount;
|
int lockcount;
|
||||||
|
#ifdef DEBUG
|
||||||
|
int ignorelock;
|
||||||
|
#endif
|
||||||
} criticalSection, *PcriticalSection;
|
} criticalSection, *PcriticalSection;
|
||||||
|
|
||||||
|
|
||||||
|
@ -18,6 +18,7 @@
|
|||||||
#include "vmcall.h"
|
#include "vmcall.h"
|
||||||
#include "maps.h"
|
#include "maps.h"
|
||||||
#include "list.h"
|
#include "list.h"
|
||||||
|
#include "vmeventhandler.h"
|
||||||
|
|
||||||
QWORD EPTMapPhysicalMemory(pcpuinfo currentcpuinfo, QWORD physicalAddress, int forcesmallpage);
|
QWORD EPTMapPhysicalMemory(pcpuinfo currentcpuinfo, QWORD physicalAddress, int forcesmallpage);
|
||||||
|
|
||||||
|
@ -117,6 +117,11 @@ int cinthandler(unsigned long long *stack, int intnr) //todo: move to it's own s
|
|||||||
DWORD thisAPICID;
|
DWORD thisAPICID;
|
||||||
int cpunr=0;
|
int cpunr=0;
|
||||||
|
|
||||||
|
#ifdef DEBUG
|
||||||
|
sendstringCS.ignorelock=1;
|
||||||
|
sendstringfCS.ignorelock=1;
|
||||||
|
#endif
|
||||||
|
|
||||||
if (readMSRSafe(IA32_FS_BASE_MSR)==0)
|
if (readMSRSafe(IA32_FS_BASE_MSR)==0)
|
||||||
{
|
{
|
||||||
sendstringf("Invalid FS base during exception\n");
|
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();
|
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.lockcount=0;
|
||||||
sendstringCS.locked=0;
|
sendstringCS.locked=0;
|
||||||
sendstringfCS.lockcount=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("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("intnr=%d\n\r",intnr);
|
||||||
sendstringf("rsp=%x\n\r",getRSP());
|
sendstringf("rsp=%x\n\r",getRSP());
|
||||||
sendstringf("cr2=%6\n\r",getCR2());
|
sendstringf("cr2=%6\n\r",getCR2());
|
||||||
|
@ -71,7 +71,9 @@ extern ULONG setCR8(UINT64 newcr8);
|
|||||||
extern void _invlpg(UINT64 address);
|
extern void _invlpg(UINT64 address);
|
||||||
extern void _invpcid(int type, PINVPCIDDESCRIPTOR datablock);
|
extern void _invpcid(int type, PINVPCIDDESCRIPTOR datablock);
|
||||||
extern void _invept(int type, PINVEPTDESCRIPTOR datablock);
|
extern void _invept(int type, PINVEPTDESCRIPTOR datablock);
|
||||||
|
extern int _invept2(int type, PINVEPTDESCRIPTOR datablock);
|
||||||
extern void _invvpid(int type, PINVVPIDDESCRIPTOR datablock);
|
extern void _invvpid(int type, PINVVPIDDESCRIPTOR datablock);
|
||||||
|
extern int _invvpid2(int type, PINVVPIDDESCRIPTOR datablock);
|
||||||
extern void _wbinvd(void);
|
extern void _wbinvd(void);
|
||||||
extern void _invd(void);
|
extern void _invd(void);
|
||||||
|
|
||||||
|
@ -4198,7 +4198,9 @@ int handleVMEvent(pcpuinfo currentcpuinfo, VMRegisters *vmregisters, FXSAVE64 *f
|
|||||||
case 50:
|
case 50:
|
||||||
{
|
{
|
||||||
sendstring("INVEPT\n\r");
|
sendstring("INVEPT\n\r");
|
||||||
return 1;
|
return handleIntelVMXInstruction(currentcpuinfo, vmregisters);
|
||||||
|
|
||||||
|
//return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
case 51:
|
case 51:
|
||||||
@ -4239,15 +4241,23 @@ int handleVMEvent(pcpuinfo currentcpuinfo, VMRegisters *vmregisters, FXSAVE64 *f
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
case 53:
|
case vm_exit_invvpid:
|
||||||
{
|
{
|
||||||
sendstring("INVVPID\n\r");
|
sendstring("INVVPID\n\r");
|
||||||
|
return handleIntelVMXInstruction(currentcpuinfo, vmregisters);
|
||||||
|
|
||||||
#ifdef DEBUG
|
#ifdef DEBUG
|
||||||
while (1);
|
while (1);
|
||||||
#endif
|
#endif
|
||||||
return 1;
|
// return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
case vm_exit_invpcid:
|
||||||
|
{
|
||||||
|
while(1);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
case 54:
|
case 54:
|
||||||
{
|
{
|
||||||
sendstring("WBINVD\n\r");
|
sendstring("WBINVD\n\r");
|
||||||
|
@ -1481,6 +1481,27 @@ invept rdi,[rsi]
|
|||||||
ret
|
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
|
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)
|
;_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]
|
invvpid rdi,[rsi]
|
||||||
ret
|
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
|
global _invlpg
|
||||||
|
@ -118,7 +118,7 @@ char * getVMExitReassonString(void)
|
|||||||
{
|
{
|
||||||
case 0: return "Exception or NMI";
|
case 0: return "Exception or NMI";
|
||||||
case 1: return "External interrupt";
|
case 1: return "External interrupt";
|
||||||
case 2: return "Tripple fault";
|
case 2: return "Triple fault";
|
||||||
case 3: return "INIT Signal";
|
case 3: return "INIT Signal";
|
||||||
case 4: return "Start-up IPI (SIPI)";
|
case 4: return "Start-up IPI (SIPI)";
|
||||||
case 5: return "SMI interrupt";
|
case 5: return "SMI interrupt";
|
||||||
@ -132,8 +132,10 @@ char * getVMExitReassonString(void)
|
|||||||
case 17: return "VMREAD";
|
case 17: return "VMREAD";
|
||||||
case 18: return "VMCALL";
|
case 18: return "VMCALL";
|
||||||
case 19: return "VMCLEAR";
|
case 19: return "VMCLEAR";
|
||||||
|
case 20: return "VMLAUNCH";
|
||||||
case 21: return "VMPTRLD";
|
case 21: return "VMPTRLD";
|
||||||
case 23: return "VMREAD";
|
case 23: return "VMREAD";
|
||||||
|
case 24: return "VMRESUME";
|
||||||
case 25: return "VMWRITE";
|
case 25: return "VMWRITE";
|
||||||
case 27: return "VMXON"; //or: omg it's one bee
|
case 27: return "VMXON"; //or: omg it's one bee
|
||||||
case 28: return "Controlregister access";
|
case 28: return "Controlregister access";
|
||||||
@ -145,8 +147,10 @@ char * getVMExitReassonString(void)
|
|||||||
case 37: return "Monitor trap flag";
|
case 37: return "Monitor trap flag";
|
||||||
case vm_exit_ept_violation: return "EPT Violation";
|
case vm_exit_ept_violation: return "EPT Violation";
|
||||||
case vm_exit_ept_misconfiguration: return "EPT Misconfiguration";
|
case vm_exit_ept_misconfiguration: return "EPT Misconfiguration";
|
||||||
|
case 50: return "INVEPT";
|
||||||
case 51: return "RDTSCP";
|
case 51: return "RDTSCP";
|
||||||
case 52: return "Preemption timer";
|
case 52: return "Preemption timer";
|
||||||
|
case 53: return "INVVPID";
|
||||||
case 55: return "XSETBV";
|
case 55: return "XSETBV";
|
||||||
default :return "NYI";
|
default :return "NYI";
|
||||||
}
|
}
|
||||||
@ -694,6 +698,9 @@ int vmexit_amd(pcpuinfo currentcpuinfo, UINT64 *registers, void *fxsave UNUSED)
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int lastexits[10];
|
||||||
|
int lastexitsindex=0;
|
||||||
|
|
||||||
#ifdef DEBUG
|
#ifdef DEBUG
|
||||||
|
|
||||||
QWORD lastbeat=0;
|
QWORD lastbeat=0;
|
||||||
@ -752,8 +759,7 @@ int vmexit(pcpuinfo currentcpuinfo, UINT64 *registers, void *fxsave)
|
|||||||
int vmexit2(pcpuinfo currentcpuinfo, UINT64 *registers, void *fxsave)
|
int vmexit2(pcpuinfo currentcpuinfo, UINT64 *registers, void *fxsave)
|
||||||
#else
|
#else
|
||||||
|
|
||||||
int lastexits[10];
|
|
||||||
int lastexitsindex=0;
|
|
||||||
|
|
||||||
int vmexit(pcpuinfo currentcpuinfo, UINT64 *registers, void *fxsave)
|
int vmexit(pcpuinfo currentcpuinfo, UINT64 *registers, void *fxsave)
|
||||||
#endif
|
#endif
|
||||||
@ -768,6 +774,25 @@ int vmexit(pcpuinfo currentcpuinfo, UINT64 *registers, void *fxsave)
|
|||||||
lastexitsindex++;
|
lastexitsindex++;
|
||||||
lastexitsindex=lastexitsindex % 10;
|
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)
|
if (dbvm_plugin_exit_pre)
|
||||||
{
|
{
|
||||||
@ -1050,9 +1075,13 @@ int vmexit(pcpuinfo currentcpuinfo, UINT64 *registers, void *fxsave)
|
|||||||
// skip=0;
|
// skip=0;
|
||||||
// break;
|
// break;
|
||||||
//
|
//
|
||||||
|
case vm_exit_vmlaunch:
|
||||||
|
verbosity=10;
|
||||||
|
skip=0;
|
||||||
|
break;
|
||||||
|
|
||||||
case vm_exit_vmresume:
|
case vm_exit_vmresume:
|
||||||
//skip=1;
|
skip=currentcpuinfo->cpunr!=0;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case vm_exit_vmcall:
|
case vm_exit_vmcall:
|
||||||
@ -1062,7 +1091,11 @@ int vmexit(pcpuinfo currentcpuinfo, UINT64 *registers, void *fxsave)
|
|||||||
break;
|
break;
|
||||||
|
|
||||||
case vm_exit_vmread:
|
case vm_exit_vmread:
|
||||||
//skip=1;
|
skip=1;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case vm_exit_vmwrite:
|
||||||
|
skip=1;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case vm_exit_vmptrld:
|
case vm_exit_vmptrld:
|
||||||
@ -1070,10 +1103,15 @@ int vmexit(pcpuinfo currentcpuinfo, UINT64 *registers, void *fxsave)
|
|||||||
|
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case vm_exit_vmwrite:
|
case vm_exit_invept:
|
||||||
//skip=1;
|
skip=1;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
case vm_exit_invvpid:
|
||||||
|
skip=1;
|
||||||
|
break;
|
||||||
|
|
||||||
|
|
||||||
case vm_exit_cpuid:
|
case vm_exit_cpuid:
|
||||||
skip=2; //REALLY verbose
|
skip=2; //REALLY verbose
|
||||||
break;
|
break;
|
||||||
@ -1177,6 +1215,7 @@ int vmexit(pcpuinfo currentcpuinfo, UINT64 *registers, void *fxsave)
|
|||||||
VMRegisters* r=(VMRegisters*)registers;
|
VMRegisters* r=(VMRegisters*)registers;
|
||||||
switch (r->rcx)
|
switch (r->rcx)
|
||||||
{
|
{
|
||||||
|
case 0x10:
|
||||||
case 0x176:
|
case 0x176:
|
||||||
case 0x175:
|
case 0x175:
|
||||||
case 0x174:
|
case 0x174:
|
||||||
@ -1195,6 +1234,7 @@ int vmexit(pcpuinfo currentcpuinfo, UINT64 *registers, void *fxsave)
|
|||||||
VMRegisters* r=(VMRegisters*)registers;
|
VMRegisters* r=(VMRegisters*)registers;
|
||||||
switch (r->rcx)
|
switch (r->rcx)
|
||||||
{
|
{
|
||||||
|
case 0x10:
|
||||||
case 0x3a:
|
case 0x3a:
|
||||||
case 0xc0000080:
|
case 0xc0000080:
|
||||||
skip=1;
|
skip=1;
|
||||||
@ -1209,6 +1249,10 @@ int vmexit(pcpuinfo currentcpuinfo, UINT64 *registers, void *fxsave)
|
|||||||
skip=1;
|
skip=1;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
case vm_exit_rdtsc:
|
||||||
|
skip=1;
|
||||||
|
break;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
case vm_exit_invalid_guest_state:
|
case vm_exit_invalid_guest_state:
|
||||||
|
@ -573,6 +573,7 @@ typedef volatile struct tcpuinfo
|
|||||||
|
|
||||||
int currenterrorcode; //if not 0, return this errorcode on vmread
|
int currenterrorcode; //if not 0, return this errorcode on vmread
|
||||||
vmxhoststate originalhoststate;
|
vmxhoststate originalhoststate;
|
||||||
|
vmxhoststate dbvmhoststate;
|
||||||
int runningvmx; //1 if the previous call was a vmlaunch/vmresume and no vmexit happened yet
|
int runningvmx; //1 if the previous call was a vmlaunch/vmresume and no vmexit happened yet
|
||||||
|
|
||||||
} vmxdata;
|
} vmxdata;
|
||||||
|
@ -79,7 +79,9 @@
|
|||||||
#define vm_exit_taskswitch 9
|
#define vm_exit_taskswitch 9
|
||||||
#define vm_exit_cpuid 10
|
#define vm_exit_cpuid 10
|
||||||
#define vm_exit_invlpg 14
|
#define vm_exit_invlpg 14
|
||||||
|
#define vm_exit_rdtsc 16
|
||||||
#define vm_exit_vmcall 18
|
#define vm_exit_vmcall 18
|
||||||
|
#define vm_exit_vmlaunch 20
|
||||||
#define vm_exit_vmptrld 21
|
#define vm_exit_vmptrld 21
|
||||||
#define vm_exit_vmread 23
|
#define vm_exit_vmread 23
|
||||||
#define vm_exit_vmresume 24
|
#define vm_exit_vmresume 24
|
||||||
@ -91,8 +93,11 @@
|
|||||||
#define vm_exit_monitor_trap_flag 37
|
#define vm_exit_monitor_trap_flag 37
|
||||||
#define vm_exit_ept_violation 48
|
#define vm_exit_ept_violation 48
|
||||||
#define vm_exit_ept_misconfiguration 49
|
#define vm_exit_ept_misconfiguration 49
|
||||||
|
#define vm_exit_invept 50
|
||||||
#define vm_exit_vmx_preemptiontimer_reachedzero 52
|
#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
|
#define vm_exit_invalid_guest_state 0x80000021
|
||||||
|
|
||||||
|
|
||||||
|
@ -21,7 +21,7 @@
|
|||||||
|
|
||||||
int emulatevmx=1;
|
int emulatevmx=1;
|
||||||
|
|
||||||
vmxhoststate *dbvm_originalhoststate;
|
//todo: vmcs link pointer implementation
|
||||||
|
|
||||||
|
|
||||||
void setHostState(vmxhoststate *hoststate)
|
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
|
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)
|
int handle_vmread(pcpuinfo currentcpuinfo, VMRegisters *vmregisters)
|
||||||
@ -953,14 +1121,8 @@ int handle_vmptrld(pcpuinfo currentcpuinfo, VMRegisters *vmregisters)
|
|||||||
unmapVMmemory(mapped, 8);
|
unmapVMmemory(mapped, 8);
|
||||||
|
|
||||||
|
|
||||||
if (dbvm_originalhoststate==NULL) //one time init
|
if (currentcpuinfo->vmxdata.dbvmhoststate.FS_BASE==0) //only needs one time init
|
||||||
{
|
getHostState((vmxhoststate *)¤tcpuinfo->vmxdata.dbvmhoststate);
|
||||||
sendstring("generating dbvm_originalhoststate\n");
|
|
||||||
dbvm_originalhoststate=malloc2(sizeof(vmxhoststate)); //no free ever
|
|
||||||
getHostState(dbvm_originalhoststate);
|
|
||||||
|
|
||||||
sendstringf("CR3=%6\n", dbvm_originalhoststate->CR3);
|
|
||||||
}
|
|
||||||
|
|
||||||
vmwrite(vm_guest_rip,vmread(vm_guest_rip)+vmread(vm_exit_instructionlength));
|
vmwrite(vm_guest_rip,vmread(vm_guest_rip)+vmread(vm_exit_instructionlength));
|
||||||
|
|
||||||
@ -987,8 +1149,9 @@ int handle_vmptrld(pcpuinfo currentcpuinfo, VMRegisters *vmregisters)
|
|||||||
else
|
else
|
||||||
{
|
{
|
||||||
sendstringf("restore: vmptrld failed: %d (error=%d)\n", vmread(vm_errorcode));
|
sendstringf("restore: vmptrld failed: %d (error=%d)\n", vmread(vm_errorcode));
|
||||||
VMfailInvalid();
|
//VMfailInvalid();
|
||||||
return 0;
|
//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
|
//change the hoststate so it exits on dbvm
|
||||||
sendstring("Editing the guest vmcs state so it exits on this host\n");
|
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;
|
vmxhoststate debugstate;
|
||||||
getHostState(&debugstate);
|
getHostState(&debugstate);
|
||||||
|
|
||||||
@ -1143,49 +1307,70 @@ int handle_vmxoff(pcpuinfo currentcpuinfo, VMRegisters *vmregisters UNUSED)
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
int handleIntelVMXInstruction(pcpuinfo currentcpuinfo, VMRegisters *vmregisters)
|
int handleIntelVMXInstruction(pcpuinfo currentcpuinfo, VMRegisters *vmregisters)
|
||||||
{
|
{
|
||||||
|
int r;
|
||||||
sendstringf("handleIntelVMXInstruction. emulatevmx=%d\n", emulatevmx);
|
sendstringf("handleIntelVMXInstruction. emulatevmx=%d\n", emulatevmx);
|
||||||
if (emulatevmx==0)
|
if (emulatevmx==0)
|
||||||
return raiseInvalidOpcodeException(currentcpuinfo);
|
return raiseInvalidOpcodeException(currentcpuinfo);
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
//try to handle it
|
//try to handle it
|
||||||
|
|
||||||
int exit_reason=currentcpuinfo->guest_error?currentcpuinfo->guest_error:vmread(vm_exit_reason) & 0x7fffffff;
|
int exit_reason=currentcpuinfo->guest_error?currentcpuinfo->guest_error:vmread(vm_exit_reason) & 0x7fffffff;
|
||||||
currentcpuinfo->guest_error=0;
|
currentcpuinfo->guest_error=0;
|
||||||
currentcpuinfo->vmxdata.currenterrorcode=0;
|
currentcpuinfo->vmxdata.currenterrorcode=0;
|
||||||
|
|
||||||
switch (exit_reason)
|
|
||||||
|
|
||||||
|
try
|
||||||
{
|
{
|
||||||
/*
|
|
||||||
19 VMCLEAR. Guest software attempted to execute VMCLEAR.
|
switch (exit_reason)
|
||||||
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:
|
|
||||||
{
|
{
|
||||||
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;
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -17,9 +17,9 @@ typedef struct _instruction_info_vm
|
|||||||
struct {
|
struct {
|
||||||
unsigned scaling :2; //0-1 scaling
|
unsigned scaling :2; //0-1 scaling
|
||||||
unsigned reserved1 :1; //2
|
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 addressSize:3; //7-9
|
||||||
unsigned usesreg :1; //10
|
unsigned usesreg :1; //10 //0 for INVEPT, INVPCID, and INVVPID
|
||||||
unsigned undefined :4; //11-14
|
unsigned undefined :4; //11-14
|
||||||
unsigned segmentReg :3; //15-17
|
unsigned segmentReg :3; //15-17
|
||||||
unsigned indexReg :4; //18-21
|
unsigned indexReg :4; //18-21
|
||||||
|
Loading…
Reference in New Issue
Block a user