From af5d51bb3d5bee4c91ca12cce6ceda2fbf99a84b Mon Sep 17 00:00:00 2001 From: Aaron Frinzell Date: Tue, 8 Dec 2020 17:18:35 -0600 Subject: [PATCH] Update vmem_cmd.py CLI --- chipsec/utilcmd/vmem_cmd.py | 298 +++++++++++++++++++++--------------- 1 file changed, 177 insertions(+), 121 deletions(-) diff --git a/chipsec/utilcmd/vmem_cmd.py b/chipsec/utilcmd/vmem_cmd.py index 499b6c70..34450770 100644 --- a/chipsec/utilcmd/vmem_cmd.py +++ b/chipsec/utilcmd/vmem_cmd.py @@ -1,6 +1,6 @@ #!/usr/bin/python #CHIPSEC: Platform Security Assessment Framework -#Copyright (c) 2010-2019, Intel Corporation +#Copyright (c) 2010-2020, Intel Corporation # #This program is free software; you can redistribute it and/or #modify it under the terms of the GNU General Public License @@ -20,7 +20,6 @@ # - """ The vmem command provides direct access to read and write virtual memory. """ @@ -28,10 +27,13 @@ The vmem command provides direct access to read and write virtual memory. import os import chipsec_util -import chipsec.defines -from chipsec.logger import print_buffer -from chipsec.command import BaseCommand -from chipsec.hal import virtmem +from chipsec.command import BaseCommand +from chipsec.hal import virtmem +from chipsec.defines import bytestostring +from chipsec.logger import print_buffer +from chipsec.file import write_file, read_file +from argparse import ArgumentParser + # Virtual Memory class VMemCommand(BaseCommand): @@ -46,137 +48,191 @@ class VMemCommand(BaseCommand): Examples: - >>> chipsec_util vmem [value|file] + >>> chipsec_util vmem [value|file] >>> chipsec_util vmem readval 0xFED40000 dword >>> chipsec_util vmem read 0x41E 0x20 buffer.bin >>> chipsec_util vmem writeval 0xA0000 dword 0x9090CCCC >>> chipsec_util vmem write 0x100000000 0x1000 buffer.bin >>> chipsec_util vmem write 0x100000000 0x10 000102030405060708090A0B0C0D0E0F >>> chipsec_util vmem allocate 0x1000 - >>> chipsec_util vmem search 0xF0000 0x10000 _SM_ - >>> chipsec_util vmem getphys 0xFED00000 + >>> chipsec_util vmem search 0xF0000 0x10000 _SM_ + >>> chipsec_util vmem getphys 0xFED00000 """ - def requires_driver(self): - # No driver required when printing the util documentation - if len(self.argv) < 3: - return False + parser = ArgumentParser(usage=VMemCommand.__doc__) + subparsers = parser.add_subparsers() + + parser_read = subparsers.add_parser('read') + parser_read.add_argument('virt_address', type=lambda x: int(x, 16), help='Address (hex)') + parser_read.add_argument('size', type=lambda x: int(x, 16), nargs='?', default=0x100, help='Length (hex)') + parser_read.add_argument('buf_file', type=str, nargs='?', default='', help='Buffer file name') + parser_read.set_defaults(func=self.vmem_read) + + parser_readval = subparsers.add_parser('readval') + parser_readval.add_argument('virt_address', type=lambda x: int(x, 16), help='Address (hex)') + parser_readval.add_argument('length', type=str, nargs='?', default=None, help='Length [byte, word, dword] or (hex)') + parser_readval.set_defaults(func=self.vmem_readval) + + parser_write = subparsers.add_parser('write') + parser_write.add_argument('virt_address', type=lambda x: int(x, 16), help='Address (hex)') + parser_write.add_argument('size', type=lambda x: int(x, 16), default=0x100, help='Length (hex)') + parser_write.add_argument('buf_file', type=str, help='Buffer file name') + parser_write.set_defaults(func=self.vmem_write) + + parser_writeval = subparsers.add_parser('writeval') + parser_writeval.add_argument('virt_address', type=lambda x: int(x, 16), help='Address (hex)') + parser_writeval.add_argument('length', type=str, help='Length [byte, word, dword] or (hex)') + parser_writeval.add_argument('value', type=lambda x: int(x, 16), help='Value (hex)') + parser_writeval.set_defaults(func=self.vmem_writeval) + + parser_search = subparsers.add_parser('search') + parser_search.add_argument('virt_address', type=lambda x: int(x, 16), help='Address (hex)') + parser_search.add_argument('size', type=lambda x: int(x, 16), help='Size of memory to search (hex)') + parser_search.add_argument('value', type=str, help='Value (string)') + parser_search.set_defaults(func=self.vmem_search) + + parser_allocate = subparsers.add_parser('allocate') + parser_allocate.add_argument('size', type=lambda x: int(x, 16), help='Size of memory to allocate (hex)') + parser_allocate.set_defaults(func=self.vmem_allocate) + + parser_getphys = subparsers.add_parser('getphys') + parser_getphys.add_argument('virt_address', type=lambda x: int(x, 16), help='Address (hex)') + parser_getphys.set_defaults(func=self.vmem_getphys) + parser.parse_args(self.argv[2:], namespace=self) return True + + def vmem_read(self): + self.logger.log( '[CHIPSEC] Reading buffer from memory: VA = 0x{:016X}, len = 0x{:X}.'.format(self.virt_address, self.size) ) + try: + buffer = self._vmem.read_virtual_mem( self.virt_address, self.size ) + except (TypeError, OSError): + self.logger.error( 'Error mapping VA to PA.' ) + return + + if self.buf_file: + write_file( self.buf_file, buffer ) + self.logger.log( "[CHIPSEC] Written 0x{:X} bytes to '{}'".format(len(buffer), self.buf_file) ) + else: + print_buffer( bytestostring(buffer) ) + + + def vmem_readval(self): + width = 0x4 + value = 0x0 + if self.length is not None: + if chipsec_util.is_option_valid_width(self.length): + width = chipsec_util.get_option_width(self.length) + else: + try: + width = int(self.length, 16) + except: + width = 0 + + self.logger.log( '[CHIPSEC] Reading {:X}-byte value from VA 0x{:016X}.'.format(width, self.virt_address) ) + try: + if 0x1 == width: value = self._vmem.read_virtual_mem_byte ( self.virt_address ) + elif 0x2 == width: value = self._vmem.read_virtual_mem_word ( self.virt_address ) + elif 0x4 == width: value = self._vmem.read_virtual_mem_dword( self.virt_address ) + else: + self.logger.error( "Must specify argument in 'mem readval' as one of {}".format(chipsec_util.CMD_OPTS_WIDTH) ) + return + except (TypeError, OSError): + self.logger.error( 'Error mapping VA to PA.' ) + return + self.logger.log( '[CHIPSEC] value = 0x{:X}'.format(value) ) + + + def vmem_write(self): + if not os.path.exists( self.buf_file ): + try: + buffer = bytearray.fromhex(self.buf_file) + except ValueError as e: + self.logger.error( "Incorrect specified: '{}'".format(self.buf_file) ) + self.logger.error( str(e) ) + return + self.logger.log( "[CHIPSEC] Read 0x{:X} hex bytes from command-line: {}'".format(len(buffer), self.buf_file) ) + else: + buffer = read_file( self.buf_file ) + self.logger.log( "[CHIPSEC] Read 0x{:X} bytes from file '{}'".format(len(buffer), self.buf_file) ) + + if len(buffer) < self.size: + self.logger.error( "Number of bytes read (0x{:X}) is less than the specified (0x{:X})".format(len(buffer), self.size) ) + return + + self.logger.log( '[CHIPSEC] Writing buffer to memory: VA = 0x{:016X}, len = 0x{:X}.'.format(self.virt_address, self.size) ) + self._vmem.write_virtual_mem( self.virt_address, self.size, buffer ) + + + def vmem_writeval(self): + if chipsec_util.is_option_valid_width(self.length): + width = chipsec_util.get_option_width(self.length) + else: + try: + width = int(self.length, 16) + except: + width = 0 + + self.logger.log( '[CHIPSEC] Writing {:X}-byte value 0x{:X} to VA 0x{:016X}..'.format(width, self.value, self.virt_address) ) + try: + if 0x1 == width: self._vmem.write_virtual_mem_byte ( self.virt_address, self.value ) + elif 0x2 == width: self._vmem.write_virtual_mem_word ( self.virt_address, self.value ) + elif 0x4 == width: self._vmem.write_virtual_mem_dword( self.virt_address, self.value ) + else: + self.logger.error( "Must specify argument in 'mem writeval' as one of {}".format(chipsec_util.CMD_OPTS_WIDTH) ) + except (TypeError, OSError): + self.logger.error( 'Error mapping VA to PA.' ) + + + def vmem_search(self): + try: + buffer = self._vmem.read_virtual_mem( self.virt_address, self.size ) + except (TypeError, OSError): + self.logger.error( 'Error mapping VA to PA.' ) + return + + buffer = bytestostring(buffer) + offset = buffer.find(self.value) + + self.logger.log( "[CHIPSEC] Search buffer for '{}':".format(self.value) ) + self.logger.log( ' VA = 0x{:016X}, len = 0x{:X}'.format(self.virt_address, self.size) ) + if offset != -1: + self.logger.log( '[CHIPSEC] Target address = 0x{:X}.'.format(self.virt_address + offset) ) + else: + self.logger.log( '[CHIPSEC] Could not find the target in the searched range.' ) + + + def vmem_allocate(self): + try: + (va, pa) = self._vmem.alloc_virtual_mem( self.size ) + except (TypeError, OSError): + self.logger.error( 'Error mapping VA to PA.' ) + return + self.logger.log( '[CHIPSEC] Allocated {:X} bytes of virtual memory:'.format(self.size) ) + self.logger.log( ' VA = 0x{:016X}'.format(va) ) + self.logger.log( ' PA = 0x{:016X}'.format(pa) ) + + + def vmem_getphys(self): + try: + pa = self._vmem.va2pa( self.virt_address ) + except (TypeError, OSError): + self.logger.error( 'Error mapping VA to PA.' ) + return + if pa is not None: + self.logger.log( '[CHIPSEC] Virtual memory:' ) + self.logger.log( ' VA = 0x{:016X}'.format(self.virt_address) ) + self.logger.log( ' PA = 0x{:016X}'.format(pa) ) + + def run(self): try: - _vmem = virtmem.VirtMemory(self.cs) + self._vmem = virtmem.VirtMemory(self.cs) except: return - size = 0x100 + self.func() - if len(self.argv) < 3: - print (VMemCommand.__doc__) - return - - op = self.argv[2] - - if 'allocate' == op and 4 == len(self.argv): - size = int(self.argv[3], 16) - (va, pa) = _vmem.alloc_virtual_mem( size ) - self.logger.log( '[CHIPSEC] Allocated {:X} bytes of virtual memory: VA = 0x{:016X}, PA = 0x{:016X}'.format(size, va, pa) ) - - elif 'search' == op and len(self.argv) > 5: - virt_address = int(self.argv[3], 16) - size = int(self.argv[4], 16) - - buffer = _vmem.read_virtual_mem( virt_address, size ) - buffer = chipsec.defines.bytestostring(buffer) - offset = buffer.find(self.argv[5]) - - if offset != -1: - self.logger.log( '[CHIPSEC] search buffer from memory: VA = 0x{:016X}, len = 0x{:X}, target address= 0x{:X}..'.format(virt_address, size, virt_address + offset) ) - else: - self.logger.log( '[CHIPSEC] search buffer from memory: VA = 0x{:016X}, len = 0x{:X}, can not find the target in the searched range..'.format(virt_address, size) ) - - elif 'read' == op: - virt_address = int(self.argv[3], 16) - size = int(self.argv[4], 16) if len(self.argv) > 4 else 0x100 - self.logger.log( '[CHIPSEC] reading buffer from memory: VA = 0x{:016X}, len = 0x{:X}..'.format(virt_address, size) ) - buffer = _vmem.read_virtual_mem( virt_address, size ) - if len(self.argv) > 5: - buf_file = self.argv[5] - chipsec.file.write_file( buf_file, buffer ) - self.logger.log( "[CHIPSEC] written 0x{:X} bytes to '{}'".format(len(buffer), buf_file) ) - else: - print_buffer( chipsec.defines.bytestostring(buffer) ) - - elif 'readval' == op: - virt_address = int(self.argv[3], 16) - width = 0x4 - if len(self.argv) > 4: - width = chipsec_util.get_option_width(self.argv[4]) if chipsec_util.is_option_valid_width(self.argv[4]) else int(self.argv[4], 16) - self.logger.log( '[CHIPSEC] reading {:X}-byte value from VA 0x{:016X}..'.format(width, virt_address) ) - if 0x1 == width: value = _vmem.read_virtual_mem_byte ( virt_address ) - elif 0x2 == width: value = _vmem.read_virtual_mem_word ( virt_address ) - elif 0x4 == width: value = _vmem.read_virtual_mem_dword( virt_address ) - self.logger.log( '[CHIPSEC] value = 0x{:X}'.format(value) ) - - elif 'write' == op: - virt_address = int(self.argv[3], 16) - if len(self.argv) > 4: - size = int(self.argv[4], 16) - else: - self.logger.error( "must specify argument in 'mem write'" ) - return - if len(self.argv) > 5: - buf_file = self.argv[5] - if not os.path.exists( buf_file ): - #buffer = buf_file.decode('hex') - try: - buffer = bytearray.fromhex(buf_file) - except ValueError as e: - self.logger.error( "incorrect specified: '{}'".format(buf_file) ) - self.logger.error( str(e) ) - return - self.logger.log( "[CHIPSEC] read 0x{:X} hex bytes from command-line: {}'".format(len(buffer), buf_file) ) - else: - buffer = chipsec.file.read_file( buf_file ) - self.logger.log( "[CHIPSEC] read 0x{:X} bytes from file '{}'".format(len(buffer), buf_file) ) - - if len(buffer) < size: - self.logger.error( "number of bytes read (0x{:X}) is less than the specified (0x{:X})".format(len(buffer), size) ) - return - - self.logger.log( '[CHIPSEC] writing buffer to memory: VA = 0x{:016X}, len = 0x{:X}..'.format(virt_address, size) ) - _vmem.write_virtual_mem( virt_address, size, buffer ) - else: - self.logger.error( "must specify | argument in 'mem write'" ) - return - - elif 'writeval' == op: - virt_address = int(self.argv[3], 16) - if len(self.argv) > 4: - width = chipsec_util.get_option_width(self.argv[4]) if chipsec_util.is_option_valid_width(self.argv[4]) else int(self.argv[4], 16) - else: - self.logger.error( "must specify argument in 'mem writeval' as one of {}".format(chipsec_util.CMD_OPTS_WIDTH) ) - return - if len(self.argv) > 5: - value = int(self.argv[5], 16) - else: - self.logger.error( "must specify argument in 'mem writeval'" ) - return - - self.logger.log( '[CHIPSEC] writing {:X}-byte value 0x{:X} to VA 0x{:016X}..'.format(width, value, virt_address) ) - if 0x1 == width: _vmem.write_virtual_mem_byte ( virt_address, value ) - elif 0x2 == width: _vmem.write_virtual_mem_word ( virt_address, value ) - elif 0x4 == width: _vmem.write_virtual_mem_dword( virt_address, value ) - - elif 'getphys' == op: - virt_address = int(self.argv[3], 16) - pa = _vmem.va2pa( virt_address ) - if pa is not None: - self.logger.log( '[CHIPSEC] Allocated {:X} bytes of virtual memory: VA = 0x{:016X}, PA = 0x{:016X}'.format(size, virt_address, pa) ) - - else: - print (VMemCommand.__doc__) - return commands = { 'vmem': VMemCommand }