Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Changes to Windows time zone preprocessor #2673 #3734

Merged
merged 1 commit into from
Jun 19, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 10 additions & 2 deletions plaso/cli/pinfo_tool.py
Original file line number Diff line number Diff line change
Expand Up @@ -862,10 +862,18 @@ def _PrintSourceConfiguration(

table_view = views.ViewsFactory.GetTableView(
self._views_format_type,
column_names=['Name', ''], title=title)
column_names=['Name', 'Offset from UTC'], title=title)

for time_zone in system_configuration.available_time_zones:
table_view.AddRow([time_zone.name, ''])
hours_from_utc, minutes_from_utc = divmod(time_zone.offset, 60)
if hours_from_utc < 0:
sign = '+'
hours_from_utc *= -1
else:
sign = '-'
time_zone_offset = '{0:s}{1:02d}:{2:02d}'.format(
sign, hours_from_utc, minutes_from_utc)
table_view.AddRow([time_zone.name, time_zone_offset])

table_view.Write(self._output_writer)

Expand Down
5 changes: 4 additions & 1 deletion plaso/containers/artifacts.py
Original file line number Diff line number Diff line change
Expand Up @@ -463,18 +463,21 @@ class TimeZoneArtifact(ArtifactAttributeContainer):
Attributes:
name (str): name describing the time zone for example Greenwich Standard
Time.
offset (int): time zone offset in number of minutes from UTC.
"""
CONTAINER_TYPE = 'time_zone'

def __init__(self, name=None):
def __init__(self, name=None, offset=None):
"""Initializes a time zone artifact.

Args:
name (Optional[str]): name describing the time zone for example Greenwich
Standard Time.
offset (Optional[int]): time zone offset in number of minutes from UTC.
"""
super(TimeZoneArtifact, self).__init__()
self.name = name
self.offset = offset


class UserAccountArtifact(ArtifactAttributeContainer):
Expand Down
10 changes: 8 additions & 2 deletions plaso/parsers/winreg_plugins/appcompatcache.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
# -*- coding: utf-8 -*-
"""Windows Registry plugin to parse the Application Compatibility Cache key."""

import os

from dfdatetime import filetime as dfdatetime_filetime
from dfdatetime import semantic_time as dfdatetime_semantic_time

Expand All @@ -9,9 +11,9 @@
from plaso.containers import events
from plaso.containers import time_events
from plaso.lib import definitions
from plaso.lib import dtfabric_helper
from plaso.lib import errors
from plaso.parsers import winreg_parser
from plaso.parsers.winreg_plugins import dtfabric_plugin
from plaso.parsers.winreg_plugins import interface


Expand Down Expand Up @@ -65,7 +67,7 @@ def __init__(self):


class AppCompatCacheWindowsRegistryPlugin(
dtfabric_plugin.DtFabricBaseWindowsRegistryPlugin):
interface.WindowsRegistryPlugin, dtfabric_helper.DtFabricHelper):
"""Application Compatibility Cache data Windows Registry plugin."""

NAME = 'appcompatcache'
Expand All @@ -81,6 +83,10 @@ class AppCompatCacheWindowsRegistryPlugin(

_DEFINITION_FILE = 'appcompatcache.yaml'

# Preserve the absolute path value of __file__ in case it is changed
# at run-time.
_DEFINITION_FILES_PATH = os.path.dirname(__file__)

_FORMAT_TYPE_2000 = 1
_FORMAT_TYPE_XP = 2
_FORMAT_TYPE_2003 = 3
Expand Down
10 changes: 8 additions & 2 deletions plaso/parsers/winreg_plugins/bagmru.py
Original file line number Diff line number Diff line change
@@ -1,15 +1,17 @@
# -*- coding: utf-8 -*-
"""This file contains BagMRU Windows Registry plugins (shellbags)."""

import os

from dtfabric.runtime import data_maps as dtfabric_data_maps

from plaso.containers import events
from plaso.containers import time_events
from plaso.lib import definitions
from plaso.lib import dtfabric_helper
from plaso.lib import errors
from plaso.parsers.shared import shell_items
from plaso.parsers import winreg_parser
from plaso.parsers.winreg_plugins import dtfabric_plugin
from plaso.parsers.winreg_plugins import interface


Expand All @@ -31,7 +33,7 @@ def __init__(self):


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

NAME = 'bagmru'
Expand All @@ -58,6 +60,10 @@ class BagMRUWindowsRegistryPlugin(

_DEFINITION_FILE = 'mru.yaml'

# Preserve the absolute path value of __file__ in case it is changed
# at run-time.
_DEFINITION_FILES_PATH = os.path.dirname(__file__)

def _ParseMRUListExEntryValue(
self, parser_mediator, registry_key, entry_number, parent_path_segments,
codepage='cp1252'):
Expand Down
10 changes: 8 additions & 2 deletions plaso/parsers/winreg_plugins/bam.py
Original file line number Diff line number Diff line change
@@ -1,15 +1,17 @@
# -*- coding: utf-8 -*-
"""Windows Registry plugin to parse the Background Activity Moderator keys."""

import os

from dfdatetime import filetime as dfdatetime_filetime

from plaso.containers import events
from plaso.containers import time_events
from plaso.lib import definitions
from plaso.lib import dtfabric_helper
from plaso.lib import errors
from plaso.parsers import winreg_parser
from plaso.parsers.winreg_plugins import interface
from plaso.parsers.winreg_plugins import dtfabric_plugin


class BackgroundActivityModeratorEventData(events.EventData):
Expand All @@ -32,7 +34,7 @@ def __init__(self):


class BackgroundActivityModeratorWindowsRegistryPlugin(
dtfabric_plugin.DtFabricBaseWindowsRegistryPlugin):
interface.WindowsRegistryPlugin, dtfabric_helper.DtFabricHelper):
"""Background Activity Moderator data Windows Registry plugin."""

NAME = 'bam'
Expand All @@ -48,6 +50,10 @@ class BackgroundActivityModeratorWindowsRegistryPlugin(

_DEFINITION_FILE = 'filetime.yaml'

# Preserve the absolute path value of __file__ in case it is changed
# at run-time.
_DEFINITION_FILES_PATH = os.path.dirname(__file__)

def _ParseValue(self, registry_value):
"""Parses the registry value.

