Пример #1
0
    def testIterateVolumes(self):
        """Test the iterate volumes functionality."""
        volume_system = tsk_volume_system.TSKVolumeSystem()
        volume_system.Open(self._tsk_path_spec)

        self.assertEqual(volume_system.bytes_per_sector, 512)

        self.assertEqual(volume_system.number_of_sections, 7)
        self.assertEqual(volume_system.number_of_volumes, 2)

        volume = volume_system.GetVolumeByIndex(1)
        self.assertIsNotNone(volume)

        self.assertEqual(volume.number_of_extents, 1)
        self.assertEqual(volume.number_of_attributes, 2)
        self.assertEqual(volume.identifier, 'p2')

        expected_value = 6
        volume_attribute = volume.GetAttribute('address')
        self.assertIsNotNone(volume_attribute)
        self.assertEqual(volume_attribute.value, expected_value)

        expected_value = 'Linux (0x83)'
        volume_attribute = volume.GetAttribute('description')
        self.assertIsNotNone(volume_attribute)
        self.assertEqual(volume_attribute.value, expected_value)

        volume = volume_system.GetVolumeByIndex(7)
        self.assertIsNone(volume)
Пример #2
0
    def _GetTSKPartitionIdentifiers(self, scan_node):

        if not scan_node or not scan_node.path_spec:
            raise errors.SourceScannerError('Invalid scan node.')

        volume_system = tsk_volume_system.TSKVolumeSystem()
        volume_system.Open(scan_node.path_spec)

        volume_identifiers = self._source_scanner.GetVolumeIdentifiers(
            volume_system)
        if not volume_identifiers:
            return []

        # TODO: refactor self._partitions to use scan options.
        if self._partitions:
            if self._partitions == 'all':
                partitions = range(1, volume_system.number_of_volumes + 1)
            else:
                partitions = self._ParseVolumeIdentifiersString(
                    self._partitions, prefix='p')

            selected_volume_identifiers = self._NormalizedVolumeIdentifiers(
                volume_system, partitions, prefix='p')

            if not set(selected_volume_identifiers).difference(
                    volume_identifiers):
                return selected_volume_identifiers

        if len(volume_identifiers) == 1:
            return volume_identifiers

        return self._NormalizedVolumeIdentifiers(volume_system,
                                                 volume_identifiers,
                                                 prefix='p')
Пример #3
0
    def _GetTSKPartitionIdentifiers(self, scan_node):
        """Determines the TSK partition identifiers.

    Args:
      scan_node: the scan node (instance of dfvfs.ScanNode).

    Returns:
      A list of partition identifiers.

    Raises:
      ScannerError: if the format of or within the source is not supported or
                    the the scan node is invalid or if the volume for
                    a specific identifier cannot be retrieved.
    """
        if not scan_node or not scan_node.path_spec:
            raise errors.ScannerError(u'Invalid scan node.')

        volume_system = tsk_volume_system.TSKVolumeSystem()
        volume_system.Open(scan_node.path_spec)

        volume_identifiers = self._source_scanner.GetVolumeIdentifiers(
            volume_system)
        if not volume_identifiers:
            raise errors.ScannerError(u'No partitions found.')

        if not self._mediator or len(volume_identifiers) == 1:
            return volume_identifiers

        try:
            return self._mediator.GetPartitionIdentifiers(
                volume_system, volume_identifiers)
        except KeyboardInterrupt:
            raise errors.ScannerError(u'File system scan aborted.')
Пример #4
0
    def testNormalizedVolumeIdentifiersPartitionedImage(self):
        """Tests the _NormalizedVolumeIdentifiers function."""
        test_mediator = TestVolumeScannerMediator()
        test_scanner = volume_scanner.VolumeScanner(mediator=test_mediator)

        test_path = self._GetTestFilePath(['tsk_volume_system.raw'])
        self._SkipIfPathNotExists(test_path)

        test_os_path_spec = path_spec_factory.Factory.NewPathSpec(
            definitions.TYPE_INDICATOR_OS, location=test_path)
        test_raw_path_spec = path_spec_factory.Factory.NewPathSpec(
            definitions.TYPE_INDICATOR_RAW, parent=test_os_path_spec)
        test_tsk_partition_path_spec = path_spec_factory.Factory.NewPathSpec(
            definitions.TYPE_INDICATOR_TSK_PARTITION,
            parent=test_raw_path_spec)

        volume_system = tsk_volume_system.TSKVolumeSystem()
        volume_system.Open(test_tsk_partition_path_spec)

        volume_identifiers = test_scanner._NormalizedVolumeIdentifiers(
            volume_system, ['p1', 'p2'], prefix='p')
        self.assertEqual(volume_identifiers, ['p1', 'p2'])

        volume_identifiers = test_scanner._NormalizedVolumeIdentifiers(
            volume_system, ['1', '2'], prefix='p')
        self.assertEqual(volume_identifiers, ['p1', 'p2'])

        volume_identifiers = test_scanner._NormalizedVolumeIdentifiers(
            volume_system, [1, 2], prefix='p')
        self.assertEqual(volume_identifiers, ['p1', 'p2'])

        # Test error conditions.
        with self.assertRaises(errors.ScannerError):
            test_scanner._NormalizedVolumeIdentifiers(volume_system, ['p3'],
                                                      prefix='p')
