Skip to content

Commit

Permalink
Code review: 240480043: Fixes for Custom Destination file parser #218
Browse files Browse the repository at this point in the history
  • Loading branch information
joachimmetz committed Jun 9, 2015
1 parent 90dd75e commit 11c4e23
Show file tree
Hide file tree
Showing 2 changed files with 87 additions and 52 deletions.
2 changes: 1 addition & 1 deletion config/dpkg/changelog
Original file line number Diff line number Diff line change
Expand Up @@ -2,4 +2,4 @@ python-plaso (1.3.0-1) unstable; urgency=low

* Auto-generated

-- Log2Timeline <[email protected]> Tue, 09 Jun 2015 16:27:40 +0200
-- Log2Timeline <[email protected]> Tue, 09 Jun 2015 22:22:44 +0200
137 changes: 86 additions & 51 deletions plaso/parsers/custom_destinations.py
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,8 @@ class CustomDestinationsParser(interface.SingleFileBaseParser):
_LNK_GUID = (
b'\x01\x14\x02\x00\x00\x00\x00\x00\xc0\x00\x00\x00\x00\x00\x00\x46')

_FOOTER_SIGNATURE = 0xbabffbab

_FILE_HEADER = construct.Struct(
u'file_header',
construct.ULInt32(u'unknown1'),
Expand All @@ -55,10 +57,48 @@ class CustomDestinationsParser(interface.SingleFileBaseParser):
u'file_footer',
construct.ULInt32(u'signature'))

def _ParseLNKFile(
self, parser_mediator, file_entry, file_offset, remaining_file_size):
"""Parses a LNK file stored within the .customDestinations-ms file.
Args:
parser_mediator: A parser mediator object (instance of ParserMediator).
file_entry: A file entry object (instance of dfvfs.FileEntry).
file_offset: The offset of the LNK file data.
remaining_file_size: The size of the data remaining in the
.customDestinations-ms file.
Returns:
The size of the LNK file data or 0 if the LNK file could not be read.
"""
path_spec = path_spec_factory.Factory.NewPathSpec(
definitions.TYPE_INDICATOR_DATA_RANGE, range_offset=file_offset,
range_size=remaining_file_size, parent=file_entry.path_spec)

display_name = u'{0:s} # 0x{1:08x}'.format(file_entry.name, file_offset)

try:
lnk_file_object = resolver.Resolver.OpenFileObject(path_spec)
except RuntimeError as exception:
message = (
u'Unable to open LNK file: {0:s} with error {1:s}').format(
display_name, exception)
parser_mediator.ProduceParseError(message)
return 0

self._WINLNK_PARSER.UpdateChainAndParseFileObject(
parser_mediator, lnk_file_object, display_name=display_name)

# We cannot trust the file size in the LNK data so we get the last offset
# that was read instead.
lnk_file_size = lnk_file_object.get_offset()

lnk_file_object.close()

return lnk_file_size