Expand Down
9 changes: 7 additions & 2 deletions plaso/parsers/winreg_plugins/mrulist.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,17 +6,18 @@
"""

import abc
import os

from dtfabric.runtime import data_maps as dtfabric_data_maps

from plaso.containers import events
from plaso.containers import time_events
from plaso.lib import definitions
from plaso.lib import dtfabric_helper
from plaso.lib import errors
from plaso.parsers import logger
from plaso.parsers import winreg_parser
from plaso.parsers.shared import shell_items
from plaso.parsers.winreg_plugins import dtfabric_plugin
from plaso.parsers.winreg_plugins import interface


Expand Down Expand Up @@ -69,11 +70,15 @@ def Match(self, registry_key):


class BaseMRUListWindowsRegistryPlugin(
dtfabric_plugin.DtFabricBaseWindowsRegistryPlugin):
interface.WindowsRegistryPlugin, dtfabric_helper.DtFabricHelper):
"""Class for common MRUList Windows Registry plugin functionality."""

_DEFINITION_FILE = 'mru.yaml'

# Preserve the absolute path value of __file__ in case it is changed
# at run-time.
_DEFINITION_FILES_PATH = os.path.dirname(__file__)

@abc.abstractmethod
def _ParseMRUListEntryValue(
self, parser_mediator, registry_key, entry_index, entry_letter, **kwargs):
Expand Down
9 changes: 7 additions & 2 deletions plaso/parsers/winreg_plugins/mrulistex.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,17 +6,18 @@
"""

import abc
import os

from dtfabric.runtime import data_maps as dtfabric_data_maps

from plaso.containers import events
from plaso.containers import time_events
from plaso.lib import errors
from plaso.lib import dtfabric_helper
from plaso.lib import definitions
from plaso.parsers import logger
from plaso.parsers import winreg_parser
from plaso.parsers.shared import shell_items
from plaso.parsers.winreg_plugins import dtfabric_plugin
from plaso.parsers.winreg_plugins import interface


Expand Down Expand Up @@ -79,11 +80,15 @@ def Match(self, registry_key):


class BaseMRUListExWindowsRegistryPlugin(
dtfabric_plugin.DtFabricBaseWindowsRegistryPlugin):
interface.WindowsRegistryPlugin, dtfabric_helper.DtFabricHelper):
"""Class for common MRUListEx Windows Registry plugin functionality."""

_DEFINITION_FILE = 'mru.yaml'

# Preserve the absolute path value of __file__ in case it is changed
# at run-time.
_DEFINITION_FILES_PATH = os.path.dirname(__file__)

