Import from old repository
This commit is contained in:
@@ -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
|
||||
@@ -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'
|
||||
@@ -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])
|
||||
@@ -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()
|
||||
@@ -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])
|
||||
@@ -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()
|
||||
@@ -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))
|
||||
@@ -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()
|
||||
@@ -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
|
||||
@@ -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])
|
||||
@@ -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()
|
||||
Reference in New Issue
Block a user