diff --git a/snippets/vmcb.py b/snippets/vmcb.py new file mode 100644 index 0000000..e3d57f5 --- /dev/null +++ b/snippets/vmcb.py @@ -0,0 +1,210 @@ +# +# +# + + +from pykd import * +import sys + + +VMCB_CONTROL_CR0 = 0x000 +VMCB_CONTROL_DR0 = 0x004 +VMCB_CONTROL_00C = 0x00C +VMCB_CONTROL_010 = 0x010 +VMCB_CONTROL_PAUSE_COUNT = 0x03E +VMCB_CONTROL_IOPM_BASE_PA = 0x040 +VMCB_CONTROL_MSRPM_BASE_PA = 0x048 +VMCB_CONTROL_GUEST_ASID = 0x058 +VMCB_CONTROL_TLB_CONTROL = 0x05C +VMCB_CONTROL_VINTERRUPT = 0x060 +VMCB_CONTROL_INRT_SHADOW = 0x068 +VMCB_CONTROL_EXITCODE = 0x070 +VMCB_CONTROL_EXITINFO1 = 0x078 +VMCB_CONTROL_EXITINFO2 = 0x080 +VMCB_CONTROL_EXITINTINFO = 0x088 +VMCB_CONTROL_NESTED_PAGING = 0x090 +VMCB_CONTROL_EVENTINJ = 0x0A8 +VMCB_CONTROL_N_CR3 = 0x0B0 +VMCB_CONTROL_LBR_VIRT = 0x0B8 +VMCB_CONTROL_CLEAN_BITS = 0x0C0 +VMCB_CONTROL_NRIP = 0x0C8 + + + +VMCB_GUEST_STATE_OFFSET = 0x400 +VMCB_GUEST_ES_OFFSET = VMCB_GUEST_STATE_OFFSET + 0x000 +VMCB_GUEST_CS_OFFSET = VMCB_GUEST_STATE_OFFSET + 0x010 +VMCB_GUEST_SS_OFFSET = VMCB_GUEST_STATE_OFFSET + 0x020 +VMCB_GUEST_DS_OFFSET = VMCB_GUEST_STATE_OFFSET + 0x030 +VMCB_GUEST_FS_OFFSET = VMCB_GUEST_STATE_OFFSET + 0x040 +VMCB_GUEST_GS_OFFSET = VMCB_GUEST_STATE_OFFSET + 0x050 +VMCB_GUEST_GDTR_OFFSET = VMCB_GUEST_STATE_OFFSET + 0x060 +VMCB_GUEST_LDTR_OFFSET = VMCB_GUEST_STATE_OFFSET + 0x070 +VMCB_GUEST_IDTR_OFFSET = VMCB_GUEST_STATE_OFFSET + 0x080 +VMCB_GUEST_TR_OFFSET = VMCB_GUEST_STATE_OFFSET + 0x090 +VMCB_GUEST_EFER_OFFSET = VMCB_GUEST_STATE_OFFSET + 0x0D0 +VMCB_GUEST_CR4_OFFSET = VMCB_GUEST_STATE_OFFSET + 0x148 +VMCB_GUEST_CR3_OFFSET = VMCB_GUEST_STATE_OFFSET + 0x150 +VMCB_GUEST_CR0_OFFSET = VMCB_GUEST_STATE_OFFSET + 0x158 +VMCB_GUEST_DR7_OFFSET = VMCB_GUEST_STATE_OFFSET + 0x160 +VMCB_GUEST_DR6_OFFSET = VMCB_GUEST_STATE_OFFSET + 0x168 +VMCB_GUEST_RFLAGS_OFFSET = VMCB_GUEST_STATE_OFFSET + 0x170 +VMCB_GUEST_RIP_OFFSET = VMCB_GUEST_STATE_OFFSET + 0x178 +VMCB_GUEST_RSP_OFFSET = VMCB_GUEST_STATE_OFFSET + 0x1D8 +VMCB_GUEST_RAX_OFFSET = VMCB_GUEST_STATE_OFFSET + 0x1F8 +VMCB_GUEST_STAR_OFFSET = VMCB_GUEST_STATE_OFFSET + 0x200 +VMCB_GUEST_LSTAR_OFFSET = VMCB_GUEST_STATE_OFFSET + 0x208 +VMCB_GUEST_CSTAR_OFFSET = VMCB_GUEST_STATE_OFFSET + 0x210 +VMCB_GUEST_SFMASK_OFFSET = VMCB_GUEST_STATE_OFFSET + 0x218 +VMCB_GUEST_KERNELGS_OFFSET = VMCB_GUEST_STATE_OFFSET + 0x220 +VMCB_GUEST_SYSENTER_CS_OFFSET = VMCB_GUEST_STATE_OFFSET + 0x228 +VMCB_GUEST_SYSENTER_ESP_OFFSET = VMCB_GUEST_STATE_OFFSET + 0x230 +VMCB_GUEST_SYSENTER_EIP_OFFSET = VMCB_GUEST_STATE_OFFSET + 0x238 +VMCB_GUEST_CR2_OFFSET = VMCB_GUEST_STATE_OFFSET + 0x240 + + + +def bin32( dw ): + return "0b" + "".join( [ ((dw & ( 0x80000000 >> i ) ) == 0) and "0" or "1" for i in xrange(32) ] ) + +def bin16( dw ): + return "0b" + "".join( [ ((dw & ( 0x8000 >> i ) ) == 0) and "0" or "1" for i in xrange(16) ] ) + +def sysselectstr( val ): + return "selector=%x attr=%x base=%x limit=%x" % ( val[0] & 0xFFFF, (val[0]>>16)&0xFFFF, val[1]&0xFFFFFFFF, (val[0]>>32)&0xFFFFFFFF ) + + +def sysselectload( addr ): + return (ptrQWord(addr), ptrQWord(addr+8) ) + + +class VmcbEntry: + + def __init__( self, desc, offset, loader, formatter ): + self.desc = desc + self.offset = offset + self.loader = loader + self.formatter = formatter + self.value = "invalid" + + def load( self, address ): + self.value = self.loader( address + self.offset ) + + + def __str__( self ): + return self.formatter( self.value ) + + + +class Vmcb: + + + def __init__( self, addr ): + + self.addr = addr + + self.controlArea = [ + VmcbEntry( "CR0 Reads/Writes", VMCB_CONTROL_CR0, ptrDWord, bin32 ), + VmcbEntry( "DR0 Reads/Writes", VMCB_CONTROL_DR0, ptrDWord, bin32 ), + VmcbEntry( "Interceptors", VMCB_CONTROL_00C, ptrDWord, bin32 ), + VmcbEntry( "Interceptors", VMCB_CONTROL_010, ptrDWord, bin32 ), + VmcbEntry( "PAUSE Filter Count",VMCB_CONTROL_PAUSE_COUNT, ptrWord, hex ), + VmcbEntry( "IOPM_BASE_PA", VMCB_CONTROL_IOPM_BASE_PA, ptrQWord, hex ), + VmcbEntry( "MSRPM_BASE_PA", VMCB_CONTROL_MSRPM_BASE_PA, ptrQWord, hex ), + VmcbEntry( "Guest ASID", VMCB_CONTROL_GUEST_ASID, ptrDWord, hex ), + VmcbEntry( "TLB_CONTROL", VMCB_CONTROL_TLB_CONTROL, ptrDWord, hex ), + VmcbEntry( "Virtual interrupt",VMCB_CONTROL_VINTERRUPT, ptrQWord, hex ), + VmcbEntry( "Interrupt Shadow", VMCB_CONTROL_INRT_SHADOW, ptrQWord, hex ), + VmcbEntry( "EXITCODE", VMCB_CONTROL_EXITCODE, ptrQWord, hex ), + VmcbEntry( "EXITINFO1", VMCB_CONTROL_EXITINFO1, ptrQWord, hex ), + VmcbEntry( "EXITINFO2", VMCB_CONTROL_EXITINFO2, ptrQWord, hex ), + VmcbEntry( "EXITINTINFO", VMCB_CONTROL_EXITINTINFO, ptrQWord, hex ), + VmcbEntry( "Nested Paging", VMCB_CONTROL_NESTED_PAGING, ptrQWord, hex ), + VmcbEntry( "EVENTINJ", VMCB_CONTROL_EVENTINJ, ptrQWord, hex ), + VmcbEntry( "N_CR3", VMCB_CONTROL_N_CR3, ptrQWord, hex ), + VmcbEntry( "LBR_VIRTUALIZATION_ENABLE", VMCB_CONTROL_LBR_VIRT, ptrQWord, hex ), + VmcbEntry( "Clean Bits", VMCB_CONTROL_CLEAN_BITS, ptrDWord, hex ), + VmcbEntry( "nRIP", VMCB_CONTROL_NRIP, ptrQWord, hex ), + ] + + self.guestArea = [ + VmcbEntry( "ES", VMCB_GUEST_ES_OFFSET, sysselectload, sysselectstr ), + VmcbEntry( "CS", VMCB_GUEST_CS_OFFSET, sysselectload, sysselectstr ), + VmcbEntry( "SS", VMCB_GUEST_SS_OFFSET, sysselectload, sysselectstr ), + VmcbEntry( "DS", VMCB_GUEST_DS_OFFSET, sysselectload, sysselectstr ), + VmcbEntry( "FS", VMCB_GUEST_FS_OFFSET, sysselectload, sysselectstr ), + VmcbEntry( "GS", VMCB_GUEST_GS_OFFSET, sysselectload, sysselectstr ), + VmcbEntry( "GDTR", VMCB_GUEST_GDTR_OFFSET, sysselectload, sysselectstr ), + VmcbEntry( "LDTR", VMCB_GUEST_LDTR_OFFSET, sysselectload, sysselectstr ), + VmcbEntry( "IDTR", VMCB_GUEST_IDTR_OFFSET, sysselectload, sysselectstr ), + VmcbEntry( "TR", VMCB_GUEST_TR_OFFSET, sysselectload, sysselectstr ), + VmcbEntry( "EFER", VMCB_GUEST_EFER_OFFSET, ptrQWord, hex ), + VmcbEntry( "CR4", VMCB_GUEST_CR4_OFFSET, ptrQWord, hex ), + VmcbEntry( "CR3", VMCB_GUEST_CR3_OFFSET, ptrQWord, hex ), + VmcbEntry( "CR0", VMCB_GUEST_CR0_OFFSET, ptrQWord, hex ), + VmcbEntry( "DR6", VMCB_GUEST_DR6_OFFSET, ptrQWord, hex ), + VmcbEntry( "DR7", VMCB_GUEST_DR7_OFFSET, ptrQWord, hex ), + VmcbEntry( "RFLAGS", VMCB_GUEST_RFLAGS_OFFSET, ptrQWord, hex ), + VmcbEntry( "RIP", VMCB_GUEST_RIP_OFFSET, ptrQWord, hex ), + VmcbEntry( "RSP", VMCB_GUEST_RSP_OFFSET, ptrQWord, hex ), + VmcbEntry( "RAX", VMCB_GUEST_RAX_OFFSET, ptrQWord, hex ), + VmcbEntry( "STAR", VMCB_GUEST_STAR_OFFSET, ptrQWord, hex ), + VmcbEntry( "LSTAR", VMCB_GUEST_LSTAR_OFFSET, ptrQWord, hex ), + VmcbEntry( "CSTAR", VMCB_GUEST_CSTAR_OFFSET, ptrQWord, hex ), + VmcbEntry( "SFMASK", VMCB_GUEST_SFMASK_OFFSET, ptrQWord, hex ), + VmcbEntry( "KERNEL GS Base", VMCB_GUEST_KERNELGS_OFFSET, ptrQWord, hex ), + VmcbEntry( "SYSENTER CS", VMCB_GUEST_SYSENTER_CS_OFFSET, ptrQWord, hex ), + VmcbEntry( "SYSENTER ESP", VMCB_GUEST_SYSENTER_ESP_OFFSET, ptrQWord, hex ), + VmcbEntry( "SYSENTER EIP", VMCB_GUEST_SYSENTER_EIP_OFFSET, ptrQWord, hex ), + VmcbEntry( "CR2", VMCB_GUEST_CR2_OFFSET, ptrQWord, hex ), + + ] + + + self.controlArea.sort( key=lambda v: v.offset ) + self.guestArea.sort( key=lambda v: v.offset ) + + for vmcbEntry in self.controlArea: vmcbEntry.load( addr ) + for vmcbEntry in self.guestArea: vmcbEntry.load( addr ) + + def __str__ ( self ): + + s = "\nVMCB Start Address: %x\n" % self.addr; + + s += "\n*** CONTROL AREA ***\n" + + + for vmcbEntry in self.controlArea: + s += "\t+%03x %s: %s\n" % ( vmcbEntry.offset, vmcbEntry.desc, str(vmcbEntry) ) + + + s += "\n*** GUEST STATE AREA ***\n" + + for vmcbEntry in self.guestArea: + s += "\t+%03x %s: %s\n" % ( vmcbEntry.offset, vmcbEntry.desc, str(vmcbEntry) ) + + return s + + +def main(): + + if not isWindbgExt(): + dprintln( "script is launch out of windbg" ) + return + + if len( sys.argv ) <= 1: + dprintln( "usage: !py vmcb " ) + return + + + try: + + dprint( str( Vmcb( expr( sys.argv[1] ) ) ) ) + + except MemoryException, e: + + dprintln( e.desc() ) + + +if __name__ == "__main__": + main()