Source code for plaso.parsers.shared.shell_items

# -*- coding: utf-8 -*-
"""Parser for Windows NT shell items."""

import pyfwsi

from dfdatetime import fat_date_time as dfdatetime_fat_date_time

from plaso.containers import windows_events
from plaso.helpers.windows import shell_folders
from plaso.lib import definitions


[docs] class ShellItemsParser(object): """Parses for Windows NT shell items.""" NAME = 'shell_items' _PATH_ESCAPE_CHARACTERS = {'\\': '\\\\'} _PATH_ESCAPE_CHARACTERS.update(definitions.NON_PRINTABLE_CHARACTERS)
[docs] def __init__(self, origin): """Initializes the parser. Args: origin (str): origin of the event. """ super(ShellItemsParser, self).__init__() self._origin = origin self._path_escape_characters = str.maketrans(self._PATH_ESCAPE_CHARACTERS) self._path_segments = []
def _GetDateTime(self, fat_date_time): """Retrieves the date and time from a FAT date time. Args: fat_date_time (int): FAT date time. Returns: dfdatetime.DateTimeValues: date and time or None if not set. """ if not fat_date_time: return None return dfdatetime_fat_date_time.FATDateTime(fat_date_time=fat_date_time) def _GetSanitizedPathString(self, path): """Retrieves a sanitize path string. Args: path (str): path. Returns: str: sanitized path string. """ if not path: return None return path.translate(self._path_escape_characters) def _ParseShellItem(self, parser_mediator, shell_item): """Parses a shell item. Args: parser_mediator (ParserMediator): mediates interactions between parsers and other components, such as storage and dfvfs. shell_item (pyfwsi.item): shell item. """ path_segment = self._ParseShellItemPathSegment(shell_item) self._path_segments.append(path_segment) # TODO: generate event_data for non file_entry shell items. if isinstance(shell_item, pyfwsi.file_entry): event_data = windows_events.WindowsShellItemFileEntryEventData() event_data.modification_time = self._GetDateTime( shell_item.get_modification_time_as_integer()) event_data.name = self._GetSanitizedPathString(shell_item.name) event_data.origin = self._origin event_data.shell_item_path = self.CopyToPath() number_of_event_data = 0 for extension_block in shell_item.extension_blocks: if isinstance(extension_block, pyfwsi.file_entry_extension): file_reference = extension_block.file_reference if file_reference: file_reference = '{0:d}-{1:d}'.format( file_reference & 0xffffffffffff, file_reference >> 48) event_data.access_time = self._GetDateTime( extension_block.get_access_time_as_integer()) event_data.creation_time = self._GetDateTime( extension_block.get_creation_time_as_integer()) event_data.file_reference = file_reference event_data.localized_name = extension_block.localized_name event_data.long_name = self._GetSanitizedPathString( extension_block.long_name) # TODO: change to generate an event_data for each extension block. if (event_data.access_time or event_data.creation_time or event_data.modification_time): parser_mediator.ProduceEventData(event_data) number_of_event_data += 1 # TODO: change to generate an event_data for each shell item. if not number_of_event_data and event_data.modification_time: parser_mediator.ProduceEventData(event_data) def _ParseShellItemPathSegment(self, shell_item): """Parses a shell item path segment. Args: shell_item (pyfwsi.item): shell item. Returns: str: shell item path segment. """ path_segment = None if isinstance(shell_item, pyfwsi.control_panel_category): # TODO: map identifier to human readable string. path_segment = f'<Control panel category: {shell_item.identifier:d}>' elif isinstance(shell_item, pyfwsi.control_panel_item): # TODO: map identifier to human readable string. path_segment = f'<Control panel item: {shell_item.identifier:s}>' elif isinstance(shell_item, pyfwsi.file_entry): long_name = '' for extension_block in shell_item.extension_blocks: if isinstance(extension_block, pyfwsi.file_entry_extension): long_name = self._GetSanitizedPathString(extension_block.long_name) if long_name: path_segment = long_name elif shell_item.name: path_segment = self._GetSanitizedPathString(shell_item.name) elif isinstance(shell_item, pyfwsi.network_location): if shell_item.location: path_segment = shell_item.location elif isinstance(shell_item, pyfwsi.root_folder): description = shell_folders.WindowsShellFoldersHelper.GetDescription( shell_item.shell_folder_identifier) if description: path_segment = description else: path_segment = '{{{0:s}}}'.format(shell_item.shell_folder_identifier) path_segment = '<{0:s}>'.format(path_segment) elif isinstance(shell_item, pyfwsi.users_property_view): path_segment = '<Users property view>' elif isinstance(shell_item, pyfwsi.volume): if shell_item.name: path_segment = self._GetSanitizedPathString(shell_item.name) elif shell_item.identifier: path_segment = '{{{0:s}}}'.format(shell_item.identifier) if path_segment is None: path_segment = '<UNKNOWN: 0x{0:02x}>'.format(shell_item.class_type) return path_segment
[docs] def CopyToPath(self): """Copies the shell items to a path. Returns: str: converted shell item list path or None. """ number_of_path_segments = len(self._path_segments) if number_of_path_segments == 0: return None strings = [self._path_segments[0]] number_of_path_segments -= 1 for path_segment in self._path_segments[1:]: # Remove a trailing \ except for the last path segment. if path_segment.endswith('\\\\') and number_of_path_segments > 1: path_segment = path_segment[:-2] if ((path_segment.startswith('<') and path_segment.endswith('>')) or len(strings) == 1): strings.append(' {0:s}'.format(path_segment)) elif path_segment.startswith('\\'): strings.append('{0:s}'.format(path_segment)) else: strings.append('\\\\{0:s}'.format(path_segment)) number_of_path_segments -= 1 return ''.join(strings)
[docs] def GetUpperPathSegment(self): """Retrieves the upper shell item path segment. Returns: str: shell item path segment or "N/A". """ if not self._path_segments: return 'N/A' return self._path_segments[-1]
[docs] def ParseByteStream( self, parser_mediator, byte_stream, parent_path_segments=None, codepage='cp1252'): """Parses the shell items from the byte stream. Args: parser_mediator (ParserMediator): mediates interactions between parsers and other components, such as storage and dfvfs. byte_stream (bytes): shell items data. parent_path_segments (Optional[list[str]]): parent shell item path segments. codepage (Optional[str]): byte stream codepage. """ if parent_path_segments and isinstance(parent_path_segments, list): self._path_segments = list(parent_path_segments) else: self._path_segments = [] shell_item_list = pyfwsi.item_list() parser_mediator.AppendToParserChain(self.NAME) try: shell_item_list.copy_from_byte_stream( byte_stream, ascii_codepage=codepage) for shell_item in iter(shell_item_list.items): self._ParseShellItem(parser_mediator, shell_item) finally: parser_mediator.PopFromParserChain()