示例#1
0
    def ParseDynamicInfo(self, value_data, cached_task):
        """Parses the DynamicInfo value data.

    Args:
      value_data (bytes): DynamicInfo value data.
      cached_task (CachedTask): cached task.

    Raises:
      ParseError: if the value data could not be parsed.
    """
        if self._debug:
            self._output_writer.WriteDebugData('DynamicInfo value data:',
                                               value_data)

        value_data_size = len(value_data)

        if value_data_size == 28:
            data_type_map = self._GetDataTypeMap('dynamic_info_record')
        elif value_data_size == 36:
            data_type_map = self._GetDataTypeMap('dynamic_info2_record')

        if not data_type_map:
            raise errors.ParseError(
                'Unsupported value data size: {0:d}.'.format(value_data_size))

        try:
            dynamic_info = data_type_map.MapByteStream(value_data)
        except (dtfabric_errors.ByteStreamTooSmallError,
                dtfabric_errors.MappingError) as exception:
            raise errors.ParseError(exception)

        cached_task.last_registered_time = self._ParseFiletime(
            dynamic_info.last_registered_time)
        cached_task.launch_time = self._ParseFiletime(dynamic_info.launch_time)

        if self._debug:
            value_string = '0x{0:08x}'.format(dynamic_info.unknown1)
            self._output_writer.WriteValue('Unknown1', value_string)

            # Note this is likely either the last registered time or
            # the update time.
            self._DebugPrintFiletimeValue('Last registered time',
                                          dynamic_info.last_registered_time)

            # Note this is likely the launch time.
            self._DebugPrintFiletimeValue('Launch time',
                                          dynamic_info.launch_time)

            value_string = '0x{0:08x}'.format(dynamic_info.unknown2)
            self._output_writer.WriteValue('Unknown2', value_string)

            value_string = '0x{0:08x}'.format(dynamic_info.unknown3)
            self._output_writer.WriteValue('Unknown3', value_string)

            if dynamic_info.unknown_time is not None:
                self._DebugPrintFiletimeValue('Unknown time',
                                              dynamic_info.unknown_time)

            self._output_writer.WriteText('')
示例#2
0
    def _ParseMountedDevicesValue(self, registry_value):
        """Parses a Windows mounted devices Windows Registry value.

    Args:
      registry_value (dfwinreg.WinRegistryValue): a mounted devices Windows
          Registry value.

    Returns:
      MountedDevice: a mounted device.

    Raises:
      ParseError: if the value could not be parsed.
    """
        mounted_device = MountedDevice(registry_value.name)
        value_data_size = len(registry_value.data)

        if value_data_size == 12:
            data_type_map = self._GetDataTypeMap(
                'mounted_devices_mbr_partition')

            try:
                partition_values = self._ReadStructureFromByteStream(
                    registry_value.data, 0, data_type_map,
                    'Mounted devices MBR partition values')
            except (ValueError, errors.ParseError) as exception:
                raise errors.ParseError((
                    'Unable to parse Mounted devices MBR partition values with '
                    'error: {0!s}').format(exception))

            mounted_device.disk_identity = partition_values.disk_identity
            mounted_device.partition_offset = partition_values.partition_offset

        elif value_data_size == 24:
            data_type_map = self._GetDataTypeMap(
                'mounted_devices_gpt_partition')

            try:
                partition_values = self._ReadStructureFromByteStream(
                    registry_value.data, 0, data_type_map,
                    'Mounted devices GPT partition values')
            except (ValueError, errors.ParseError) as exception:
                raise errors.ParseError((
                    'Unable to parse Mounted devices GPT partition values with '
                    'error: {0!s}').format(exception))

            mounted_device.partition_identifier = (
                partition_values.partition_identifier)

        else:
            mounted_device.device = registry_value.data.decode('utf-16-le')

        return mounted_device
示例#3
0
  def _ReadStructureFromByteStream(
      self, byte_stream, file_offset, data_type_map, description, context=None):
    """Reads a structure from a byte stream.

    Args:
      byte_stream (bytes): byte stream.
      file_offset (int): offset of the structure data relative to the start
          of the file-like object.
      data_type_map (dtfabric.DataTypeMap): data type map of the structure.
      description (str): description of the structure.
      context (Optional[dtfabric.DataTypeMapContext]): data type map context.

    Returns:
      object: structure values object.

    Raises:
      ParseError: if the structure cannot be read.
      ValueError: if file-like object or data type map is missing.
    """
    if not byte_stream:
      raise ValueError('Missing byte stream.')

    if not data_type_map:
      raise ValueError('Missing data type map.')

    try:
      return data_type_map.MapByteStream(byte_stream, context=context)
    except (dtfabric_errors.ByteStreamTooSmallError,
            dtfabric_errors.MappingError) as exception:
      raise errors.ParseError((
          'Unable to map {0:s} data at offset: 0x{1:08x} with error: '
          '{2!s}').format(description, file_offset, exception))
