def _mount_pytsk3_volumes(self): """Generator that mounts every partition of this image and yields the mountpoint.""" # Loop over all volumes in image. for p in self._find_pytsk3_volumes(): import pytsk3 volume = Volume(disk=self, **self.args) self.volumes.append(volume) # Fill volume with more information volume.offset = p.start * self.block_size volume.fsdescription = p.desc.strip() if self.index is not None: volume.index = '{0}.{1}'.format(self.index, p.addr) else: volume.index = p.addr volume.size = p.len * self.block_size if p.flags == pytsk3.TSK_VS_PART_FLAG_ALLOC: volume.flag = 'alloc' volume.slot = _util.determine_slot(p.table_num, p.slot_num) self._assign_disktype_data(volume) logger.info("Found allocated {2}: block offset: {0}, length: {1} ".format(p.start, p.len, volume.fsdescription)) elif p.flags == pytsk3.TSK_VS_PART_FLAG_UNALLOC: volume.flag = 'unalloc' logger.info("Found unallocated space: block offset: {0}, length: {1} ".format(p.start, p.len)) elif p.flags == pytsk3.TSK_VS_PART_FLAG_META: volume.flag = 'meta' logger.info("Found meta volume: block offset: {0}, length: {1} ".format(p.start, p.len)) # unalloc / meta partitions do not have stats and can not be mounted if volume.flag != 'alloc': yield volume continue for v in volume.init(): yield v
def _mount_parted_volumes(self): """Finds and mounts all volumes based on parted.""" # for some reason, parted does not properly return extended volume types in its machine # output, so we need to execute it twice. meta_volumes = [] try: output = _util.check_output_(['parted', self.get_raw_path(), 'print']) for line in output.splitlines(): if 'extended' in line: meta_volumes.append(int(line.split()[0])) except Exception: logger.exception("Failed executing parted command.") # skip detection of meta volumes try: # parted does not support passing in the vstype. It either works, or it doesn't. cmd = ['parted', self.get_raw_path(), '-sm', 'unit s', 'print free'] output = _util.check_output_(cmd) self.volume_source = 'multi' except Exception as e: logger.exception("Failed executing parted command") return num = 0 for line in output.splitlines(): if line.startswith("Warning") or not line or ':' not in line or line.startswith(self.get_raw_path()): continue line = line[:-1] # remove last ; try: slot, start, end, length, description = line.split(':', 4) if ':' in description: description, label, flags = description.split(':', 2) else: description, label, flags = description, '', '' volume = Volume(disk=self, **self.args) self.volumes.append(volume) volume.offset = int(start[:-1]) * self.block_size # remove last s volume.size = int(length[:-1]) * self.block_size volume.fsdescription = description if self.index is not None: volume.index = '{0}.{1}'.format(self.index, num) else: volume.index = num # TODO: detection of meta volumes if description == 'free': volume.flag = 'unalloc' logger.info("Found unallocated space: block offset: {0}, length: {1}".format(start[:-1], length[:-1])) elif int(slot) in meta_volumes: volume.flag = 'meta' volume.slot = int(slot) logger.info("Found meta volume: block offset: {0}, length: {1}".format(start[:-1], length[:-1])) else: volume.flag = 'alloc' volume.slot = int(slot) self._assign_disktype_data(volume) logger.info("Found allocated {2}: block offset: {0}, length: {1} ".format(start[:-1], length[:-1], volume.fsdescription)) except AttributeError as e: logger.exception("Error while parsing parted output") continue num += 1 # unalloc / meta partitions do not have stats and can not be mounted if volume.flag != 'alloc': yield volume continue for v in volume.init(): yield v
def _mount_mmls_volumes(self): """Finds and mounts all volumes based on mmls.""" try: cmd = ['mmls'] if self.vstype != 'detect': cmd.extend(['-t', self.vstype]) cmd.append(self.get_raw_path()) output = _util.check_output_(cmd, stderr=subprocess.STDOUT) self.volume_source = 'multi' except Exception as e: # some bug in sleuthkit makes detection sometimes difficult, so we hack around it: if hasattr(e, 'output') and "(GPT or DOS at 0)" in e.output.decode() and self.vstype != 'gpt': self.vstype = 'gpt' try: logger.warning("Error in retrieving volume info: mmls couldn't decide between GPT and DOS, " "choosing GPT for you. Use --vstype=dos to force DOS.", exc_info=True) cmd = ['mmls', '-t', self.vstype, self.get_raw_path()] output = _util.check_output_(cmd, stderr=subprocess.STDOUT) self.volume_source = 'multi' except Exception as e: logger.exception("Failed executing mmls command") return else: logger.exception("Failed executing mmls command") return output = output.split("Description", 1)[-1] for line in output.splitlines(): if not line: continue try: values = line.split(None, 5) # sometimes there are only 5 elements available description = '' index, slot, start, end, length = values[0:5] if len(values) > 5: description = values[5] volume = Volume(disk=self, **self.args) self.volumes.append(volume) volume.offset = int(start) * self.block_size volume.fsdescription = description if self.index is not None: volume.index = '{0}.{1}'.format(self.index, int(index[:-1])) else: volume.index = int(index[:-1]) volume.size = int(length) * self.block_size except Exception as e: logger.exception("Error while parsing mmls output") continue if slot.lower() == 'meta': volume.flag = 'meta' logger.info("Found meta volume: block offset: {0}, length: {1}".format(start, length)) elif slot.lower() == '-----': volume.flag = 'unalloc' logger.info("Found unallocated space: block offset: {0}, length: {1}".format(start, length)) else: volume.flag = 'alloc' if ":" in slot: volume.slot = _util.determine_slot(*slot.split(':')) else: volume.slot = _util.determine_slot(-1, slot) self._assign_disktype_data(volume) logger.info("Found allocated {2}: block offset: {0}, length: {1} ".format(start, length, volume.fsdescription)) # unalloc / meta partitions do not have stats and can not be mounted if volume.flag != 'alloc': yield volume continue for v in volume.init(): yield v