Skip to content

Commit

Permalink
Merge master
Browse files Browse the repository at this point in the history
  • Loading branch information
Onager committed Aug 1, 2018
2 parents face521 + 6feb93b commit a17c426
Show file tree
Hide file tree
Showing 6 changed files with 81 additions and 61 deletions.
80 changes: 37 additions & 43 deletions plaso/parsers/winreg_plugins/bagmru.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,17 +3,20 @@

from __future__ import unicode_literals

import construct
from dtfabric.runtime import data_maps as dtfabric_data_maps

from plaso.containers import time_events
from plaso.containers import windows_events
from plaso.lib import definitions
from plaso.lib import errors
from plaso.parsers.shared import shell_items
from plaso.parsers import winreg
from plaso.parsers.winreg_plugins import dtfabric_plugin
from plaso.parsers.winreg_plugins import interface


class BagMRUPlugin(interface.WindowsRegistryPlugin):
class BagMRUWindowsRegistryPlugin(
dtfabric_plugin.DtFabricBaseWindowsRegistryPlugin):
"""Class that defines a BagMRU Windows Registry plugin."""

NAME = 'bagmru'
Expand Down Expand Up @@ -42,7 +45,7 @@ class BagMRUPlugin(interface.WindowsRegistryPlugin):
('https://github.com/libyal/winreg-kb/blob/master/documentation/'
'MRU%20keys.asciidoc#bagmru-key')]

_MRULISTEX_ENTRY = construct.ULInt32('entry_number')
_DEFINITION_FILE = 'mru.yaml'

_SOURCE_APPEND = ': BagMRU'

