A forum for reverse engineering, OS internals and malware analysis 

Ask your beginner questions here.
 #12842  by zico_guru
 Sat Apr 21, 2012 2:15 pm
Hello again
i am going to virtualized current os...
I have Setup VMCS ...
but it still giving the error 0x21 ( 33 ) Invalid Guest State...
i have upload the code also
plz anybody help me......
Code: Select all
u64 SetupVMCS()
{
   u16 count;
   u64 idt_base;
   u64 gdt_base;
   UCHAR idtr[10];
   UCHAR gdtr[10];
   u16 idt_limit;
   u16 gdt_limit;
   u32 temp32;
   u64 temp64;
   u16 ES,CS,DS,SS,FS,GS,TR,LDTR;
   LARGE_INTEGER MSRValue;
	
	RtlZeroMemory(idtr,10);
	RtlZeroMemory(gdtr,10);
	
	
	GetGDTR(gdtr);
	GetIDTR(idtr);
		
	idt_base=* (u64 *)((PUCHAR) &idtr+2);
	gdt_base=* (u64 *)((PUCHAR) &gdtr+2);
		   
	idt_limit=*(u16 *)(idtr);
	gdt_limit=*(u16 *)(gdtr);
	
		
	 ES=GetES_Sel();
		WriteVMCS(GUEST_ES_SELECTOR,ES & 0xf8);  
		temp32 = GetSegmentDescriptorBase(gdt_base,ES) ;
		WriteVMCS(GUEST_ES_BASE,temp32); 
		temp32=GetSegmentDescriptorLimit(gdt_base,ES);
 	    WriteVMCS(GUEST_ES_LIMIT,temp32);
	    temp32 = GetSegmentDescriptorAR(gdt_base,ES);
		DbgPrint("ES AR Field %x",temp32);
	    WriteVMCS(GUEST_ES_AR,temp32); 
      	
	 CS=GetCS_Sel();
		WriteVMCS(GUEST_CS_SELECTOR,CS & 0xf8);
		temp32 = GetSegmentDescriptorBase(gdt_base,CS) ;
		WriteVMCS(GUEST_CS_BASE,temp32); 
		temp32=GetSegmentDescriptorLimit(gdt_base,CS);
 	    WriteVMCS(GUEST_CS_LIMIT,temp32);
	    temp32 = GetSegmentDescriptorAR(gdt_base,CS);
		DbgPrint("CS* AR Field %x",temp32);
	    WriteVMCS(GUEST_CS_AR,temp32); 
    
	 SS=GetSS_Sel();
	    WriteVMCS(GUEST_SS_SELECTOR,SS & 0xf8);	
	    temp32 = GetSegmentDescriptorBase(gdt_base,SS) ;
 		WriteVMCS(GUEST_SS_BASE,temp32); 
		temp32=GetSegmentDescriptorLimit(gdt_base,SS);
 	    WriteVMCS(GUEST_SS_LIMIT,temp32);
	    temp32 = GetSegmentDescriptorAR(gdt_base,SS);
		DbgPrint("SS AR Field %x",temp32);
	    WriteVMCS(GUEST_SS_AR,temp32); 

	 DS=GetDS_Sel();
        WriteVMCS(GUEST_DS_SELECTOR,DS & 0xf8);	
		temp32 = GetSegmentDescriptorBase(gdt_base,DS) ;
		WriteVMCS(GUEST_DS_BASE,temp32); 
		temp32=GetSegmentDescriptorLimit(gdt_base,DS);
 	    WriteVMCS(GUEST_DS_LIMIT,temp32);
	    temp32 = GetSegmentDescriptorAR(gdt_base,DS);
		DbgPrint("DS AR Field %x",temp32);
	    WriteVMCS(GUEST_DS_AR,temp32); 	    

	 GS=GetGS_Sel();
    	WriteVMCS(GUEST_GS_SELECTOR, GS & 0xf8);
	    temp64=ReadMSR(IA32_GS_BASE);
	    WriteVMCS(GUEST_GS_BASE,temp64);
	    temp32=GetSegmentDescriptorLimit(gdt_base,GS);
	    WriteVMCS(GUEST_GS_LIMIT,temp32);
	    temp32 = GetSegmentDescriptorAR(gdt_base,GS);
		DbgPrint("GS AR Field %x",temp32);
	    WriteVMCS(GUEST_GS_AR,temp32); 	    

	 FS=GetFS_Sel();
    	WriteVMCS(GUEST_FS_SELECTOR, FS & 0xf8);
	    temp64=ReadMSR(IA32_FS_BASE);
	    WriteVMCS(GUEST_FS_BASE,temp64);
	    temp32=GetSegmentDescriptorLimit(gdt_base,FS);
	    WriteVMCS(GUEST_FS_LIMIT,temp32);
	    temp32 = GetSegmentDescriptorAR(gdt_base,FS);
		DbgPrint("FS AR Field %x",temp32);
	    WriteVMCS(GUEST_FS_AR,temp32); 	    

   	 TR=GetTR_Sel();
     	WriteVMCS(GUEST_TR_SELECTOR,TR & 0xf8);
		temp32 = GetSegmentDescriptorBase(gdt_base,TR) ;
		WriteVMCS(GUEST_TR_BASE,temp32); 
		temp32=GetSegmentDescriptorLimit(gdt_base,TR);
 	    WriteVMCS(GUEST_TR_LIMIT,temp32);
	    temp32 = GetSegmentDescriptorAR(gdt_base,TR);
		DbgPrint("TR AR Field %x",temp32);
	    WriteVMCS(GUEST_TR_AR,temp32); 	    
		
	 LDTR=GetLDTR_Sel();
     	  WriteVMCS(GUEST_LDTR_SELECTOR,LDTR & 0xf8);
		  temp32 = GetSegmentDescriptorBase(gdt_base,LDTR) ;
		  WriteVMCS(GUEST_LDTR_BASE,temp32); 
		  temp32=GetSegmentDescriptorLimit(gdt_base,LDTR);
 	      WriteVMCS(GUEST_LDTR_LIMIT,temp32);
	      temp32 = GetSegmentDescriptorAR(gdt_base,LDTR);
		  DbgPrint("LDTR AR Field %x",temp32);
	      WriteVMCS(GUEST_LDTR_AR,temp32); 	    
	 
	
	//VMCS Link Pointer
	
	temp32=0xFFFFFFFF;
	WriteVMCS(VMCS_LINK_POINTER,temp32);
	WriteVMCS(VMCS_LINK_POINTER_HIGH,temp32);
	
    temp64=ReadMSR(	IA32_DBGCTL_MSR)	;
	temp32=temp64 & 0xFFFFFFFF;
	WriteVMCS(GUEST_IA32_DEBUGCTL,temp32);
	
	temp32=temp64 >> 32 ; 
	WriteVMCS(GUEST_IA32_DEBUGCTL_HIGH,temp32);
	
	WriteVMCS(GUEST_GDTR_BASE,gdt_base);   
	WriteVMCS(GUEST_GDTR_LIMIT,gdt_limit);   
	
	DbgPrint("Guest gdt_base %llx",gdt_base);
	DbgPrint("Guest gdt_base %llx",idt_base);
	
	DbgPrint("Guest gdt_base %llx",gdt_limit);
	DbgPrint("Guest gdt_base %llx",idt_limit);
	
	WriteVMCS(GUEST_IDTR_BASE,idt_base);   
	WriteVMCS(GUEST_IDTR_LIMIT,idt_limit);   
	
	
	WriteVMCS(GUEST_SYSENTER_CS,ReadMSR(MSR_IA32_SYSENTER_CS));
	WriteVMCS(GUEST_SYSENTER_ESP,0xFFFFF00000000000);
	WriteVMCS(GUEST_SYSENTER_EIP,0xFFFFF00000000000);
	
	 WriteVMCS (VM_EXIT_MSR_STORE_COUNT, 0);
     WriteVMCS (VM_EXIT_MSR_LOAD_COUNT, 0);

     WriteVMCS (VM_ENTRY_MSR_LOAD_COUNT, 0);
     WriteVMCS (VM_ENTRY_INTR_INFO_FIELD, 0);
	 WriteVMCS (EXCEPTION_BITMAP,0);
	 
	 WriteVMCS (CR3_TARGET_VALUE0, 0);      
     WriteVMCS (CR3_TARGET_VALUE1, 0);      
     WriteVMCS (CR3_TARGET_VALUE2, 0);      
     WriteVMCS (CR3_TARGET_VALUE3, 0);      

     WriteVMCS (GUEST_CR0,GETREGCR0());
	 WriteVMCS (GUEST_CR3,GETCR3());
	 WriteVMCS (GUEST_CR4,GETREGCR4());
	  
	 WriteVMCS (GUEST_DR7,0x400); 
	 
	 WriteVMCS (GUEST_RFLAGS,GETFLAGS()); 
	
	 
	
	 WriteVMCS(GUEST_ACTIVITY_STATE,0);
	 WriteVMCS(GUEST_INTERRUPTIBILITY_INFO, 0);
	
	
	//// VM Entry Control Field
	 temp32=0;
	   MSRValue.QuadPart=ReadMSR(IA32_VMX_ENTRY_CLTS);
	   temp32 |=   VM_ENTRY_IA32E_MODE ;  // Guest Is Allowed to Enter In Ia32 Long Mode...
	   temp32 &= MSRValue.HighPart ;
	   temp32 |= MSRValue.LowPart  ;
	   WriteVMCS(VM_ENTRY_CONTROLS,temp32) ;
	  
	 temp32=0;
	   MSRValue.QuadPart=ReadMSR(IA32_VMX_EXIT_CLTS);
	   temp32 |= VM_EXIT_IA32E_MODE ;
	   temp32 &= MSRValue.HighPart ;
	   temp32 |= MSRValue.LowPart  ;
	   WriteVMCS(VM_EXIT_CONTROLS,temp32) ; 
	   
	 temp32=0;
	   MSRValue.QuadPart=ReadMSR(IA32_VMX_PINBASED_CLTS);
	   temp32 |= 0;
       temp32 &= MSRValue.HighPart ;
	   temp32 |= MSRValue.LowPart  ;
	   WriteVMCS(PIN_BASED_VM_EXEC_CONTROL,temp32) ; 
	   
	 temp32=0;
	   MSRValue.QuadPart=ReadMSR(IA32_VMX_PROCBASED_CLTS );
	   temp32 |= CPU_BASED_PAUSE_EXITING  ;
	   temp32 &= MSRValue.HighPart ;
	   temp32 |= MSRValue.LowPart  ;
	   WriteVMCS(CPU_BASED_VM_EXEC_CONTROL,temp32) ;   
	 
		 
	 
     
	
	WriteVMCS(HOST_ES_SELECTOR,GetES_Sel() & 0xf8);
	WriteVMCS(HOST_CS_SELECTOR,GetCS_Sel() & 0xf8);
    WriteVMCS(HOST_SS_SELECTOR,GetSS_Sel() & 0xf8);	 
	WriteVMCS(HOST_DS_SELECTOR,GetDS_Sel() & 0xf8);
    WriteVMCS(HOST_FS_SELECTOR,GetFS_Sel() & 0xf8);
	WriteVMCS(HOST_GS_SELECTOR,GetGS_Sel() & 0xf8);
	WriteVMCS(HOST_TR_SELECTOR,GetTR_Sel() & 0xf8);
	
	WriteVMCS(HOST_CR0,GETREGCR0());
	WriteVMCS(HOST_CR3,GETCR3());
	WriteVMCS(HOST_CR4,GETREGCR4());
	
	WriteVMCS(HOST_GDTR_BASE,gdt_base);
	WriteVMCS(HOST_IDTR_BASE,idt_base);
	
	temp64=ReadMSR(IA32_GS_BASE);
	WriteVMCS(HOST_GS_BASE,temp64);
	
	temp64=ReadMSR(IA32_FS_BASE);
	WriteVMCS(HOST_FS_BASE,temp64);
	
	WriteVMCS(HOST_IA32_SYSENTER_ESP,0x0) ;
    WriteVMCS(HOST_IA32_SYSENTER_EIP,0x0) ;
	
	WriteVMCS(HOST_RSP,(u64)HostStack);
	WriteVMCS(HOST_RIP,(u64)VmmHandler);  // VMM Handler!!!
	
  return STATUS_SUCCESS; 
}
Attachments
Code
(136.62 KiB) Downloaded 34 times
Last edited by GamingMasteR on Sun Apr 22, 2012 9:44 am, edited 1 time in total. Reason: added code tag
 #12864  by feryno
 Mon Apr 23, 2012 1:41 pm
hi, sorry as I don't understand C well enough, I'm quite skilled only in asm
this hypervisor is for 64 bits
I'm guessing this line is trying to get 32 bit base but it should be 64 (temp64) and also the procedure should be modified to extract 64 bit base (which is certainly something like FFFFF8........, not only 32 bit with truncated upper bits of the qword)
temp32 = GetSegmentDescriptorBase(gdt_base,TR)

and the same for LDT

let me know whether it helps or not (then I'll check your nice work again)

I see it is running only on 1 CPU, if you are interested I can describe how to run it on SMP, but as first it must run well on 1 CPU.
If you are interested I also have a method how to turn off vmx and resume OS without necessity of reboot (my vmx has private paging tables separated from OS = private CR3 and the only difficulty was to change CR3 while resuming OS after vmxoff)
 #12866  by zico_guru
 Mon Apr 23, 2012 6:03 pm
thanks for the response feryno!!! :|
my problem is solved......
the Segment Descriptor is not formed welly ...

now my hypervisor is running as expected....!!!!! :D