示例#4
0
    def ParseTZIValue(self, value_data, time_zone):
        """Parses the TZI value data.

    Args:
      value_data (bytes): TZI value data.
      time_zone (TimeZone): time zone.

    Raises:
      ParseError: if the value data could not be parsed.
    """
        data_type_map = self._GetDataTypeMap('tzi_record')

        try:
            tzi_record = self._ReadStructureFromByteStream(
                value_data, 0, data_type_map, 'TZI record')
        except (ValueError, errors.ParseError) as exception:
            raise errors.ParseError(
                'Unable to parse TZI record value with error: {0!s}'.format(
                    exception))

        if self._debug:
            self._DebugPrintStructureObject(tzi_record,
                                            self._DEBUG_INFO_TZI_RECORD)

        if tzi_record.standard_bias:
            time_zone.offset = tzi_record.standard_bias
        else:
            time_zone.offset = tzi_record.bias
示例#5
0
    def _GetCachedEntryDataTypeMap(self, format_type, value_data,
                                   cached_entry_offset):
        """Determines the cached entry data type map.

    Args:
      format_type (int): format type.
      value_data (bytes): value data.
      cached_entry_offset (int): offset of the first cached entry data
          relative to the start of the value data.

    Returns:
      dtfabric.DataTypeMap: data type map which contains a data type definition,
          such as a structure, that can be mapped onto binary data or None
          if the data type map is not defined.

    Raises:
      ParseError: if the cached entry data type map cannot be determined.
    """
        if format_type not in self._SUPPORTED_FORMAT_TYPES:
            raise errors.ParseError(
                'Unsupported format type: {0:d}'.format(format_type))

        data_type_map_name = ''

        if format_type == self._FORMAT_TYPE_XP:
            data_type_map_name = 'appcompatcache_cached_entry_xp_32bit'

        elif format_type in (self._FORMAT_TYPE_8, self._FORMAT_TYPE_10):
            data_type_map_name = 'appcompatcache_cached_entry_header_8'

        else:
            cached_entry = self._ParseCommon2003CachedEntry(
                value_data, cached_entry_offset)

            # Assume the entry is 64-bit if the 32-bit path offset is 0 and
            # the 64-bit path offset is set.
            if (cached_entry.path_offset_32bit == 0
                    and cached_entry.path_offset_64bit != 0):
                number_of_bits = '64'
            else:
                number_of_bits = '32'

            if format_type == self._FORMAT_TYPE_2003:
                data_type_map_name = (
                    'appcompatcache_cached_entry_2003_{0:s}bit'.format(
                        number_of_bits))
            elif format_type == self._FORMAT_TYPE_VISTA:
                data_type_map_name = (
                    'appcompatcache_cached_entry_vista_{0:s}bit'.format(
                        number_of_bits))
            elif format_type == self._FORMAT_TYPE_7:
                data_type_map_name = ('appcompatcache_cached_entry_7_{0:s}bit'.
                                      format(number_of_bits))

        return self._GetDataTypeMap(data_type_map_name)
示例#6
0
    def _ParseCommon2003CachedEntry(self, value_data, cached_entry_offset):
        """Parses the cached entry structure common for Windows 2003, Vista and 7.

    Args:
      value_data (bytes): value data.
      cached_entry_offset (int): offset of the first cached entry data
          relative to the start of the value data.

    Returns:
      appcompatcache_cached_entry_2003_common: cached entry structure common
          for Windows 2003, Windows Vista and Windows 7.

    Raises:
      ParseError: if the value data could not be parsed.
    """
        cached_entry_data = value_data[cached_entry_offset:]

        data_type_map = self._GetDataTypeMap(
            'appcompatcache_cached_entry_2003_common')

        try:
            cached_entry = self._ReadStructureFromByteStream(
                cached_entry_data, cached_entry_offset, data_type_map,
                'cached entry')
        except (ValueError, errors.ParseError) as exception:
            raise errors.ParseError(
                'Unable to parse cached entry value with error: {0!s}'.format(
                    exception))

        if cached_entry.path_size > cached_entry.maximum_path_size:
            raise errors.ParseError('Path size value out of bounds.')

        path_end_of_string_size = (cached_entry.maximum_path_size -
                                   cached_entry.path_size)
        if cached_entry.path_size == 0 or path_end_of_string_size != 2:
            raise errors.ParseError('Unsupported path size values.')

        return cached_entry
示例#7
0
    def ParseEntry(self, format_version, entry_data):
        """Parses an UserAssist entry.

    Args:
      format_version (int): format version.
      entry_data (bytes): entry data.

    Returns:
      user_assist_entry_v3|user_assist_entry_v5: UserAssist entry.

    Raises:
      ParseError: if the value data could not be parsed.
    """
        if format_version == 3:
            data_type_map = self._GetDataTypeMap('user_assist_entry_v3')
            entry_data_size = 16
        elif format_version == 5:
            data_type_map = self._GetDataTypeMap('user_assist_entry_v5')
            entry_data_size = 72

        if entry_data_size != len(entry_data):
            raise errors.ParseError(
                ('Version: {0:d} size mismatch (calculated: {1:d}, '
                 'stored: {2:d}).').format(format_version, entry_data_size,
                                           len(entry_data)))

        try:
            user_assist_entry = self._ReadStructureFromByteStream(
                entry_data, 0, data_type_map, 'UserAssist entry')
        except (ValueError, errors.ParseError) as exception:
            raise errors.ParseError(
                'Unable to parse UserAssist entry value with error: {0!s}'.
                format(exception))

        if self._debug:
            self._DebugPrintEntry(format_version, user_assist_entry)

        return user_assist_entry