Expand Down Expand Up @@ -99,47 +102,29 @@ def _ParseMRUListExEntryValue(

return path_segment

def _ParseMRUListExValue(self, parser_mediator, registry_key):
def _ParseMRUListExValue(self, registry_key):
"""Parses the MRUListEx value in a given Registry key.
Args:
parser_mediator (ParserMediator): mediates interactions between parsers
and other components, such as storage and dfvfs.
registry_key (dfwinreg.WinRegistryKey): Windows Registry key that contains
the MRUListEx value.
Yields:
tuple: containing:
int: MRUListEx index, where 0 is the first index value.
int: entry number.
Returns:
mrulistex_entries: MRUListEx entries or None if not available.
"""
mru_list_value = registry_key.GetValueByName('MRUListEx')
if mru_list_value:
mrulistex_data = mru_list_value.data
data_size = len(mrulistex_data)
_, remainder = divmod(data_size, 4)
mrulistex_value = registry_key.GetValueByName('MRUListEx')

if remainder != 0:
parser_mediator.ProduceExtractionError((
'MRUListEx value data size is not a multitude of 4 '
'in MRU key: {0:s}').format(registry_key.path))
data_size -= remainder

entry_index = 0
data_offset = 0
while data_offset < data_size:
try:
entry_number = self._MRULISTEX_ENTRY.parse(
mrulistex_data[data_offset:])
yield entry_index, entry_number
except construct.FieldError:
parser_mediator.ProduceExtractionError((
'Unable to parse MRUListEx value data at offset: {0:d} '
'in MRU key: {1:s}').format(data_offset, registry_key.path))

entry_index += 1
data_offset += 4
# The key exists but does not contain a value named "MRUList".
if not mrulistex_value:
return None

mrulistex_entries_map = self._GetDataTypeMap('mrulistex_entries')

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

return self._ReadStructureFromByteStream(
mrulistex_value.data, 0, mrulistex_entries_map, context=context)

def _ParseSubKey(
self, parser_mediator, registry_key, parent_path_segments,
Expand All @@ -153,21 +138,30 @@ def _ParseSubKey(
parent_path_segments (list[str]): parent shell item path segments.
codepage (Optional[str]): extended ASCII string codepage.
"""
try:
mrulistex = self._ParseMRUListExValue(registry_key)
except (ValueError, errors.ParseError) as exception:
parser_mediator.ProduceExtractionError(
'unable to parse MRUListEx value with error: {0!s}'.format(exception))
return

if not mrulistex:
return

entry_numbers = {}
values_dict = {}
value_strings = {}

found_terminator = False
for index, entry_number in self._ParseMRUListExValue(
parser_mediator, registry_key):
if entry_number == 0xffffffff:
found_terminator = True
for index, entry_number in enumerate(mrulistex):
# The MRU list is terminated with -1 (0xffffffff).
if entry_number == -1:
continue

if found_terminator:
parser_mediator.ProduceExtractionError((
'Found additional MRUListEx entries after terminator '
'in key: {0:s}.').format(registry_key.path))
'found additional MRUListEx entries after terminator in key: '
'{0:s}.').format(registry_key.path))

# Only create one parser error per terminator.
found_terminator = False
Expand Down Expand Up @@ -218,4 +212,4 @@ def ExtractEvents(
self._ParseSubKey(parser_mediator, registry_key, [], codepage=codepage)


winreg.WinRegistryParser.RegisterPlugin(BagMRUPlugin)
winreg.WinRegistryParser.RegisterPlugin(BagMRUWindowsRegistryPlugin)
4 changes: 2 additions & 2 deletions plaso/parsers/winreg_plugins/mru.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -34,13 +34,13 @@ name: mrulist_entries
type: sequence
description: MRUList entries
element_data_type: uint16
elements_terminator: 0
elements_data_size: data_size
---
name: mrulistex_entries
type: sequence
description: MRUListEx entries
element_data_type: int32
elements_terminator: -1
elements_data_size: data_size
---
name: utf16le_string
type: string
Expand Down
36 changes: 25 additions & 11 deletions plaso/parsers/winreg_plugins/mrulist.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,10 +5,11 @@

import abc

from dtfabric.runtime import data_maps as dtfabric_data_maps

from plaso.containers import time_events
from plaso.containers import windows_events
from plaso.lib import definitions
from plaso.lib import binary
from plaso.lib import errors
from plaso.parsers import logger
from plaso.parsers import winreg
Expand Down Expand Up @@ -93,8 +94,11 @@ def _ParseMRUListValue(self, registry_key):

mrulist_entries_map = self._GetDataTypeMap('mrulist_entries')

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

return self._ReadStructureFromByteStream(
mrulist_value.data, 0, mrulist_entries_map)
mrulist_value.data, 0, mrulist_entries_map, context=context)

def _ParseMRUListKey(self, parser_mediator, registry_key, codepage='cp1252'):
"""Extract event objects from a MRUList Registry key.
Expand All @@ -116,11 +120,20 @@ def _ParseMRUListKey(self, parser_mediator, registry_key, codepage='cp1252'):
return

values_dict = {}
found_terminator = False
for entry_index, entry_letter in enumerate(mrulist):
# The MRU list is terminated with '\0' (0x0000).
if entry_letter == 0:
break

if found_terminator:
parser_mediator.ProduceExtractionError((
'found additional MRUList entries after terminator in key: '
'{0:s}.').format(registry_key.path))

# Only create one parser error per terminator.
found_terminator = False

entry_letter = chr(entry_letter)

value_string = self._ParseMRUListEntryValue(
Expand Down Expand Up @@ -185,17 +198,18 @@ def _ParseMRUListEntryValue(
logger.debug((
'[{0:s}] Non-string MRUList entry value: {1:s} parsed as string '
'in key: {2:s}.').format(self.NAME, entry_letter, registry_key.path))
utf16_stream = binary.ByteStreamCopyToUTF16String(value.data)

utf16le_string_map = self._GetDataTypeMap('utf16le_string')

try:
value_string = utf16_stream.decode('utf-16-le')
except UnicodeDecodeError as exception:
value_string = binary.HexifyBuffer(utf16_stream)
logger.warning((
'[{0:s}] Unable to decode UTF-16 stream: {1:s} in MRUList entry '
'value: {2:s} in key: {3:s} with error: {4!s}').format(
self.NAME, value_string, entry_letter, registry_key.path,
exception))
value_string = self._ReadStructureFromByteStream(
value.data, 0, utf16le_string_map)
except (ValueError, errors.ParseError) as exception:
parser_mediator.ProduceExtractionError((
'unable to parse MRUList entry value: {0:s} with error: '
'{1!s}').format(entry_letter, exception))

value_string = value_string.rstrip('\x00')

return value_string

Expand Down
14 changes: 13 additions & 1 deletion plaso/parsers/winreg_plugins/mrulistex.py
Original file line number Diff line number Diff line change
Expand Up @@ -104,8 +104,11 @@ def _ParseMRUListExValue(self, registry_key):

mrulistex_entries_map = self._GetDataTypeMap('mrulistex_entries')

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

return self._ReadStructureFromByteStream(
mrulistex_value.data, 0, mrulistex_entries_map)
mrulistex_value.data, 0, mrulistex_entries_map, context=context)

def _ParseMRUListExKey(
self, parser_mediator, registry_key, codepage='cp1252'):
Expand All @@ -128,11 +131,20 @@ def _ParseMRUListExKey(
return

values_dict = {}
found_terminator = False
for entry_index, entry_number in enumerate(mrulistex):
# The MRU list is terminated with -1 (0xffffffff).
if entry_number == -1:
break

if found_terminator:
parser_mediator.ProduceExtractionError((
'found additional MRUListEx entries after terminator in key: '
'{0:s}.').format(registry_key.path))

# Only create one parser error per terminator.
found_terminator = False

value_string = self._ParseMRUListExEntryValue(
parser_mediator, registry_key, entry_index, entry_number,
codepage=codepage)
Expand Down
6 changes: 3 additions & 3 deletions tests/parsers/winreg_plugins/bagmru.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,12 +13,12 @@
from tests.parsers.winreg_plugins import test_lib


class TestBagMRUPlugin(test_lib.RegistryPluginTestCase):
class TestBagMRUWindowsRegistryPlugin(test_lib.RegistryPluginTestCase):
"""Tests for the BagMRU plugin."""

def testFilters(self):
"""Tests the FILTERS class attribute."""
plugin = bagmru.BagMRUPlugin()
plugin = bagmru.BagMRUWindowsRegistryPlugin()

key_path = (
'HKEY_CURRENT_USER\\Software\\Microsoft\\Windows\\Shell\\BagMRU')
Expand Down Expand Up @@ -54,7 +54,7 @@ def testFilters(self):
@shared_test_lib.skipUnlessHasTestFile(['NTUSER.DAT'])
def testProcess(self):
"""Tests the Process function."""
plugin = bagmru.BagMRUPlugin()
plugin = bagmru.BagMRUWindowsRegistryPlugin()
test_file_entry = self._GetTestFileEntry(['NTUSER.DAT'])
key_path = (
'HKEY_CURRENT_USER\\Software\\Microsoft\\Windows\\ShellNoRoam\\BagMRU')
Expand Down
2 changes: 1 addition & 1 deletion tests/parsers/winreg_plugins/mrulist.py
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,7 @@ def _CreateTestKey(self, key_path, time_string):
offset=1892)
registry_key.AddValue(registry_value)

value_data = 'c:/evil.exe'.encode('utf_16_le')
value_data = 'c:/evil.exe\x00'.encode('utf_16_le')
registry_value = dfwinreg_fake.FakeWinRegistryValue(
'b', data=value_data, data_type=dfwinreg_definitions.REG_BINARY,
offset=612)
Expand Down

0 comments on commit a17c426

Please sign in to comment.