"""Parser for Windows Program Compatibility Assistant (PCA) log files."""
from dfdatetime import time_elements as dfdatetime_time_elements
from plaso.containers import events
from plaso.lib import errors
from plaso.parsers import dsv_parser
from plaso.parsers import manager
[docs]
class WindowsPCAEventData(events.EventData):
"""Windows PCA (Program Compatibility Assistant) event data.
Attributes:
description (str): description of the executable.
executable (str): executable filename.
exit_code (str): final result of the execution.
last_execution_time (dfdatetime.DateTimeValues): entry last execution
date and time.
program_identifier (str): program identifier.
run_status (str): execution status.
vendor (str): vendor of executed software.
version (str): version of executed software.
"""
DATA_TYPE = "windows:pca_log:entry"
[docs]
def __init__(self):
"""Initializes event data."""
super().__init__(data_type=self.DATA_TYPE)
self.description = None
self.executable = None
self.exit_code = None
self.last_execution_time = None
self.program_identifier = None
self.run_status = None
self.vendor = None
self.version = None
[docs]
class WindowsPCABaseParser(dsv_parser.DSVParser):
"""Shared code for parsing Program Compatibility Assistant (PCA) log files."""
# pylint: disable=abstract-method
DELIMITER = "|"
COLUMNS = ()
_MINIMUM_NUMBER_OF_COLUMNS = None
def _ParseDateTime(self, date_time_string):
"""Parses date and time elements of a log line.
Args:
date_time_string (string): date and time string.
Returns:
dfdatetime.TimeElements: date and time value.
Raises:
ParseError: if a valid date and time value cannot be derived from
the time elements.
"""
date_time = dfdatetime_time_elements.TimeElementsInMilliseconds()
try:
date_time.CopyFromDateTimeString(date_time_string)
except ValueError:
raise errors.ParseError(
f"Unsupported date and time string: {date_time_string!s}"
)
return date_time
[docs]
def VerifyRow(self, parser_mediator, row):
"""Verifies if a line of the file is in the expected format.
Args:
parser_mediator (ParserMediator): mediates interactions between parsers
and other components, such as storage and dfVFS.
row (dict[str, str]): fields of a single row, as specified in COLUMNS.
Returns:
bool: True if this is the correct parser, False otherwise.
"""
if len(row) < self._MINIMUM_NUMBER_OF_COLUMNS:
return False
try:
self._ParseDateTime(row["datetime"])
except errors.ParseError:
return False
return "\\" in row["program"]
[docs]
class WindowsPCADB0Parser(WindowsPCABaseParser):
"""Parses Windows Program Compatibility Assistant DB0 log files."""
NAME = "winpca_db0"
DATA_FORMAT = "Windows PCA DB0 log file"
COLUMNS = [
"datetime",
"run_status",
"program",
"description",
"vendor",
"version",
"program_id",
"exit_code",
]
_MINIMUM_NUMBER_OF_COLUMNS = 8
[docs]
def ParseRow(
self, parser_mediator, row_offset, row
): # pylint: disable=unused-argument
"""Parses a line of the log file and produces events.
Args:
parser_mediator (ParserMediator): mediates interactions between parsers
and other components, such as storage and dfVFS.
row_offset (int): offset of the line from which the row was extracted.
row (dict[str, str]): fields of a single row, as specified in COLUMNS.
"""
datetime_value = row["datetime"]
try:
last_execution_time = self._ParseDateTime(datetime_value)
except errors.ParseError:
parser_mediator.ProduceExtractionWarning(
f"Unsupported date and time string: {datetime_value!s}"
)
event_data = WindowsPCAEventData()
event_data.description = row["description"]
event_data.executable = row["program"]
event_data.exit_code = row["exit_code"]
event_data.last_execution_time = last_execution_time
event_data.program_identifier = row["program_id"]
event_data.run_status = row["run_status"]
event_data.vendor = row["vendor"]
event_data.version = row["version"]
parser_mediator.ProduceEventData(event_data)
[docs]
class WindowsPCADicParser(WindowsPCABaseParser):
"""Parses the Windows Program Compatibility Assistant DIC log files."""
NAME = "winpca_dic"
DATA_FORMAT = "Windows PCA DIC log file"
COLUMNS = ["program", "datetime"]
_MINIMUM_NUMBER_OF_COLUMNS = 2
[docs]
def ParseRow(self, parser_mediator, row_offset, row):
"""Parses a line of the log file and produces events.
Args:
parser_mediator (ParserMediator): mediates interactions between parsers
and other components, such as storage and dfVFS.
row_offset (int): offset of the line from which the row was extracted.
row (dict[str, str]): fields of a single row, as specified in COLUMNS.
"""
datetime_value = row["datetime"]
try:
last_execution_time = self._ParseDateTime(datetime_value)
except errors.ParseError:
parser_mediator.ProduceExtractionWarning(
f"Unsupported date and time string: {datetime_value!s}"
)
event_data = WindowsPCAEventData()
event_data.executable = row["program"]
event_data.last_execution_time = last_execution_time
parser_mediator.ProduceEventData(event_data)
manager.ParsersManager.RegisterParsers([WindowsPCADicParser, WindowsPCADB0Parser])