示例#8
0
    def _ParseHeader(self, value_data):
        """Parses a header from the value data.

    Args:
      value_data (bytes): value data.

    Returns:
      tuple: contains:

        programscache_header: header.
        int: header data size.

    Raises:
      ParseError: if the header could not be parsed.
    """
        data_type_map = self._GetDataTypeMap('programscache_header')
        data_size = data_type_map.GetByteSize()

        if self._debug:
            self._DebugPrintData('Header data', value_data[:data_size])

        try:
            header = self._ReadStructureFromByteStream(value_data, 0,
                                                       data_type_map, 'header')
        except (ValueError, errors.ParseError) as exception:
            raise errors.ParseError(
                'Unable to parse header value with error: {0!s}'.format(
                    exception))

        if self._debug:
            self._DebugPrintHeader(header)

        if header.format_version not in (1, 9, 12, 19):
            raise errors.ParseError('Unsupported format.')

        return header, data_size
示例#9
0
  def ParseCValue(self, value_data):
    """Parses the C value data.

    Args:
      value_data (bytes): F value data.

    Raises:
      ParseError: if the value data could not be parsed.
    """
    data_type_map = self._GetDataTypeMap('c_value')

    try:
      c_value = self._ReadStructureFromByteStream(
          value_data, 0, data_type_map, 'C value')
    except (ValueError, errors.ParseError) as exception:
      raise errors.ParseError(
          'Unable to parse C value with error: {0!s}'.format(exception))

    if self._debug:
      self._DebugPrintStructureObject(c_value, self._DEBUG_INFO_C_VALUE)
示例#10
0
    def CheckSignature(self, value_data):
        """Parses and validates the signature.

    Args:
      value_data (bytes): value data.

    Returns:
      int: format type or None if format could not be determined.

    Raises:
      ParseError: if the value data could not be parsed.
    """
        data_type_map = self._GetDataTypeMap('uint32le')

        try:
            signature = self._ReadStructureFromByteStream(
                value_data, 0, data_type_map, 'signature')
        except (ValueError, errors.ParseError) as exception:
            raise errors.ParseError(
                'Unable to parse signature value with error: {0!s}'.format(
                    exception))

        format_type = self._HEADER_SIGNATURES.get(signature, None)

        if format_type == self._FORMAT_TYPE_2003:
            # TODO: determine which format version is used (2003 or Vista).
            return self._FORMAT_TYPE_2003

        if format_type == self._FORMAT_TYPE_8:
            cached_entry_signature = value_data[signature:signature + 4]
            if cached_entry_signature in (self._CACHED_ENTRY_SIGNATURE_8_0,
                                          self._CACHED_ENTRY_SIGNATURE_8_1):
                return self._FORMAT_TYPE_8

        elif format_type == self._FORMAT_TYPE_10:
            # Windows 10 uses the same cache entry signature as Windows 8.1
            cached_entry_signature = value_data[signature:signature + 4]
            if cached_entry_signature == self._CACHED_ENTRY_SIGNATURE_8_1:
                return self._FORMAT_TYPE_10

        return format_type
示例#11
0
    def _ParseEntryFooter(self, value_data, value_data_offset):
        """Parses an entry footer from the value data.

    Args:
      value_data (bytes): value data.
      value_data_offset (int): offset of the entry footer relative to the start
          of the value data.

    Returns:
      tuple: contains:

        programscache_entry_footer: entry footer.
        int: entry footer data size.

    Raises:
      ParseError: if the entry footer could not be parsed.
    """
        data_type_map = self._GetDataTypeMap('programscache_entry_footer')
        data_size = data_type_map.GetByteSize()

        if self._debug:
            self._DebugPrintData(
                'Entry footer data',
                value_data[value_data_offset:value_data_offset + data_size])

        try:
            entry_footer = self._ReadStructureFromByteStream(
                value_data[value_data_offset:], value_data_offset,
                data_type_map, 'entry footer')
        except (ValueError, errors.ParseError) as exception:
            raise errors.ParseError(
                'Unable to parse entry footer value with error: {0!s}'.format(
                    exception))

        if self._debug:
            self._DebugPrintEntryFooter(entry_footer)

        return entry_footer, data_size