@abc.abstractmethod
def _ParseMRUListExEntryValue(
self, parser_mediator, registry_key, entry_index, entry_number, **kwargs):
Expand Down
60 changes: 60 additions & 0 deletions plaso/preprocessors/time_zone_information.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
name: time_zone_information
type: format
description: Time Zone Information (TZI) format
---
name: uint16
type: integer
attributes:
format: unsigned
size: 2
units: bytes
---
name: int32
type: integer
attributes:
format: signed
size: 4
units: bytes
---
name: system_time
type: structure
members:
- name: year
data_type: uint16
- name: month
data_type: uint16
- name: weekday
data_type: uint16
- name: day_of_month
data_type: uint16
- name: hours
data_type: uint16
- name: minutes
data_type: uint16
- name: seconds
data_type: uint16
- name: milliseconds
data_type: uint16
---
name: tzi_record
type: structure
description: Time Zone Information (TZI)
aliases: ['TIME_ZONE_INFORMATION', '_REG_TZI_FORMAT']
attributes:
byte_order: little-endian
members:
- name: bias
aliases: ['Bias']
data_type: int32
- name: standard_bias
aliases: ['StandardBias']
data_type: int32
- name: daylight_bias
aliases: ['DaylightBias']
data_type: int32
- name: standard_date
aliases: ['StandardDate']
data_type: system_time
- name: daylight_date
aliases: ['DaylightDate']
data_type: system_time
53 changes: 51 additions & 2 deletions plaso/preprocessors/windows.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,10 @@
# -*- coding: utf-8 -*-
"""This file contains preprocessors for Windows."""

import os

from plaso.containers import artifacts
from plaso.lib import dtfabric_helper
from plaso.lib import errors
from plaso.preprocessors import interface
from plaso.preprocessors import logger
Expand Down Expand Up @@ -195,11 +198,18 @@ def Collect(self, mediator):


class WindowsAvailableTimeZonesPlugin(
interface.WindowsRegistryKeyArtifactPreprocessorPlugin):
interface.WindowsRegistryKeyArtifactPreprocessorPlugin,
dtfabric_helper.DtFabricHelper):
"""The Windows available time zones plugin."""

ARTIFACT_DEFINITION_NAME = 'WindowsAvailableTimeZones'

_DEFINITION_FILE = 'time_zone_information.yaml'

# Preserve the absolute path value of __file__ in case it is changed
# at run-time.
_DEFINITION_FILES_PATH = os.path.dirname(__file__)

def _ParseKey(self, mediator, registry_key, value_name):
"""Parses a Windows Registry key for a preprocessing attribute.

Expand All @@ -212,14 +222,53 @@ def _ParseKey(self, mediator, registry_key, value_name):
Raises:
errors.PreProcessFail: if the preprocessing fails.
"""
tzi_value = registry_key.GetValueByName('TZI')
if not tzi_value:
mediator.ProducePreprocessingWarning(
self.ARTIFACT_DEFINITION_NAME,
'TZI value missing from Windows Registry key: {0:s}'.format(
registry_key.key_path))
return

time_zone_artifact = artifacts.TimeZoneArtifact(name=registry_key.name)
try:
self._ParseTZIValue(tzi_value.data, time_zone_artifact)

except (ValueError, errors.ParseError) as exception:
mediator.ProducePreprocessingWarning(
self.ARTIFACT_DEFINITION_NAME,
'Unable to parse TZI record value in Windows Registry key: {0:s} '
'with error: {2!s}'.format(
registry_key.key_path, exception))
return

try:
mediator.knowledge_base.AddAvailableTimeZone(time_zone_artifact)
except KeyError:
mediator.ProducePreprocessingWarning(
self.ARTIFACT_DEFINITION_NAME,
'Unable to set time zone in knowledge base.')
'Unable to set add time zone: {0:s} to knowledge base.'.format(
registry_key.name))

def _ParseTZIValue(self, value_data, time_zone_artifact):
"""Parses the time zone information (TZI) value data.

Args:
value_data (bytes): time zone information (TZI) value data.
time_zone_artifact (TimeZoneArtifact): time zone artifact.

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

tzi_record = self._ReadStructureFromByteStream(
value_data, 0, data_type_map)

if tzi_record.standard_bias:
time_zone_artifact.offset = tzi_record.standard_bias
else:
time_zone_artifact.offset = tzi_record.bias


class WindowsCodepagePlugin(
Expand Down