コード例 #1
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')
コード例 #2
0
    def _GetLVMVolumeIdentifiers(self, scan_node):
        """Determines the LVM volume identifiers.

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

    Returns:
      list[str]: LVM volume identifiers.

    Raises:
      SourceScannerError: if the scan node is invalid or more than 1 volume
          was found but no volumes were specified.
      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 = lvm_volume_system.LVMVolumeSystem()
        volume_system.Open(scan_node.path_spec)

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

        # TODO: refactor self._volumes to use scan options.
        if self._volumes:
            if self._volumes == 'all':
                volumes = volume_system.volume_identifiers
            else:
                volumes = self._mediator.ParseVolumeIdentifiersString(
                    self._volumes, prefix='lvm')

            selected_volume_identifiers = self._NormalizedVolumeIdentifiers(
                volume_system, volumes, prefix='lvm')

            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 volume found but no volumes specified.')

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

        return self._NormalizedVolumeIdentifiers(volume_system,
                                                 volume_identifiers,
                                                 prefix='lvm')
コード例 #3
0
    def _GetAPFSVolumeIdentifiers(self, scan_node):
        """Determines the APFS volume identifiers.

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

    Returns:
      list[str]: APFS volume identifiers.

    Raises:
      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 = apfs_volume_system.APFSVolumeSystem()
        volume_system.Open(scan_node.path_spec)

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

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

            selected_volume_identifiers = self._NormalizedVolumeIdentifiers(
                volume_system, volumes, prefix='apfs')

            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 volume found but no volumes specified.')

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

        return self._NormalizedVolumeIdentifiers(volume_system,
                                                 volume_identifiers,
                                                 prefix='apfs')
コード例 #4
0
ファイル: storage_media_tool.py プロジェクト: naaya17/plaso
    def ScanSource_CARPE(self, source_path, par_name):
        if os.path.islink(source_path):
            source_path = os.path.realpath(source_path)

        if (not source_path.startswith('\\\\.\\')
                and not os.path.exists(source_path)):
            raise errors.SourceScannerError(
                'No such device, file or directory: {0:s}.'.format(
                    source_path))

        scan_context = source_scanner.SourceScannerContext()
        scan_context.OpenSourcePath(source_path)

        try:
            self._source_scanner.Scan(scan_context)
        except (ValueError, dfvfs_errors.BackEndError) as exception:
            raise errors.SourceScannerError(
                'Unable to scan source with error: {0!s}.'.format(exception))

        if scan_context.source_type not in (
                scan_context.SOURCE_TYPE_STORAGE_MEDIA_DEVICE,
                scan_context.SOURCE_TYPE_STORAGE_MEDIA_IMAGE):
            scan_node = scan_context.GetRootScanNode()
            self._source_path_specs.append(scan_node.path_spec)
            return scan_context

        # Get the first node where where we need to decide what to process.
        scan_node = scan_context.GetRootScanNode()
        while len(scan_node.sub_nodes) == 1:
            scan_node = scan_node.sub_nodes[0]

        base_path_specs = []
        if scan_node.type_indicator != (
                dfvfs_definitions.TYPE_INDICATOR_TSK_PARTITION):
            self._ScanVolume(scan_context, scan_node, base_path_specs)

        else:
            # Determine which partition needs to be processed.
            partition_identifier = par_name
            if not partition_identifier:
                raise errors.SourceScannerError('No partitions found.')

            location = '/{0:s}'.format(partition_identifier)
            sub_scan_node = scan_node.GetSubNodeByLocation(location)
            self._ScanVolume(scan_context, sub_scan_node, base_path_specs)

        if not base_path_specs:
            raise errors.SourceScannerError(
                'No supported file system found in source.')

        self._source_path_specs = base_path_specs

        return scan_context
コード例 #5
0
    def _ScanEncryptedVolume(self, scan_context, scan_node):
        """Scans an encrypted volume scan node for volume and file systems.

    Args:
      scan_context (SourceScannerContext): source scanner context.
      scan_node (SourceScanNode): volume scan node.

    Raises:
      SourceScannerError: if the format of or within the source is not
          supported, the scan node is invalid or there are no credentials
          defined for the format.
    """
        if not scan_node or not scan_node.path_spec:
            raise errors.SourceScannerError('Invalid or missing scan node.')

        credentials = credentials_manager.CredentialsManager.GetCredentials(
            scan_node.path_spec)
        if not credentials:
            raise errors.SourceScannerError(
                'Missing credentials for scan node.')

        credentials_dict = dict(self._credentials)

        is_unlocked = False
        for credential_type in sorted(credentials.CREDENTIALS):
            credential_data = credentials_dict.get(credential_type, None)
            if not credential_data:
                continue

            is_unlocked = self._source_scanner.Unlock(scan_context,
                                                      scan_node.path_spec,
                                                      credential_type,
                                                      credential_data)
            if is_unlocked:
                self._AddCredentialConfiguration(scan_node.path_spec,
                                                 credential_type,
                                                 credential_data)
                break

        if not is_unlocked and self._unattended_mode:
            is_unlocked, credential_type, credential_data = (
                self._mediator.PromptUserForEncryptedVolumeCredential(
                    self._source_scanner, scan_context, scan_node,
                    credentials))

        if is_unlocked:
            self._AddCredentialConfiguration(scan_node.path_spec,
                                             credential_type, credential_data)
            self._source_scanner.Scan(scan_context,
                                      scan_path_spec=scan_node.path_spec)
