def var_find(self): _vars = self._uefi.list_EFI_variables() if _vars is None: self.logger.log_warning( 'Could not enumerate UEFI variables (non-UEFI OS?)' ) return is_guid = 0 try: _input_var = str(uuid.UUID(self.name_guid)) is_guid = 1 except ValueError: _input_var = self.name_guid if is_guid: self.logger.log( "[*] Searching for UEFI variable with GUID {{{}}}..".format(_input_var) ) for name in _vars: n = 0 for (off, buf, hdr, data, guid, attrs) in _vars[name]: if _input_var == guid: var_fname = '{}_{}_{}_{:d}.bin'.format(name, guid, get_attr_string(attrs).strip(), n) self.logger.log_good( "Found UEFI variable {}:{}. Dumped to '{}'".format(guid, name, var_fname) ) write_file( var_fname, data ) n += 1 else: self.logger.log( "[*] Searching for UEFI variable with name {}..".format(_input_var) ) name = _input_var if name in list(_vars.keys()): n = 0 for (off, buf, hdr, data, guid, attrs) in _vars[name]: var_fname = '{}_{}_{}_{:d}.bin'.format(name, guid, get_attr_string(attrs).strip(), n) self.logger.log_good( "Found UEFI variable {}:{}. Dumped to '{}'".format(guid, name, var_fname) ) write_file( var_fname, data ) n += 1
def check_vars(self, do_modify): res = ModuleResult.PASSED vars = self._uefi.list_EFI_variables() if vars is None: self.logger.log_warning( 'Could not enumerate UEFI Variables from runtime.') self.logger.log_important( "Note that UEFI variables may still exist, OS just did not expose runtime UEFI Variable API to read them.\nYou can extract variables directly from ROM file via 'chipsec_util.py uefi nvram bios.bin' command and verify their attributes manually." ) return ModuleResult.SKIPPED uefispec_concern = [] ro_concern = [] rw_variables = [] self.logger.log('[*] Testing UEFI variables ..') for name in vars.keys(): if name is None: pass if vars[name] is None: pass if len(vars[name]) > 1: self.logger.log_important( 'Found two instances of the variable {}.'.format(name)) for (off, buf, hdr, data, guid, attrs) in vars[name]: self.logger.log('[*] Variable {} ({})'.format( name, get_attr_string(attrs))) perms = self.uefispec_vars.get(name) if perms is not None: if perms != attrs: attr_diffs = (perms ^ attrs) extra_attr = attr_diffs & attrs missing_attr = attr_diffs & ~extra_attr uefispec_concern.append(name) if extra_attr != 0: self.logger.log_important( ' Extra attributes:' + get_attr_string(extra_attr)) if (extra_attr & ~( EFI_VARIABLE_AUTHENTICATED_WRITE_ACCESS | EFI_VARIABLE_TIME_BASED_AUTHENTICATED_WRITE_ACCESS | EFI_VARIABLE_APPEND_WRITE) != 0): res = ModuleResult.FAILED if missing_attr != 0: self.logger.log_important( ' Missing attributes:' + get_attr_string(missing_attr)) if res != ModuleResult.FAILED: res = ModuleResult.WARNING if do_modify: self.logger.log( "[*] Testing modification of {} ..".format(name)) if name in self.uefispec_ro_vars: if self.can_modify(name, guid, data): ro_concern.append(name) self.logger.log_bad( "Variable {} should be read only.".format( name)) res = ModuleResult.FAILED else: if self.can_modify(name, guid, data): rw_variables.append(name) if uefispec_concern: self.logger.log('') self.logger.log_bad( 'Variables with attributes that differ from UEFI spec:') for name in uefispec_concern: self.logger.log(' {}'.format(name)) if do_modify: if ro_concern: self.logger.log('') self.logger.log_bad( 'Variables that should have been read-only and were not:') for name in ro_concern: self.logger.log(' {}'.format(name)) if rw_variables: self.logger.log('') self.logger.log_unknown( 'Variables that are read-write (manual investigation is required):' ) for name in rw_variables: self.logger.log(' {}'.format(name)) self.logger.log('') if ModuleResult.PASSED == res: self.logger.log_passed( 'All checked EFI variables are protected according to spec.') elif ModuleResult.FAILED == res: self.logger.log_failed( 'Some EFI variables were not protected according to spec.') return res