Пример #5
0
    def _get_tsk_partition_identifiers(self, scan_node, interactive):
        """Determines the TSK partition identifiers.
        Args:
            scan_node: the scan node (instance of dfvfs.ScanNode).
        Returns:
            A list of partition identifiers.
        Raises:
            RuntimeError: if the format of or within the source is not supported or
                                        the the scan node is invalid or if the volume for
                                        a specific identifier cannot be retrieved.
        """
        if not scan_node or not scan_node.path_spec:
            raise RuntimeError(u'Invalid scan node.')

        volume_system = tsk_volume_system.TSKVolumeSystem()
        volume_system.Open(scan_node.path_spec)

        volume_identifiers = self._source_scanner.GetVolumeIdentifiers(
            volume_system)
        if not volume_identifiers:
            print(u'[WARNING] No partitions found.')
            return

        if len(volume_identifiers) == 1:
            return volume_identifiers

        # TODO REMOVE INTERACTION
        # try:
        #     selected_volume_identifier = self._prompt_user_for_partition_identifier(
        #         volume_system, volume_identifiers, interactive)
        # except KeyboardInterrupt:
        #     raise RuntimeError(u'File system scan aborted.')
        #
        # if selected_volume_identifier == u'all':
        return volume_identifiers
Пример #6
0
    def _GetTSKPartitionIdentifiers(self, scan_node):
        """Determines the TSK partition identifiers.

    This method first checks for the preferred partition number, then
    falls back to prompt the user if no usable preferences were specified.

    Args:
      scan_node (dfvfs.SourceScanNode): scan node.

    Returns:
      list[str]: TSK partition identifiers.

    Raises:
      RuntimeError: if the volume for a specific identifier cannot be
          retrieved.
      SourceScannerError: if the format of or within the source
          is not supported or the the scan node is invalid.
      UserAbort: if the user requested to abort.
    """
        if not scan_node or not scan_node.path_spec:
            raise errors.SourceScannerError('Invalid scan node.')

        volume_system = tsk_volume_system.TSKVolumeSystem()
        volume_system.Open(scan_node.path_spec)

        volume_identifiers = self._source_scanner.GetVolumeIdentifiers(
            volume_system)
        if not volume_identifiers:
            return []

        # TODO: refactor self._partitions to use scan options.
        if self._partitions:
            if self._partitions == 'all':
                partitions = range(1, volume_system.number_of_volumes + 1)
            else:
                partitions = self._ParseVolumeIdentifiersString(
                    self._partitions, prefix='p')

            selected_volume_identifiers = self._NormalizedVolumeIdentifiers(
                volume_system, partitions, prefix='p')

            if not set(selected_volume_identifiers).difference(
                    volume_identifiers):
                return selected_volume_identifiers

        if len(volume_identifiers) > 1:
            if self._unattended_mode:
                raise errors.SourceScannerError(
                    'More than 1 parition found but no paritions specified.')

            try:
                volume_identifiers = self._PromptUserForPartitionIdentifiers(
                    volume_system, volume_identifiers)
            except KeyboardInterrupt:
                raise errors.UserAbort('File system scan aborted.')

        return self._NormalizedVolumeIdentifiers(volume_system,
                                                 volume_identifiers,
                                                 prefix='p')
Пример #7
0
    def _GetTSKPartitionIdentifiers(self, scan_node):
        if not scan_node or not scan_node.path_spec:
            raise RuntimeError(u'Invalid scan node.')

        volume_system = tsk_volume_system.TSKVolumeSystem()
        volume_system.Open(scan_node.path_spec)

        volume_identifiers = self._source_scanner.GetVolumeIdentifiers(
            volume_system)

        if not volume_identifiers:
            print(u'[WARNING] No partitions found.')
            return

        return volume_identifiers
Пример #8
0
  def testGetVolumeIdentifiers(self):
    """Test the GetVolumeIdentifiers function."""
    test_path = self._GetTestFilePath(['tsk_volume_system.raw'])
    test_os_path_spec = path_spec_factory.Factory.NewPathSpec(
        definitions.TYPE_INDICATOR_OS, location=test_path)
    test_raw_path_spec = path_spec_factory.Factory.NewPathSpec(
        definitions.TYPE_INDICATOR_RAW, parent=test_os_path_spec)
    test_tsk_partition_path_spec = path_spec_factory.Factory.NewPathSpec(
        definitions.TYPE_INDICATOR_TSK_PARTITION, parent=test_raw_path_spec)

    volume_system = tsk_volume_system.TSKVolumeSystem()
    volume_system.Open(test_tsk_partition_path_spec)

    volume_identifiers = self._source_scanner.GetVolumeIdentifiers(
        volume_system)
    self.assertEqual(volume_identifiers, ['p1', 'p2'])
Пример #9
0
    def _GetTSKPartitionIdentifiers(self, scan_node):
        """Determines the TSK partition identifiers.

    This method first checks for the preferred partition number, then
    falls back to prompt the user if no usable preferences were specified.

    Args:
      scan_node (dfvfs.SourceScanNode): scan node.

    Returns:
      list[str]: TSK partition identifiers.

    Raises:
      RuntimeError: if the volume for a specific identifier cannot be
          retrieved.
      SourceScannerError: if the format of or within the source
          is not supported or the the scan node is invalid.
      UserAbort: if the user requested to abort.
    """
        if not scan_node or not scan_node.path_spec:
            raise errors.SourceScannerError('Invalid scan node.')

        volume_system = tsk_volume_system.TSKVolumeSystem()
        volume_system.Open(scan_node.path_spec)

        volume_identifiers = self._source_scanner.GetVolumeIdentifiers(
            volume_system)
        if not volume_identifiers:
            return []

        # TODO: refactor self._partitions to use scan options.
        if self._partitions:
            partitions = range(1, volume_system.number_of_volumes + 1)

            selected_volume_identifiers = self._NormalizedVolumeIdentifiers(
                volume_system, partitions, prefix='p')

            if not set(selected_volume_identifiers).difference(
                    volume_identifiers):
                return selected_volume_identifiers

        if len(volume_identifiers) == 1:
            return volume_identifiers

        return self._NormalizedVolumeIdentifiers(volume_system,
                                                 volume_identifiers,
                                                 prefix='p')