示例#12
0
    def ParseFValue(self, value_data, user_account):
        """Parses the F value data.

    Args:
      value_data (bytes): F value data.
      user_account (UserAccount): user account.

    Raises:
      ParseError: if the value data could not be parsed.
    """
        data_type_map = self._GetDataTypeMap('f_value')

        try:
            f_value = self._ReadStructureFromByteStream(
                value_data, 0, data_type_map, 'F value')
        except (ValueError, errors.ParseError) as exception:
            raise errors.ParseError(
                'Unable to parse F value with error: {0!s}'.format(exception))

        # TODO: change FILETIME timestamps into date time values.
        # date_time = self._ParseFiletime(f_value.last_login_time)

        user_account.last_login_time = f_value.last_login_time

        user_account.last_password_set_time = f_value.last_password_set_time
        user_account.account_expiration_time = f_value.account_expiration_time
        user_account.last_password_failure_time = f_value.last_password_failure_time
        user_account.rid = f_value.rid
        user_account.primary_gid = f_value.primary_gid
        user_account.user_account_control_flags = f_value.user_account_control_flags
        user_account.codepage = f_value.codepage
        user_account.number_of_password_failures = (
            f_value.number_of_password_failures)
        user_account.number_of_logons = f_value.number_of_logons

        if self._debug:
            self._DebugPrintFValue(f_value)
示例#13
0
  def _ProcessKeyWithMRUListValue(self, registry_key):
    """Processes a Windows Registry key that contains a MRUList value.

    Args:
      registry_key (dfwinreg.WinRegistryKey): Windows Registry key.

    Returns:
      bool: True if a Most Recently Used (MRU) key was found, False if not.

    Raises:
      ParseError: if the MRUList value could not be parsed.
    """
    registry_value = registry_key.GetValueByName('MRUList')

    data_type_map = self._GetDataTypeMap('mrulist_entries')

    context = dtfabric_data_maps.DataTypeMapContext(values={
        'data_size': len(registry_value.data)})

    try:
      mrulist_entries = self._ReadStructureFromByteStream(
          registry_value.data, 0, data_type_map, 'MRUList entries',
          context=context)
    except (ValueError, errors.ParseError) as exception:
      raise errors.ParseError(
          'Unable to parse MRUList entries with error: {0!s}'.format(exception))

    mrulist = set([])
    recovered_mrulist = set([])
    is_recovered = False
    for entry_letter in mrulist_entries:
      if entry_letter == 0:
        is_recovered = True

      entry_letter = chr(entry_letter)

      if is_recovered:
        recovered_mrulist.add(entry_letter)
      else:
        mrulist.add(entry_letter)

    result = False
    for registry_value in registry_key.GetValues():
      if registry_value.name in ('MRUList', 'NodeSlot', 'NodeSlots'):
        continue

      if self._debug:
        description = 'Key: {0:s}\nValue: {1:s}'.format(
            registry_key.path, registry_value.name)
        self._output_writer.WriteText(description)

      if self._InKeyPaths(registry_key.path, self._SHELL_ITEM_MRU_KEY_PATHS):
        self._ProcessMRUEntryShellItem(
            registry_key.path, registry_value.name, registry_value.data)

      elif self._InKeyPaths(
          registry_key.path, self._SHELL_ITEM_LIST_MRU_KEY_PATHS):
        self._ProcessMRUEntryShellItemList(
            registry_key.path, registry_value.name, registry_value.data)

      elif self._InKeyPaths(
          registry_key.path, self._STRING_AND_SHELL_ITEM_MRU_KEY_PATHS):
        self._ProcessMRUEntryStringAndShellItem(
            registry_key.path, registry_value.name, registry_value.data)

      elif self._InKeyPaths(
          registry_key.path, self._STRING_AND_SHELL_ITEM_LIST_MRU_KEY_PATHS):
        self._ProcessMRUEntryStringAndShellItemList(
            registry_key.path, registry_value.name, registry_value.data)

      else:
        self._ProcessMRUEntryString(
            registry_key.path, registry_value.name, registry_value.data)

      result = True

    return result
示例#14
0
  def ParseVValue(self, value_data, user_account):
    """Parses the V value data.

    Args:
      value_data (bytes): V value data.
      user_account (UserAccount): user account.

    Raises:
      ParseError: if the value data could not be parsed.
    """
    data_type_map = self._GetDataTypeMap('v_value')

    try:
      v_value = self._ReadStructureFromByteStream(
          value_data, 0, data_type_map, 'V value')
    except (ValueError, errors.ParseError) as exception:
      raise errors.ParseError(
          'Unable to parse V value with error: {0!s}'.format(exception))

    for index in range(0, 17):
      user_information_descriptor = v_value[index]

      data_start_offset = user_information_descriptor.offset + 0xcc
      data_end_offset = data_start_offset + user_information_descriptor.size
      descriptor_data = value_data[data_start_offset:data_end_offset]

      if self._debug:
        self._DebugPrintUserInformationDescriptor(
            index, user_information_descriptor, data_start_offset,
            descriptor_data)

      if index == 0:
        if self._debug:
          value_string = self._FormatSecurityDescriptor(descriptor_data)

          self._DebugPrintText('Security descriptor:\n')
          self._DebugPrintText(value_string)
          self._DebugPrintText('\n')

      elif index == 1:
        user_account.username = descriptor_data.decode(
            'utf-16-le').rstrip('\x00')

        if self._debug:
          self._DebugPrintValue('Username', user_account.username)
          self._DebugPrintText('\n')

      elif index == 2:
        user_account.full_name = descriptor_data.decode(
            'utf-16-le').rstrip('\x00')

        if self._debug:
          self._DebugPrintValue('Full name', user_account.full_name)
          self._DebugPrintText('\n')

      elif index == 3:
        user_account.comment = descriptor_data.decode(
            'utf-16-le').rstrip('\x00')

        if self._debug:
          self._DebugPrintValue('Comment', user_account.comment)
          self._DebugPrintText('\n')

      elif index == 4:
        user_account.user_comment = descriptor_data.decode(
            'utf-16-le').rstrip('\x00')

        if self._debug:
          self._DebugPrintValue(
              'User comment', user_account.user_comment)
          self._DebugPrintText('\n')

    if self._debug:
      self._DebugPrintText('\n')