def ParseFileObject(self, parser_mediator, file_object, **kwargs):
# There's a backslash in the class docstring, so as not to confuse Sphinx.
# pylint: disable=anomalous-backslash-in-string
"""Parses a \*.customDestinations-ms file-like object.
"""Parses a .customDestinations-ms file-like object.
Args:
parser_mediator: A parser mediator object (instance of ParserMediator).
Expand All @@ -67,23 +107,26 @@ def ParseFileObject(self, parser_mediator, file_object, **kwargs):
Raises:
UnableToParseFile: when the file cannot be parsed.
"""
file_entry = parser_mediator.GetFileEntry()
display_name = parser_mediator.GetDisplayName()

file_object.seek(0, os.SEEK_SET)
try:
file_header = self._FILE_HEADER.parse_stream(file_object)
except (IOError, construct.FieldError) as exception:
raise errors.UnableToParseFile((
u'Unable to parse Custom Destination file header with error: '
u'{0:s}').format(exception))
u'Invalid Custom Destination: {0:s} - unable to parse '
u'file header with error: {1:s}').format(display_name, exception))

if file_header.unknown1 != 2:
raise errors.UnableToParseFile((
u'Unsupported Custom Destination file - invalid unknown1: '
u'{0:d}.').format(file_header.unknown1))
u'Unsupported Custom Destination file: {0:s} - invalid unknown1: '
u'{1:d}.').format(display_name, file_header.unknown1))

if file_header.header_values_type > 2:
raise errors.UnableToParseFile((
u'Unsupported Custom Destination file - invalid header value type: '
u'{0:d}.').format(file_header.header_values_type))
u'Unsupported Custom Destination file: {0:s} - invalid header value '
u'type: {1:d}.').format(display_name, file_header.header_values_type))

if file_header.header_values_type == 0:
data_structure = self._HEADER_VALUE_TYPE_0
Expand All @@ -94,8 +137,9 @@ def ParseFileObject(self, parser_mediator, file_object, **kwargs):
_ = data_structure.parse_stream(file_object)
except (IOError, construct.FieldError) as exception:
raise errors.UnableToParseFile((
u'Unable to parse Custom Destination file header value with error: '
u'{0:s}').format(exception))
u'Invalid Custom Destination file: {0:s} - unable to parse '
u'header value with error: {1:s}').format(
display_name, exception))

file_size = file_object.get_size()
file_offset = file_object.get_offset()
Expand All @@ -109,54 +153,44 @@ def ParseFileObject(self, parser_mediator, file_object, **kwargs):
try:
entry_header = self._ENTRY_HEADER.parse_stream(file_object)
except (IOError, construct.FieldError) as exception:
error_message = (
u'Invalid Custom Destination file: {0:s} - unable to parse '
u'entry header with error: {1:s}').format(
display_name, exception)

if not first_guid_checked:
raise errors.UnableToParseFile((
u'Unable to parse Custom Destination file entry header with '
u'error: {0:s}').format(exception))
else:
logging.warning((
u'Unable to parse Custom Destination file entry header with '
u'error: {0:s}').format(exception))
raise errors.UnableToParseFile(error_message)

logging.warning(error_message)
break

if entry_header.guid != self._LNK_GUID:
error_message = (
u'Unsupported Custom Destination file: {0:s} - invalid entry '
u'header.').format(display_name)

if not first_guid_checked:
raise errors.UnableToParseFile(
u'Unsupported Custom Destination file - invalid entry header.')
else:
logging.warning(
u'Unsupported Custom Destination file - invalid entry header.')
raise errors.UnableToParseFile(error_message)

file_object.seek(-16, os.SEEK_CUR)
try:
file_footer = self._FILE_FOOTER.parse_stream(self._file_object)
except (IOError, construct.FieldError) as exception:
raise IOError((
u'Unable to parse file footer at offset: 0x{0:08x} '
u'with error: {1:s}').format(file_offset, exception))

if file_footer.signature != self._FOOTER_SIGNATURE:
logging.warning(error_message)

break

first_guid_checked = True
file_offset += 16
remaining_file_size -= 16

path_spec = path_spec_factory.Factory.NewPathSpec(
definitions.TYPE_INDICATOR_DATA_RANGE, range_offset=file_offset,
range_size=remaining_file_size,
parent=parser_mediator.GetFileEntry().path_spec)

try:
lnk_file_object = resolver.Resolver.OpenFileObject(path_spec)
except RuntimeError as exception:
message = u'Unable to open LNK file with error {0:s}'.format(exception)
parser_mediator.ProduceParseError(message)
return

display_name = u'{0:s} # 0x{1:08x}'.format(
parser_mediator.GetFileEntry().name, file_offset)

self._WINLNK_PARSER.UpdateChainAndParseFileObject(
parser_mediator, lnk_file_object, display_name=display_name)

# We cannot trust the file size in the LNK data so we get the last offset
# that was read instead.
lnk_file_size = lnk_file_object.get_offset()

lnk_file_object.close()
lnk_file_size = self._ParseLNKFile(
parser_mediator, file_entry, file_offset, remaining_file_size)

file_offset += lnk_file_size
remaining_file_size -= lnk_file_size
Expand All @@ -167,12 +201,13 @@ def ParseFileObject(self, parser_mediator, file_object, **kwargs):
file_footer = self._FILE_FOOTER.parse_stream(file_object)
except (IOError, construct.FieldError) as exception:
logging.warning((
u'Unable to parse Custom Destination file footer with error: '
u'{0:s}').format(exception))
u'Invalid Custom Destination file: {0:s} - unable to parse '
u'footer with error: {1:s}').format(display_name, exception))

if file_footer.signature != 0xbabffbab:
logging.warning(
u'Unsupported Custom Destination file - invalid footer signature.')
if file_footer.signature != self._FOOTER_SIGNATURE:
logging.warning((
u'Unsupported Custom Destination file: {0:s} - invalid footer '
u'signature.').format(display_name))


manager.ParsersManager.RegisterParser(CustomDestinationsParser)

0 comments on commit 11c4e23

Please sign in to comment.