Пример #10
0
    def _GetTSKPartitionIdentifiers(self, scan_node):
        """Determines the TSK partition identifiers.

    Args:
      scan_node (SourceScanNode): scan node.

    Returns:
      list[str]: TSK partition identifiers.

    Raises:
      ScannerError: if the format of or within the source is not supported or
          the scan node is invalid or if the volume for a specific identifier
          cannot be retrieved.
      UserAbort: if the user requested to abort.
    """
        if not scan_node or not scan_node.path_spec:
            raise errors.ScannerError('Invalid scan node.')

        volume_system = tsk_volume_system.TSKVolumeSystem()
        volume_system.Open(scan_node.path_spec)

        volume_identifiers = self._source_scanner.GetVolumeIdentifiers(
            volume_system)
        if not volume_identifiers:
            return []

        if len(volume_identifiers) == 1:
            return volume_identifiers

        if not self._mediator:
            raise errors.ScannerError(
                'Unable to proceed. Partitions found but no mediator to determine '
                'how they should be used.')

        try:
            volume_identifiers = self._mediator.GetPartitionIdentifiers(
                volume_system, volume_identifiers)

        except KeyboardInterrupt:
            raise errors.UserAbort('File system scan aborted.')

        return self._NormalizedVolumeIdentifiers(volume_system,
                                                 volume_identifiers,
                                                 prefix='p')
Пример #11
0
  def testPrintTSKPartitionIdentifiersOverview(self):
    """Tests the _PrintTSKPartitionIdentifiersOverview function."""
    test_file_path = self._GetTestFilePath(['tsk_volume_system.raw'])
    self._SkipIfPathNotExists(test_file_path)

    test_os_path_spec = path_spec_factory.Factory.NewPathSpec(
        dfvfs_definitions.TYPE_INDICATOR_OS, location=test_file_path)
    test_raw_path_spec = path_spec_factory.Factory.NewPathSpec(
        dfvfs_definitions.TYPE_INDICATOR_RAW, parent=test_os_path_spec)
    test_tsk_partition_path_spec = path_spec_factory.Factory.NewPathSpec(
        dfvfs_definitions.TYPE_INDICATOR_TSK_PARTITION,
        parent=test_raw_path_spec)

    volume_system = tsk_volume_system.TSKVolumeSystem()
    volume_system.Open(test_tsk_partition_path_spec)

    file_object = io.BytesIO()
    test_output_writer = tools.FileObjectOutputWriter(file_object)

    test_mediator = storage_media_tool.StorageMediaToolMediator(
        output_writer=test_output_writer)

    test_mediator._PrintTSKPartitionIdentifiersOverview(
        volume_system, ['p1', 'p2'])

    file_object.seek(0, os.SEEK_SET)
    output_data = file_object.read()

    expected_output_data = [
        b'The following partitions were found:',
        b'',
        b'Identifier      Offset (in bytes)       Size (in bytes)',
        (b'p1              512 (0x00000200)        175.0KiB / 179.2kB '
         b'(179200 B)'),
        b'p2              180224 (0x0002c000)     1.2MiB / 1.3MB (1294336 B)',
        b'',
        b'']

    if not win32console:
      # Using join here since Python 3 does not support format of bytes.
      expected_output_data[2] = b''.join([
          b'\x1b[1m', expected_output_data[2], b'\x1b[0m'])

    self.assertEqual(output_data.split(b'\n'), expected_output_data)
Пример #12
0
    def testPrintTSKPartitionIdentifiersOverview(self):
        """Tests the _PrintTSKPartitionIdentifiersOverview function."""
        test_path = self._GetTestFilePath(['mbr.raw'])
        self._SkipIfPathNotExists(test_path)

        test_os_path_spec = path_spec_factory.Factory.NewPathSpec(
            definitions.TYPE_INDICATOR_OS, location=test_path)
        test_raw_path_spec = path_spec_factory.Factory.NewPathSpec(
            definitions.TYPE_INDICATOR_RAW, parent=test_os_path_spec)
        test_tsk_partition_path_spec = path_spec_factory.Factory.NewPathSpec(
            definitions.TYPE_INDICATOR_TSK_PARTITION,
            parent=test_raw_path_spec)

        volume_system = tsk_volume_system.TSKVolumeSystem()
        volume_system.Open(test_tsk_partition_path_spec)

        file_object = io.BytesIO()
        test_output_writer = command_line.FileObjectOutputWriter(file_object)

        test_mediator = command_line.CLIVolumeScannerMediator(
            output_writer=test_output_writer)

        test_mediator._PrintPartitionIdentifiersOverview(
            volume_system, ['p1', 'p2'])

        file_object.seek(0, os.SEEK_SET)
        output_data = file_object.read()

        expected_output_data = [
            b'The following partitions were found:', b'',
            b'Identifier      Offset (in bytes)       Size (in bytes)',
            b'p1              512 (0x00000200)        64.5KiB / 66.0kB (66048 B)',
            b'p2              67072 (0x00010600)      64.5KiB / 66.0kB (66048 B)',
            b''
        ]

        if not win32console:
            # Using join here since Python 3 does not support format of bytes.
            expected_output_data[2] = b''.join(
                [b'\x1b[1m', expected_output_data[2], b'\x1b[0m'])

        self.assertEqual(output_data.split(b'\n'), expected_output_data)
