Source code for plaso.parsers.winreg_plugins.sam_users
# -*- coding: utf-8 -*-
""""Windows Registry plugin for SAM Users Account information."""
from __future__ import unicode_literals
from dfdatetime import filetime as dfdatetime_filetime
from plaso.containers import events
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 import winreg
from plaso.parsers.winreg_plugins import dtfabric_plugin
from plaso.parsers.winreg_plugins import interface
[docs]class SAMUsersWindowsRegistryEventData(events.EventData):
"""Class that defines SAM users Windows Registry event data.
Attributes:
account_rid (int): account relative identifier (RID).
comments (str): comments.
fullname (str): full name.
key_path (str): Windows Registry key path.
login_count (int): login count.
username (str): a string containing the username.
"""
DATA_TYPE = 'windows:registry:sam_users'
def __init__(self):
"""Initializes event data."""
super(SAMUsersWindowsRegistryEventData, self).__init__(
data_type=self.DATA_TYPE)
self.account_rid = None
self.comments = None
self.fullname = None
self.key_path = None
self.login_count = None
self.username = None
[docs]class SAMUsersWindowsRegistryPlugin(
dtfabric_plugin.DtFabricBaseWindowsRegistryPlugin):
"""Windows Registry plugin for SAM Users Account information."""
NAME = 'windows_sam_users'
DESCRIPTION = 'Parser for SAM Users and Names Registry keys.'
FILTERS = frozenset([
interface.WindowsRegistryKeyPathFilter(
'HKEY_LOCAL_MACHINE\\SAM\\SAM\\Domains\\Account\\Users')])
_DEFINITION_FILE = 'sam_users.yaml'
_V_VALUE_STRINGS_OFFSET = 0xcc
_SOURCE_APPEND = ': User Account Information'
def _ParseFValue(self, registry_key):
"""Parses an F value.
Args:
registry_key (dfwinreg.WinRegistryKey): Windows Registry key.
Returns:
f_value: F value stored in the Windows Registry key.
Raises:
ParseError: if the Windows Registry key does not contain an F value or
F value cannot be parsed.
"""
registry_value = registry_key.GetValueByName('F')
if not registry_value:
raise errors.ParseError(
'missing value: "F" in Windows Registry key: {0:s}.'.format(
registry_key.name))
f_value_map = self._GetDataTypeMap('f_value')
try:
return self._ReadStructureFromByteStream(
registry_value.data, 0, f_value_map)
except (ValueError, errors.ParseError) as exception:
raise errors.ParseError(exception)
def _ParseVValueString(
self, parser_mediator, data, user_information_descriptor):
"""Parses a V value string.
Args:
parser_mediator (ParserMediator): mediates interactions between parsers
and other components, such as storage and dfvfs.
data (bytes): Windows Registry V value data.
user_information_descriptor (user_information_descriptor): V value
user information descriptor.
Returns:
str: string value stored in the Windows Registry V value data.
"""
data_start_offset = (
user_information_descriptor.offset + self._V_VALUE_STRINGS_OFFSET)
data_end_offset = data_start_offset + user_information_descriptor.size
descriptor_data = data[data_start_offset:data_end_offset]
try:
username = descriptor_data.decode('utf-16-le')
except (UnicodeDecodeError, UnicodeEncodeError) as exception:
username = descriptor_data.decode('utf-16-le', errors='replace')
parser_mediator.ProduceExtractionError((
'unable to decode V value string with error: {0!s}. Characters '
'that cannot be decoded will be replaced with "?" or '
'"\\ufffd".').format(exception))
return username
# pylint 1.9.3 wants a docstring for kwargs, but this is not useful to add.
# pylint: disable=missing-param-doc
[docs] def ExtractEvents(self, parser_mediator, registry_key, **kwargs):
"""Extracts events from a Windows 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.
"""
names_key = registry_key.GetSubkeyByName('Names')
if not names_key:
parser_mediator.ProduceExtractionError('missing subkey: Names.')
return
last_written_time_per_username = {
registry_value.name: registry_value.last_written_time
for registry_value in names_key.GetSubkeys()}
for subkey in registry_key.GetSubkeys():
if subkey.name == 'Names':
continue
try:
f_value = self._ParseFValue(subkey)
except errors.ParseError as exception:
parser_mediator.ProduceExtractionError(
'unable to parse F value with error: {0!s}'.format(exception))
continue
registry_value = subkey.GetValueByName('V')
if not registry_value:
parser_mediator.ProduceExtractionError(
'missing Registry value: "V" in subkey: {0:s}.'.format(
subkey.name))
continue
v_value_map = self._GetDataTypeMap('v_value')
try:
v_value = self._ReadStructureFromByteStream(
registry_value.data, 0, v_value_map)
except (ValueError, errors.ParseError) as exception:
parser_mediator.ProduceExtractionError(
'unable to parse V value with error: {0!s}'.format(exception))
continue
username = self._ParseVValueString(
parser_mediator, registry_value.data, v_value[1])
fullname = self._ParseVValueString(
parser_mediator, registry_value.data, v_value[2])
comments = self._ParseVValueString(
parser_mediator, registry_value.data, v_value[3])
last_written_time = last_written_time_per_username.get(username, None)
# TODO: check if subkey.name == f_value.rid
if last_written_time:
values_dict = {
'account_rid': f_value.rid,
'login_count': f_value.number_of_logons}
if username:
values_dict['username'] = username
if fullname:
values_dict['full_name'] = fullname
if comments:
values_dict['comments'] = comments
event_data = windows_events.WindowsRegistryEventData()
event_data.key_path = registry_key.path
event_data.regvalue = values_dict
event_data.source_append = self._SOURCE_APPEND
event = time_events.DateTimeValuesEvent(
last_written_time, definitions.TIME_DESCRIPTION_WRITTEN)
parser_mediator.ProduceEventWithEventData(event, event_data)
event_data = SAMUsersWindowsRegistryEventData()
event_data.account_rid = f_value.rid
event_data.comments = comments
event_data.fullname = fullname
event_data.key_path = registry_key.path
event_data.login_count = f_value.number_of_logons
event_data.username = username
if f_value.last_login_time != 0:
date_time = dfdatetime_filetime.Filetime(
timestamp=f_value.last_login_time)
event = time_events.DateTimeValuesEvent(
date_time, definitions.TIME_DESCRIPTION_LAST_LOGIN)
parser_mediator.ProduceEventWithEventData(event, event_data)
if f_value.last_password_set_time != 0:
date_time = dfdatetime_filetime.Filetime(
timestamp=f_value.last_password_set_time)
event = time_events.DateTimeValuesEvent(
date_time, definitions.TIME_DESCRIPTION_LAST_PASSWORD_RESET)
parser_mediator.ProduceEventWithEventData(event, event_data)
winreg.WinRegistryParser.RegisterPlugin(SAMUsersWindowsRegistryPlugin)