示例#15
0
    def ParseVValue(self, value_data, user_account):
        """Parses the V value data.

    Args:
      value_data (bytes): V value data.
      user_account (UserAccount): user account.

    Raises:
      ParseError: if the value data could not be parsed.
    """
        data_type_map = self._GetDataTypeMap('v_value')

        try:
            v_value = self._ReadStructureFromByteStream(
                value_data, 0, data_type_map, 'V value')
        except (ValueError, errors.ParseError) as exception:
            raise errors.ParseError(
                'Unable to parse F value with error: {0!s}'.format(exception))

        for index in range(0, 17):
            user_information_descriptor = v_value[index]

            data_start_offset = user_information_descriptor.offset + 0xcc
            data_end_offset = data_start_offset + user_information_descriptor.size
            descriptor_data = value_data[data_start_offset:data_end_offset]

            if self._debug:
                description_string = 'Descriptor: {0:d} description'.format(
                    index + 1)
                value_string = self._USER_INFORMATION_DESCRIPTORS[index]
                self._DebugPrintValue(description_string, value_string)

                value_description = 'Descriptor: {0:d} offset'.format(index +
                                                                      1)
                value_string = '0x{0:08x} (0x{1:08x})'.format(
                    user_information_descriptor.offset, data_start_offset)
                self._DebugPrintValue(value_description, value_string)

                value_description = 'Descriptor: {0:d} size'.format(index + 1)
                self._DebugPrintDecimalValue(value_description,
                                             user_information_descriptor.size)

                unknown1_string = 'Descriptor: {0:d} unknown1'.format(index +
                                                                      1)
                value_string = '0x{0:08x}'.format(
                    user_information_descriptor.unknown1)
                self._DebugPrintValue(unknown1_string, value_string)

                data_string = 'Descriptor: {0:d} data:'.format(index + 1)
                self._DebugPrintData(data_string, descriptor_data)

            if index == 1:
                user_account.username = descriptor_data.decode(
                    'utf-16-le').rstrip('\x00')

                if self._debug:
                    self._DebugPrintValue('Username', user_account.username)
                    self._DebugPrintText('\n')

            elif index == 2:
                user_account.full_name = descriptor_data.decode(
                    'utf-16-le').rstrip('\x00')

                if self._debug:
                    self._DebugPrintValue('Full name', user_account.full_name)
                    self._DebugPrintText('\n')

            elif index == 3:
                user_account.comment = descriptor_data.decode(
                    'utf-16-le').rstrip('\x00')

                if self._debug:
                    self._DebugPrintValue('Comment', user_account.comment)
                    self._DebugPrintText('\n')

            elif index == 4:
                user_account.user_comment = descriptor_data.decode(
                    'utf-16-le').rstrip('\x00')

                if self._debug:
                    self._DebugPrintValue('User comment',
                                          user_account.user_comment)
                    self._DebugPrintText('\n')

        if self._debug:
            self._DebugPrintText('\n')