コード例 #6
0
    def _ScanVolumeSystemRoot(self, scan_context, scan_node, base_path_specs):
        """Scans a volume system root scan node for volume and file systems.

    Args:
      scan_context (SourceScannerContext): source scanner context.
      scan_node (SourceScanNode): volume system root scan node.
      base_path_specs (list[PathSpec]): file system base path specifications.

    Raises:
      SourceScannerError: if the scan node is invalid, the scan node type is not
          supported or if a sub scan node cannot be retrieved.
    """
        if not scan_node or not scan_node.path_spec:
            raise errors.SourceScannerError('Invalid scan node.')

        if scan_node.type_indicator == (
                dfvfs_definitions.TYPE_INDICATOR_APFS_CONTAINER):
            volume_identifiers = self._GetAPFSVolumeIdentifiers(scan_node)

        elif scan_node.type_indicator == dfvfs_definitions.TYPE_INDICATOR_LVM:
            volume_identifiers = self._GetLVMVolumeIdentifiers(scan_node)

        elif scan_node.type_indicator == dfvfs_definitions.TYPE_INDICATOR_VSHADOW:
            if not self._process_vss:
                volume_identifiers = []
            else:
                volume_identifiers = self._GetVSSStoreIdentifiers(scan_node)
                # Process VSS stores (snapshots) starting with the most recent one.
                volume_identifiers.reverse()

                if (not self._vss_only and not self._unattended_mode
                        and volume_identifiers):
                    self._vss_only = not self._mediator.PromptUserForVSSCurrentVolume(
                    )

        else:
            raise errors.SourceScannerError(
                'Unsupported volume system type: {0:s}.'.format(
                    scan_node.type_indicator))

        for volume_identifier in volume_identifiers:
            location = '/{0:s}'.format(volume_identifier)
            sub_scan_node = scan_node.GetSubNodeByLocation(location)
            if not sub_scan_node:
                raise errors.SourceScannerError(
                    'Scan node missing for volume identifier: {0:s}.'.format(
                        volume_identifier))

            self._ScanVolume(scan_context, sub_scan_node, base_path_specs)