Пример #13
0
    def _GetTSKPartitionIdentifiers(self, scan_node):
        """Determines the TSK partition identifiers.

    Args:
      scan_node: the scan node (instance of dfvfs.ScanNode).

    Returns:
      A list of partition identifiers.

    Raises:
      RuntimeError: if the format of or within the source is not supported or
                    the the scan node is invalid or if the volume for
                    a specific identifier cannot be retrieved.
    """
        if not scan_node or not scan_node.path_spec:
            raise RuntimeError(u'Invalid scan node.')

        volume_system = tsk_volume_system.TSKVolumeSystem()
        volume_system.Open(scan_node.path_spec)

        volume_identifiers = self._source_scanner.GetVolumeIdentifiers(
            volume_system)
        if not volume_identifiers:
            print(u'[WARNING] No partitions found.')
            return

        if len(volume_identifiers) == 1:
            return volume_identifiers

        try:
            selected_volume_identifier = self._PromptUserForPartitionIdentifier(
                volume_system, volume_identifiers)
        except KeyboardInterrupt:
            raise RuntimeError(u'File system scan aborted.')

        if selected_volume_identifier == u'all':
            return volume_identifiers

        return [selected_volume_identifier]
Пример #14
0
    def testGetNormalizedTSKVolumeIdentifiers(self):
        """Tests the _GetNormalizedTSKVolumeIdentifiers function."""
        test_tool = storage_media_tool.StorageMediaTool()

        test_path = self._GetTestFilePath(['tsk_volume_system.raw'])
        os_path_spec = path_spec_factory.Factory.NewPathSpec(
            dfvfs_definitions.TYPE_INDICATOR_OS, location=test_path)
        tsk_partition_path_spec = path_spec_factory.Factory.NewPathSpec(
            dfvfs_definitions.TYPE_INDICATOR_TSK_PARTITION,
            parent=os_path_spec)

        volume_system = tsk_volume_system.TSKVolumeSystem()
        volume_system.Open(tsk_partition_path_spec)

        volume_identifiers = test_tool._GetNormalizedTSKVolumeIdentifiers(
            volume_system, ['p1', 'p2'])
        self.assertEqual(volume_identifiers, [1, 2])

        with self.assertRaises(KeyError):
            test_tool._GetNormalizedTSKVolumeIdentifiers(volume_system, [1, 2])

        with self.assertRaises(KeyError):
            test_tool._GetNormalizedTSKVolumeIdentifiers(volume_system, ['p3'])
Пример #15
0
    def _GetNextLevelTSKPartionVolumeSystemPathSpec(self, source_path_spec):
        """Determines the next level volume system path specification.

    Args:
      source_path_spec: the source path specification (instance of
                        dfvfs.PathSpec).

    Returns:
      The next level volume system path specification (instance of
      dfvfs.PathSpec).

    Raises:
      RuntimeError: if the format of or within the source is not supported.
    """
        volume_system_path_spec = path_spec_factory.Factory.NewPathSpec(
            definitions.TYPE_INDICATOR_TSK_PARTITION,
            location=u'/',
            parent=source_path_spec)

        volume_system = tsk_volume_system.TSKVolumeSystem()
        volume_system.Open(volume_system_path_spec)

        volume_identifiers = []
        for volume in volume_system.volumes:
            volume_identifier = getattr(volume, 'identifier', None)
            if volume_identifier:
                volume_identifiers.append(volume_identifier)

        if not volume_identifiers:
            logging.warning(u'No supported partitions found.')
            return source_path_spec

        if len(volume_identifiers) == 1:
            return path_spec_factory.Factory.NewPathSpec(
                definitions.TYPE_INDICATOR_TSK_PARTITION,
                location=u'/p1',
                parent=source_path_spec)

        print(u'The following partitions were found:')
        print(u'Identifier\tOffset\t\t\tSize')

        for volume_identifier in sorted(volume_identifiers):
            volume = volume_system.GetVolumeByIdentifier(volume_identifier)
            if not volume:
                raise RuntimeError(
                    u'Volume missing for identifier: {0:s}.'.format(
                        volume_identifier))

            volume_extent = volume.extents[0]
            print(u'{0:s}\t\t{1:d} (0x{1:08x})\t{2:s}'.format(
                volume.identifier, volume_extent.offset,
                self._GetHumanReadableSize(volume_extent.size)))

        print(u'')

        while True:
            print(
                u'Please specify the identifier of the partition that should '
                u'be processed:')

            selected_volume_identifier = sys.stdin.readline()
            selected_volume_identifier = selected_volume_identifier.strip()

            if selected_volume_identifier in volume_identifiers:
                break

            print(u'')
            print(
                u'Unsupported partition identifier, please try again or abort '
                u'with Ctrl^C.')
            print(u'')

        location = u'/{0:s}'.format(selected_volume_identifier)

        return path_spec_factory.Factory.NewPathSpec(
            definitions.TYPE_INDICATOR_TSK_PARTITION,
            location=location,
            parent=source_path_spec)