示例#16
0
    def _ProcessKeyWithMRUListExValue(self, registry_key):
        """Processes a Windows Registry key that contains a MRUListEx value.

    Args:
      registry_key (dfwinreg.WinRegistryKey): Windows Registry key.

    Returns:
      bool: True if a Most Recently Used (MRU) key was found, False if not.
    """
        # TODO: determine what trailing data is in:
        # HKEY_CURRENT_USER\Software\Microsoft\Windows\CurrentVersion\Explorer\
        # ComDlg32\CIDSizeMRU

        registry_value = registry_key.GetValueByName('MRUListEx')

        data_type_map = self._GetDataTypeMap('mrulistex_entries')

        context = dtfabric_data_maps.DataTypeMapContext(
            values={'data_size': len(registry_value.data)})

        try:
            mrulistex_entries = self._ReadStructureFromByteStream(
                registry_value.data,
                0,
                data_type_map,
                'MRUListEx entries',
                context=context)
        except (ValueError, errors.ParseError) as exception:
            raise errors.ParseError(
                'Unable to parse MRUListEx entries with error: {0!s}'.format(
                    exception))

        mrulistex = set([])
        recovered_mrulistex = set([])
        is_recovered = False
        for entry_number in mrulistex_entries:
            if entry_number == 0:
                is_recovered = True

            if is_recovered:
                recovered_mrulistex.add(entry_number)
            else:
                mrulistex.add(entry_number)

        result = False
        for registry_value in registry_key.GetValues():
            if registry_value.name in ('MRUListEx', 'NodeSlot', 'NodeSlots'):
                continue

            if self._debug:
                description = 'Key: {0:s}\nValue: {1:s}'.format(
                    registry_key.path, registry_value.name)
                self._output_writer.WriteText(description)

            if self._InKeyPaths(registry_key.path,
                                self._SHELL_ITEM_MRU_KEY_PATHS):
                self._ProcessMRUEntryShellItem(registry_key.path,
                                               registry_value.name,
                                               registry_value.data)

            elif self._InKeyPaths(registry_key.path,
                                  self._SHELL_ITEM_LIST_MRU_KEY_PATHS):
                self._ProcessMRUEntryShellItemList(registry_key.path,
                                                   registry_value.name,
                                                   registry_value.data)

            elif self._InKeyPaths(registry_key.path,
                                  self._STRING_AND_SHELL_ITEM_MRU_KEY_PATHS):
                self._ProcessMRUEntryStringAndShellItem(
                    registry_key.path, registry_value.name,
                    registry_value.data)

            elif self._InKeyPaths(
                    registry_key.path,
                    self._STRING_AND_SHELL_ITEM_LIST_MRU_KEY_PATHS):
                self._ProcessMRUEntryStringAndShellItemList(
                    registry_key.path, registry_value.name,
                    registry_value.data)

            else:
                self._ProcessMRUEntryString(registry_key.path,
                                            registry_value.name,
                                            registry_value.data)

            result = True

        return result
示例#17
0
    def Parse(self, value_data):
        """Parses the value data.

    Args:
      value_data (bytes): value data.

    Raises:
      ParseError: if the value data could not be parsed.
    """
        if self._debug:
            self._DebugPrintData('Value data', value_data)

        header, value_data_offset = self._ParseHeader(value_data)

        if header.format_version == 1:
            value_data_offset += 4

        elif header.format_version == 9:
            data_type_map = self._GetDataTypeMap('programscache_header9')

            try:
                header9 = self._ReadStructureFromByteStream(
                    value_data[value_data_offset:], value_data_offset,
                    data_type_map, 'header9')
            except (ValueError, errors.ParseError) as exception:
                raise errors.ParseError(
                    'Unable to parse header9 value with error: {0!s}'.format(
                        exception))

            value_data_offset += data_type_map.GetByteSize()

            if self._debug:
                value_string = '0x{0:08x}'.format(header9.unknown1)
                self._DebugPrintValue('Unknown1', value_string)

        elif header.format_version in (12, 19):
            uuid_object = uuid.UUID(bytes_le=value_data[4:20])
            value_data_offset += 16

            if self._debug:
                value_string = '{0!s}'.format(uuid_object)
                self._DebugPrintValue('Known folder identifier', value_string)

        sentinel = 0
        if header.format_version != 9:
            entry_footer, data_size = self._ParseEntryFooter(
                value_data, value_data_offset)

            value_data_offset += data_size

            sentinel = entry_footer.sentinel

        if self._debug:
            self._DebugPrintText('\n')

        value_data_size = len(value_data)
        while sentinel in (0, 1):
            if value_data_offset >= value_data_size:
                break

            data_type_map = self._GetDataTypeMap('programscache_entry_header')

            try:
                entry_header = self._ReadStructureFromByteStream(
                    value_data[value_data_offset:], value_data_offset,
                    data_type_map, 'entry header')
            except (ValueError, errors.ParseError) as exception:
                raise errors.ParseError(
                    'Unable to parse entry header value with error: {0!s}'.
                    format(exception))

            if self._debug:
                value_string = '0x{0:08x}'.format(value_data_offset)
                self._DebugPrintValue('Entry data offset', value_string)

                self._DebugPrintEntryHeader(entry_header)

            value_data_offset += data_type_map.GetByteSize()

            entry_data_size = entry_header.data_size

            shell_item_list = pyfwsi.item_list()
            shell_item_list.copy_from_byte_stream(
                value_data[value_data_offset:])

            for shell_item in iter(shell_item_list.items):
                if self._debug:
                    self._DebugPrintShellItem(shell_item)

            value_data_offset += entry_data_size

            entry_footer, data_size = self._ParseEntryFooter(
                value_data, value_data_offset)

            value_data_offset += data_size

            if self._debug:
                self._DebugPrintText('\n')

            if entry_footer.sentinel == 2 and value_data_offset < value_data_size:
                # TODO: determine the logic to this value.
                while ord(value_data[value_data_offset]) != 0x00:
                    value_data_offset += 1
                value_data_offset += 7

                entry_footer, data_size = self._ParseEntryFooter(
                    value_data, value_data_offset)

                value_data_offset += data_size

                if self._debug:
                    self._DebugPrintText('\n')

        if value_data_offset < value_data_size:
            value_string = '0x{0:08x}'.format(value_data_offset)
            self._DebugPrintValue('Trailing data offset', value_string)

            self._DebugPrintData('Trailing data:',
                                 value_data[value_data_offset:])
