From bbaea2bc11cf45ed3f6d2de4fe45c8c6217f672a Mon Sep 17 00:00:00 2001 From: "Frinzell, Aaron" Date: Thu, 2 Jun 2022 18:46:50 -0500 Subject: [PATCH] Add usage documentation to pcie_fuzz.py Signed-off-by: Frinzell, Aaron --- chipsec/modules/tools/vmm/pcie_fuzz.py | 73 +++++++++++++++----------- 1 file changed, 43 insertions(+), 30 deletions(-) diff --git a/chipsec/modules/tools/vmm/pcie_fuzz.py b/chipsec/modules/tools/vmm/pcie_fuzz.py index 12911c0c..1d7658b5 100644 --- a/chipsec/modules/tools/vmm/pcie_fuzz.py +++ b/chipsec/modules/tools/vmm/pcie_fuzz.py @@ -25,8 +25,8 @@ Simple PCIe device Memory-Mapped I/O (MMIO) and I/O ranges VMM emulation fuzzer Usage: ``chipsec_main -m tools.vmm.pcie_fuzz [-a ]`` - - ```` : Bus # to fuzz (in hex) - - ```` : Device # to fuzz (in hex) + - ```` : Bus # to fuzz (in hex) + - ```` : Device # to fuzz (in hex) - ```` : Function # to fuzz (in hex) Where: @@ -37,12 +37,21 @@ Examples: >>> chipsec_main.py -i -m tools.vmm.pcie_fuzz -l log.txt >>> chipsec_main.py -i -m tools.vmm.pcie_fuzz -a 0 1f 0 +Additional options set within the module: + - ``IO_FUZZ`` : Set to fuzz IO BARs + - ``CALC_BAR_SIZE`` : Set to calculate BAR sizes + - ``TIMEOUT`` : Timeout between memory writes (seconds) + - ``ACTIVE_RANGE`` : Set to fuzz MMIO BAR in Active range + - ``BIT_FLIP`` : Set to fuzz using bit flips + - ``_EXCLUDE_BAR`` : BARs to exclude (list) + .. note:: - - Returns a Warning by default. - - System may be in an unknown state, further evaluation may be needed. + - Returns a Warning by default + - System may be in an unknown state, further evaluation may be needed .. important:: - This module is designed to run in a VM environment + - Behavior on physical HW is undefined """ @@ -73,12 +82,12 @@ class pcie_fuzz(BaseModule): # Issue 8/16/32-bit I/O requests with various values to all I/O ports (aligned and unaligned) for port_off in range(size): port_value = self.cs.io.read_port_byte(bar + port_off) - self.cs.io.write_port_byte (bar + port_off, port_value) - self.cs.io.write_port_byte (bar + port_off, ((~port_value) & 0xFF)) - self.cs.io.write_port_byte (bar + port_off, 0xFF) - self.cs.io.write_port_byte (bar + port_off, 0x00) - self.cs.io.write_port_word (bar + port_off, 0xFFFF) - self.cs.io.write_port_word (bar + port_off, 0x0000) + self.cs.io.write_port_byte(bar + port_off, port_value) + self.cs.io.write_port_byte(bar + port_off, ~port_value & 0xFF) + self.cs.io.write_port_byte(bar + port_off, 0xFF) + self.cs.io.write_port_byte(bar + port_off, 0x00) + self.cs.io.write_port_word(bar + port_off, 0xFFFF) + self.cs.io.write_port_word(bar + port_off, 0x0000) self.cs.io.write_port_dword(bar + port_off, 0xFFFFFFFF) self.cs.io.write_port_dword(bar + port_off, 0x00000000) @@ -97,7 +106,7 @@ class pcie_fuzz(BaseModule): self.cs.mem.write_physical_mem_byte(bar + reg_off + 1, 0xFF) def fuzz_mmio_bar(self, bar, is64bit, size=0x1000): - self.logger.log( "[*] Fuzzing MMIO BAR 0x{:016X}, size = 0x{:X}..".format(bar, size) ) + self.logger.log("[*] Fuzzing MMIO BAR 0x{:016X}, size = 0x{:X}..".format(bar, size)) reg_off = 0 # Issue aligned 32-bit MMIO requests with various values to all MMIO registers for reg_off in range(0, size, 4): @@ -108,34 +117,34 @@ class pcie_fuzz(BaseModule): self.cs.mmio.write_MMIO_reg(bar, reg_off, reg_value) def fuzz_mmio_bar_random(self, bar, is64bit, size=0x1000): - self.logger.log( "[*] Fuzzing MMIO BAR in random mode 0x{:016X}, size = 0x{:X}..".format(bar, size) ) + self.logger.log("[*] Fuzzing MMIO BAR in random mode 0x{:016X}, size = 0x{:X}..".format(bar, size)) reg_off = 0 while 1: - rand = random.randint(0, size /4 -1) - self.fuzz_offset(bar, reg_off, rand *4, is64bit) - self.fuzz_offset(bar, reg_off, rand *4 +1, is64bit) - self.fuzz_unaligned(bar, rand *4, is64bit) + rand = random.randint(0, size / 4 - 1) + self.fuzz_offset(bar, reg_off, rand * 4, is64bit) + self.fuzz_offset(bar, reg_off, rand * 4 + 1, is64bit) + self.fuzz_unaligned(bar, rand * 4, is64bit) def fuzz_mmio_bar_in_active_range(self, bar, is64bit, list): - self.logger.log( "[*] Fuzzing MMIO BAR in Active range 0x{:016X}, size of range = 0x{:X}..".format(bar, len(list)) ) + self.logger.log("[*] Fuzzing MMIO BAR in Active range 0x{:016X}, size of range = 0x{:X}..".format(bar, len(list))) for reg_off in list: rand = random.randint(0, 255) self.fuzz_offset(bar, reg_off, rand, is64bit) self.fuzz_unaligned(bar, reg_off, is64bit) def fuzz_mmio_bar_in_active_range_random(self, bar, is64bit, list): - self.logger.log( "[*] Fuzzing MMIO BAR in Active range 0x{:016X} in random mode, size of range = 0x{:X}..".format(bar, len(list)) ) + self.logger.log("[*] Fuzzing MMIO BAR in Active range 0x{:016X} in random mode, size of range = 0x{:X}..".format(bar, len(list))) reg_off = 0 self.fuzz_unaligned(bar, reg_off, is64bit) while 1: - rand = random.randint(0, len(list) -1) + rand = random.randint(0, len(list) - 1) self.fuzz_offset(bar, reg_off, list[rand], is64bit) def fuzz_mmio_bar_in_active_range_bit_flip(self, bar, is64bit, list): - self.logger.log( "[*] Fuzzing (bit flipping) MMIO BAR in Active range 0x{:016X}, size of range = 0x{:X}..".format(bar, len(list)) ) + self.logger.log("[*] Fuzzing (bit flipping) MMIO BAR in Active range 0x{:016X}, size of range = 0x{:X}..".format(bar, len(list))) reg_off = 0 while 1: - rand_index = random.randint(0, len(list) -1) + rand_index = random.randint(0, len(list) - 1) reg_value = self.cs.mmio.read_MMIO_reg(bar, list[rand_index]) rand_offset = random.randint(0, 32) @@ -147,14 +156,15 @@ class pcie_fuzz(BaseModule): self.cs.mmio.write_MMIO_reg(bar, reg_off, reg_value) def find_active_range(self, bar, size): - self.logger.log( "[*] Determine MMIO BAR Active range 0x{:016X}, size 0x{:X}..".format(bar, size) ) + self.logger.log("[*] Determine MMIO BAR Active range 0x{:016X}, size 0x{:X}..".format(bar, size)) one = self.cs.mem.read_physical_mem(bar, size) time.sleep(TIMEOUT) two = self.cs.mem.read_physical_mem(bar, size) diff_index = [] - for i in range(len(one) //4 - 1): - if one[4 *i] != two[4 *i] or one[4 *i +1] != two[4 *i +1] or one[4 *i +2] != two[4 *i +2] or one[4 *i +3] != two[4 *i +3]: - diff_index.append(i *4) + for i in range(len(one) // 4 - 1): + j = 4 * i + if (one[j] != two[j]) or (one[j + 1] != two[j + 1]) or (one[j + 2] != two[j + 2]) or (one[j + 3] != two[j + 3]): + diff_index.append(j) return diff_index def fuzz_pcie_device(self, b, d, f): @@ -164,7 +174,7 @@ class pcie_fuzz(BaseModule): if bar not in _EXCLUDE_BAR: # Fuzzing MMIO registers of the PCIe device if isMMIO: - self.logger.log( "[*] + 0x{:02X} ({:X}): MMIO BAR at 0x{:016X} (64-bit? {:d}) with size: 0x{:08X}. Fuzzing..".format(bar_off, bar_reg, bar, is64bit, size) ) + self.logger.log("[*] + 0x{:02X} ({:X}): MMIO BAR at 0x{:016X} (64-bit? {:d}) with size: 0x{:08X}. Fuzzing..".format(bar_off, bar_reg, bar, is64bit, size)) if ACTIVE_RANGE and (size > 0x1000): list = [] list = self.find_active_range(bar, size) @@ -180,7 +190,7 @@ class pcie_fuzz(BaseModule): # Fuzzing I/O registers of the PCIe device else: if IO_FUZZ: - self.logger.log( "[*] + 0x{:02X}: I/O BAR at 0x{:08X}. Fuzzing..".format(bar_off, bar) ) + self.logger.log("[*] + 0x{:02X}: I/O BAR at 0x{:08X}. Fuzzing..".format(bar_off, bar)) self.fuzz_io_bar(bar) def run(self, module_argv): @@ -191,16 +201,19 @@ class pcie_fuzz(BaseModule): _bus = int(module_argv[0], 16) _dev = int(module_argv[1], 16) _fun = int(module_argv[2], 16) - pcie_devices.append( (_bus, _dev, _fun, 0, 0) ) + pcie_devices.append((_bus, _dev, _fun, 0, 0)) else: self.logger.log("[*] Enumerating available PCIe devices..") pcie_devices = self.cs.pci.enumerate_devices() self.logger.log("[*] About to fuzz the following PCIe devices..") print_pci_devices(pcie_devices) + for (b, d, f, _, _) in pcie_devices: - self.logger.log( "[+] Fuzzing device {:02X}:{:02X}.{:X}".format(b, d, f) ) + self.logger.log("[+] Fuzzing device {:02X}:{:02X}.{:X}".format(b, d, f)) self.fuzz_pcie_device(b, d, f) + self.logger.log_information('Module completed') self.logger.log_warning('System may be in an unknown state, further evaluation may be needed.') - return ModuleResult.WARNING + self.res = ModuleResult.WARNING + return self.res