Example #1
0
class VMMCommand(BaseCommand):
    def requires_driver(self):
        parser = ArgumentParser(prog='chipsec_util vmm', usage=__doc__)
        subparsers = parser.add_subparsers()

        parser_hypercall = subparsers.add_parser('hypercall')
        parser_hypercall.add_argument('ax',
                                      type=lambda x: int(x, 16),
                                      help='rax/eax value (hex)')
        parser_hypercall.add_argument('bx',
                                      type=lambda x: int(x, 16),
                                      help='rbx/ebx value (hex)')
        parser_hypercall.add_argument('cx',
                                      type=lambda x: int(x, 16),
                                      help='rcx/ecx value (hex)')
        parser_hypercall.add_argument('dx',
                                      type=lambda x: int(x, 16),
                                      help='rdx/edx value (hex)')
        parser_hypercall.add_argument('di',
                                      type=lambda x: int(x, 16),
                                      help='rdi/edi value (hex)')
        parser_hypercall.add_argument('si',
                                      type=lambda x: int(x, 16),
                                      help='rsi/esi value (hex)')
        parser_hypercall.add_argument('r8',
                                      type=lambda x: int(x, 16),
                                      nargs='?',
                                      default=0,
                                      help='r8 value (hex)')
        parser_hypercall.add_argument('r9',
                                      type=lambda x: int(x, 16),
                                      nargs='?',
                                      default=0,
                                      help='r9 value (hex)')
        parser_hypercall.add_argument('r10',
                                      type=lambda x: int(x, 16),
                                      nargs='?',
                                      default=0,
                                      help='r10 value (hex)')
        parser_hypercall.add_argument('r11',
                                      type=lambda x: int(x, 16),
                                      nargs='?',
                                      default=0,
                                      help='r11 value (hex)')
        parser_hypercall.set_defaults(func=self.vmm_hypercall)

        parser_pt = subparsers.add_parser('pt')
        parser_pt.add_argument('eptp',
                               type=lambda x: int(x, 16),
                               help='Pointer (hex)')
        parser_pt.set_defaults(func=self.vmm_pt)

        parser_ept = subparsers.add_parser('ept')
        parser_ept.add_argument('eptp',
                                type=lambda x: int(x, 16),
                                help='Pointer (hex)')
        parser_ept.set_defaults(func=self.vmm_pt)

        parser_virtio = subparsers.add_parser('virtio')
        parser_virtio.add_argument('bdf',
                                   type=str,
                                   nargs='?',
                                   default=None,
                                   help='<bus>:<device>.<function>')
        parser_virtio.set_defaults(func=self.vmm_virtio)

        parser.parse_args(self.argv[2:], namespace=self)
        return True

    def vmm_virtio(self):
        if self.bdf is not None:
            match = re.search(
                r"^([0-9a-f]{1,2}):([0-1]?[0-9a-f]{1})\.([0-7]{1})$", self.bdf)
            if match:
                _bus = int(match.group(1), 16) & 0xFF
                _dev = int(match.group(2), 16) & 0x1F
                _fun = int(match.group(3), 16) & 0x07
                vid = self.cs.pci.read_word(_bus, _dev, _fun, 0)
                did = self.cs.pci.read_word(_bus, _dev, _fun, 2)
                dev = (_bus, _dev, _fun, vid, did)
                virt_dev = [dev]
            else:
                self.logger.error("Invalid B:D.F ({})".format(self.bdf))
                self.logger.log(VMMCommand.__doc__)
                return
        else:
            self.logger.log("[CHIPSEC] Enumerating VirtIO devices...")
            virt_dev = get_virtio_devices(self.cs.pci.enumerate_devices())

        if len(virt_dev) > 0:
            self.logger.log("[CHIPSEC] Available VirtIO devices:")
            print_pci_devices(virt_dev)
            for (b, d, f, vid, did) in virt_dev:
                VirtIO_Device(self.cs, b, d, f).dump_device()
        else:
            self.logger.log("[CHIPSEC] No VirtIO devices found")

    def vmm_hypercall(self):
        self.logger.log('')
        self.logger.log("[CHIPSEC] > hypercall")
        self.logger.log("[CHIPSEC]   RAX: 0x{:016X}".format(self.ax))
        self.logger.log("[CHIPSEC]   RBX: 0x{:016X}".format(self.bx))
        self.logger.log("[CHIPSEC]   RCX: 0x{:016X}".format(self.cx))
        self.logger.log("[CHIPSEC]   RDX: 0x{:016X}".format(self.dx))
        self.logger.log("[CHIPSEC]   RSI: 0x{:016X}".format(self.si))
        self.logger.log("[CHIPSEC]   RDI: 0x{:016X}".format(self.di))
        self.logger.log("[CHIPSEC]   R8 : 0x{:016X}".format(self.r8))
        self.logger.log("[CHIPSEC]   R9 : 0x{:016X}".format(self.r9))
        self.logger.log("[CHIPSEC]   R10: 0x{:016X}".format(self.r10))
        self.logger.log("[CHIPSEC]   R11: 0x{:016X}".format(self.r11))

        rax = self.vmm.hypercall(self.ax, self.bx, self.cx, self.dx, self.si,
                                 self.di, self.r8, self.r9, self.r10, self.r11)

        self.logger.log("[CHIPSEC] < RAX: 0x{:016X}".format(rax))

    def vmm_pt(self):
        if self.eptp is not None:
            pt_fname = 'ept_{:08X}'.format(self.eptp)
            self.logger.log("[CHIPSEC] EPT physical base: 0x{:016X}".format(
                self.eptp))
            self.logger.log(
                "[CHIPSEC] Dumping EPT to '{}'...".format(pt_fname))
            self.vmm.dump_EPT_page_tables(self.eptp, pt_fname)
        else:
            self.logger.log(
                "[CHIPSEC] Finding EPT hierarchy in memory is not implemented yet"
            )
            self.logger.error(VMMCommand.__doc__)
            return

    def run(self):
        t = time.time()

        try:
            self.vmm = VMM(self.cs)
        except VMMRuntimeError as msg:
            self.logger.error(msg)
            return

        self.vmm.init()

        self.func()

        self.logger.log("[CHIPSEC] (vmm) time elapsed {:.3f}".format(
            (time.time() - t)))