示例#18
0
    def ParseHeader(self, format_type, value_data):
        """Parses the header.

    Args:
      format_type (int): format type.
      value_data (bytes): value data.

    Returns:
      AppCompatCacheHeader: header.

    Raises:
      ParseError: if the value data could not be parsed.
    """
        data_type_map_name = self._HEADER_DATA_TYPE_MAP_NAMES.get(
            format_type, None)
        if not data_type_map_name:
            raise errors.ParseError(
                'Unsupported format type: {0:d}'.format(format_type))

        data_type_map = self._GetDataTypeMap(data_type_map_name)
        context = dtfabric_data_maps.DataTypeMapContext()

        try:
            header = self._ReadStructureFromByteStream(value_data,
                                                       0,
                                                       data_type_map,
                                                       'header',
                                                       context=context)
        except (ValueError, errors.ParseError) as exception:
            raise errors.ParseError(
                'Unable to parse header value with error: {0!s}'.format(
                    exception))

        header_data_size = context.byte_size
        if format_type == self._FORMAT_TYPE_10:
            header_data_size = header.signature

        cache_header = AppCompatCacheHeader()
        cache_header.header_size = header_data_size
        cache_header.number_of_cached_entries = getattr(
            header, 'number_of_cached_entries', None)

        if self._debug:
            self._DebugPrintHeader(format_type, header)

        if format_type == self._FORMAT_TYPE_XP:
            if self._debug:
                self._DebugPrintText('LRU entries:')

            data_offset = 16
            number_of_lru_entries = header.number_of_lru_entries
            if 0 <= number_of_lru_entries <= 96:
                data_type_map = self._GetDataTypeMap('uint32le')

                for lru_entry_index in range(number_of_lru_entries):
                    try:
                        lru_entry = self._ReadStructureFromByteStream(
                            value_data[data_offset:data_offset + 4],
                            data_offset, data_type_map, 'LRU entry')
                    except (ValueError, errors.ParseError) as exception:
                        raise errors.ParseError(
                            'Unable to parse LRU entry value with error: {0!s}'
                            .format(exception))

                    data_offset += 4

                    if self._debug:
                        description = 'LRU entry: {0:d}'.format(
                            lru_entry_index)
                        value_string = '{0:d} (offset: 0x{1:08x})'.format(
                            lru_entry, 400 + (lru_entry * 552))
                        self._DebugPrintValue(description, value_string)

                if self._debug:
                    self._DebugPrintText('\n')

            if self._debug:
                self._DebugPrintData('Unknown data',
                                     value_data[data_offset:400])

        self._cached_entry_data_type_map = None

        return cache_header