Пример #16
0
    def _GetTSKPartitionIdentifiers(self,
                                    scan_node,
                                    partition_offset=None,
                                    partitions=None):
        """Determines the TSK partition identifiers.

    This method first checks for the preferred partition number, then for
    the preferred partition offset and falls back to prompt the user if
    no usable preferences were specified.

    Args:
      scan_node (dfvfs.SourceScanNode): scan node.
      partition_offset (Optional[int]): preferred partition byte offset.
      partitions (Optional[list[str]]): preferred partition identifiers.

    Returns:
      list[str]: partition identifiers.

    Raises:
      RuntimeError: if the volume for a specific identifier cannot be
          retrieved.
      SourceScannerError: if the format of or within the source
          is not supported or the the scan node is invalid.
    """
        if not scan_node or not scan_node.path_spec:
            raise errors.SourceScannerError('Invalid scan node.')

        volume_system = tsk_volume_system.TSKVolumeSystem()
        volume_system.Open(scan_node.path_spec)

        volume_identifiers = self._source_scanner.GetVolumeIdentifiers(
            volume_system)
        if not volume_identifiers:
            self._output_writer.Write('[WARNING] No partitions found.\n')
            return None

        normalized_volume_identifiers = self._GetNormalizedTSKVolumeIdentifiers(
            volume_system, volume_identifiers)

        if partitions:
            if partitions == ['all']:
                partitions = range(1, volume_system.number_of_volumes + 1)

            if not set(partitions).difference(normalized_volume_identifiers):
                return [
                    'p{0:d}'.format(partition_number)
                    for partition_number in partitions
                ]

        if partition_offset is not None:
            for volume in volume_system.volumes:
                volume_extent = volume.extents[0]
                if volume_extent.offset == partition_offset:
                    return [volume.identifier]

            self._output_writer.Write(
                ('[WARNING] No such partition with offset: {0:d} '
                 '(0x{0:08x}).\n').format(partition_offset))

        if len(volume_identifiers) == 1:
            return volume_identifiers

        try:
            selected_volume_identifier = self._PromptUserForPartitionIdentifier(
                volume_system, volume_identifiers)
        except KeyboardInterrupt:
            raise errors.UserAbort('File system scan aborted.')

        if selected_volume_identifier == 'all':
            return volume_identifiers

        return [selected_volume_identifier]
Пример #17
0
    def _ProcessPartition(self, evidence_path, path_spec):
        """Generate RawDiskPartition from a PathSpec.

    Args:
      evidence_path (str): Local path of the parent evidence
      path_spec (dfvfs.PathSpec): dfVFS path spec.

    Returns:
      A new RawDiskPartition evidence item and a list of strings containing
      partition information to add to the status report.
    """
        status_report = []

        fs_path_spec = path_spec
        fs_location = None
        partition_location = None
        volume_index = None
        partition_index = None
        partition_offset = None
        partition_size = None

        # File system location / identifier
        fs_location = getattr(path_spec, 'location', None)
        while path_spec.HasParent():
            type_indicator = path_spec.type_indicator
            if type_indicator == dfvfs_definitions.TYPE_INDICATOR_APFS_CONTAINER:
                # APFS volume index
                volume_index = getattr(path_spec, 'volume_index', None)

            if type_indicator == dfvfs_definitions.TYPE_INDICATOR_TSK_PARTITION:
                if fs_location in ('\\', '/'):
                    # Partition location / identifier
                    fs_location = getattr(path_spec, 'location', None)
                partition_location = getattr(path_spec, 'location', None)
                # Partition index
                partition_index = getattr(path_spec, 'part_index', None)

                volume_system = tsk_volume_system.TSKVolumeSystem()
                try:
                    volume_system.Open(path_spec)
                    volume_identifier = partition_location.replace('/', '')
                    volume = volume_system.GetVolumeByIdentifier(
                        volume_identifier)

                    partition_offset = volume.extents[0].offset
                    partition_size = volume.extents[0].size
                except dfvfs_errors.VolumeSystemError as e:
                    raise TurbiniaException(
                        'Could not process partition: {0!s}'.format(e))
                break

            path_spec = path_spec.parent

        status_report.append(fmt.heading5('{0!s}:'.format(fs_location)))
        if partition_index:
            if not volume_index is None:
                status_report.append(
                    fmt.bullet('Volume index: {0!s}'.format(volume_index)))
            status_report.append(
                fmt.bullet('Partition index: {0!s}'.format(partition_index)))
            status_report.append(
                fmt.bullet('Partition offset: {0!s}'.format(partition_offset)))
            status_report.append(
                fmt.bullet('Partition size: {0!s}'.format(partition_size)))
        else:
            status_report.append(
                fmt.bullet('Source evidence is a volume image'))

        partition_evidence = RawDiskPartition(
            source_path=evidence_path,
            path_spec=fs_path_spec,
            partition_offset=partition_offset,
            partition_size=partition_size)

        return partition_evidence, status_report
