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

209 lines
8.4 KiB
Python

#!/usr/bin/python
# -*- coding: utf-8 -*-
#
# Copyright 2012 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 UserAssist Windows Registry plugin."""
import logging
import construct
from plaso.events import windows_events
from plaso.lib import timelib
from plaso.parsers import winreg
from plaso.parsers.winreg_plugins import interface
from plaso.winnt import environ_expand
from plaso.winnt import known_folder_ids
class UserAssistPlugin(interface.KeyPlugin):
"""Plugin that parses an UserAssist key."""
NAME = 'winreg_userassist'
DESCRIPTION = u'Parser for User Assist Registry data.'
REG_TYPE = 'NTUSER'
REG_KEYS = [
(u'\\Software\\Microsoft\\Windows\\CurrentVersion\\Explorer'
u'\\UserAssist\\{{FA99DFC7-6AC2-453A-A5E2-5E2AFF4507BD}}'),
(u'\\Software\\Microsoft\\Windows\\CurrentVersion\\Explorer'
u'\\UserAssist\\{{F4E57C4B-2036-45F0-A9AB-443BCFE33D9F}}'),
(u'\\Software\\Microsoft\\Windows\\CurrentVersion\\Explorer'
u'\\UserAssist\\{{F2A1CB5A-E3CC-4A2E-AF9D-505A7009D442}}'),
(u'\\Software\\Microsoft\\Windows\\CurrentVersion\\Explorer'
u'\\UserAssist\\{{CEBFF5CD-ACE2-4F4F-9178-9926F41749EA}}'),
(u'\\Software\\Microsoft\\Windows\\CurrentVersion\\Explorer'
u'\\UserAssist\\{{CAA59E3C-4792-41A5-9909-6A6A8D32490E}}'),
(u'\\Software\\Microsoft\\Windows\\CurrentVersion\\Explorer'
u'\\UserAssist\\{{B267E3AD-A825-4A09-82B9-EEC22AA3B847}}'),
(u'\\Software\\Microsoft\\Windows\\CurrentVersion\\Explorer'
u'\\UserAssist\\{{A3D53349-6E61-4557-8FC7-0028EDCEEBF6}}'),
(u'\\Software\\Microsoft\\Windows\\CurrentVersion\\Explorer'
u'\\UserAssist\\{{9E04CAB2-CC14-11DF-BB8C-A2F1DED72085}}'),
(u'\\Software\\Microsoft\\Windows\\CurrentVersion\\Explorer'
u'\\UserAssist\\{{75048700-EF1F-11D0-9888-006097DEACF9}}'),
(u'\\Software\\Microsoft\\Windows\\CurrentVersion\\Explorer'
u'\\UserAssist\\{{5E6AB780-7743-11CF-A12B-00AA004AE837}}'),
(u'\\Software\\Microsoft\\Windows\\CurrentVersion\\Explorer'
u'\\UserAssist\\{{0D6D4F41-2994-4BA0-8FEF-620E43CD2812}}'),
(u'\\Software\\Microsoft\\Windows\\CurrentVersion\\Explorer'
u'\\UserAssist\\{{BCB48336-4DDD-48FF-BB0B-D3190DACB3E2}}')]
URL = [
u'http://blog.didierstevens.com/programs/userassist/',
u'https://code.google.com/p/winreg-kb/wiki/UserAssistKeys',
u'http://intotheboxes.files.wordpress.com/2010/04'
u'/intotheboxes_2010_q1.pdf']
# UserAssist format version used in Windows 2000, XP, 2003, Vista.
USERASSIST_V3_STRUCT = construct.Struct(
'userassist_entry',
construct.Padding(4),
construct.ULInt32('count'),
construct.ULInt64('timestamp'))
# UserAssist format version used in Windows 2008, 7, 8.
USERASSIST_V5_STRUCT = construct.Struct(
'userassist_entry',
construct.Padding(4),
construct.ULInt32('count'),
construct.ULInt32('app_focus_count'),
construct.ULInt32('focus_duration'),
construct.Padding(44),
construct.ULInt64('timestamp'),
construct.Padding(4))
def GetEntries(
self, parser_context, key=None, registry_type=None, file_entry=None,
parser_chain=None, **unused_kwargs):
"""Parses a UserAssist 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.
"""
version_value = key.GetValue('Version')
count_subkey = key.GetSubkey('Count')
if not version_value:
logging.error(u'missing version value')
elif not version_value.DataIsInteger():
logging.error(u'unsupported version value data type')
elif version_value.data not in [3, 5]:
logging.error(u'unsupported version: {0:d}'.format(version_value.data))
elif not count_subkey:
logging.error(u'missing count subkey')
else:
userassist_entry_index = 0
for value in count_subkey.GetValues():
try:
value_name = value.name.decode('rot-13')
except UnicodeEncodeError as exception:
logging.debug((
u'Unable to decode UserAssist string: {0:s} with error: {1:s}.\n'
u'Attempting piecewise decoding.').format(
value.name, exception))
characters = []
for char in value.name:
if ord(char) < 128:
try:
characters.append(char.decode('rot-13'))
except UnicodeEncodeError:
characters.append(char)
else:
characters.append(char)
value_name = u''.join(characters)
if version_value.data == 5:
path_segments = value_name.split(u'\\')
for segment_index in range(0, len(path_segments)):
# Remove the { } from the path segment to get the GUID.
guid = path_segments[segment_index][1:-1]
path_segments[segment_index] = known_folder_ids.PATHS.get(
guid, path_segments[segment_index])
value_name = u'\\'.join(path_segments)
# Check if we might need to substitute values.
if '%' in value_name:
# TODO: deprecate direct use of pre_obj.
value_name = environ_expand.ExpandWindowsEnvironmentVariables(
value_name, parser_context.knowledge_base.pre_obj)
if not value.DataIsBinaryData():
logging.error(u'unsupported value data type: {0:s}'.format(
value.data_type_string))
elif version_value.data == 3:
if len(value.data) != self.USERASSIST_V3_STRUCT.sizeof():
logging.error(u'unsupported value data size: {0:d}'.format(
len(value.data)))
else:
parsed_data = self.USERASSIST_V3_STRUCT.parse(value.data)
filetime = parsed_data.get('timestamp', 0)
count = parsed_data.get('count', 0)
if count > 5:
count -= 5
text_dict = {}
text_dict[value_name] = u'[Count: {0:d}]'.format(count)
event_object = windows_events.WindowsRegistryEvent(
timelib.Timestamp.FromFiletime(filetime), count_subkey.path,
text_dict, offset=value.offset, registry_type=registry_type)
parser_context.ProduceEvent(
event_object, parser_chain=parser_chain, file_entry=file_entry)
elif version_value.data == 5:
if len(value.data) != self.USERASSIST_V5_STRUCT.sizeof():
logging.error(u'unsupported value data size: {0:d}'.format(
len(value.data)))
parsed_data = self.USERASSIST_V5_STRUCT.parse(value.data)
userassist_entry_index += 1
count = parsed_data.get('count', None)
app_focus_count = parsed_data.get('app_focus_count', None)
focus_duration = parsed_data.get('focus_duration', None)
timestamp = parsed_data.get('timestamp', 0)
text_dict = {}
text_dict[value_name] = (
u'[UserAssist entry: {0:d}, Count: {1:d}, '
u'Application focus count: {2:d}, Focus duration: {3:d}]').format(
userassist_entry_index, count, app_focus_count,
focus_duration)
event_object = windows_events.WindowsRegistryEvent(
timelib.Timestamp.FromFiletime(timestamp), count_subkey.path,
text_dict, offset=count_subkey.offset,
registry_type=registry_type)
parser_context.ProduceEvent(
event_object, parser_chain=parser_chain, file_entry=file_entry)
winreg.WinRegistryParser.RegisterPlugin(UserAssistPlugin)