コード例 #7
0
ファイル: storage_media_tool.py プロジェクト: kr11/plaso
    def _GetVSSStoreIdentifiers(self, scan_node, vss_stores=None):
        """Determines the VSS store identifiers.

    Args:
      scan_node: the scan node (instance of dfvfs.ScanNode).
      vss_stores: Optional list of preferred VSS store identifiers. The
                  default is None.

    Returns:
      A list of VSS store identifiers.

    Raises:
      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 = vshadow_volume_system.VShadowVolumeSystem()
        volume_system.Open(scan_node.path_spec)

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

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

        return selected_store_identifiers
コード例 #8
0
ファイル: storage_media_tool.py プロジェクト: yehias/plaso
    def _PrintTSKPartitionIdentifiersOverview(self, volume_system,
                                              volume_identifiers):
        """Prints an overview of TSK partition identifiers.

    Args:
      volume_system (dfvfs.TSKVolumeSystem): volume system.
      volume_identifiers (list[str]): allowed volume identifiers.

    Raises:
      SourceScannerError: if a volume cannot be resolved from the volume
          identifier.
    """
        header = 'The following partitions were found:\n'
        self._output_writer.Write(header)

        column_names = ['Identifier', 'Offset (in bytes)', 'Size (in bytes)']
        table_view = views.CLITabularTableView(column_names=column_names)

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

            volume_extent = volume.extents[0]
            volume_offset = '{0:d} (0x{0:08x})'.format(volume_extent.offset)
            volume_size = self._FormatHumanReadableSize(volume_extent.size)

            table_view.AddRow([volume.identifier, volume_offset, volume_size])

        self._output_writer.Write('\n')
        table_view.Write(self._output_writer)
        self._output_writer.Write('\n')
コード例 #9
0
  def _PromptUserForPartitionIdentifier(
      self, volume_system, volume_identifiers):
    """Prompts the user to provide a partition identifier.

    Args:
      volume_system (dfvfs.TSKVolumeSystem): volume system.
      volume_identifiers (list[str]): allowed volume identifiers.

    Returns:
      str: partition identifier or 'all'.

    Raises:
      SourceScannerError: if the source cannot be processed.
    """
    self._output_writer.Write(
        u'The following partitions were found:\n'
        u'Identifier\tOffset (in bytes)\tSize (in bytes)\n')

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

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

    self._output_writer.Write(u'\n')

    while True:
      self._output_writer.Write(
          u'Please specify the identifier of the partition that should be '
          u'processed.\nAll partitions can be defined as: "all". Note that you '
          u'can abort with Ctrl^C.\n')

      selected_volume_identifier = self._input_reader.Read()
      selected_volume_identifier = selected_volume_identifier.strip()

      if not selected_volume_identifier.startswith(u'p'):
        try:
          partition_number = int(selected_volume_identifier, 10)
          selected_volume_identifier = u'p{0:d}'.format(partition_number)
        except ValueError:
          pass

      if (selected_volume_identifier == u'all' or
          selected_volume_identifier in volume_identifiers):
        break

      self._output_writer.Write(
          u'\n'
          u'Unsupported partition identifier, please try again or abort '
          u'with Ctrl^C.\n'
          u'\n')

    self._output_writer.Write(u'\n')
    return selected_volume_identifier
コード例 #10
0
    def _ScanVolume(self, scan_context, volume_scan_node):
        """Scans the volume scan node for volume and file systems.

    Args:
      scan_context (dfvfs.SourceScannerContext): source scanner context.
      volume_scan_node (dfvfs.SourceScanNode): volume scan node.

    Raises:
      SourceScannerError: if the format of or within the source
          is not supported or the the scan node is invalid.
    """
        if not volume_scan_node or not volume_scan_node.path_spec:
            raise errors.SourceScannerError(
                'Invalid or missing volume scan node.')

        selected_vss_stores = []
        if not volume_scan_node.sub_nodes:
            self._ScanVolumeScanNode(scan_context, volume_scan_node,
                                     selected_vss_stores)

        else:
            # Some volumes contain other volume or file systems e.g. BitLocker ToGo
            # has an encrypted and unencrypted volume.
            for sub_scan_node in volume_scan_node.sub_nodes:
                self._ScanVolumeScanNode(scan_context, sub_scan_node,
                                         selected_vss_stores)
コード例 #11
0
ファイル: storage_media_tool.py プロジェクト: yehias/plaso
    def _PrintAPFSVolumeIdentifiersOverview(self, volume_system,
                                            volume_identifiers):
        """Prints an overview of APFS volume identifiers.

    Args:
      volume_system (dfvfs.APFSVolumeSystem): volume system.
      volume_identifiers (list[str]): allowed volume identifiers.

    Raises:
      SourceScannerError: if a volume cannot be resolved from the volume
          identifier.
    """
        header = 'The following Apple File System (APFS) volumes were found:\n'
        self._output_writer.Write(header)

        column_names = ['Identifier', 'Name']
        table_view = views.CLITabularTableView(column_names=column_names)

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

            volume_attribute = volume.GetAttribute('name')
            table_view.AddRow([volume.identifier, volume_attribute.value])

        self._output_writer.Write('\n')
        table_view.Write(self._output_writer)
        self._output_writer.Write('\n')
コード例 #12
0
  def _PrintLVMVolumeIdentifiersOverview(
      self, volume_system, volume_identifiers):
    """Prints an overview of LVM volume identifiers.

    Args:
      volume_system (dfvfs.LVMVolumeSystem): volume system.
      volume_identifiers (list[str]): allowed volume identifiers.

    Raises:
      SourceScannerError: if a volume cannot be resolved from the volume
          identifier.
    """
    header = 'The following Logical Volume Manager (LVM) volumes were found:\n'
    self._output_writer.Write(header)

    column_names = ['Identifier']
    table_view = views.CLITabularTableView(column_names=column_names)

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

      table_view.AddRow([volume.identifier])

    self._output_writer.Write('\n')
    table_view.Write(self._output_writer)
    self._output_writer.Write('\n')
コード例 #13
0
    def _GetNormalizedVShadowVolumeIdentifiers(self, volume_system,
                                               volume_identifiers):
        """Retrieves the normalized VShadow volume identifiers.

    Args:
      volume_system (dfvfs.VShadowVolumeSystem): volume system.
      volume_identifiers (list[str]): allowed volume identifiers.

    Returns:
      list[int]: normalized volume identifiers.
    """
        normalized_volume_identifiers = []
        for volume_identifier in volume_identifiers:
            volume = volume_system.GetVolumeByIdentifier(volume_identifier)
            if not volume:
                raise errors.SourceScannerError(
                    'Volume missing for identifier: {0:s}.'.format(
                        volume_identifier))

            try:
                volume_identifier = int(volume.identifier[3:], 10)
                normalized_volume_identifiers.append(volume_identifier)
            except ValueError:
                pass

        return normalized_volume_identifiers
コード例 #14
0
  def _GetVolumeVssStoreIdentifiers(self, scan_context, vss_stores=None):
    """Determines the VSS store identifiers.

    Args:
      scan_context: the scan context (instance of dfvfs.ScanContext).
      vss_stores: Optional list of preferred VSS stored identifiers. The
                  default is None.

    Raises:
      SourceScannerError: if the format of or within the source
                          is not supported or the the scan context
                          is invalid.
    """
    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 = vshadow_volume_system.VShadowVolumeSystem()
    volume_system.Open(scan_context.last_scan_node.path_spec)

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

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

    return
コード例 #15
0
    def _ScanVolume(self, scan_context, scan_node, base_path_specs):
        """Scans a volume scan node for volume and file systems.

    Args:
      scan_context (SourceScannerContext): source scanner context.
      scan_node (SourceScanNode): volume scan node.
      base_path_specs (list[PathSpec]): file system base path specifications.

    Raises:
      SourceScannerError: if the format of or within the source
          is not supported or the scan node is invalid.
    """
        if not scan_node or not scan_node.path_spec:
            raise errors.SourceScannerError('Invalid or missing scan node.')

        if scan_context.IsLockedScanNode(scan_node.path_spec):
            # The source scanner found a locked volume and we need a credential to
            # unlock it.
            self._ScanEncryptedVolume(scan_context, scan_node)

            if scan_context.IsLockedScanNode(scan_node.path_spec):
                return

        if scan_node.IsVolumeSystemRoot():
            self._ScanVolumeSystemRoot(scan_context, scan_node,
                                       base_path_specs)

        elif scan_node.IsFileSystem():
            self._ScanFileSystem(scan_node, base_path_specs)

        elif scan_node.type_indicator == dfvfs_definitions.TYPE_INDICATOR_VSHADOW:
            if self._process_vss:
                # TODO: look into building VSS store on demand.

                # We "optimize" here for user experience, alternatively we could scan
                # for a file system instead of hard coding a TSK child path
                # specification.
                if dfvfs_definitions.PREFERRED_NTFS_BACK_END == (
                        dfvfs_definitions.TYPE_INDICATOR_TSK):
                    location = '/'
                else:
                    location = '\\'

                path_spec = path_spec_factory.Factory.NewPathSpec(
                    dfvfs_definitions.PREFERRED_NTFS_BACK_END,
                    location=location,
                    parent=scan_node.path_spec)

                base_path_specs.append(path_spec)

        else:
            for sub_scan_node in scan_node.sub_nodes:
                self._ScanVolume(scan_context, sub_scan_node, base_path_specs)
コード例 #16
0
    def _GetVSSStoreIdentifiers(self, scan_node):
        """Determines the VSS store identifiers.

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

    Returns:
      list[str]: VSS store identifiers.

    Raises:
      SourceScannerError: if 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 = vshadow_volume_system.VShadowVolumeSystem()
        volume_system.Open(scan_node.path_spec)

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

        # TODO: refactor to use scan options.
        if self._vss_stores:
            if self._vss_stores == 'all':
                vss_stores = volume_system.volume_identifiers
            else:
                vss_stores = self._mediator.ParseVolumeIdentifiersString(
                    self._vss_stores, prefix='vss')

            selected_volume_identifiers = self._NormalizedVolumeIdentifiers(
                volume_system, vss_stores, prefix='vss')

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

        if self._unattended_mode:
            return []

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

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

        return self._NormalizedVolumeIdentifiers(volume_system,
                                                 volume_identifiers,
                                                 prefix='vss')