Пример #18
0
  def _GetVolumeTSKPartition(
      self, scan_context, partition_number=None, partition_offset=None):
    """Determines the volume path specification.

    Args:
      scan_context: the scan context (instance of dfvfs.ScanContext).
      partition_number: Optional preferred partition number. The default is
                        None.
      partition_offset: Optional preferred partition byte offset. The default
                        is None.

    Returns:
      The volume scan node (instance of dfvfs.SourceScanNode) or None
      if no supported partition was found.

    Raises:
      SourceScannerError: if the format of or within the source
                          is not supported or the the scan context
                          is invalid.
      RuntimeError: if the volume for a specific identifier cannot be
                    retrieved.
    """
    if (not scan_context or not scan_context.last_scan_node or
        not scan_context.last_scan_node.path_spec):
      raise errors.SourceScannerError(u'Invalid scan context.')

    volume_system = tsk_volume_system.TSKVolumeSystem()
    volume_system.Open(scan_context.last_scan_node.path_spec)

    volume_identifiers = self._source_scanner.GetVolumeIdentifiers(
        volume_system)
    if not volume_identifiers:
      logging.info(u'No supported partitions found.')
      return

    if partition_number is not None and partition_number > 0:
      # Plaso uses partition numbers starting with 1 while dfvfs expects
      # the volume index to start with 0.
      volume = volume_system.GetVolumeByIndex(partition_number - 1)
      if volume:
        volume_location = u'/{0:s}'.format(volume.identifier)
        volume_scan_node = scan_context.last_scan_node.GetSubNodeByLocation(
            volume_location)
        if not volume_scan_node:
          raise RuntimeError(
              u'Unable to retrieve volume scan node by location: {0:s}'.format(
                  volume_location))
        return volume_scan_node

      logging.warning(u'No such partition: {0:d}.'.format(partition_number))

    if partition_offset is not None:
      for volume in volume_system.volumes:
        volume_extent = volume.extents[0]
        if volume_extent.offset == partition_offset:
          volume_location = u'/{0:s}'.format(volume.identifier)
          volume_scan_node = scan_context.last_scan_node.GetSubNodeByLocation(
              volume_location)
          if not volume_scan_node:
            raise RuntimeError((
                u'Unable to retrieve volume scan node by location: '
                u'{0:s}').format(volume_location))
          return volume_scan_node

      logging.warning(
          u'No such partition with offset: {0:d} (0x{0:08x}).'.format(
              partition_offset))

    if len(volume_identifiers) == 1:
      volume_location = u'/{0:s}'.format(volume_identifiers[0])

    else:
      try:
        selected_volume_identifier = self._GetPartitionIdentifierFromUser(
            volume_system, volume_identifiers)
      except KeyboardInterrupt:
        raise errors.UserAbort(u'File system scan aborted.')

      volume = volume_system.GetVolumeByIdentifier(selected_volume_identifier)
      if not volume:
        raise RuntimeError(
            u'Unable to retrieve volume by identifier: {0:s}'.format(
                selected_volume_identifier))

      volume_location = u'/{0:s}'.format(selected_volume_identifier)

    volume_scan_node = scan_context.last_scan_node.GetSubNodeByLocation(
        volume_location)
    if not volume_scan_node:
      raise RuntimeError(
          u'Unable to retrieve volume scan node by location: {0:s}'.format(
              volume_location))
    return volume_scan_node
Пример #19
0
    def testGetPartitionIdentifiers(self):
        """Tests the GetPartitionIdentifiers function."""
        test_path = self._GetTestFilePath(['tsk_volume_system.raw'])
        test_os_path_spec = path_spec_factory.Factory.NewPathSpec(
            definitions.TYPE_INDICATOR_OS, location=test_path)
        test_raw_path_spec = path_spec_factory.Factory.NewPathSpec(
            definitions.TYPE_INDICATOR_RAW, parent=test_os_path_spec)
        test_tsk_partition_path_spec = path_spec_factory.Factory.NewPathSpec(
            definitions.TYPE_INDICATOR_TSK_PARTITION,
            parent=test_raw_path_spec)

        volume_system = tsk_volume_system.TSKVolumeSystem()
        volume_system.Open(test_tsk_partition_path_spec)

        file_object = io.BytesIO()
        test_output_writer = command_line.FileObjectOutputWriter(file_object)

        test_mediator = command_line.CLIVolumeScannerMediator(
            output_writer=test_output_writer)

        # Test selection of single partition.
        input_file_object = io.BytesIO(b'2\n')
        test_input_reader = command_line.FileObjectInputReader(
            input_file_object)

        output_file_object = io.BytesIO()
        test_output_writer = command_line.FileObjectOutputWriter(
            output_file_object)

        test_mediator = command_line.CLIVolumeScannerMediator(
            input_reader=test_input_reader, output_writer=test_output_writer)

        volume_identifiers = test_mediator.GetPartitionIdentifiers(
            volume_system, ['p1', 'p2'])

        self.assertEqual(volume_identifiers, ['p2'])

        # Test selection of single partition.
        input_file_object = io.BytesIO(b'p2\n')
        test_input_reader = command_line.FileObjectInputReader(
            input_file_object)

        output_file_object = io.BytesIO()
        test_output_writer = command_line.FileObjectOutputWriter(
            output_file_object)

        test_mediator = command_line.CLIVolumeScannerMediator(
            input_reader=test_input_reader, output_writer=test_output_writer)

        volume_identifiers = test_mediator.GetPartitionIdentifiers(
            volume_system, ['p1', 'p2'])

        self.assertEqual(volume_identifiers, ['p2'])

        # Test selection of single partition with invalid input on first attempt.
        input_file_object = io.BytesIO(b'bogus\np2\n')
        test_input_reader = command_line.FileObjectInputReader(
            input_file_object)

        output_file_object = io.BytesIO()
        test_output_writer = command_line.FileObjectOutputWriter(
            output_file_object)

        test_mediator = command_line.CLIVolumeScannerMediator(
            input_reader=test_input_reader, output_writer=test_output_writer)

        volume_identifiers = test_mediator.GetPartitionIdentifiers(
            volume_system, ['p1', 'p2'])

        self.assertEqual(volume_identifiers, ['p2'])

        # Test selection of all partitions.
        input_file_object = io.BytesIO(b'all\n')
        test_input_reader = command_line.FileObjectInputReader(
            input_file_object)

        output_file_object = io.BytesIO()
        test_output_writer = command_line.FileObjectOutputWriter(
            output_file_object)

        test_mediator = command_line.CLIVolumeScannerMediator(
            input_reader=test_input_reader, output_writer=test_output_writer)

        volume_identifiers = test_mediator.GetPartitionIdentifiers(
            volume_system, ['p1', 'p2'])

        self.assertEqual(volume_identifiers, ['p1', 'p2'])

        # Test selection of no partitions.
        input_file_object = io.BytesIO(b'\n')
        test_input_reader = command_line.FileObjectInputReader(
            input_file_object)

        output_file_object = io.BytesIO()
        test_output_writer = command_line.FileObjectOutputWriter(
            output_file_object)

        test_mediator = command_line.CLIVolumeScannerMediator(
            input_reader=test_input_reader, output_writer=test_output_writer)

        volume_identifiers = test_mediator.GetPartitionIdentifiers(
            volume_system, ['p1', 'p2'])

        self.assertEqual(volume_identifiers, [])
