Example #1
0
PPTE_PAE mapAddressAtPML4(QWORD address)
{
  static criticalSection CS;
  int index;

  csEnter(&CS);

  sendstringf("mapAddressAtPML4(%6)\n", address);

  index=getFreePML4Index();

  if (index==-1)
  {
    sendstring("No PML4 entries free\n");
    csLeave(&CS);
    return NULL;
  }

  *(QWORD*)(&pml4table[index])=address;
  pml4table[index].P=1;
  pml4table[index].RW=1;
  asm volatile ("": : :"memory");
  csLeave(&CS);


  QWORD result=((QWORD)index << 39);
  if (result>=0x800000000000ULL) //sign extend
    result|=0xffff000000000000ULL;

  _invlpg(result);

  _wbinvd();

  return (PPTE_PAE)result;
}
int handleInvalidEntryState(pcpuinfo currentcpuinfo,VMRegisters *vmregisters)
{

  sendstring("Handling invalid entry state\n\r");
  //fix interruptability state (common bug when emulating and fixing it won't cause a problem)

  fixInterruptabilityState();



  if (ISREALMODE(currentcpuinfo))
  {
    int result;
    sendstring("Inside realmode. Trying to emulate instructions\n\r");
    result=emulateRealMode(currentcpuinfo, vmregisters)==0;

    sendstringf("emulateRealMode(...) returned %d\n\r",result);

    if (result==0)
    {
      sendstring("emulation was handled properly\n");
      return 0; //handled at least one instruction
    }
    else
      sendstring("emulation was a total failure. Not one instruction got emulated. Trying to fix the state");




    //emulateRealMode failed
    if (ISREALMODE(currentcpuinfo)) //still realmode ? (most likely, but possible it isn't anymore once enough has been emulated)
    {
      Access_Rights reg_rmaccessrights,reg_traccessrights;
      RFLAGS guestrflags;
      DWORD gdtbase, idtbase;
      guestrflags.value=0;

      gdtbase=VirtualToPhysical(getGDTbase());
      idtbase=VirtualToPhysical((UINT64)idttable32);

      sendstring("Still in realmode, enabling VMx86 mode if not already in it and fixing possible other bugs\n\r");
      //set taskregister to realmode tr
      //set GDT and IDT to my own (so a 32-bit interrupt is possible)
      vmwrite(vm_guest_gdtr_base, gdtbase);
      vmwrite(vm_guest_gdt_limit, getGDTsize());
      vmwrite(vm_guest_idtr_base, idtbase);
      vmwrite(vm_guest_idt_limit, 256*8);
      setupTSS8086();
      vmwrite(vm_guest_tr_base,(UINT64)VirtualToPhysical((UINT64)VirtualMachineTSS_V8086)); //tr base
      vmwrite(vm_guest_tr_limit,(ULONG)sizeof(TSS)+32+8192+1); //tr limit
      vmwrite(vm_guest_tr,64); //the tss o

#ifdef DEBUG
      UINT64 idtbase2, gdtbase2;
      gdtbase2=vmread(vm_guest_gdtr_base);
      idtbase2=vmread(vm_guest_idtr_base);

      sendstringf("Set vm_guest_gdtr_base to %6 while I wanted to set it to %6\n\r",gdtbase2, gdtbase);
      sendstringf("Set vm_guest_idtr_base to %6 while I wanted to set it to %6\n\r",idtbase2, idtbase);
#endif


      reg_rmaccessrights.AccessRights=0;
      reg_rmaccessrights.Segment_type=3;
      reg_rmaccessrights.S=1;
      reg_rmaccessrights.DPL=3;
      reg_rmaccessrights.P=1;
      reg_rmaccessrights.G=0;
      reg_rmaccessrights.D_B=0;

      reg_traccessrights.AccessRights=0;
      reg_traccessrights.Segment_type=11; //11=32-bit 3=16-bit
      reg_traccessrights.S=0;
      reg_traccessrights.DPL=0;
      reg_traccessrights.P=1;
      reg_traccessrights.G=0;
      reg_traccessrights.D_B=1;
      vmwrite(vm_guest_es_access_rights,(ULONG)reg_rmaccessrights.AccessRights); //es access rights
      vmwrite(vm_guest_cs_access_rights,(ULONG)reg_rmaccessrights.AccessRights); //cs access rights
      vmwrite(vm_guest_ss_access_rights,(ULONG)reg_rmaccessrights.AccessRights); //ss access rights
      vmwrite(vm_guest_ds_access_rights,(ULONG)reg_rmaccessrights.AccessRights); //ds access rights
      vmwrite(vm_guest_fs_access_rights,(ULONG)reg_rmaccessrights.AccessRights); //fs access rights
      vmwrite(vm_guest_gs_access_rights,(ULONG)reg_rmaccessrights.AccessRights); //gs access rights
      vmwrite(vm_guest_ldtr_access_rights,(ULONG)(1<<16)); //ldtr access rights (bit 16 is unusable bit
      vmwrite(vm_guest_tr_access_rights,(ULONG)reg_traccessrights.AccessRights); //tr access rights

      vmwrite(vm_guest_es,(ULONG)vmread(vm_guest_es_base) >> 4); //es selector
      vmwrite(vm_guest_cs,(ULONG)vmread(vm_guest_cs_base) >> 4); //cs selector
      vmwrite(vm_guest_ss,(ULONG)vmread(vm_guest_ss_base) >> 4); //ss selector
      vmwrite(vm_guest_ds,(ULONG)vmread(vm_guest_ds_base) >> 4); //ds selector
      vmwrite(vm_guest_fs,(ULONG)vmread(vm_guest_fs_base) >> 4); //fs selector
      vmwrite(vm_guest_gs,(ULONG)vmread(vm_guest_gs_base) >> 4); //gs selector
      vmwrite(vm_guest_ldtr,(ULONG)0); //ldtr selector
      vmwrite(vm_guest_tr,(ULONG)0); //tr selector

      vmwrite(vm_guest_es_limit,(ULONG)0xffff); //es limit
      vmwrite(vm_guest_cs_limit,(ULONG)0xffff); //cs limit
      vmwrite(vm_guest_ss_limit,(ULONG)0xffff); //ss limit
      vmwrite(vm_guest_ds_limit,(ULONG)0xffff); //ds limit
      vmwrite(vm_guest_fs_limit,(ULONG)0xffff); //fs limit
      vmwrite(vm_guest_gs_limit,(ULONG)0xffff); //gs limit


      //make sure VM flag is set appropriatly for vm mode
      guestrflags.value=vmread(vm_guest_rflags);
      guestrflags.IOPL=3;
      guestrflags.VM=1;
//      pguesteflags->v
      //currentcpuinfo->hasIF=pguesteflags->IF;
      vmwrite(vm_guest_rflags,guestrflags.value);

      return 0;
    }
  }
  else
  {