Source code for

# -*- coding: utf-8 -*-
"""Symantec AV Corporate Edition and Endpoint Protection log file parser."""

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 SymantecEventData(events.EventData): """Symantec event data. Attributes: access (str): access. action0 (str): action0. action1 (str): action1. action1_status (str): action1 status. action2 (str): action2. action2_status (str): action2 status. address (str): address. backup_id (str): backup identifier. cat (str): category. cleaninfo (str): clean information. clientgroup (str): client group. compressed (str): compressed. computer (str): computer. definfo (str): definfo. defseqnumber (str): def sequence number. deleteinfo (str): delete information. depth (str): depth. description (str): description. domain_guid (str): domain identifier (GUID). domainname (str): domain name. err_code (str): error code. event_data (str): event data. event (str): event. extra (str): extra. file (str): file. flags (str): flags. groupid (str): group identifier. guid (str): guid. last_written_time (dfdatetime.DateTimeValues): entry last written date and time. license_expiration_dt (str): license expiration date. license_feature_name (str): license feature name. license_feature_ver (str): license feature ver. license_fulfillment_id (str): license fulfillment identifier. license_lifecycle (str): license lifecycle. license_seats_delta (str): license seats delta. license_seats (str): license seats. license_seats_total (str): license seats total. license_serial_num (str): license serial number. license_start_dt (str): license start date. logger (str): logger. login_domain (str): login domain. log_session_guid (str): log session identifier (GUID). macaddr (str): MAC address. new_ext (str): new ext. ntdomain (str): ntdomain. offset (str): offset. parent (str): parent. quarfwd_status (str): quarfwd status. remote_machine_ip (str): remote machine IP address. remote_machine (str): remote machine. scanid (str): scan identifier. snd_status (str): snd status. status (str): status. still_infected (str): still infected. time (str): time. user (str): user. vbin_id (str): vbin identifier. vbin_session_id (str): vbin session identifier. version (str): version. virus_id (str): virus identifier. virus (str): virus. virustype (str): virustype. """ DATA_TYPE = 'av:symantec:scanlog'
[docs] def __init__(self): """Initializes event data.""" super(SymantecEventData, self).__init__(data_type=self.DATA_TYPE) self.access = None self.action0 = None self.action1 = None self.action1_status = None self.action2 = None self.action2_status = None self.address = None self.backup_id = None = None self.cleaninfo = None self.clientgroup = None self.compressed = None = None self.definfo = None self.defseqnumber = None self.deleteinfo = None self.depth = None self.description = None self.domain_guid = None self.domainname = None self.err_code = None self.event_data = None self.event = None self.extra = None self.file = None self.flags = None self.groupid = None self.guid = None self.last_written_time = None self.license_expiration_dt = None self.license_feature_name = None self.license_feature_ver = None self.license_fulfillment_id = None self.license_lifecycle = None self.license_seats_delta = None self.license_seats = None self.license_seats_total = None self.license_serial_num = None self.license_start_dt = None self.logger = None self.login_domain = None self.log_session_guid = None self.macaddr = None self.new_ext = None self.ntdomain = None self.offset = None self.parent = None self.quarfwd_status = None self.remote_machine_ip = None self.remote_machine = None self.scanid = None self.snd_status = None self.status = None self.still_infected = None self.time = None self.user = None self.vbin_id = None self.vbin_session_id = None self.version = None self.virus_id = None self.virus = None self.virustype = None
[docs] class SymantecParser(dsv_parser.DSVParser): """Parses Symantec AV Corporate Edition and Endpoint Protection log files.""" NAME = 'symantec_scanlog' DATA_FORMAT = 'Symantec AV Corporate Edition and Endpoint Protection log file' # Define the columns that make up the structure of a Symantec log file. # COLUMNS = [ 'time', 'event', 'cat', 'logger', 'computer', 'user', 'virus', 'file', 'action1', 'action2', 'action0', 'virustype', 'flags', 'description', 'scanid', 'new_ext', 'groupid', 'event_data', 'vbin_id', 'virus_id', 'quarfwd_status', 'access', 'snd_status', 'compressed', 'depth', 'still_infected', 'definfo', 'defseqnumber', 'cleaninfo', 'deleteinfo', 'backup_id', 'parent', 'guid', 'clientgroup', 'address', 'domainname', 'ntdomain', 'macaddr', 'version:', 'remote_machine', 'remote_machine_ip', 'action1_status', 'action2_status', 'license_feature_name', 'license_feature_ver', 'license_serial_num', 'license_fulfillment_id', 'license_start_dt', 'license_expiration_dt', 'license_lifecycle', 'license_seats_total', 'license_seats', 'err_code', 'license_seats_delta', 'status', 'domain_guid', 'log_session_guid', 'vbin_session_id', 'login_domain', 'extra'] def _ParseTimestamp(self, timestamp): """Parses a Symantec log timestamp. A Symantec log timestamp consist of six hexadecimal octets, that represent: First octet: Number of years since 1970 Second octet: Month, where 0 represents January. Third octet: Day of the month Fourth octet: Number of hours Fifth octet: Number of minutes Sixth octet: Number of seconds For example, 200A13080122 represents November 19, 2002, 8:01:34 AM. Args: timestamp (str): hexadecimal encoded date and time values. Returns: dfdatetime.TimeElements: date and time value. Raises: ParseError: if a valid date and time value cannot be derived from the time elements. """ try: year, month, day_of_month, hours, minutes, seconds = ( int(hexdigit[0] + hexdigit[1], 16) for hexdigit in zip( timestamp[::2], timestamp[1::2])) time_elements_tuple = ( 1970 + year, month + 1, day_of_month, hours, minutes, seconds) date_time = dfdatetime_time_elements.TimeElements( time_elements_tuple=time_elements_tuple) date_time.is_local_time = True return date_time except (TypeError, ValueError) as exception: raise errors.ParseError( 'Unable to parse time elements with error: {0!s}'.format(exception))
[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): line number of the row. row (dict[str, str]): fields of a single row, as specified in COLUMNS. """ timestamp = row['time'] # TODO: remove unused attributes. event_data = SymantecEventData() event_data.access = row.get('access', None) event_data.action0 = row.get('action0', None) event_data.action1 = row.get('action1', None) event_data.action1_status = row.get('action1_status', None) event_data.action2 = row.get('action2', None) event_data.action2_status = row.get('action2_status', None) event_data.address = row.get('address', None) event_data.backup_id = row.get('backup_id', None) = row.get('cat', None) event_data.cleaninfo = row.get('cleaninfo', None) event_data.clientgroup = row.get('clientgroup', None) event_data.compressed = row.get('compressed', None) = row.get('computer', None) event_data.definfo = row.get('definfo', None) event_data.defseqnumber = row.get('defseqnumber', None) event_data.deleteinfo = row.get('deleteinfo', None) event_data.depth = row.get('depth', None) event_data.description = row.get('description', None) event_data.domain_guid = row.get('domain_guid', None) event_data.domainname = row.get('domainname', None) event_data.err_code = row.get('err_code', None) event_data.event_data = row.get('event_data', None) event_data.event = row.get('event', None) event_data.extra = row.get('extra', None) event_data.file = row.get('file', None) event_data.flags = row.get('flags', None) event_data.groupid = row.get('groupid', None) event_data.guid = row.get('guid', None) event_data.last_written_time = self._ParseTimestamp(timestamp) event_data.license_expiration_dt = row.get('license_expiration_dt', None) event_data.license_feature_name = row.get('license_feature_name', None) event_data.license_feature_ver = row.get('license_feature_ver', None) event_data.license_fulfillment_id = row.get('license_fulfillment_id', None) event_data.license_lifecycle = row.get('license_lifecycle', None) event_data.license_seats_delta = row.get('license_seats_delta', None) event_data.license_seats = row.get('license_seats', None) event_data.license_seats_total = row.get('license_seats_total', None) event_data.license_serial_num = row.get('license_serial_num', None) event_data.license_start_dt = row.get('license_start_dt', None) event_data.logger = row.get('logger', None) event_data.login_domain = row.get('login_domain', None) event_data.log_session_guid = row.get('log_session_guid', None) event_data.macaddr = row.get('macaddr', None) event_data.new_ext = row.get('new_ext', None) event_data.ntdomain = row.get('ntdomain', None) event_data.offset = row_offset event_data.parent = row.get('parent', None) event_data.quarfwd_status = row.get('quarfwd_status', None) event_data.remote_machine_ip = row.get('remote_machine_ip', None) event_data.remote_machine = row.get('remote_machine', None) event_data.scanid = row.get('scanid', None) event_data.snd_status = row.get('snd_status', None) event_data.status = row.get('status', None) event_data.still_infected = row.get('still_infected', None) event_data.time = row.get('time', None) event_data.user = row.get('user', None) event_data.vbin_id = row.get('vbin_id', None) event_data.vbin_session_id = row.get('vbin_session_id', None) event_data.version = row.get('version:', None) event_data.virus_id = row.get('virus_id', None) event_data.virus = row.get('virus', None) event_data.virustype = row.get('virustype', None) parser_mediator.ProduceEventData(event_data)
[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. """ timestamp = row['time'] try: self._ParseTimestamp(timestamp) except errors.ParseError: return False try: my_event = int(row['event'], 10) except (TypeError, ValueError): return False if my_event < 1 or my_event > 77: return False try: category = int(row['cat'], 10) except (TypeError, ValueError): return False if category < 1 or category > 4: return False return True