Пример #20
0
    def _GetTSKPartitionIdentifiers(self,
                                    scan_node,
                                    partition_string=None,
                                    partition_offset=None):
        """Determines the TSK partition identifiers.

    This method first checks for the preferred partition number, then for
    the preferred partition offset and falls back to prompt the user if
    no usable preferences were specified.

    Args:
      scan_node: the scan node (instance of dfvfs.ScanNode).
      partition_string: Optional preferred partition number string. The default
                        is None.
      partition_offset: Optional preferred partition byte offset. The default
                        is None.

    Returns:
      A list of partition identifiers.

    Raises:
      RuntimeError: if the volume for a specific identifier cannot be
                    retrieved.
      SourceScannerError: if the format of or within the source
                          is not supported or the the scan node is invalid.
    """
        if not scan_node or not scan_node.path_spec:
            raise errors.SourceScannerError(u'Invalid scan node.')

        volume_system = tsk_volume_system.TSKVolumeSystem()
        volume_system.Open(scan_node.path_spec)

        volume_identifiers = self._source_scanner.GetVolumeIdentifiers(
            volume_system)
        if not volume_identifiers:
            self._output_writer.Write(u'[WARNING] No partitions found.\n')
            return

        if partition_string == u'all':
            return volume_identifiers

        if partition_string is not None and not partition_string.startswith(
                u'p'):
            return volume_identifiers

        partition_number = None
        if partition_string:
            try:
                partition_number = int(partition_string[1:], 10)
            except ValueError:
                pass

        if partition_number is not None and partition_number > 0:
            # Plaso uses partition numbers starting with 1 while dfvfs expects
            # the volume index to start with 0.
            volume = volume_system.GetVolumeByIndex(partition_number - 1)
            if volume:
                return [u'p{0:d}'.format(partition_number)]

            self._output_writer.Write(
                u'[WARNING] No such partition: {0:d}.\n'.format(
                    partition_number))

        if partition_offset is not None:
            for volume in volume_system.volumes:
                volume_extent = volume.extents[0]
                if volume_extent.offset == partition_offset:
                    return [volume.identifier]

            self._output_writer.Write(
                (u'[WARNING] No such partition with offset: {0:d} '
                 u'(0x{0:08x}).\n').format(partition_offset))

        if len(volume_identifiers) == 1:
            return volume_identifiers

        try:
            selected_volume_identifier = self._PromptUserForPartitionIdentifier(
                volume_system, volume_identifiers)
        except KeyboardInterrupt:
            raise errors.UserAbort(u'File system scan aborted.')

        if selected_volume_identifier == u'all':
            return volume_identifiers

        return [selected_volume_identifier]
