/* * ultimap.c * * Created on: May 28, 2011 * Author: erich */ #include "common.h" #include "vmreadwrite.h" #include "ultimap.h" #include "msrnames.h" #include "vmmhelper.h" #include "main.h" #ifdef ULTIMAPDEBUG void ultimap_debugoutput(pcpuinfo currentcpuinfo, PULTIMAPDEBUGINFO UltimapDebugInfo) { // int error; //UINT64 pagefaultaddress; //if (!error) { UltimapDebugInfo->Active=currentcpuinfo->Ultimap.Active; UltimapDebugInfo->CR3=currentcpuinfo->Ultimap.CR3; UltimapDebugInfo->DEBUGCTL=currentcpuinfo->Ultimap.DEBUGCTL; UltimapDebugInfo->DS_AREA=currentcpuinfo->Ultimap.DS_AREA; UltimapDebugInfo->OriginalDebugCTL=currentcpuinfo->Ultimap.OriginalDebugCTL; UltimapDebugInfo->OriginalDS_AREA=currentcpuinfo->Ultimap.OriginalDS_AREA; UltimapDebugInfo->CR3_switchcount=currentcpuinfo->Ultimap.CR3_switchcount; UltimapDebugInfo->CR3_switchcount2=currentcpuinfo->Ultimap.CR3_switchcount2; UltimapDebugInfo->LastOldCR3=currentcpuinfo->Ultimap.LastOldCR3; UltimapDebugInfo->LastNewCR3=currentcpuinfo->Ultimap.LastNewCR3; UltimapDebugInfo->CpuNr=currentcpuinfo->cpunr; } } #endif void ultimap_pause(pcpuinfo currentcpuinfo) { ultimap_disable(currentcpuinfo); } void ultimap_resume(pcpuinfo currentcpuinfo) { currentcpuinfo->Ultimap.Active=1; } void ultimap_disable(pcpuinfo currentcpuinfo) { if (currentcpuinfo->Ultimap.Active) { vmwrite(vm_guest_IA32_DEBUGCTL, currentcpuinfo->Ultimap.OriginalDebugCTL); writeMSR(IA32_DS_AREA, currentcpuinfo->Ultimap.OriginalDS_AREA); currentcpuinfo->Ultimap.Active=0; } } void ultimap_setup(pcpuinfo currentcpuinfo, QWORD CR3, QWORD DEBUGCTL, QWORD DS_AREA) { currentcpuinfo->Ultimap.CR3=CR3; currentcpuinfo->Ultimap.DEBUGCTL=DEBUGCTL; currentcpuinfo->Ultimap.DS_AREA=DS_AREA; currentcpuinfo->Ultimap.Active=1; currentcpuinfo->Ultimap.OriginalDebugCTL=vmread(vm_guest_IA32_DEBUGCTL); currentcpuinfo->Ultimap.OriginalDS_AREA=readMSR(IA32_DS_AREA); } void ultimap_handleCR3Change(pcpuinfo currentcpuinfo, QWORD oldcr3, QWORD newcr3) /* * Called when cr3 changes and ultimap is active */ { currentcpuinfo->Ultimap.CR3_switchcount++; if (oldcr3 != newcr3) { if (currentcpuinfo->Ultimap.CR3==newcr3) //if the new cr3 is the process to watch { currentcpuinfo->Ultimap.CR3_switchcount2++; currentcpuinfo->Ultimap.LastOldCR3=oldcr3; currentcpuinfo->Ultimap.LastNewCR3=newcr3; //set the MSR values currentcpuinfo->Ultimap.OriginalDebugCTL=vmread(vm_guest_IA32_DEBUGCTL); currentcpuinfo->Ultimap.OriginalDS_AREA=readMSR(IA32_DS_AREA); vmwrite(vm_guest_IA32_DEBUGCTL, currentcpuinfo->Ultimap.DEBUGCTL); writeMSR(IA32_DS_AREA, currentcpuinfo->Ultimap.DS_AREA); //and register a vm-exit event on MSR read/write for DEBUGCTL and DS_AREA MSRBitmap[IA32_DS_AREA/8]|=1 << (IA32_DS_AREA % 8); MSRBitmap[1024+IA32_DS_AREA/8]|=1 << (IA32_DS_AREA % 8); MSRBitmap[IA32_DEBUGCTL_MSR/8]|=1 << (IA32_DEBUGCTL_MSR % 8); MSRBitmap[1024+IA32_DEBUGCTL_MSR/8]|=1 << (IA32_DEBUGCTL_MSR % 8); } else if (currentcpuinfo->Ultimap.CR3==currentcpuinfo->guestCR3) //if the old cr3 is the process to watch and is switched out to a different one { //unset the MSR values vmwrite(vm_guest_IA32_DEBUGCTL, currentcpuinfo->Ultimap.OriginalDebugCTL); writeMSR(IA32_DS_AREA, currentcpuinfo->Ultimap.OriginalDS_AREA); //and unregister the vm-exit event on MSR read/write for DEBUGCTL and DS_AREA MSRBitmap[IA32_DS_AREA/8]&=~(1 << (IA32_DS_AREA % 8)); MSRBitmap[1024+IA32_DS_AREA/8]&=~(1 << (IA32_DS_AREA % 8)); MSRBitmap[IA32_DEBUGCTL_MSR/8]&=~(1 << (IA32_DEBUGCTL_MSR % 8)); MSRBitmap[1024+IA32_DEBUGCTL_MSR/8]&=~(1 << (IA32_DEBUGCTL_MSR % 8)); } } } void ultimap_handleDB(pcpuinfo currentcpuinfo) /* * Called when an int1 happens */ { currentcpuinfo->Ultimap.OriginalDebugCTL&=~1; //disable the LBR flag on bp if (currentcpuinfo->guestCR3 != currentcpuinfo->Ultimap.CR3) vmwrite(vm_guest_IA32_DEBUGCTL, vmread(vm_guest_IA32_DEBUGCTL) & ~1); else vmwrite(vm_guest_IA32_DEBUGCTL, currentcpuinfo->Ultimap.DEBUGCTL); //just write it again } void ultimap_handleMSRWrite(pcpuinfo currentcpuinfo, DWORD msr, QWORD value) { switch (msr) { case IA32_DEBUGCTL_MSR: { currentcpuinfo->Ultimap.OriginalDebugCTL=value; if ((currentcpuinfo->Ultimap.Active) && (currentcpuinfo->Ultimap.CR3==currentcpuinfo->guestCR3)) vmwrite(vm_guest_IA32_DEBUGCTL, currentcpuinfo->Ultimap.DEBUGCTL); else vmwrite(vm_guest_IA32_DEBUGCTL, value); break; } case IA32_DS_AREA: { currentcpuinfo->Ultimap.OriginalDS_AREA=value; if ((currentcpuinfo->Ultimap.Active) && (currentcpuinfo->Ultimap.CR3==currentcpuinfo->guestCR3)) writeMSR(IA32_DS_AREA, currentcpuinfo->Ultimap.DS_AREA); else writeMSR(IA32_DS_AREA, value); break; } } } QWORD ultimap_handleMSRRead(pcpuinfo currentcpuinfo, DWORD msr) { switch (msr) { case IA32_DEBUGCTL_MSR: { if ((currentcpuinfo->Ultimap.Active) && (currentcpuinfo->Ultimap.CR3==currentcpuinfo->guestCR3)) return currentcpuinfo->Ultimap.OriginalDebugCTL; else return vmread(vm_guest_IA32_DEBUGCTL); } case IA32_DS_AREA: { if ((currentcpuinfo->Ultimap.Active) && (currentcpuinfo->Ultimap.CR3==currentcpuinfo->guestCR3)) return currentcpuinfo->Ultimap.OriginalDS_AREA; else return readMSR(IA32_DS_AREA); } } }