plaso-rubanetra/plaso/parsers/winreg_plugins/task_scheduler.py
2020-04-06 18:48:34 +02:00

170 lines
5.8 KiB
Python

#!/usr/bin/python
# -*- coding: utf-8 -*-
#
# Copyright 2014 The Plaso Project Authors.
# Please see the AUTHORS file for details on individual authors.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
"""This file contains the Task Scheduler Registry keys plugins."""
import logging
import construct
from plaso.events import windows_events
from plaso.events import time_events
from plaso.parsers import winreg
from plaso.parsers.winreg_plugins import interface
class TaskCacheEvent(time_events.FiletimeEvent):
"""Convenience class for a Task Cache event."""
DATA_TYPE = 'task_scheduler:task_cache:entry'
def __init__(
self, timestamp, timestamp_description, task_name, task_identifier):
"""Initializes the event.
Args:
timestamp: The FILETIME value for the timestamp.
timestamp_description: The usage string for the timestamp value.
task_name: String containing the name of the task.
task_identifier: String containing the identifier of the task.
"""
super(TaskCacheEvent, self).__init__(timestamp, timestamp_description)
self.offset = 0
self.task_name = task_name
self.task_identifier = task_identifier
class TaskCachePlugin(interface.KeyPlugin):
"""Plugin that parses a Task Cache key."""
NAME = 'winreg_task_cache'
DESCRIPTION = u'Parser for Task Scheduler cache Registry data.'
REG_TYPE = 'SOFTWARE'
REG_KEYS = [
u'\\Microsoft\\Windows NT\\CurrentVersion\\Schedule\\TaskCache']
URL = [
u'https://code.google.com/p/winreg-kb/wiki/TaskSchedulerKeys']
_DYNAMIC_INFO_STRUCT = construct.Struct(
'dynamic_info_record',
construct.ULInt32('version'),
construct.ULInt64('last_registered_time'),
construct.ULInt64('launch_time'),
construct.Padding(8))
_DYNAMIC_INFO_STRUCT_SIZE = _DYNAMIC_INFO_STRUCT.sizeof()
def _GetIdValue(self, key):
"""Retrieves the Id value from Task Cache Tree key.
Args:
key: A Windows Registry key (instance of WinRegKey).
Yields:
A tuple containing a Windows Registry Key (instance of WinRegKey) and
a Windows Registry value (instance of WinRegValue).
"""
id_value = key.GetValue(u'Id')
if id_value:
yield key, id_value
for sub_key in key.GetSubkeys():
for value_key, id_value in self._GetIdValue(sub_key):
yield value_key, id_value
def GetEntries(
self, parser_context, key=None, registry_type=None, file_entry=None,
parser_chain=None, **unused_kwargs):
"""Parses a Task Cache Registry key.
Args:
parser_context: A parser context object (instance of ParserContext).
key: Optional Registry key (instance of winreg.WinRegKey).
The default is None.
registry_type: Optional Registry type string. The default is None.
file_entry: Optional file entry object (instance of dfvfs.FileEntry).
The default is None.
parser_chain: Optional string containing the parsing chain up to this
point. The default is None.
"""
tasks_key = key.GetSubkey(u'Tasks')
tree_key = key.GetSubkey(u'Tree')
if not tasks_key or not tree_key:
logging.warning(u'Task Cache is missing a Tasks or Tree sub key.')
return
task_guids = {}
for sub_key in tree_key.GetSubkeys():
for value_key, id_value in self._GetIdValue(sub_key):
# The GUID is in the form {%GUID%} and stored an UTF-16 little-endian
# string and should be 78 bytes in size.
if len(id_value.raw_data) != 78:
logging.warning(
u'[{0:s}] unsupported Id value data size.'.format(self.NAME))
continue
task_guids[id_value.data] = value_key.name
for sub_key in tasks_key.GetSubkeys():
dynamic_info_value = sub_key.GetValue(u'DynamicInfo')
if not dynamic_info_value:
continue
if len(dynamic_info_value.raw_data) != self._DYNAMIC_INFO_STRUCT_SIZE:
logging.warning(
u'[{0:s}] unsupported DynamicInfo value data size.'.format(
self.NAME))
continue
dynamic_info = self._DYNAMIC_INFO_STRUCT.parse(
dynamic_info_value.raw_data)
name = task_guids.get(sub_key.name, sub_key.name)
text_dict = {}
text_dict[u'Task: {0:s}'.format(name)] = u'[ID: {0:s}]'.format(
sub_key.name)
event_object = windows_events.WindowsRegistryEvent(
key.last_written_timestamp, key.path, text_dict, offset=key.offset,
registry_type=registry_type)
parser_context.ProduceEvent(
event_object, parser_chain=parser_chain, file_entry=file_entry)
if dynamic_info.last_registered_time:
# Note this is likely either the last registered time or
# the update time.
event_object = TaskCacheEvent(
dynamic_info.last_registered_time, u'Last registered time', name,
sub_key.name)
parser_context.ProduceEvent(
event_object, parser_chain=parser_chain, file_entry=file_entry)
if dynamic_info.launch_time:
# Note this is likely the launch time.
event_object = TaskCacheEvent(
dynamic_info.launch_time, u'Launch time', name, sub_key.name)
parser_context.ProduceEvent(
event_object, parser_chain=parser_chain, file_entry=file_entry)
# TODO: Add support for the Triggers value.
winreg.WinRegistryParser.RegisterPlugin(TaskCachePlugin)