示例#19
0
    def ParseCachedEntry(self, format_type, value_data, cached_entry_index,
                         cached_entry_offset):
        """Parses a cached entry.

    Args:
      format_type (int): format type.
      value_data (bytes): value data.
      cached_entry_index (int): cached entry index.
      cached_entry_offset (int): offset of the first cached entry data
          relative to the start of the value data.

    Returns:
      AppCompatCacheCachedEntry: cached entry.

    Raises:
      ParseError: if the value data could not be parsed.
    """
        if not self._cached_entry_data_type_map:
            self._cached_entry_data_type_map = self._GetCachedEntryDataTypeMap(
                format_type, value_data, cached_entry_offset)

        if not self._cached_entry_data_type_map:
            raise errors.ParseError(
                'Unable to determine cached entry data type.')

        cached_entry_size = self._cached_entry_data_type_map.GetSizeHint()
        cached_entry_end_offset = cached_entry_offset + cached_entry_size
        cached_entry_data = value_data[
            cached_entry_offset:cached_entry_end_offset]

        if self._debug:
            if format_type not in (self._FORMAT_TYPE_8, self._FORMAT_TYPE_10):
                description = 'Cached entry: {0:d} data'.format(
                    cached_entry_index)
                self._DebugPrintData(description, cached_entry_data)

        try:
            cached_entry = self._ReadStructureFromByteStream(
                cached_entry_data, cached_entry_offset,
                self._cached_entry_data_type_map, 'cached entry')
        except (ValueError, errors.ParseError) as exception:
            if self._debug:
                if format_type in (self._FORMAT_TYPE_8, self._FORMAT_TYPE_10):
                    description = 'Cached entry: {0:d} header data'.format(
                        cached_entry_index)
                    self._DebugPrintData(description, cached_entry_data)

            raise errors.ParseError(
                'Unable to parse cached entry value with error: {0!s}'.format(
                    exception))

        if format_type in (self._FORMAT_TYPE_8, self._FORMAT_TYPE_10):
            if cached_entry.signature not in (
                    self._CACHED_ENTRY_SIGNATURE_8_0,
                    self._CACHED_ENTRY_SIGNATURE_8_1):
                if self._debug:
                    description = 'Cached entry: {0:d} header data'.format(
                        cached_entry_index)
                    self._DebugPrintData(description, cached_entry_data)

                raise errors.ParseError('Unsupported cache entry signature')

        cached_entry_object = AppCompatCacheCachedEntry()

        data_offset = 0
        data_size = 0

        if format_type == self._FORMAT_TYPE_XP:
            if self._debug:
                self._DebugPrintCachedEntryXP(cached_entry)

            # TODO: have dtFabric handle string conversion.
            string_size = 0
            for string_index in range(0, 528, 2):
                if (cached_entry.path[string_index] == 0
                        and cached_entry.path[string_index + 1] == 0):
                    break
                string_size += 2

            last_modification_time = cached_entry.last_modification_time
            path = bytearray(
                cached_entry.path[0:string_size]).decode('utf-16-le')

            cached_entry_object.last_update_time = cached_entry.last_update_time

        elif format_type in (self._FORMAT_TYPE_2003, self._FORMAT_TYPE_VISTA,
                             self._FORMAT_TYPE_7):
            if self._debug:
                self._DebugPrintCachedEntry2003(cached_entry)

            last_modification_time = cached_entry.last_modification_time

            if format_type in (self._FORMAT_TYPE_VISTA, self._FORMAT_TYPE_7):
                cached_entry_object.insertion_flags = cached_entry.insertion_flags
                cached_entry_object.shim_flags = cached_entry.shim_flags

            path_size = cached_entry.path_size
            maximum_path_size = cached_entry.maximum_path_size
            path_offset = cached_entry.path_offset

            if path_offset > 0 and path_size > 0:
                path_size += path_offset
                maximum_path_size += path_offset

                if self._debug:
                    self._DebugPrintData(
                        'Path data', value_data[path_offset:maximum_path_size])

                path = value_data[path_offset:path_size].decode('utf-16-le')

                if self._debug:
                    self._DebugPrintValue('Path', path)

            if format_type == self._FORMAT_TYPE_7:
                data_offset = cached_entry.data_offset
                data_size = cached_entry.data_size

        elif format_type in (self._FORMAT_TYPE_8, self._FORMAT_TYPE_10):
            cached_entry_data_size = cached_entry.cached_entry_data_size
            cached_entry_size = 12 + cached_entry_data_size
            cached_entry_end_offset = cached_entry_offset + cached_entry_size

            cached_entry_data = value_data[
                cached_entry_offset:cached_entry_end_offset]

            if self._debug:
                description = 'Cached entry: {0:d} data'.format(
                    cached_entry_index)
                self._DebugPrintData(description, cached_entry_data)

            if format_type == self._FORMAT_TYPE_10:
                data_type_map_name = 'appcompatcache_cached_entry_body_10'
            elif cached_entry.signature == self._CACHED_ENTRY_SIGNATURE_8_0:
                data_type_map_name = 'appcompatcache_cached_entry_body_8_0'
            elif cached_entry.signature == self._CACHED_ENTRY_SIGNATURE_8_1:
                data_type_map_name = 'appcompatcache_cached_entry_body_8_1'

            data_type_map = self._GetDataTypeMap(data_type_map_name)
            context = dtfabric_data_maps.DataTypeMapContext()

            try:
                cached_entry_body = self._ReadStructureFromByteStream(
                    cached_entry_data[12:],
                    cached_entry_offset + 12,
                    data_type_map,
                    'cached entry body',
                    context=context)
            except (ValueError, errors.ParseError) as exception:
                raise errors.ParseError(
                    'Unable to parse cached entry body with error: {0!s}'.
                    format(exception))

            if self._debug:
                self._DebugPrintCachedEntry8(cached_entry, cached_entry_body)

            last_modification_time = cached_entry_body.last_modification_time
            path = cached_entry_body.path

            if format_type == self._FORMAT_TYPE_8:
                cached_entry_object.insertion_flags = cached_entry_body.insertion_flags
                cached_entry_object.shim_flags = cached_entry_body.shim_flags

            data_offset = cached_entry_offset + context.byte_size
            data_size = cached_entry_body.data_size

        if self._debug:
            self._DebugPrintText('\n')

        cached_entry_object.cached_entry_size = cached_entry_size
        cached_entry_object.file_size = getattr(cached_entry, 'file_size',
                                                None)
        cached_entry_object.last_modification_time = last_modification_time
        cached_entry_object.path = path

        if data_size > 0:
            cached_entry_object.data = value_data[data_offset:data_offset +
                                                  data_size]

            if self._debug:
                self._DebugPrintData('Data', cached_entry_object.data)

        return cached_entry_object