Example #2
0
class HyperV(BaseModuleDebug):
    def __init__(self):
        BaseModuleDebug.__init__(self)
        self.hypercall = VMM(self.cs)
        self.hypercall.init()
        self.membuf = self.cs.mem.alloc_physical_mem(4*0x1000, 0xFFFFFFFF)
        self.cs.mem.write_physical_mem(self.membuf[1], 4*0x1000, '\x00' * 4*0x1000)
        self.old_sint2 = []
        self.old_simp  = []
        self.old_siefp = []
        self.simp   = []
        self.siefp  = []

    def __del__(self):
        BaseModuleDebug.__del__(self)
        self.dbg('Free kernel memory')
        #if self.membuf[0] <> 0:
        #    self.cs.mem.free_physical_mem(self.membuf[0])
        if len(self.old_sint2) == 2:
            self.cs.msr.write_msr(0, HV_X64_MSR_SINT2, self.old_sint2[0], self.old_sint2[1])
        if len(self.old_simp)  == 2:
            self.cs.msr.write_msr(0, HV_X64_MSR_SIMP,  self.old_simp[0],  self.old_simp[1])
        if len(self.old_siefp) == 2:
            self.cs.msr.write_msr(0, HV_X64_MSR_SIEFP, self.old_siefp[0], self.old_siefp[1])
        for i in [x for x in self.ringbuffers]:
            del self.ringbuffers[i]

    ##
    ##  hv_init
    ##
    def hv_init(self):
        self.old_sint2 = self.cs.msr.read_msr(0, HV_X64_MSR_SINT2)
        self.old_simp  = self.cs.msr.read_msr(0, HV_X64_MSR_SIMP)
        self.old_siefp = self.cs.msr.read_msr(0, HV_X64_MSR_SIEFP)
        pa = self.membuf[1]
        self.sint3 = self.cs.msr.read_msr(0, HV_X64_MSR_SINT3)
        self.cs.msr.write_msr(0, HV_X64_MSR_SINT2, self.sint3[0], self.sint3[1])
        self.cs.msr.write_msr(0, HV_X64_MSR_SIEFP, (pa & 0xFFFFFFFF) | 0x1, pa >> 32)
        #self.cs.msr.write_msr(0, HV_X64_MSR_SCONTROL, 0x1, 0x0)
        self.simp  = self.cs.msr.read_msr(0, HV_X64_MSR_SIMP)
        self.siefp = self.cs.msr.read_msr(0, HV_X64_MSR_SIEFP)
        self.simp  = (self.simp[0]  + (self.simp[1]  << 32)) & 0xFFFFFFFFFFFFF000
        self.siefp = (self.siefp[0] + (self.siefp[1] << 32)) & 0xFFFFFFFFFFFFF000
        return

    ##
    ##  hv_post_msg - Send a message
    ##
    def hv_post_msg(self, message):
        retries = 3
        hciv    = hv_hciv(0, 0, HV_POST_MESSAGE)
        while retries > 0:
            result = self.hypercall.hypercall64_memory_based(hciv, message[:0x100]) & 0xFFFF
            if result == HV_STATUS_INSUFFICIENT_BUFFERS:
                retries -= 1
                time.sleep(0.1)
            else:
                retries  = 0
        return result

    ##
    ##  hv_recv_msg - recieve message if exist otherwise empty string
    ##
    def hv_recv_msg(self, sint):
        buffer = self.cs.mem.read_physical_mem(self.simp + 0x100*sint, 0x100)
        message_type, payload_size, message_flags = unpack('<LBB', buffer[0:6])
        if message_type == HVMSG_NONE:
            buffer = ''
        else:
            self.cs.mem.write_physical_mem(self.simp + 0x100*sint, 0x4, DD(HVMSG_NONE))
            if message_flags & 0x1:
                self.cs.msr.write_msr(0, HV_X64_MSR_EOM, 0x0, 0x0)
        return buffer

    ##
    ##  hv_signal_event - send an event notification
    ##
    def hv_signal_event(self, connection_id, flag_number):
        hciv   = hv_hciv(0, 0, HV_SIGNAL_EVENT)
        buffer = pack('<LHH', connection_id, flag_number, 0x0)
        result = self.hypercall.hypercall64_memory_based(hciv, buffer) & 0xFFFF
        return result

    ##
    ##  hv_recv_events - recieve all current events
    ##
    def hv_recv_events(self, sint):
        events = set()
        buffer = self.cs.mem.read_physical_mem(self.siefp + 0x100*sint, 0x100)
        buffer = unpack('<64L', buffer)
        for i in xrange(64):
            if buffer[i]:
                for n in xrange(32):
                    if (buffer[i] >> n) & 0x1:
                        events.add(i*32 + n)
        return events