コード例 #17
0
ファイル: storage_media_tool.py プロジェクト: yehias/plaso
    def _GetVSSStoreIdentifiers(self, scan_node):
        """Determines the VSS store identifiers.

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

    Returns:
      list[str]: VSS store identifiers.

    Raises:
      SourceScannerError: if the format of or within the source is not
          supported or 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 = vshadow_volume_system.VShadowVolumeSystem()
        volume_system.Open(scan_node.path_spec)

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

        # TODO: refactor to use scan options.
        if self._vss_stores:
            if self._vss_stores == 'all':
                vss_stores = range(1, volume_system.number_of_volumes + 1)
            else:
                vss_stores = self._vss_stores

            selected_volume_identifiers = self._NormalizedVolumeIdentifiers(
                volume_system, vss_stores, prefix='vss')

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

        try:
            volume_identifiers = self._PromptUserForVSSStoreIdentifiers(
                volume_system, volume_identifiers)

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

        return self._NormalizedVolumeIdentifiers(volume_system,
                                                 volume_identifiers,
                                                 prefix='vss')
コード例 #18
0
ファイル: storage_media_tool.py プロジェクト: yehias/plaso
    def _ScanFileSystem(self, scan_node, base_path_specs):
        """Scans a file system scan node for file systems.

    Args:
      scan_node (SourceScanNode): file system scan node.
      base_path_specs (list[PathSpec]): file system base path specifications.

    Raises:
      SourceScannerError: if the scan node is invalid.
    """
        if not scan_node or not scan_node.path_spec:
            raise errors.SourceScannerError(
                'Invalid or missing file system scan node.')

        base_path_specs.append(scan_node.path_spec)
コード例 #19
0
ファイル: storage_media_tool.py プロジェクト: naaya17/plaso
    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')
コード例 #20
0
ファイル: storage_media_tool.py プロジェクト: yehias/plaso
    def _NormalizedVolumeIdentifiers(self,
                                     volume_system,
                                     volume_identifiers,
                                     prefix='v'):
        """Normalizes volume identifiers.

    Args:
      volume_system (VolumeSystem): volume system.
      volume_identifiers (list[int|str]): allowed volume identifiers, formatted
          as an integer or string with prefix.
      prefix (Optional[str]): volume identifier prefix.

    Returns:
      list[str]: volume identifiers with prefix.

    Raises:
      SourceScannerError: if the volume identifier is not supported or no
          volume could be found that corresponds with the identifier.
    """
        normalized_volume_identifiers = []
        for volume_identifier in volume_identifiers:
            if isinstance(volume_identifier, int):
                volume_identifier = '{0:s}{1:d}'.format(
                    prefix, volume_identifier)

            elif not volume_identifier.startswith(prefix):
                try:
                    volume_identifier = int(volume_identifier, 10)
                    volume_identifier = '{0:s}{1:d}'.format(
                        prefix, volume_identifier)
                except (TypeError, ValueError):
                    pass

            try:
                volume = volume_system.GetVolumeByIdentifier(volume_identifier)
            except KeyError:
                volume = None

            if not volume:
                raise errors.SourceScannerError(
                    'Volume missing for identifier: {0:s}.'.format(
                        volume_identifier))

            normalized_volume_identifiers.append(volume_identifier)

        return normalized_volume_identifiers
コード例 #21
0
    def _ScanVolumeScanNode(self, scan_context, volume_scan_node,
                            selected_vss_stores):
        """Scans an individual volume scan node for volume and file systems.

    Args:
      scan_context (dfvfs.SourceScannerContext): source scanner context.
      volume_scan_node (dfvfs.SourceScanNode): volume scan node.
      selected_vss_stores (list[str]): selected VSS store identifiers.

    Raises:
      SourceScannerError: if the format of or within the source
          is not supported or the the scan node is invalid.
    """
        if not volume_scan_node or not volume_scan_node.path_spec:
            raise errors.SourceScannerError(
                'Invalid or missing volume scan node.')

        # Get the first node where where we need to decide what to process.
        scan_node = volume_scan_node
        while len(scan_node.sub_nodes) == 1:
            # Make sure that we prompt the user about VSS selection.
            if scan_node.type_indicator == dfvfs_definitions.TYPE_INDICATOR_VSHADOW:
                location = getattr(scan_node.path_spec, 'location', None)
                if location == '/':
                    break

            scan_node = scan_node.sub_nodes[0]

        # The source scanner found an encrypted volume and we need
        # a credential to unlock the volume.
        if scan_node.type_indicator in (
                dfvfs_definitions.ENCRYPTED_VOLUME_TYPE_INDICATORS):
            self._ScanVolumeScanNodeEncrypted(scan_context, scan_node)

        elif scan_node.type_indicator == dfvfs_definitions.TYPE_INDICATOR_VSHADOW:
            self._ScanVolumeScanNodeVSS(scan_node, selected_vss_stores)

        elif scan_node.type_indicator in (
                dfvfs_definitions.FILE_SYSTEM_TYPE_INDICATORS):
            if (not self._vss_only or not selected_vss_stores
                    or self._PromptUserForVSSCurrentVolume()):
                self._source_path_specs.append(scan_node.path_spec)
コード例 #22
0
  def _ScanFileSystem(self, scan_node, base_path_specs):
    """Scans a file system scan node for file systems.

    Args:
      scan_node (SourceScanNode): file system scan node.
      base_path_specs (list[PathSpec]): file system base path specifications.

    Raises:
      SourceScannerError: if the scan node is invalid.
    """
    if not scan_node or not scan_node.path_spec:
      raise errors.SourceScannerError(
          'Invalid or missing file system scan node.')

    if self._vss_only:
      if scan_node.parent_node.sub_nodes[0].type_indicator == (
          dfvfs_definitions.TYPE_INDICATOR_VSHADOW):
        return

    base_path_specs.append(scan_node.path_spec)
コード例 #23
0
ファイル: storage_media_tool.py プロジェクト: yehias/plaso
    def _PrintVSSStoreIdentifiersOverview(self, volume_system,
                                          volume_identifiers):
        """Prints an overview of VSS store identifiers.

    Args:
      volume_system (dfvfs.VShadowVolumeSystem): volume system.
      volume_identifiers (list[str]): allowed volume identifiers.

    Raises:
      SourceScannerError: if a volume cannot be resolved from the volume
          identifier.
    """
        header = 'The following Volume Shadow Snapshots (VSS) were found:\n'
        self._output_writer.Write(header)

        column_names = ['Identifier', 'Creation Time']
        table_view = views.CLITabularTableView(column_names=column_names)

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

            volume_attribute = volume.GetAttribute('creation_time')
            filetime = dfdatetime_filetime.Filetime(
                timestamp=volume_attribute.value)
            creation_time = filetime.CopyToDateTimeString()

            if volume.HasExternalData():
                creation_time = '{0:s}\tWARNING: data stored outside volume'.format(
                    creation_time)

            table_view.AddRow([volume.identifier, creation_time])

        self._output_writer.Write('\n')
        table_view.Write(self._output_writer)
        self._output_writer.Write('\n')
コード例 #24
0
ファイル: storage_media_tool.py プロジェクト: kr11/plaso
    def _ScanVolume(self, scan_context, volume_scan_node):
        """Scans the volume scan node for volume and file systems.

    Args:
      scan_context: the source scanner context (instance of
                    SourceScannerContext).
      volume_scan_node: the volume scan node (instance of dfvfs.ScanNode).

    Raises:
      SourceScannerError: if the format of or within the source
                          is not supported or the the scan node is invalid.
    """
        if not volume_scan_node or not volume_scan_node.path_spec:
            raise errors.SourceScannerError(
                u'Invalid or missing volume scan node.')

        if len(volume_scan_node.sub_nodes) == 0:
            self._ScanVolumeScanNode(scan_context, volume_scan_node)

        else:
            # Some volumes contain other volume or file systems e.g. BitLocker ToGo
            # has an encrypted and unencrypted volume.
            for sub_scan_node in volume_scan_node.sub_nodes:
                self._ScanVolumeScanNode(scan_context, sub_scan_node)
コード例 #25
0
    def _PromptUserForVSSStoreIdentifiers(self,
                                          volume_system,
                                          volume_identifiers,
                                          vss_stores=None):
        """Prompts the user to provide the VSS store identifiers.

    This method first checks for the preferred VSS stores and falls back
    to prompt the user if no usable preferences were specified.

    Args:
      volume_system (dfvfs.VShadowVolumeSystem): volume system.
      volume_identifiers (list[str]): allowed volume identifiers.
      vss_stores (Optional[list[str]]): preferred VSS store identifiers.

    Returns:
      list[str]: selected VSS store identifiers.

    Raises:
      SourceScannerError: if the source cannot be processed.
    """
        normalized_volume_identifiers = self._GetNormalizedVShadowVolumeIdentifiers(
            volume_system, volume_identifiers)

        # TODO: refactor this to _GetVSSStoreIdentifiers.
        if vss_stores:
            if vss_stores == ['all']:
                # We need to set the stores to cover all vss stores.
                vss_stores = range(1, volume_system.number_of_volumes + 1)

            if not set(vss_stores).difference(normalized_volume_identifiers):
                return vss_stores

        print_header = True
        while True:
            if print_header:
                self._output_writer.Write(
                    'The following Volume Shadow Snapshots (VSS) were found:\n'
                )

                table_view = views.CLITabularTableView(
                    column_names=['Identifier', 'Creation Time'])

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

                    vss_creation_time = volume.GetAttribute('creation_time')
                    filetime = dfdatetime_filetime.Filetime(
                        timestamp=vss_creation_time.value)
                    vss_creation_time = filetime.GetPlasoTimestamp()
                    vss_creation_time = timelib.Timestamp.CopyToIsoFormat(
                        vss_creation_time)

                    if volume.HasExternalData():
                        vss_creation_time = (
                            '{0:s}\tWARNING: data stored outside volume'
                        ).format(vss_creation_time)

                    table_view.AddRow([volume.identifier, vss_creation_time])

                self._output_writer.Write('\n')
                table_view.Write(self._output_writer)
                self._output_writer.Write('\n')

                print_header = False

            self._output_writer.Write(
                'Please specify the identifier(s) of the VSS that should be '
                'processed:\nNote that a range of stores can be defined as: 3..5. '
                'Multiple stores can\nbe defined as: 1,3,5 (a list of comma '
                'separated values). Ranges and lists can\nalso be combined '
                'as: 1,3..5. The first store is 1. All stores can be defined\n'
                'as "all". If no stores are specified none will be processed. You\n'
                'can abort with Ctrl^C.\n')

            selected_vss_stores = self._input_reader.Read()

            selected_vss_stores = selected_vss_stores.strip()
            if not selected_vss_stores:
                return []

            try:
                selected_vss_stores = self._ParseVSSStoresString(
                    selected_vss_stores)
            except errors.BadConfigOption:
                selected_vss_stores = []

            if selected_vss_stores == ['all']:
                # We need to set the stores to cover all vss stores.
                selected_vss_stores = range(
                    1, volume_system.number_of_volumes + 1)

            if not set(selected_vss_stores).difference(
                    normalized_volume_identifiers):
                break

            self._output_writer.Write(
                '\n'
                'Unsupported VSS identifier(s), please try again or abort with '
                'Ctrl^C.\n'
                '\n')

        self._output_writer.Write('\n')
        return selected_vss_stores
コード例 #26
0
    def _PromptUserForPartitionIdentifier(self, volume_system,
                                          volume_identifiers):
        """Prompts the user to provide a partition identifier.

    Args:
      volume_system (dfvfs.TSKVolumeSystem): volume system.
      volume_identifiers (list[str]): allowed volume identifiers.

    Returns:
      str: partition identifier or "all".

    Raises:
      SourceScannerError: if the source cannot be processed.
    """
        self._output_writer.Write('The following partitions were found:\n')

        table_view = views.CLITabularTableView(column_names=[
            'Identifier', 'Offset (in bytes)', 'Size (in bytes)'
        ])

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

            volume_extent = volume.extents[0]
            volume_offset = '{0:d} (0x{0:08x})'.format(volume_extent.offset)
            volume_size = self._FormatHumanReadableSize(volume_extent.size)

            table_view.AddRow([volume.identifier, volume_offset, volume_size])

        self._output_writer.Write('\n')
        table_view.Write(self._output_writer)
        self._output_writer.Write('\n')

        while True:
            self._output_writer.Write(
                'Please specify the identifier of the partition that should be '
                'processed.\nAll partitions can be defined as: "all". Note that you '
                'can abort with Ctrl^C.\n')

            selected_volume_identifier = self._input_reader.Read()
            selected_volume_identifier = selected_volume_identifier.strip()

            if not selected_volume_identifier.startswith('p'):
                try:
                    partition_number = int(selected_volume_identifier, 10)
                    selected_volume_identifier = 'p{0:d}'.format(
                        partition_number)
                except ValueError:
                    pass

            if (selected_volume_identifier == 'all'
                    or selected_volume_identifier in volume_identifiers):
                break

            self._output_writer.Write(
                '\n'
                'Unsupported partition identifier, please try again or abort '
                'with Ctrl^C.\n'
                '\n')

        self._output_writer.Write('\n')
        return selected_volume_identifier
コード例 #27
0
ファイル: storage_media_tool.py プロジェクト: yehias/plaso
    def ScanSource(self, source_path):
        """Scans the source path for volume and file systems.

    This function sets the internal source path specification and source
    type values.

    Args:
      source_path (str): path to the source.

    Returns:
      dfvfs.SourceScannerContext: source scanner context.

    Raises:
      SourceScannerError: if the format of or within the source is
          not supported.
    """
        # Symbolic links are resolved here and not earlier to preserve the user
        # specified source path in storage and reporting.
        if os.path.islink(source_path):
            source_path = os.path.realpath(source_path)

        if (not source_path.startswith('\\\\.\\')
                and not os.path.exists(source_path)):
            raise errors.SourceScannerError(
                'No such device, file or directory: {0:s}.'.format(
                    source_path))

        scan_context = source_scanner.SourceScannerContext()
        scan_context.OpenSourcePath(source_path)

        try:
            self._source_scanner.Scan(scan_context)
        except (ValueError, dfvfs_errors.BackEndError) as exception:
            raise errors.SourceScannerError(
                'Unable to scan source with error: {0!s}.'.format(exception))

        if scan_context.source_type not in (
                scan_context.SOURCE_TYPE_STORAGE_MEDIA_DEVICE,
                scan_context.SOURCE_TYPE_STORAGE_MEDIA_IMAGE):
            scan_node = scan_context.GetRootScanNode()
            self._source_path_specs.append(scan_node.path_spec)
            return scan_context

        # Get the first node where where we need to decide what to process.
        scan_node = scan_context.GetRootScanNode()
        while len(scan_node.sub_nodes) == 1:
            scan_node = scan_node.sub_nodes[0]

        base_path_specs = []
        if scan_node.type_indicator != (
                dfvfs_definitions.TYPE_INDICATOR_TSK_PARTITION):
            self._ScanVolume(scan_context, scan_node, base_path_specs)

        else:
            # Determine which partition needs to be processed.
            partition_identifiers = self._GetTSKPartitionIdentifiers(scan_node)
            if not partition_identifiers:
                raise errors.SourceScannerError('No partitions found.')

            for partition_identifier in partition_identifiers:
                location = '/{0:s}'.format(partition_identifier)
                sub_scan_node = scan_node.GetSubNodeByLocation(location)
                self._ScanVolume(scan_context, sub_scan_node, base_path_specs)

        if not base_path_specs:
            raise errors.SourceScannerError(
                'No supported file system found in source.')

        self._source_path_specs = base_path_specs

        return scan_context
コード例 #28
0
ファイル: storage_media_tool.py プロジェクト: kr11/plaso
    def ScanSource(self):
        """Scans the source path for volume and file systems.

    This function sets the internal source path specification and source
    type values.

    Returns:
      The scan context (instance of dfvfs.ScanContext).

    Raises:
      SourceScannerError: if the format of or within the source is
                          not supported.
    """
        if (not self._source_path.startswith(u'\\\\.\\')
                and not os.path.exists(self._source_path)):
            raise errors.SourceScannerError(
                u'No such device, file or directory: {0:s}.'.format(
                    self._source_path))

        scan_context = source_scanner.SourceScannerContext()
        scan_context.OpenSourcePath(self._source_path)

        try:
            self._source_scanner.Scan(scan_context)
        except (dfvfs_errors.BackEndError, ValueError) as exception:
            raise errors.SourceScannerError(
                u'Unable to scan source with error: {0:s}.'.format(exception))

        if scan_context.source_type not in [
                scan_context.SOURCE_TYPE_STORAGE_MEDIA_DEVICE,
                scan_context.SOURCE_TYPE_STORAGE_MEDIA_IMAGE
        ]:
            scan_node = scan_context.GetRootScanNode()
            self._source_path_specs.append(scan_node.path_spec)
            return scan_context

        # Get the first node where where we need to decide what to process.
        scan_node = scan_context.GetRootScanNode()
        while len(scan_node.sub_nodes) == 1:
            scan_node = scan_node.sub_nodes[0]

        # The source scanner found a partition table and we need to determine
        # which partition needs to be processed.
        if scan_node.type_indicator not in [
                dfvfs_definitions.TYPE_INDICATOR_TSK_PARTITION
        ]:
            partition_identifiers = None

        else:
            partition_identifiers = self._GetTSKPartitionIdentifiers(
                scan_node,
                partition_string=self._partition_string,
                partition_offset=self._partition_offset)

        if not partition_identifiers:
            self._ScanVolume(scan_context, scan_node)

        else:
            for partition_identifier in partition_identifiers:
                location = u'/{0:s}'.format(partition_identifier)
                sub_scan_node = scan_node.GetSubNodeByLocation(location)
                self._ScanVolume(scan_context, sub_scan_node)

        if not self._source_path_specs:
            raise errors.SourceScannerError(
                u'No supported file system found in source.')

        return scan_context
コード例 #29
0
ファイル: storage_media_tool.py プロジェクト: kr11/plaso
    def _PromptUserForVSSStoreIdentifiers(self,
                                          volume_system,
                                          volume_identifiers,
                                          vss_stores=None):
        """Prompts the user to provide the VSS store identifiers.

    This method first checks for the preferred VSS stores and falls back
    to prompt the user if no usable preferences were specified.

    Args:
      volume_system: The volume system (instance of dfvfs.VShadowVolumeSystem).
      volume_identifiers: List of allowed volume identifiers.
      vss_stores: Optional list of preferred VSS store identifiers. The
                  default is None.

    Returns:
      The list of selected VSS store identifiers.

    Raises:
      SourceScannerError: if the source cannot be processed.
    """
        normalized_volume_identifiers = []
        for volume_identifier in volume_identifiers:
            volume = volume_system.GetVolumeByIdentifier(volume_identifier)
            if not volume:
                raise errors.SourceScannerError(
                    u'Volume missing for identifier: {0:s}.'.format(
                        volume_identifier))

            try:
                volume_identifier = int(volume.identifier[3:], 10)
                normalized_volume_identifiers.append(volume_identifier)
            except ValueError:
                pass

        # TODO: refactor this to _GetVSSStoreIdentifiers.
        if vss_stores:
            if vss_stores == [u'all']:
                # We need to set the stores to cover all vss stores.
                vss_stores = range(1, volume_system.number_of_volumes + 1)

            if not set(vss_stores).difference(normalized_volume_identifiers):
                return vss_stores

        print_header = True
        while True:
            if print_header:
                self._output_writer.Write(
                    u'The following Volume Shadow Snapshots (VSS) were found:\n'
                    u'Identifier\t\tCreation Time\n')

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

                    vss_creation_time = volume.GetAttribute(u'creation_time')
                    vss_creation_time = timelib.Timestamp.FromFiletime(
                        vss_creation_time.value)
                    vss_creation_time = timelib.Timestamp.CopyToIsoFormat(
                        vss_creation_time)

                    if volume.HasExternalData():
                        external_data = u'\tWARNING: data stored outside volume'
                    else:
                        external_data = u''

                    self._output_writer.Write(
                        u'{0:s}\t\t\t{1:s}{2:s}\n'.format(
                            volume.identifier, vss_creation_time,
                            external_data))

                self._output_writer.Write(u'\n')

                print_header = False

            self._output_writer.Write(
                u'Please specify the identifier(s) of the VSS that should be '
                u'processed:\nNote that a range of stores can be defined as: 3..5. '
                u'Multiple stores can\nbe defined as: 1,3,5 (a list of comma '
                u'separated values). Ranges and lists can\nalso be combined '
                u'as: 1,3..5. The first store is 1. All stores can be defined\n'
                u'as "all". If no stores are specified none will be processed. You\n'
                u'can abort with Ctrl^C.\n')

            selected_vss_stores = self._input_reader.Read()

            selected_vss_stores = selected_vss_stores.strip()
            if not selected_vss_stores:
                return []

            try:
                selected_vss_stores = self._ParseVSSStoresString(
                    selected_vss_stores)
            except errors.BadConfigOption:
                selected_vss_stores = []

            if selected_vss_stores == [u'all']:
                # We need to set the stores to cover all vss stores.
                selected_vss_stores = range(
                    1, volume_system.number_of_volumes + 1)

            if not set(selected_vss_stores).difference(
                    normalized_volume_identifiers):
                break

            self._output_writer.Write(
                u'\n'
                u'Unsupported VSS identifier(s), please try again or abort with '
                u'Ctrl^C.\n'
                u'\n')

        return selected_vss_stores
コード例 #30
0
ファイル: storage_media_tool.py プロジェクト: kr11/plaso
    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]