Пример #21
0
    def _ProcessPartition(self, path_spec):
        """Generate RawDiskPartition from a PathSpec.

    Args:
      path_spec (dfvfs.PathSpec): dfVFS path spec.

    Returns:
      A new RawDiskPartition evidence item and a list of strings containing
      partition information to add to the status report.
    """
        status_report = []

        fs_path_spec = path_spec
        fs_location = None
        partition_location = None
        volume_index = None
        partition_index = None
        partition_offset = None
        partition_size = None
        lv_uuid = None

        # File system location / identifier
        is_lvm = False
        fs_location = getattr(path_spec, 'location', None)
        while path_spec.HasParent():
            type_indicator = path_spec.type_indicator
            if type_indicator == dfvfs_definitions.TYPE_INDICATOR_APFS_CONTAINER:
                # APFS volume index
                volume_index = getattr(path_spec, 'volume_index', None)

            if type_indicator in (
                    dfvfs_definitions.TYPE_INDICATOR_GPT,
                    dfvfs_definitions.TYPE_INDICATOR_LVM,
                    dfvfs_definitions.TYPE_INDICATOR_TSK_PARTITION):
                if fs_location in ('\\', '/'):
                    # Partition location / identifier
                    fs_location = getattr(path_spec, 'location', None)
                partition_location = getattr(path_spec, 'location', None)
                # Partition index
                partition_index = getattr(path_spec, 'part_index', None)

                if type_indicator == dfvfs_definitions.TYPE_INDICATOR_TSK_PARTITION:
                    volume_system = tsk_volume_system.TSKVolumeSystem()
                elif type_indicator == dfvfs_definitions.TYPE_INDICATOR_LVM:
                    is_lvm = True
                    volume_system = lvm_volume_system.LVMVolumeSystem()
                else:
                    volume_system = gpt_volume_system.GPTVolumeSystem()
                try:
                    volume_system.Open(path_spec)
                    volume_identifier = partition_location.replace('/', '')
                    volume = volume_system.GetVolumeByIdentifier(
                        volume_identifier)

                    if is_lvm:
                        # LVM Logical Volume UUID
                        lv_uuid = volume.GetAttribute('identifier')
                        if lv_uuid:
                            lv_uuid = lv_uuid.value

                    partition_offset = volume.extents[0].offset
                    partition_size = volume.extents[0].size
                except dfvfs_errors.VolumeSystemError as e:
                    raise TurbiniaException(
                        'Could not process partition: {0!s}'.format(e))
                break

            path_spec = path_spec.parent

        status_report.append(fmt.heading5('{0!s}:'.format(fs_location)))
        status_report.append(
            fmt.bullet('Filesystem: {0!s}'.format(
                fs_path_spec.type_indicator)))
        if volume_index is not None:
            status_report.append(
                fmt.bullet('Volume index: {0!s}'.format(volume_index)))
        if partition_index is not None:
            status_report.append(
                fmt.bullet('Partition index: {0!s}'.format(partition_index)))
            status_report.append(
                fmt.bullet('Partition offset: {0!s}'.format(partition_offset)))
            status_report.append(
                fmt.bullet('Partition size: {0!s}'.format(partition_size)))
        if volume_index is None and partition_index is None:
            status_report.append(
                fmt.bullet('Source evidence is a volume image'))

        # Not setting path_spec here as it will need to be generated for each task
        partition_evidence = DiskPartition(partition_location=fs_location,
                                           partition_offset=partition_offset,
                                           partition_size=partition_size,
                                           lv_uuid=lv_uuid)

        return partition_evidence, status_report
Пример #22
0
  def _GetPartitionIdentifiers(self, scan_node, options):
    """Determines the partition identifiers.

    This function determines which partition identifiers need to be scanned
    based on the volume scanner options. If no options are provided and there
    is more than a single partition the mediator is used to ask the user.

    Args:
      scan_node (SourceScanNode): scan node.
      options (VolumeScannerOptions): volume scanner options.

    Returns:
      list[str]: partition identifiers.

    Raises:
      ScannerError: if the scan node is invalid or the scanner does not know
          how to proceed.
      UserAbort: if the user requested to abort.
    """
    if not scan_node or not scan_node.path_spec:
      raise errors.ScannerError('Invalid scan node.')

    if scan_node.path_spec.type_indicator == definitions.TYPE_INDICATOR_GPT:
      volume_system = gpt_volume_system.GPTVolumeSystem()
      volume_system.Open(scan_node.path_spec)
      prefix = 'gpt'
    else:
      volume_system = tsk_volume_system.TSKVolumeSystem()
      volume_system.Open(scan_node.path_spec)
      prefix = 'p'

    volume_identifiers = self._source_scanner.GetVolumeIdentifiers(
        volume_system)
    if not volume_identifiers:
      return []

    if options.partitions:
      if options.partitions == ['all']:
        partitions = range(1, volume_system.number_of_volumes + 1)
      else:
        partitions = options.partitions

      try:
        selected_volumes = self._NormalizedVolumeIdentifiers(
            volume_system, partitions, prefix=prefix)

        if not set(selected_volumes).difference(volume_identifiers):
          return selected_volumes
      except errors.ScannerError as exception:
        if self._mediator:
          self._mediator.PrintWarning('{0!s}'.format(exception))

    if len(volume_identifiers) > 1:
      if not self._mediator:
        raise errors.ScannerError(
            'Unable to proceed. More than one partitions found but no mediator '
            'to determine how they should be used.')

      try:
        volume_identifiers = self._mediator.GetPartitionIdentifiers(
            volume_system, volume_identifiers)

      except KeyboardInterrupt:
        raise errors.UserAbort('File system scan aborted.')

    return self._NormalizedVolumeIdentifiers(
        volume_system, volume_identifiers, prefix=prefix)
Пример #23
0
if not type_indicators:
    # The RAW storage media image type cannot be detected based on
    # a signature so we try to detect it based on common file naming
    # schemas.
    file_system = resolver.Resolver.OpenFileSystem(path_spec)
    raw_path_spec = path_spec_factory.Factory.NewPathSpec(
        definitions.TYPE_INDICATOR_RAW, parent=path_spec)

    glob_results = raw.RawGlobPathSpec(file_system, raw_path_spec)
    if glob_results:
        path_spec = raw_path_spec

volume_system_path_spec = path_spec_factory.Factory.NewPathSpec(
    definitions.TYPE_INDICATOR_TSK_PARTITION, location=u'/', parent=path_spec)

volume_system = tsk_volume_system.TSKVolumeSystem()
volume_system.Open(volume_system_path_spec)

volume_identifiers = []
for volume in volume_system.volumes:
    volume_identifier = getattr(volume, 'identifier', None)
    if volume_identifier:
        volume_identifiers.append(volume_identifier)

print(u'The following partitions were found:')
print(u'Identifier\tOffset\t\t\tSize')

for volume_identifier in sorted(volume_identifiers):
    volume = volume_system.GetVolumeByIdentifier(volume_identifier)
    if not volume:
        raise RuntimeError(