Example #3
0
class HyperV(BaseModuleDebug):
    def __init__(self):
        BaseModuleDebug.__init__(self)
        self.hypercall = VMM(self.cs)
        self.hypercall.init()
        self.membuf = self.cs.mem.alloc_physical_mem(4 * 0x1000, 0xFFFFFFFF)
        self.cs.mem.write_physical_mem(self.membuf[1], 4 * 0x1000,
                                       '\x00' * 4 * 0x1000)
        self.old_sint2 = []
        self.old_simp = []
        self.old_siefp = []
        self.simp = []
        self.siefp = []

    def __del__(self):
        BaseModuleDebug.__del__(self)
        self.dbg('Free kernel memory')
        #if self.membuf[0] <> 0:
        #    self.cs.mem.free_physical_mem(self.membuf[0])
        if len(self.old_sint2) == 2:
            self.cs.msr.write_msr(0, HV_X64_MSR_SINT2, self.old_sint2[0],
                                  self.old_sint2[1])
        if len(self.old_simp) == 2:
            self.cs.msr.write_msr(0, HV_X64_MSR_SIMP, self.old_simp[0],
                                  self.old_simp[1])
        if len(self.old_siefp) == 2:
            self.cs.msr.write_msr(0, HV_X64_MSR_SIEFP, self.old_siefp[0],
                                  self.old_siefp[1])
        for i in [x for x in self.ringbuffers]:
            del self.ringbuffers[i]

    ##
    ##  hv_init
    ##
    def hv_init(self):
        self.old_sint2 = self.cs.msr.read_msr(0, HV_X64_MSR_SINT2)
        self.old_simp = self.cs.msr.read_msr(0, HV_X64_MSR_SIMP)
        self.old_siefp = self.cs.msr.read_msr(0, HV_X64_MSR_SIEFP)
        pa = self.membuf[1]
        self.sint3 = self.cs.msr.read_msr(0, HV_X64_MSR_SINT3)
        self.cs.msr.write_msr(0, HV_X64_MSR_SINT2, self.sint3[0],
                              self.sint3[1])
        self.cs.msr.write_msr(0, HV_X64_MSR_SIEFP, (pa & 0xFFFFFFFF) | 0x1,
                              pa >> 32)
        #self.cs.msr.write_msr(0, HV_X64_MSR_SCONTROL, 0x1, 0x0)
        self.simp = self.cs.msr.read_msr(0, HV_X64_MSR_SIMP)
        self.siefp = self.cs.msr.read_msr(0, HV_X64_MSR_SIEFP)
        self.simp = (self.simp[0] + (self.simp[1] << 32)) & 0xFFFFFFFFFFFFF000
        self.siefp = (self.siefp[0] +
                      (self.siefp[1] << 32)) & 0xFFFFFFFFFFFFF000
        return

    ##
    ##  hv_post_msg - Send a message
    ##
    def hv_post_msg(self, message):
        retries = 3
        hciv = hv_hciv(0, 0, HV_POST_MESSAGE)
        while retries > 0:
            result = self.hypercall.hypercall64_memory_based(
                hciv, message[:0x100]) & 0xFFFF
            if result == HV_STATUS_INSUFFICIENT_BUFFERS:
                retries -= 1
                time.sleep(0.1)
            else:
                retries = 0
        return result

    ##
    ##  hv_recv_msg - recieve message if exist otherwise empty string
    ##
    def hv_recv_msg(self, sint):
        buffer = self.cs.mem.read_physical_mem(self.simp + 0x100 * sint, 0x100)
        message_type, payload_size, message_flags = unpack('<LBB', buffer[0:6])
        if message_type == HVMSG_NONE:
            buffer = ''
        else:
            self.cs.mem.write_physical_mem(self.simp + 0x100 * sint, 0x4,
                                           DD(HVMSG_NONE))
            if message_flags & 0x1:
                self.cs.msr.write_msr(0, HV_X64_MSR_EOM, 0x0, 0x0)
        return buffer

    ##
    ##  hv_signal_event - send an event notification
    ##
    def hv_signal_event(self, connection_id, flag_number):
        hciv = hv_hciv(0, 0, HV_SIGNAL_EVENT)
        buffer = pack('<LHH', connection_id, flag_number, 0x0)
        result = self.hypercall.hypercall64_memory_based(hciv, buffer) & 0xFFFF
        return result

    ##
    ##  hv_recv_events - recieve all current events
    ##
    def hv_recv_events(self, sint):
        events = set()
        buffer = self.cs.mem.read_physical_mem(self.siefp + 0x100 * sint,
                                               0x100)
        buffer = unpack('<64L', buffer)
        for i in xrange(64):
            if buffer[i]:
                for n in xrange(32):
                    if (buffer[i] >> n) & 0x1:
                        events.add(i * 32 + n)
        return events