Import from old repository

This commit is contained in:
Stefan
2020-04-06 18:48:34 +02:00
commit 0da6783a45
762 changed files with 103065 additions and 0 deletions
+22
View File
@@ -0,0 +1,22 @@
#!/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 an import statement for each preprocess plugin."""
from plaso.preprocessors import linux
from plaso.preprocessors import macosx
from plaso.preprocessors import windows
+223
View File
@@ -0,0 +1,223 @@
#!/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 classes used for preprocessing in plaso."""
import abc
import logging
from dfvfs.helpers import file_system_searcher
from plaso.lib import errors
class PreprocessPlugin(object):
"""Class that defines the preprocess plugin object interface.
Any preprocessing plugin that implements this interface
should define which operating system this plugin supports.
The OS variable supports the following values:
+ Windows
+ Linux
+ MacOSX
Since some plugins may require knowledge gained from
other checks all plugins have a weight associated to it.
The weight variable can have values from one to three:
+ 1 - Requires no prior knowledge, can run immediately.
+ 2 - Requires knowledge from plugins with weight 1.
+ 3 - Requires knowledge from plugins with weight 2.
The default weight of 3 is assigned to plugins, so each
plugin needs to overwrite that value if needed.
The plugins are grouped by the operating system they work
on and then on their weight. That means that if the tool
is run against a Windows system all plugins that support
Windows are grouped together, and only plugins with weight
one are run, then weight two followed by the rest of the
plugins with the weight of three. There is no priority or
guaranteed order of plugins that have the same weight, which
makes it important to define the weight appropriately.
"""
# Defines the OS that this plugin supports.
SUPPORTED_OS = []
# Weight is an INT, with the value of 1-3.
WEIGHT = 3
# Defines the knowledge base attribute to be set.
ATTRIBUTE = ''
@property
def plugin_name(self):
"""Return the name of the plugin."""
return self.__class__.__name__
def _FindFileEntry(self, searcher, path):
"""Searches for a file entry that matches the path.
Args:
searcher: The file system searcher object (instance of
dfvfs.FileSystemSearcher).
path: The location of the file entry relative to the file system
of the searcher.
Returns:
The file entry if successful or None otherwise.
Raises:
errors.PreProcessFail: if the file entry cannot be found or opened.
"""
find_spec = file_system_searcher.FindSpec(
location=path, case_sensitive=False)
path_specs = list(searcher.Find(find_specs=[find_spec]))
if not path_specs or len(path_specs) != 1:
raise errors.PreProcessFail(u'Unable to find: {0:s}'.format(path))
try:
file_entry = searcher.GetFileEntryByPathSpec(path_specs[0])
except IOError as exception:
raise errors.PreProcessFail(
u'Unable to retrieve file entry: {0:s} with error: {1:s}'.format(
path, exception))
return file_entry
@abc.abstractmethod
def GetValue(self, searcher, knowledge_base):
"""Return the value for the attribute.
Args:
searcher: The file system searcher object (instance of
dfvfs.FileSystemSearcher).
knowledge_base: A knowledge base object (instance of KnowledgeBase),
which contains information from the source data needed
for parsing.
"""
raise NotImplementedError
def Run(self, searcher, knowledge_base):
"""Set the attribute of the object store to the value from GetValue.
Args:
searcher: The file system searcher object (instance of
dfvfs.FileSystemSearcher).
knowledge_base: A knowledge base object (instance of KnowledgeBase),
which contains information from the source data needed
for parsing.
"""
value = self.GetValue(searcher, knowledge_base)
knowledge_base.SetValue(self.ATTRIBUTE, value)
value = knowledge_base.GetValue(self.ATTRIBUTE, default_value=u'N/A')
logging.info(u'[PreProcess] Set attribute: {0:s} to {1:s}'.format(
self.ATTRIBUTE, value))
class PathPreprocessPlugin(PreprocessPlugin):
"""Return a simple path."""
WEIGHT = 1
def GetValue(self, searcher, unused_knowledge_base):
"""Returns the path as found by the searcher.
Args:
searcher: The file system searcher object (instance of
dfvfs.FileSystemSearcher).
knowledge_base: A knowledge base object (instance of KnowledgeBase),
which contains information from the source data needed
for parsing.
Returns:
The first path location string.
Raises:
PreProcessFail: if the path could not be found.
"""
find_spec = file_system_searcher.FindSpec(
location_regex=self.PATH, case_sensitive=False)
path_specs = list(searcher.Find(find_specs=[find_spec]))
if not path_specs:
raise errors.PreProcessFail(
u'Unable to find path: {0:s}'.format(self.PATH))
relative_path = searcher.GetRelativePath(path_specs[0])
if not relative_path:
raise errors.PreProcessFail(
u'Missing relative path for: {0:s}'.format(self.PATH))
return relative_path
def GuessOS(searcher):
"""Returns a string representing what we think the underlying OS is.
The available return strings are:
+ Windows
+ MacOSX
+ Linux
Args:
searcher: The file system searcher object (instance of
dfvfs.FileSystemSearcher).
Returns:
A string indicating which OS we are dealing with.
"""
find_specs = [
file_system_searcher.FindSpec(
location=u'/etc', case_sensitive=False),
file_system_searcher.FindSpec(
location=u'/System/Library', case_sensitive=False),
file_system_searcher.FindSpec(
location=u'/Windows/System32', case_sensitive=False),
file_system_searcher.FindSpec(
location=u'/WINNT/System32', case_sensitive=False),
file_system_searcher.FindSpec(
location=u'/WINNT35/System32', case_sensitive=False),
file_system_searcher.FindSpec(
location=u'/WTSRV/System32', case_sensitive=False)]
locations = []
for path_spec in searcher.Find(find_specs=find_specs):
relative_path = searcher.GetRelativePath(path_spec)
if relative_path:
locations.append(relative_path.lower())
# We need to check for both forward and backward slashes since the path
# spec will be OS dependent, as in running the tool on Windows will return
# Windows paths (backward slash) vs. forward slash on *NIX systems.
windows_locations = set([
u'/windows/system32', u'\\windows\\system32', u'/winnt/system32',
u'\\winnt\\system32', u'/winnt35/system32', u'\\winnt35\\system32',
u'\\wtsrv\\system32', u'/wtsrv/system32'])
if windows_locations.intersection(set(locations)):
return 'Windows'
if u'/system/library' in locations:
return 'MacOSX'
if u'/etc' in locations:
return 'Linux'
return 'None'
+118
View File
@@ -0,0 +1,118 @@
#!/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 preprocessors for Linux."""
import csv
from dfvfs.helpers import text_file
from plaso.lib import errors
from plaso.preprocessors import interface
from plaso.preprocessors import manager
class LinuxHostname(interface.PreprocessPlugin):
"""A preprocessing class that fetches hostname on Linux."""
SUPPORTED_OS = ['Linux']
WEIGHT = 1
ATTRIBUTE = 'hostname'
def GetValue(self, searcher, unused_knowledge_base):
"""Determines the hostname based on the contents of /etc/hostname.
Args:
searcher: The file system searcher object (instance of
dfvfs.FileSystemSearcher).
knowledge_base: A knowledge base object (instance of KnowledgeBase),
which contains information from the source data needed
for parsing.
Returns:
The hostname.
Raises:
errors.PreProcessFail: if the preprocessing fails.
"""
path = u'/etc/hostname'
file_entry = self._FindFileEntry(searcher, path)
if not file_entry:
raise errors.PreProcessFail(
u'Unable to find file entry for path: {0:s}.'.format(path))
file_object = file_entry.GetFileObject()
file_data = file_object.read(512)
file_object.close()
hostname, _, _ = file_data.partition('\n')
return u'{0:s}'.format(hostname)
class LinuxUsernames(interface.PreprocessPlugin):
"""A preprocessing class that fetches usernames on Linux."""
SUPPORTED_OS = ['Linux']
WEIGHT = 1
ATTRIBUTE = 'users'
def GetValue(self, searcher, unused_knowledge_base):
"""Determines the user information based on the contents of /etc/passwd.
Args:
searcher: The file system searcher object (instance of
dfvfs.FileSystemSearcher).
knowledge_base: A knowledge base object (instance of KnowledgeBase),
which contains information from the source data needed
for parsing.
Returns:
A list containing username information dicts.
Raises:
errors.PreProcessFail: if the preprocessing fails.
"""
# TODO: Add passwd.cache, might be good if nss cache is enabled.
path = u'/etc/passwd'
file_entry = self._FindFileEntry(searcher, path)
if not file_entry:
raise errors.PreProcessFail(
u'Unable to find file entry for path: {0:s}.'.format(path))
file_object = file_entry.GetFileObject()
text_file_object = text_file.TextFile(file_object)
reader = csv.reader(text_file_object, delimiter=':')
users = []
for row in reader:
# TODO: as part of artifacts, create a proper object for this.
user = {
'uid': row[2],
'gid': row[3],
'name': row[0],
'path': row[5],
'shell': row[6]}
users.append(user)
file_object.close()
return users
manager.PreprocessPluginsManager.RegisterPlugins([
LinuxHostname, LinuxUsernames])
+100
View File
@@ -0,0 +1,100 @@
#!/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.
"""Tests for the Linux preprocess plug-ins."""
import unittest
from dfvfs.helpers import file_system_searcher
from dfvfs.path import fake_path_spec
from plaso.artifacts import knowledge_base
from plaso.preprocessors import linux
from plaso.preprocessors import test_lib
class LinuxHostnameTest(test_lib.PreprocessPluginTest):
"""Tests for the Linux hostname preprocess plug-in object."""
_FILE_DATA = (
'plaso.kiddaland.net\n')
def setUp(self):
"""Sets up the needed objects used throughout the test."""
self._fake_file_system = self._BuildSingleFileFakeFileSystem(
u'/etc/hostname', self._FILE_DATA)
mount_point = fake_path_spec.FakePathSpec(location=u'/')
self._searcher = file_system_searcher.FileSystemSearcher(
self._fake_file_system, mount_point)
def testGetValue(self):
"""Tests the GetValue function."""
knowledge_base_object = knowledge_base.KnowledgeBase()
plugin = linux.LinuxHostname()
plugin.Run(self._searcher, knowledge_base_object)
self.assertEquals(knowledge_base_object.hostname, u'plaso.kiddaland.net')
class LinuxUsernamesTest(test_lib.PreprocessPluginTest):
"""Tests for the Linux usernames preprocess plug-in object."""
_FILE_DATA = (
'root:x:0:0:root:/root:/bin/bash\n'
'bin:x:1:1:bin:/bin:/sbin/nologin\n'
'daemon:x:2:2:daemon:/sbin:/sbin/nologin\n'
'adm:x:3:4:adm:/var/adm:/sbin/nologin\n'
'lp:x:4:7:lp:/var/spool/lpd:/sbin/nologin\n'
'sync:x:5:0:sync:/sbin:/bin/sync\n'
'shutdown:x:6:0:shutdown:/sbin:/sbin/shutdown\n'
'halt:x:7:0:halt:/sbin:/sbin/halt\n'
'mail:x:8:12:mail:/var/spool/mail:/sbin/nologin\n'
'operator:x:11:0:operator:/root:/sbin/nologin\n'
'games:x:12:100:games:/usr/games:/sbin/nologin\n'
'ftp:x:14:50:FTP User:/var/ftp:/sbin/nologin\n'
'nobody:x:99:99:Nobody:/:/sbin/nologin\n')
def setUp(self):
"""Sets up the needed objects used throughout the test."""
self._fake_file_system = self._BuildSingleFileFakeFileSystem(
u'/etc/passwd', self._FILE_DATA)
mount_point = fake_path_spec.FakePathSpec(location=u'/')
self._searcher = file_system_searcher.FileSystemSearcher(
self._fake_file_system, mount_point)
def testGetValue(self):
"""Tests the GetValue function."""
knowledge_base_object = knowledge_base.KnowledgeBase()
plugin = linux.LinuxUsernames()
plugin.Run(self._searcher, knowledge_base_object)
users = knowledge_base_object.GetValue('users')
self.assertEquals(len(users), 13)
self.assertEquals(users[11].get('uid', None), u'14')
self.assertEquals(users[11].get('gid', None), u'50')
self.assertEquals(users[11].get('name', None), u'ftp')
self.assertEquals(users[11].get('path', None), u'/var/ftp')
self.assertEquals(users[11].get('shell', None), u'/sbin/nologin')
if __name__ == '__main__':
unittest.main()
+390
View File
@@ -0,0 +1,390 @@
#!/usr/bin/python
# -*- coding: utf-8 -*-
#
# Copyright 2013 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 preprocessors for Mac OS X."""
import logging
from binplist import binplist
from dfvfs.helpers import file_system_searcher
from xml.etree import ElementTree
from plaso.lib import errors
from plaso.lib import utils
from plaso.parsers.plist_plugins import interface as plist_interface
from plaso.preprocessors import interface
from plaso.preprocessors import manager
class PlistPreprocessPlugin(interface.PreprocessPlugin):
"""Class that defines the plist preprocess plugin object."""
SUPPORTED_OS = ['MacOSX']
WEIGHT = 2
# Path to the plist file to be parsed, can depend on paths discovered
# in previous preprocessors.
PLIST_PATH = ''
# The key that's value should be returned back. It is an ordered list
# of preference. If the first value is found it will be returned and no
# others will be searched.
PLIST_KEYS = ['']
def GetValue(self, searcher, unused_knowledge_base):
"""Returns a value retrieved from keys within a plist file.
Where the name of the keys are defined in PLIST_KEYS.
Args:
searcher: The file system searcher object (instance of
dfvfs.FileSystemSearcher).
knowledge_base: A knowledge base object (instance of KnowledgeBase),
which contains information from the source data needed
for parsing.
Returns:
The value of the first key that is found.
Raises:
errors.PreProcessFail: if the preprocessing fails.
"""
file_entry = self._FindFileEntry(searcher, self.PLIST_PATH)
if not file_entry:
raise errors.PreProcessFail(
u'Unable to open file: {0:s}'.format(self.PLIST_PATH))
file_object = file_entry.GetFileObject()
value = self.ParseFile(file_entry, file_object)
file_object.close()
return value
def ParseFile(self, file_entry, file_object):
"""Parses the plist file and returns the parsed key.
Args:
file_entry: The file entry (instance of dfvfs.FileEntry).
file_object: The file-like object.
Returns:
The value of the first key defined by PLIST_KEYS that is found.
Raises:
errors.PreProcessFail: if the preprocessing fails.
"""
try:
plist_file = binplist.BinaryPlist(file_object)
top_level_object = plist_file.Parse()
except binplist.FormatError as exception:
raise errors.PreProcessFail(
u'File is not a plist: {0:s} with error: {1:s}'.format(
file_entry.path_spec.comparable, exception))
except OverflowError as exception:
raise errors.PreProcessFail(
u'Unable to process plist: {0:s} with error: {1:s}'.format(
file_entry.path_spec.comparable, exception))
if not plist_file:
raise errors.PreProcessFail(
u'File is not a plist: {0:s}'.format(file_entry.path_spec.comparable))
match = None
key_name = ''
for plist_key in self.PLIST_KEYS:
try:
match = plist_interface.GetKeys(
top_level_object, frozenset([plist_key]))
except KeyError:
continue
if match:
key_name = plist_key
break
if not match:
raise errors.PreProcessFail(
u'Keys not found inside plist file: {0:s}.'.format(
u','.join(self.PLIST_KEYS)))
return self.ParseKey(match, key_name)
def ParseKey(self, key, key_name):
"""Retrieves a specific value from the key.
Args:
key: The key object (instance of dict).
key_name: The name of the key.
Returns:
The value of the key defined by key_name.
Raises:
errors.PreProcessFail: if the preprocessing fails.
"""
value = key.get(key_name, None)
if not value:
raise errors.PreProcessFail(
u'Value of key: {0:s} not found.'.format(key_name))
return value
class XMLPlistPreprocessPlugin(PlistPreprocessPlugin):
"""Class that defines the Mac OS X XML plist preprocess plugin object."""
def _GetKeys(self, xml_root, key_name):
"""Return a dict with the requested keys."""
match = {}
generator = xml_root.iter()
for key in generator:
if 'key' in key.tag and key_name in key.text:
value_key = generator.next()
value = ''
for subkey in value_key.iter():
if 'string' in subkey.tag:
value = subkey.text
match[key.text] = value
# Now we need to go over the match dict and retrieve values.
return match
def ParseFile(self, file_entry, file_object):
"""Parse the file and return parsed key.
Args:
file_entry: The file entry (instance of dfvfs.FileEntry).
file_object: The file-like object.
Returns:
The value of the first key defined by PLIST_KEYS that is found.
Raises:
errors.PreProcessFail: if the preprocessing fails.
"""
# TODO: Move to defusedxml for safer XML parsing.
try:
xml = ElementTree.parse(file_object)
except ElementTree.ParseError:
raise errors.PreProcessFail(u'File is not a XML file.')
except IOError:
raise errors.PreProcessFail(u'File is not a XML file.')
xml_root = xml.getroot()
key_name = ''
match = None
for key in self.PLIST_KEYS:
match = self._GetKeys(xml_root, key)
if match:
key_name = key
break
if not match:
raise errors.PreProcessFail(
u'Keys not found inside plist file: {0:s}.'.format(
u','.join(self.PLIST_KEYS)))
return self.ParseKey(match, key_name)
class MacOSXBuild(XMLPlistPreprocessPlugin):
"""Fetches build information about a Mac OS X system."""
ATTRIBUTE = 'build'
PLIST_PATH = '/System/Library/CoreServices/SystemVersion.plist'
PLIST_KEYS = ['ProductUserVisibleVersion']
class MacOSXHostname(XMLPlistPreprocessPlugin):
"""Fetches hostname information about a Mac OS X system."""
ATTRIBUTE = 'hostname'
PLIST_PATH = '/Library/Preferences/SystemConfiguration/preferences.plist'
PLIST_KEYS = ['ComputerName', 'LocalHostName']
class MacOSXKeyboard(PlistPreprocessPlugin):
"""Fetches keyboard information from a Mac OS X system."""
ATTRIBUTE = 'keyboard_layout'
PLIST_PATH = '/Library/Preferences/com.apple.HIToolbox.plist'
PLIST_KEYS = ['AppleCurrentKeyboardLayoutInputSourceID']
def ParseKey(self, key, key_name):
"""Determines the keyboard layout."""
value = super(MacOSXKeyboard, self).ParseKey(key, key_name)
if type(value) in (list, tuple):
value = value[0]
_, _, keyboard_layout = value.rpartition('.')
return keyboard_layout
class MacOSXTimeZone(interface.PreprocessPlugin):
"""Gather timezone information from a Mac OS X system."""
ATTRIBUTE = 'time_zone_str'
SUPPORTED_OS = ['MacOSX']
WEIGHT = 1
ZONE_FILE_PATH = u'/private/etc/localtime'
def GetValue(self, searcher, unused_knowledge_base):
"""Determines the local time zone settings.
Args:
searcher: The file system searcher object (instance of
dfvfs.FileSystemSearcher).
knowledge_base: A knowledge base object (instance of KnowledgeBase),
which contains information from the source data needed
for parsing.
Returns:
The local timezone settings.
Raises:
errors.PreProcessFail: if the preprocessing fails.
"""
path = self.ZONE_FILE_PATH
file_entry = self._FindFileEntry(searcher, path)
if not file_entry:
raise errors.PreProcessFail(
u'Unable to find file: {0:s}'.format(path))
if not file_entry.link:
raise errors.PreProcessFail(
u'Unable to retrieve timezone information from: {0:s}.'.format(path))
_, _, zone = file_entry.link.partition(u'zoneinfo/')
return zone
class MacOSXUsers(interface.PreprocessPlugin):
"""Get information about user accounts on a Mac OS X system."""
SUPPORTED_OS = ['MacOSX']
ATTRIBUTE = 'users'
WEIGHT = 1
# Define the path to the user account information.
USER_PATH = '/private/var/db/dslocal/nodes/Default/users/[^_].+.plist'
_KEYS = frozenset(['name', 'uid', 'home', 'realname'])
def _OpenPlistFile(self, searcher, path_spec):
"""Open a Plist file given a path and returns a plist top level object.
Args:
searcher: The file system searcher object (instance of
dfvfs.FileSystemSearcher).
path_spec: The path specification (instance of dfvfs.PathSpec)
of the plist file.
Raises:
errors.PreProcessFail: if the preprocessing fails.
"""
plist_file_location = getattr(path_spec, 'location', u'')
file_entry = searcher.GetFileEntryByPathSpec(path_spec)
file_object = file_entry.GetFileObject()
try:
plist_file = binplist.BinaryPlist(file_object)
top_level_object = plist_file.Parse()
except binplist.FormatError as exception:
exception = utils.GetUnicodeString(exception)
raise errors.PreProcessFail(
u'File is not a plist: {0:s}'.format(exception))
except OverflowError as exception:
raise errors.PreProcessFail(
u'Error processing: {0:s} with error: {1:s}'.format(
plist_file_location, exception))
if not plist_file:
raise errors.PreProcessFail(
u'File is not a plist: {0:s}'.format(plist_file_location))
return top_level_object
def GetValue(self, searcher, unused_knowledge_base):
"""Determines the user accounts.
Args:
searcher: The file system searcher object (instance of
dfvfs.FileSystemSearcher).
knowledge_base: A knowledge base object (instance of KnowledgeBase),
which contains information from the source data needed
for parsing.
Returns:
A list containing username information dicts.
Raises:
errors.PreProcessFail: if the preprocessing fails.
"""
find_spec = file_system_searcher.FindSpec(
location_regex=self.USER_PATH, case_sensitive=False)
path_specs = list(searcher.Find(find_specs=[find_spec]))
if not path_specs:
raise errors.PreProcessFail(u'Unable to find user plist files.')
users = []
for path_spec in path_specs:
plist_file_location = getattr(path_spec, 'location', u'')
if not plist_file_location:
raise errors.PreProcessFail(u'Missing user plist file location.')
try:
top_level_object = self._OpenPlistFile(searcher, path_spec)
except IOError:
logging.warning(u'Unable to parse user plist file: {0:s}'.format(
plist_file_location))
continue
try:
match = plist_interface.GetKeysDefaultEmpty(
top_level_object, self._KEYS)
except KeyError as exception:
logging.warning(
u'Unable to read user plist file: {0:s} with error: {1:s}'.format(
plist_file_location, exception))
continue
# TODO: as part of artifacts, create a proper object for this.
user = {
'uid': match.get('uid', [-1])[0],
'path': match.get('home', [u'<not set>'])[0],
'name': match.get('name', [u'<not set>'])[0],
'realname': match.get('realname', [u'N/A'])[0]}
users.append(user)
if not users:
raise errors.PreProcessFail(u'Unable to find any users on the system.')
return users
manager.PreprocessPluginsManager.RegisterPlugins([
MacOSXBuild, MacOSXHostname, MacOSXKeyboard, MacOSXTimeZone, MacOSXUsers])
+221
View File
@@ -0,0 +1,221 @@
#!/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.
"""Tests for the Mac OS X preprocess plug-ins."""
import os
import unittest
from dfvfs.helpers import file_system_searcher
from dfvfs.path import fake_path_spec
from plaso.artifacts import knowledge_base
from plaso.preprocessors import macosx
from plaso.preprocessors import test_lib
class MacOSXBuildTest(test_lib.PreprocessPluginTest):
"""Tests for the Mac OS X build information preprocess plug-in object."""
_FILE_DATA = (
'<?xml version="1.0" encoding="UTF-8"?>\n'
'<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" '
'"http://www.apple.com/DTDs/PropertyList-1.0.dtd">\n'
'<plist version="1.0">\n'
'<dict>\n'
'\t<key>ProductBuildVersion</key>\n'
'\t<string>13C64</string>\n'
'\t<key>ProductCopyright</key>\n'
'\t<string>1983-2014 Apple Inc.</string>\n'
'\t<key>ProductName</key>\n'
'\t<string>Mac OS X</string>\n'
'\t<key>ProductUserVisibleVersion</key>\n'
'\t<string>10.9.2</string>\n'
'\t<key>ProductVersion</key>\n'
'\t<string>10.9.2</string>\n'
'</dict>\n'
'</plist>\n')
def setUp(self):
"""Sets up the needed objects used throughout the test."""
self._fake_file_system = self._BuildSingleFileFakeFileSystem(
u'/System/Library/CoreServices/SystemVersion.plist',
self._FILE_DATA)
mount_point = fake_path_spec.FakePathSpec(location=u'/')
self._searcher = file_system_searcher.FileSystemSearcher(
self._fake_file_system, mount_point)
def testGetValue(self):
"""Tests the GetValue function."""
knowledge_base_object = knowledge_base.KnowledgeBase()
plugin = macosx.MacOSXBuild()
plugin.Run(self._searcher, knowledge_base_object)
build = knowledge_base_object.GetValue('build')
self.assertEquals(build, u'10.9.2')
class MacOSXHostname(test_lib.PreprocessPluginTest):
"""Tests for the Mac OS X hostname preprocess plug-in object."""
# Note that is only part of the normal preferences.plist file data.
_FILE_DATA = (
'<?xml version="1.0" encoding="UTF-8"?>\n'
'<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" '
'"http://www.apple.com/DTDs/PropertyList-1.0.dtd">\n'
'<plist version="1.0">\n'
'<dict>\n'
'\t<key>System</key>\n'
'\t<dict>\n'
'\t\t<key>Network</key>\n'
'\t\t<dict>\n'
'\t\t\t<key>HostNames</key>\n'
'\t\t\t<dict>\n'
'\t\t\t\t<key>LocalHostName</key>\n'
'\t\t\t\t<string>Plaso\'s Mac mini</string>\n'
'\t\t\t</dict>\n'
'\t\t</dict>\n'
'\t\t<key>System</key>\n'
'\t\t<dict>\n'
'\t\t\t<key>ComputerName</key>\n'
'\t\t\t<string>Plaso\'s Mac mini</string>\n'
'\t\t\t<key>ComputerNameEncoding</key>\n'
'\t\t\t<integer>0</integer>\n'
'\t\t</dict>\n'
'\t</dict>\n'
'</dict>\n'
'</plist>\n')
def setUp(self):
"""Sets up the needed objects used throughout the test."""
self._fake_file_system = self._BuildSingleFileFakeFileSystem(
u'/Library/Preferences/SystemConfiguration/preferences.plist',
self._FILE_DATA)
mount_point = fake_path_spec.FakePathSpec(location=u'/')
self._searcher = file_system_searcher.FileSystemSearcher(
self._fake_file_system, mount_point)
def testGetValue(self):
"""Tests the GetValue function."""
knowledge_base_object = knowledge_base.KnowledgeBase()
plugin = macosx.MacOSXHostname()
plugin.Run(self._searcher, knowledge_base_object)
self.assertEquals(knowledge_base_object.hostname, u'Plaso\'s Mac mini')
class MacOSXKeyboard(test_lib.PreprocessPluginTest):
"""Tests for the Mac OS X keyboard layout preprocess plug-in object."""
def setUp(self):
"""Sets up the needed objects used throughout the test."""
file_object = open(os.path.join(
self._TEST_DATA_PATH, u'com.apple.HIToolbox.plist'))
file_data = file_object.read()
file_object.close()
self._fake_file_system = self._BuildSingleFileFakeFileSystem(
u'/Library/Preferences/com.apple.HIToolbox.plist',
file_data)
mount_point = fake_path_spec.FakePathSpec(location=u'/')
self._searcher = file_system_searcher.FileSystemSearcher(
self._fake_file_system, mount_point)
def testGetValue(self):
"""Tests the GetValue function."""
knowledge_base_object = knowledge_base.KnowledgeBase()
plugin = macosx.MacOSXKeyboard()
plugin.Run(self._searcher, knowledge_base_object)
keyboard_layout = knowledge_base_object.GetValue('keyboard_layout')
self.assertEquals(keyboard_layout, u'US')
class MacOSXTimezone(test_lib.PreprocessPluginTest):
"""Tests for the Mac OS X timezone preprocess plug-in object."""
def setUp(self):
"""Sets up the needed objects used throughout the test."""
self._fake_file_system = self._BuildSingleLinkFakeFileSystem(
u'/private/etc/localtime', u'/usr/share/zoneinfo/Europe/Amsterdam')
mount_point = fake_path_spec.FakePathSpec(location=u'/')
self._searcher = file_system_searcher.FileSystemSearcher(
self._fake_file_system, mount_point)
def testGetValue(self):
"""Tests the GetValue function."""
knowledge_base_object = knowledge_base.KnowledgeBase()
plugin = macosx.MacOSXTimeZone()
plugin.Run(self._searcher, knowledge_base_object)
time_zone_str = knowledge_base_object.GetValue('time_zone_str')
self.assertEquals(time_zone_str, u'Europe/Amsterdam')
class MacOSXUsersTest(test_lib.PreprocessPluginTest):
"""Tests for the Mac OS X usernames preprocess plug-in object."""
def setUp(self):
"""Sets up the needed objects used throughout the test."""
file_object = open(os.path.join(
self._TEST_DATA_PATH, u'com.apple.HIToolbox.plist'))
file_data = file_object.read()
file_object.close()
self._fake_file_system = self._BuildSingleFileFakeFileSystem(
u'/private/var/db/dslocal/nodes/Default/users/nobody.plist',
file_data)
mount_point = fake_path_spec.FakePathSpec(location=u'/')
self._searcher = file_system_searcher.FileSystemSearcher(
self._fake_file_system, mount_point)
def testGetValue(self):
"""Tests the GetValue function."""
knowledge_base_object = knowledge_base.KnowledgeBase()
plugin = macosx.MacOSXUsers()
plugin.Run(self._searcher, knowledge_base_object)
users = knowledge_base_object.GetValue('users')
self.assertEquals(len(users), 1)
# TODO: fix the parsing of the following values to match the behavior on
# Mac OS X.
# The string -2 is converted into the integer -1.
self.assertEquals(users[0].get('uid', None), -1)
# 'home' is 0 which represents: /var/empty but we convert it
# into u'<not set>'.
self.assertEquals(users[0].get('path', None), u'<not set>')
# 'name' is 0 which represents: nobody but we convert it into u'<not set>'.
self.assertEquals(users[0].get('name', None), u'<not set>')
# 'realname' is 0 which represents: 'Unprivileged User' but we convert it
# into u'N/A'.
self.assertEquals(users[0].get('realname', None), u'N/A')
if __name__ == '__main__':
unittest.main()
+138
View File
@@ -0,0 +1,138 @@
#!/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.
"""The preprocess plugins manager."""
import logging
from plaso.lib import errors
class PreprocessPluginsManager(object):
"""Class that implements the preprocess plugins manager."""
_plugin_classes = {}
@classmethod
def _GetPluginsByWeight(cls, platform, weight):
"""Returns all plugins for a specific platform of a certain weight.
Args:
platform: A string containing the supported operating system
of the plugin.
weight: An integer containing the weight of the plugin.
Yields:
A preprocess plugin objects that matches the platform and weight.
"""
for plugin_class in cls._plugin_classes.itervalues():
plugin_supported_os = getattr(plugin_class, 'SUPPORTED_OS', [])
plugin_weight = getattr(plugin_class, 'WEIGHT', 0)
if platform in plugin_supported_os and weight == plugin_weight:
yield plugin_class()
@classmethod
def _GetWeights(cls, platform):
"""Returns a list of all weights that are used by preprocessing plugins.
Args:
platform: A string containing the supported operating system
of the plugin.
Returns:
A list of weights.
"""
weights = {}
for plugin_class in cls._plugin_classes.itervalues():
plugin_supported_os = getattr(plugin_class, 'SUPPORTED_OS', [])
plugin_weight = getattr(plugin_class, 'WEIGHT', 0)
if platform in plugin_supported_os:
weights[plugin_weight] = 1
return sorted(weights.keys())
@classmethod
def DeregisterPlugin(cls, plugin_class):
"""Deregisters a plugin class.
Args:
plugin_class: the class object of the plugin.
Raises:
KeyError: if plugin class is not set for the corresponding name.
"""
if plugin_class.__name__ not in cls._plugin_classes:
raise KeyError(
u'Plugin class not set for name: {0:s}.'.format(
plugin_class.__name__))
del cls._plugin_classes[plugin_class.__name__]
@classmethod
def RegisterPlugin(cls, plugin_class):
"""Registers a plugin class.
Args:
plugin_class: the class object of the plugin.
Raises:
KeyError: if plugin class is already set for the corresponding name.
"""
if plugin_class.__name__ in cls._plugin_classes:
raise KeyError((
u'Plugin class already set for name: {0:s}.').format(
plugin_class.__name__))
cls._plugin_classes[plugin_class.__name__] = plugin_class
@classmethod
def RegisterPlugins(cls, plugin_classes):
"""Registers a plugin classes.
Args:
plugin_classes: a list of class objects of the plugins.
Raises:
KeyError: if plugin class is already set for the corresponding name.
"""
for plugin_class in plugin_classes:
cls.RegisterPlugin(plugin_class)
@classmethod
def RunPlugins(cls, platform, searcher, knowledge_base):
"""Runs the plugins for a specific platform.
Args:
platform: A string containing the supported operating system
of the plugin.
searcher: The file system searcher object (instance of
dfvfs.FileSystemSearcher).
knowledge_base: A knowledge base object (instance of KnowledgeBase),
which contains information from the source data needed
for parsing.
"""
for weight in cls._GetWeights(platform):
for plugin_object in cls._GetPluginsByWeight(platform, weight):
try:
plugin_object.Run(searcher, knowledge_base)
except (IOError, errors.PreProcessFail) as exception:
logging.warning((
u'Unable to run preprocessor: {0:s} for attribute: {1:s} '
u'with error: {2:s}').format(
plugin_object.plugin_name, plugin_object.ATTRIBUTE,
exception))
+71
View File
@@ -0,0 +1,71 @@
#!/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.
"""Tests for the preprocess plugins manager."""
import unittest
from plaso.preprocessors import interface
from plaso.preprocessors import manager
class TestPreprocessPlugin(interface.PreprocessPlugin):
"""Preprocess test plugin."""
def GetValue(self, searcher, unused_knowledge_base):
"""Returns the path as found by the searcher.
Args:
searcher: The file system searcher object (instance of
dfvfs.FileSystemSearcher).
knowledge_base: A knowledge base object (instance of KnowledgeBase),
which contains information from the source data needed
for parsing.
Returns:
The first path location string.
Raises:
PreProcessFail: if the path could not be found.
"""
return
class PreprocessPluginsManagerTest(unittest.TestCase):
"""Tests for the preprocess plugins manager."""
def testRegistration(self):
"""Tests the RegisterPlugin and DeregisterPlugin functions."""
# pylint: disable=protected-access
number_of_plugins = len(manager.PreprocessPluginsManager._plugin_classes)
manager.PreprocessPluginsManager.RegisterPlugin(TestPreprocessPlugin)
self.assertEquals(
len(manager.PreprocessPluginsManager._plugin_classes),
number_of_plugins + 1)
with self.assertRaises(KeyError):
manager.PreprocessPluginsManager.RegisterPlugin(TestPreprocessPlugin)
manager.PreprocessPluginsManager.DeregisterPlugin(TestPreprocessPlugin)
self.assertEquals(
len(manager.PreprocessPluginsManager._plugin_classes),
number_of_plugins)
if __name__ == '__main__':
unittest.main()
+91
View File
@@ -0,0 +1,91 @@
#!/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.
"""Preprocess plug-in related functions and classes for testing."""
import os
import unittest
from dfvfs.lib import definitions as dfvfs_definitions
from dfvfs.resolver import context
from dfvfs.vfs import fake_file_system
class PreprocessPluginTest(unittest.TestCase):
"""The unit test case for a preprocess plug-in object."""
_TEST_DATA_PATH = os.path.join(os.getcwd(), 'test_data')
def _BuildSingleFileFakeFileSystem(self, path, file_data):
"""Builds a single file fake file system.
Args:
path: The path of the file.
file_data: The data of the file.
Returns:
The fake file system (instance of dvfvs.FakeFileSystem).
"""
resolver_context = context.Context()
file_system = fake_file_system.FakeFileSystem(
resolver_context)
file_system.AddFileEntry(
u'/', file_entry_type=dfvfs_definitions.FILE_ENTRY_TYPE_DIRECTORY)
path_segments = path.split(u'/')
for segment_index in range(2, len(path_segments)):
path_segment = u'{0:s}'.format(
u'/'.join(path_segments[:segment_index]))
file_system.AddFileEntry(
path_segment,
file_entry_type=dfvfs_definitions.FILE_ENTRY_TYPE_DIRECTORY)
file_system.AddFileEntry(path, file_data=file_data)
return file_system
def _BuildSingleLinkFakeFileSystem(self, path, linked_path):
"""Builds a single link fake file system.
Args:
path: The path of the link.
linked_path: The path that is linked.
Returns:
The fake file system (instance of dvfvs.FakeFileSystem).
"""
resolver_context = context.Context()
file_system = fake_file_system.FakeFileSystem(
resolver_context)
file_system.AddFileEntry(
u'/', file_entry_type=dfvfs_definitions.FILE_ENTRY_TYPE_DIRECTORY)
path_segments = path.split(u'/')
for segment_index in range(2, len(path_segments)):
path_segment = u'{0:s}'.format(
u'/'.join(path_segments[:segment_index]))
file_system.AddFileEntry(
path_segment,
file_entry_type=dfvfs_definitions.FILE_ENTRY_TYPE_DIRECTORY)
file_system.AddFileEntry(
path, file_entry_type=dfvfs_definitions.FILE_ENTRY_TYPE_LINK,
link_data=linked_path)
return file_system
+556
View File
@@ -0,0 +1,556 @@
#!/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 preprocessors for Windows."""
import abc
import logging
from dfvfs.helpers import file_system_searcher
from plaso.lib import errors
from plaso.preprocessors import interface
from plaso.preprocessors import manager
from plaso.winreg import cache
from plaso.winreg import path_expander as winreg_path_expander
from plaso.winreg import utils
from plaso.winreg import winregistry
class WindowsRegistryPreprocessPlugin(interface.PreprocessPlugin):
"""Class that defines the Windows Registry preprocess plugin object.
By default registry needs information about system paths, which excludes
them to run in priority 1, in some cases they may need to run in priority
3, for instance if the Registry key is dependent on which version of Windows
is running, information that is collected during priority 2.
"""
__abstract = True
SUPPORTED_OS = ['Windows']
WEIGHT = 2
REG_KEY = '\\'
REG_PATH = '{sysregistry}'
REG_FILE = 'SOFTWARE'
def __init__(self):
"""Initializes the Window Registry preprocess plugin object."""
super(WindowsRegistryPreprocessPlugin, self).__init__()
self._file_path_expander = winreg_path_expander.WinRegistryKeyPathExpander()
self._key_path_expander = None
def GetValue(self, searcher, knowledge_base):
"""Returns a value gathered from a Registry key for preprocessing.
Args:
searcher: The file system searcher object (instance of
dfvfs.FileSystemSearcher).
knowledge_base: A knowledge base object (instance of KnowledgeBase),
which contains information from the source data needed
for parsing.
Raises:
errors.PreProcessFail: If the preprocessing fails.
"""
# TODO: optimize this in one find.
try:
# TODO: do not pass the full pre_obj here but just the necessary values.
path = self._file_path_expander.ExpandPath(
self.REG_PATH, pre_obj=knowledge_base.pre_obj)
except KeyError:
path = u''
if not path:
raise errors.PreProcessFail(
u'Unable to expand path: {0:s}'.format(self.REG_PATH))
find_spec = file_system_searcher.FindSpec(
location=path, case_sensitive=False)
path_specs = list(searcher.Find(find_specs=[find_spec]))
if not path_specs or len(path_specs) != 1:
raise errors.PreProcessFail(
u'Unable to find directory: {0:s}'.format(self.REG_PATH))
directory_location = searcher.GetRelativePath(path_specs[0])
if not directory_location:
raise errors.PreProcessFail(
u'Missing directory location for: {0:s}'.format(self.REG_PATH))
# The path is split in segments to make it path segement separator
# independent (and thus platform independent).
path_segments = searcher.SplitPath(directory_location)
path_segments.append(self.REG_FILE)
find_spec = file_system_searcher.FindSpec(
location=path_segments, case_sensitive=False)
path_specs = list(searcher.Find(find_specs=[find_spec]))
if not path_specs:
raise errors.PreProcessFail(
u'Unable to find file: {0:s} in directory: {1:s}'.format(
self.REG_FILE, directory_location))
if len(path_specs) != 1:
raise errors.PreProcessFail((
u'Find for file: {1:s} in directory: {0:s} returned {2:d} '
u'results.').format(
self.REG_FILE, directory_location, len(path_specs)))
file_location = getattr(path_specs[0], 'location', None)
if not directory_location:
raise errors.PreProcessFail(
u'Missing file location for: {0:s} in directory: {1:s}'.format(
self.REG_FILE, directory_location))
try:
file_entry = searcher.GetFileEntryByPathSpec(path_specs[0])
except IOError as exception:
raise errors.PreProcessFail(
u'Unable to open file entry: {0:s} with error: {1:s}'.format(
file_location, exception))
if not file_entry:
raise errors.PreProcessFail(
u'Unable to open file entry: {0:s}'.format(file_location))
# TODO: remove this check win_registry.OpenFile doesn't fail instead?
try:
file_object = file_entry.GetFileObject()
file_object.close()
except IOError as exception:
raise errors.PreProcessFail(
u'Unable to open file object: {0:s} with error: {1:s}'.format(
file_location, exception))
win_registry = winregistry.WinRegistry(
winregistry.WinRegistry.BACKEND_PYREGF)
try:
winreg_file = win_registry.OpenFile(
file_entry, codepage=knowledge_base.codepage)
except IOError as exception:
raise errors.PreProcessFail(
u'Unable to open Registry file: {0:s} with error: {1:s}'.format(
file_location, exception))
self.winreg_file = winreg_file
if not self._key_path_expander:
# TODO: it is more efficient to have one cache that is passed to every
# plugin, or maybe one path expander. Or replace the path expander by
# dfvfs WindowsPathResolver?
reg_cache = cache.WinRegistryCache()
reg_cache.BuildCache(winreg_file, self.REG_FILE)
self._key_path_expander = winreg_path_expander.WinRegistryKeyPathExpander(
reg_cache=reg_cache)
try:
# TODO: do not pass the full pre_obj here but just the necessary values.
key_path = self._key_path_expander.ExpandPath(
self.REG_KEY, pre_obj=knowledge_base.pre_obj)
except KeyError:
key_path = u''
if not key_path:
raise errors.PreProcessFail(
u'Unable to expand path: {0:s}'.format(self.REG_KEY))
try:
key = winreg_file.GetKeyByPath(key_path)
except IOError as exception:
raise errors.PreProcessFail(
u'Unable to fetch Registry key: {0:s} with error: {1:s}'.format(
key_path, exception))
if not key:
raise errors.PreProcessFail(
u'Registry key {0:s} does not exist.'.format(self.REG_KEY))
return self.ParseKey(key)
@abc.abstractmethod
def ParseKey(self, key):
"""Extract information from a Registry key and save in storage."""
class WindowsCodepage(WindowsRegistryPreprocessPlugin):
"""A preprocessing class that fetches codepage information."""
# Defines the preprocess attribute to be set.
ATTRIBUTE = 'code_page'
# Depend upon the current control set, thus lower the priority.
WEIGHT = 3
REG_KEY = '{current_control_set}\\Control\\Nls\\CodePage'
REG_FILE = 'SYSTEM'
def ParseKey(self, key):
"""Retrieves the codepage or cp1252 by default."""
value = key.GetValue('ACP')
if value and type(value.data) == unicode:
return u'cp{0:s}'.format(value.data)
logging.warning(
u'Unable to determine ASCII string codepage, defaulting to cp1252.')
return u'cp1252'
class WindowsHostname(WindowsRegistryPreprocessPlugin):
"""A preprocessing class that fetches the hostname information."""
ATTRIBUTE = 'hostname'
# Depend upon the current control set to be found.
WEIGHT = 3
REG_KEY = '{current_control_set}\\Control\\ComputerName\\ComputerName'
REG_FILE = 'SYSTEM'
def ParseKey(self, key):
"""Extract the hostname from the registry."""
value = key.GetValue('ComputerName')
if value and type(value.data) == unicode:
return value.data
class WindowsProgramFilesPath(WindowsRegistryPreprocessPlugin):
"""Fetch about the location for the Program Files directory."""
ATTRIBUTE = 'programfiles'
REGFILE = 'SOFTWARE'
REG_KEY = '\\Microsoft\\Windows\\CurrentVersion'
def ParseKey(self, key):
"""Extract the version information from the key."""
value = key.GetValue('ProgramFilesDir')
if value:
# Remove the first drive letter, eg: "C:\Program Files".
return u'{0:s}'.format(value.data.partition('\\')[2])
class WindowsProgramFilesX86Path(WindowsRegistryPreprocessPlugin):
"""Fetch about the location for the Program Files directory."""
ATTRIBUTE = 'programfilesx86'
REGFILE = 'SOFTWARE'
REG_KEY = '\\Microsoft\\Windows\\CurrentVersion'
def ParseKey(self, key):
"""Extract the version information from the key."""
value = key.GetValue(u'ProgramFilesDir (x86)')
if value:
# Remove the first drive letter, eg: "C:\Program Files".
return u'{0:s}'.format(value.data.partition('\\')[2])
class WindowsSystemRegistryPath(interface.PathPreprocessPlugin):
"""Get the system registry path."""
SUPPORTED_OS = ['Windows']
ATTRIBUTE = 'sysregistry'
PATH = '/(Windows|WinNT|WINNT35|WTSRV)/System32/config'
class WindowsSystemRootPath(interface.PathPreprocessPlugin):
"""Get the system root path."""
SUPPORTED_OS = ['Windows']
ATTRIBUTE = 'systemroot'
PATH = '/(Windows|WinNT|WINNT35|WTSRV)'
class WindowsTimeZone(WindowsRegistryPreprocessPlugin):
"""A preprocessing class that fetches timezone information."""
# Defines the preprocess attribute to be set.
ATTRIBUTE = 'time_zone_str'
# Depend upon the current control set, thus lower the priority.
WEIGHT = 3
REG_KEY = '{current_control_set}\\Control\\TimeZoneInformation'
REG_FILE = 'SYSTEM'
# transform gathered from these sources:
# Prebuilt from:
# HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Time Zones\
ZONE_LIST = {
'IndiaStandardTime': 'Asia/Kolkata',
'EasternStandardTime': 'EST5EDT',
'EasternDaylightTime': 'EST5EDT',
'MountainStandardTime': 'MST7MDT',
'MountainDaylightTime': 'MST7MDT',
'PacificStandardTime': 'PST8PDT',
'PacificDaylightTime': 'PST8PDT',
'CentralStandardTime': 'CST6CDT',
'CentralDaylightTime': 'CST6CDT',
'SamoaStandardTime': 'US/Samoa',
'HawaiianStandardTime': 'US/Hawaii',
'AlaskanStandardTime': 'US/Alaska',
'MexicoStandardTime2': 'MST7MDT',
'USMountainStandardTime': 'MST7MDT',
'CanadaCentralStandardTime': 'CST6CDT',
'MexicoStandardTime': 'CST6CDT',
'CentralAmericaStandardTime': 'CST6CDT',
'USEasternStandardTime': 'EST5EDT',
'SAPacificStandardTime': 'EST5EDT',
'MalayPeninsulaStandardTime': 'Asia/Kuching',
'PacificSAStandardTime': 'Canada/Atlantic',
'AtlanticStandardTime': 'Canada/Atlantic',
'SAWesternStandardTime': 'Canada/Atlantic',
'NewfoundlandStandardTime': 'Canada/Newfoundland',
'AzoresStandardTime': 'Atlantic/Azores',
'CapeVerdeStandardTime': 'Atlantic/Azores',
'GMTStandardTime': 'GMT',
'GreenwichStandardTime': 'GMT',
'W.CentralAfricaStandardTime': 'Europe/Belgrade',
'W.EuropeStandardTime': 'Europe/Belgrade',
'CentralEuropeStandardTime': 'Europe/Belgrade',
'RomanceStandardTime': 'Europe/Belgrade',
'CentralEuropeanStandardTime': 'Europe/Belgrade',
'E.EuropeStandardTime': 'Egypt',
'SouthAfricaStandardTime': 'Egypt',
'IsraelStandardTime': 'Egypt',
'EgyptStandardTime': 'Egypt',
'NorthAsiaEastStandardTime': 'Asia/Bangkok',
'SingaporeStandardTime': 'Asia/Bangkok',
'ChinaStandardTime': 'Asia/Bangkok',
'W.AustraliaStandardTime': 'Australia/Perth',
'TaipeiStandardTime': 'Asia/Bangkok',
'TokyoStandardTime': 'Asia/Tokyo',
'KoreaStandardTime': 'Asia/Seoul',
'@tzres.dll,-10': 'Atlantic/Azores',
'@tzres.dll,-11': 'Atlantic/Azores',
'@tzres.dll,-12': 'Atlantic/Azores',
'@tzres.dll,-20': 'Atlantic/Cape_Verde',
'@tzres.dll,-21': 'Atlantic/Cape_Verde',
'@tzres.dll,-22': 'Atlantic/Cape_Verde',
'@tzres.dll,-40': 'Brazil/East',
'@tzres.dll,-41': 'Brazil/East',
'@tzres.dll,-42': 'Brazil/East',
'@tzres.dll,-70': 'Canada/Newfoundland',
'@tzres.dll,-71': 'Canada/Newfoundland',
'@tzres.dll,-72': 'Canada/Newfoundland',
'@tzres.dll,-80': 'Canada/Atlantic',
'@tzres.dll,-81': 'Canada/Atlantic',
'@tzres.dll,-82': 'Canada/Atlantic',
'@tzres.dll,-104': 'America/Cuiaba',
'@tzres.dll,-105': 'America/Cuiaba',
'@tzres.dll,-110': 'EST5EDT',
'@tzres.dll,-111': 'EST5EDT',
'@tzres.dll,-112': 'EST5EDT',
'@tzres.dll,-120': 'EST5EDT',
'@tzres.dll,-121': 'EST5EDT',
'@tzres.dll,-122': 'EST5EDT',
'@tzres.dll,-130': 'EST5EDT',
'@tzres.dll,-131': 'EST5EDT',
'@tzres.dll,-132': 'EST5EDT',
'@tzres.dll,-140': 'CST6CDT',
'@tzres.dll,-141': 'CST6CDT',
'@tzres.dll,-142': 'CST6CDT',
'@tzres.dll,-150': 'America/Guatemala',
'@tzres.dll,-151': 'America/Guatemala',
'@tzres.dll,-152': 'America/Guatemala',
'@tzres.dll,-160': 'CST6CDT',
'@tzres.dll,-161': 'CST6CDT',
'@tzres.dll,-162': 'CST6CDT',
'@tzres.dll,-170': 'America/Mexico_City',
'@tzres.dll,-171': 'America/Mexico_City',
'@tzres.dll,-172': 'America/Mexico_City',
'@tzres.dll,-180': 'MST7MDT',
'@tzres.dll,-181': 'MST7MDT',
'@tzres.dll,-182': 'MST7MDT',
'@tzres.dll,-190': 'MST7MDT',
'@tzres.dll,-191': 'MST7MDT',
'@tzres.dll,-192': 'MST7MDT',
'@tzres.dll,-200': 'MST7MDT',
'@tzres.dll,-201': 'MST7MDT',
'@tzres.dll,-202': 'MST7MDT',
'@tzres.dll,-210': 'PST8PDT',
'@tzres.dll,-211': 'PST8PDT',
'@tzres.dll,-212': 'PST8PDT',
'@tzres.dll,-220': 'US/Alaska',
'@tzres.dll,-221': 'US/Alaska',
'@tzres.dll,-222': 'US/Alaska',
'@tzres.dll,-230': 'US/Hawaii',
'@tzres.dll,-231': 'US/Hawaii',
'@tzres.dll,-232': 'US/Hawaii',
'@tzres.dll,-260': 'GMT',
'@tzres.dll,-261': 'GMT',
'@tzres.dll,-262': 'GMT',
'@tzres.dll,-271': 'UTC',
'@tzres.dll,-272': 'UTC',
'@tzres.dll,-280': 'Europe/Budapest',
'@tzres.dll,-281': 'Europe/Budapest',
'@tzres.dll,-282': 'Europe/Budapest',
'@tzres.dll,-290': 'Europe/Warsaw',
'@tzres.dll,-291': 'Europe/Warsaw',
'@tzres.dll,-292': 'Europe/Warsaw',
'@tzres.dll,-331': 'Europe/Nicosia',
'@tzres.dll,-332': 'Europe/Nicosia',
'@tzres.dll,-340': 'Africa/Cairo',
'@tzres.dll,-341': 'Africa/Cairo',
'@tzres.dll,-342': 'Africa/Cairo',
'@tzres.dll,-350': 'Europe/Sofia',
'@tzres.dll,-351': 'Europe/Sofia',
'@tzres.dll,-352': 'Europe/Sofia',
'@tzres.dll,-365': 'Egypt',
'@tzres.dll,-390': 'Asia/Kuwait',
'@tzres.dll,-391': 'Asia/Kuwait',
'@tzres.dll,-392': 'Asia/Kuwait',
'@tzres.dll,-400': 'Asia/Baghdad',
'@tzres.dll,-401': 'Asia/Baghdad',
'@tzres.dll,-402': 'Asia/Baghdad',
'@tzres.dll,-410': 'Africa/Nairobi',
'@tzres.dll,-411': 'Africa/Nairobi',
'@tzres.dll,-412': 'Africa/Nairobi',
'@tzres.dll,-434': 'Asia/Tbilisi',
'@tzres.dll,-435': 'Asia/Tbilisi',
'@tzres.dll,-440': 'Asia/Muscat',
'@tzres.dll,-441': 'Asia/Muscat',
'@tzres.dll,-442': 'Asia/Muscat',
'@tzres.dll,-447': 'Asia/Baku',
'@tzres.dll,-448': 'Asia/Baku',
'@tzres.dll,-449': 'Asia/Baku',
'@tzres.dll,-450': 'Asia/Yerevan',
'@tzres.dll,-451': 'Asia/Yerevan',
'@tzres.dll,-452': 'Asia/Yerevan',
'@tzres.dll,-460': 'Asia/Kabul',
'@tzres.dll,-461': 'Asia/Kabul',
'@tzres.dll,-462': 'Asia/Kabul',
'@tzres.dll,-471': 'Asia/Yekaterinburg',
'@tzres.dll,-472': 'Asia/Yekaterinburg',
'@tzres.dll,-480': 'Asia/Karachi',
'@tzres.dll,-481': 'Asia/Karachi',
'@tzres.dll,-482': 'Asia/Karachi',
'@tzres.dll,-490': 'Asia/Kolkata',
'@tzres.dll,-491': 'Asia/Kolkata',
'@tzres.dll,-492': 'Asia/Kolkata',
'@tzres.dll,-500': 'Asia/Kathmandu',
'@tzres.dll,-501': 'Asia/Kathmandu',
'@tzres.dll,-502': 'Asia/Kathmandu',
'@tzres.dll,-510': 'Asia/Dhaka',
'@tzres.dll,-511': 'Asia/Aqtau',
'@tzres.dll,-512': 'Asia/Aqtau',
'@tzres.dll,-570': 'Asia/Chongqing',
'@tzres.dll,-571': 'Asia/Chongqing',
'@tzres.dll,-572': 'Asia/Chongqing',
'@tzres.dll,-650': 'Australia/Darwin',
'@tzres.dll,-651': 'Australia/Darwin',
'@tzres.dll,-652': 'Australia/Darwin',
'@tzres.dll,-660': 'Australia/Adelaide',
'@tzres.dll,-661': 'Australia/Adelaide',
'@tzres.dll,-662': 'Australia/Adelaide',
'@tzres.dll,-670': 'Australia/Sydney',
'@tzres.dll,-671': 'Australia/Sydney',
'@tzres.dll,-672': 'Australia/Sydney',
'@tzres.dll,-680': 'Australia/Brisbane',
'@tzres.dll,-681': 'Australia/Brisbane',
'@tzres.dll,-682': 'Australia/Brisbane',
'@tzres.dll,-721': 'Pacific/Port_Moresby',
'@tzres.dll,-722': 'Pacific/Port_Moresby',
'@tzres.dll,-731': 'Pacific/Fiji',
'@tzres.dll,-732': 'Pacific/Fiji',
'@tzres.dll,-840': 'America/Argentina/Buenos_Aires',
'@tzres.dll,-841': 'America/Argentina/Buenos_Aires',
'@tzres.dll,-842': 'America/Argentina/Buenos_Aires',
'@tzres.dll,-880': 'UTC',
'@tzres.dll,-930': 'UTC',
'@tzres.dll,-931': 'UTC',
'@tzres.dll,-932': 'UTC',
'@tzres.dll,-1010': 'Asia/Aqtau',
'@tzres.dll,-1020': 'Asia/Dhaka',
'@tzres.dll,-1021': 'Asia/Dhaka',
'@tzres.dll,-1022': 'Asia/Dhaka',
'@tzres.dll,-1070': 'Asia/Tbilisi',
'@tzres.dll,-1120': 'America/Cuiaba',
'@tzres.dll,-1140': 'Pacific/Fiji',
'@tzres.dll,-1460': 'Pacific/Port_Moresby',
'@tzres.dll,-1530': 'Asia/Yekaterinburg',
'@tzres.dll,-1630': 'Europe/Nicosia',
'@tzres.dll,-1660': 'America/Bahia',
'@tzres.dll,-1661': 'America/Bahia',
'@tzres.dll,-1662': 'America/Bahia',
'Central Standard Time': 'CST6CDT',
'Pacific Standard Time': 'PST8PDT',
}
def ParseKey(self, key):
"""Extract timezone information from the registry."""
value = key.GetValue('StandardName')
if value and type(value.data) == unicode:
# Do a mapping to a value defined as in the Olson database.
return self.ZONE_LIST.get(value.data.replace(' ', ''), value.data)
class WindowsUsers(WindowsRegistryPreprocessPlugin):
"""Fetch information about user profiles."""
ATTRIBUTE = 'users'
REG_FILE = 'SOFTWARE'
REG_KEY = '\\Microsoft\\Windows NT\\CurrentVersion\\ProfileList'
def ParseKey(self, key):
"""Extract current control set information."""
users = []
for sid in key.GetSubkeys():
# TODO: as part of artifacts, create a proper object for this.
user = {}
user['sid'] = sid.name
value = sid.GetValue('ProfileImagePath')
if value:
user['path'] = value.data
user['name'] = utils.WinRegBasename(user['path'])
users.append(user)
return users
class WindowsVersion(WindowsRegistryPreprocessPlugin):
"""Fetch information about the current Windows version."""
ATTRIBUTE = 'osversion'
REGFILE = 'SOFTWARE'
REG_KEY = '\\Microsoft\\Windows NT\\CurrentVersion'
def ParseKey(self, key):
"""Extract the version information from the key."""
value = key.GetValue('ProductName')
if value:
return u'{0:s}'.format(value.data)
class WindowsWinDirPath(interface.PathPreprocessPlugin):
"""Get the system path."""
SUPPORTED_OS = ['Windows']
ATTRIBUTE = 'windir'
PATH = '/(Windows|WinNT|WINNT35|WTSRV)'
manager.PreprocessPluginsManager.RegisterPlugins([
WindowsCodepage, WindowsHostname, WindowsProgramFilesPath,
WindowsProgramFilesX86Path, WindowsSystemRegistryPath,
WindowsSystemRootPath, WindowsTimeZone, WindowsUsers, WindowsVersion,
WindowsWinDirPath])
+265
View File
@@ -0,0 +1,265 @@
#!/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.
"""Tests for the Windows preprocess plug-ins."""
import os
import unittest
from dfvfs.helpers import file_system_searcher
from dfvfs.path import fake_path_spec
from plaso.artifacts import knowledge_base
from plaso.preprocessors import windows
from plaso.preprocessors import test_lib
class WindowsSoftwareRegistryTest(test_lib.PreprocessPluginTest):
"""Base class for tests that use the SOFTWARE Registry file."""
def setUp(self):
"""Sets up the needed objects used throughout the test."""
file_object = open(os.path.join(
self._TEST_DATA_PATH, u'SYSTEM'), 'rb')
file_data = file_object.read()
file_object.close()
self._fake_file_system = self._BuildSingleFileFakeFileSystem(
u'/Windows/System32/config/SYSTEM', file_data)
file_object = open(os.path.join(
self._TEST_DATA_PATH, u'SOFTWARE'), 'rb')
file_data = file_object.read()
file_object.close()
self._fake_file_system.AddFileEntry(
u'/Windows/System32/config/SOFTWARE', file_data=file_data)
mount_point = fake_path_spec.FakePathSpec(location=u'/')
self._searcher = file_system_searcher.FileSystemSearcher(
self._fake_file_system, mount_point)
class WindowsSystemRegistryTest(test_lib.PreprocessPluginTest):
"""Base class for tests that use the SYSTEM Registry file."""
def setUp(self):
"""Sets up the needed objects used throughout the test."""
file_object = open(os.path.join(
self._TEST_DATA_PATH, u'SYSTEM'), 'rb')
file_data = file_object.read()
file_object.close()
self._fake_file_system = self._BuildSingleFileFakeFileSystem(
u'/Windows/System32/config/SYSTEM', file_data)
mount_point = fake_path_spec.FakePathSpec(location=u'/')
self._searcher = file_system_searcher.FileSystemSearcher(
self._fake_file_system, mount_point)
class WindowsCodepageTest(WindowsSystemRegistryTest):
"""Tests for the Windows codepage preprocess plug-in object."""
def testGetValue(self):
"""Tests the GetValue function."""
knowledge_base_object = knowledge_base.KnowledgeBase()
# The plug-in needs to expand {sysregistry} so we need to run
# the WindowsSystemRegistryPath plug-in first.
plugin = windows.WindowsSystemRegistryPath()
plugin.Run(self._searcher, knowledge_base_object)
plugin = windows.WindowsCodepage()
plugin.Run(self._searcher, knowledge_base_object)
self.assertEquals(knowledge_base_object.codepage, u'cp1252')
class WindowsHostnameTest(WindowsSystemRegistryTest):
"""Tests for the Windows hostname preprocess plug-in object."""
def testGetValue(self):
"""Tests the GetValue function."""
knowledge_base_object = knowledge_base.KnowledgeBase()
# The plug-in needs to expand {sysregistry} so we need to run
# the WindowsSystemRegistryPath plug-in first.
plugin = windows.WindowsSystemRegistryPath()
plugin.Run(self._searcher, knowledge_base_object)
plugin = windows.WindowsHostname()
plugin.Run(self._searcher, knowledge_base_object)
self.assertEquals(knowledge_base_object.hostname, u'WKS-WIN732BITA')
class WindowsProgramFilesPath(WindowsSoftwareRegistryTest):
"""Tests for the Windows Program Files path preprocess plug-in object."""
def testGetValue(self):
"""Tests the GetValue function."""
knowledge_base_object = knowledge_base.KnowledgeBase()
# The plug-in needs to expand {sysregistry} so we need to run
# the WindowsSystemRegistryPath plug-in first.
plugin = windows.WindowsSystemRegistryPath()
plugin.Run(self._searcher, knowledge_base_object)
plugin = windows.WindowsProgramFilesPath()
plugin.Run(self._searcher, knowledge_base_object)
path = knowledge_base_object.GetValue('programfiles')
self.assertEquals(path, u'Program Files')
class WindowsProgramFilesX86Path(WindowsSoftwareRegistryTest):
"""Tests for the Windows Program Files X86 path preprocess plug-in object."""
def testGetValue(self):
"""Tests the GetValue function."""
knowledge_base_object = knowledge_base.KnowledgeBase()
# The plug-in needs to expand {sysregistry} so we need to run
# the WindowsSystemRegistryPath plug-in first.
plugin = windows.WindowsSystemRegistryPath()
plugin.Run(self._searcher, knowledge_base_object)
plugin = windows.WindowsProgramFilesX86Path()
plugin.Run(self._searcher, knowledge_base_object)
path = knowledge_base_object.GetValue('programfilesx86')
# The test SOFTWARE Registry file does not contain a value for
# the Program Files X86 path.
self.assertEquals(path, None)
class WindowsSystemRegistryPathTest(test_lib.PreprocessPluginTest):
"""Tests for the Windows system Registry path preprocess plug-in object."""
_FILE_DATA = 'regf'
def setUp(self):
"""Sets up the needed objects used throughout the test."""
self._fake_file_system = self._BuildSingleFileFakeFileSystem(
u'/Windows/System32/config/SYSTEM', self._FILE_DATA)
mount_point = fake_path_spec.FakePathSpec(location=u'/')
self._searcher = file_system_searcher.FileSystemSearcher(
self._fake_file_system, mount_point)
def testGetValue(self):
"""Tests the GetValue function."""
knowledge_base_object = knowledge_base.KnowledgeBase()
plugin = windows.WindowsSystemRegistryPath()
plugin.Run(self._searcher, knowledge_base_object)
path = knowledge_base_object.GetValue('sysregistry')
self.assertEquals(path, u'/Windows/System32/config')
class WindowsSystemRootPathTest(test_lib.PreprocessPluginTest):
"""Tests for the Windows system Root path preprocess plug-in object."""
_FILE_DATA = 'regf'
def setUp(self):
"""Sets up the needed objects used throughout the test."""
self._fake_file_system = self._BuildSingleFileFakeFileSystem(
u'/Windows/System32/config/SYSTEM', self._FILE_DATA)
mount_point = fake_path_spec.FakePathSpec(location=u'/')
self._searcher = file_system_searcher.FileSystemSearcher(
self._fake_file_system, mount_point)
def testGetValue(self):
"""Tests the GetValue function."""
knowledge_base_object = knowledge_base.KnowledgeBase()
plugin = windows.WindowsSystemRootPath()
plugin.Run(self._searcher, knowledge_base_object)
path = knowledge_base_object.GetValue('systemroot')
self.assertEquals(path, u'/Windows')
class WindowsTimeZoneTest(WindowsSystemRegistryTest):
"""Tests for the Windows timezone preprocess plug-in object."""
def testGetValue(self):
"""Tests the GetValue function."""
knowledge_base_object = knowledge_base.KnowledgeBase()
# The plug-in needs to expand {sysregistry} so we need to run
# the WindowsSystemRegistryPath plug-in first.
plugin = windows.WindowsSystemRegistryPath()
plugin.Run(self._searcher, knowledge_base_object)
plugin = windows.WindowsTimeZone()
plugin.Run(self._searcher, knowledge_base_object)
time_zone_str = knowledge_base_object.GetValue('time_zone_str')
self.assertEquals(time_zone_str, u'EST5EDT')
class WindowsUsersTest(WindowsSoftwareRegistryTest):
"""Tests for the Windows username preprocess plug-in object."""
def testGetValue(self):
"""Tests the GetValue function."""
knowledge_base_object = knowledge_base.KnowledgeBase()
# The plug-in needs to expand {sysregistry} so we need to run
# the WindowsSystemRegistryPath plug-in first.
plugin = windows.WindowsSystemRegistryPath()
plugin.Run(self._searcher, knowledge_base_object)
plugin = windows.WindowsUsers()
plugin.Run(self._searcher, knowledge_base_object)
users = knowledge_base_object.GetValue('users')
self.assertEquals(len(users), 11)
expected_sid = u'S-1-5-21-2036804247-3058324640-2116585241-1114'
self.assertEquals(users[9].get('sid', None), expected_sid)
self.assertEquals(users[9].get('name', None), u'rsydow')
self.assertEquals(users[9].get('path', None), u'C:\\Users\\rsydow')
class WindowsVersionTest(WindowsSoftwareRegistryTest):
"""Tests for the Windows version preprocess plug-in object."""
def testGetValue(self):
"""Tests the GetValue function."""
knowledge_base_object = knowledge_base.KnowledgeBase()
# The plug-in needs to expand {sysregistry} so we need to run
# the WindowsSystemRegistryPath plug-in first.
plugin = windows.WindowsSystemRegistryPath()
plugin.Run(self._searcher, knowledge_base_object)
plugin = windows.WindowsVersion()
plugin.Run(self._searcher, knowledge_base_object)
osversion = knowledge_base_object.GetValue('osversion')
self.assertEquals(osversion, u'Windows 7 Ultimate')
if __name__ == '__main__':
unittest.main()