Skip to content

Commit

Permalink
Code review: 216000043: Changes for Windows Event Log message strings…
Browse files Browse the repository at this point in the history
… support #99
  • Loading branch information
joachimmetz committed Mar 16, 2015
1 parent 070cf76 commit bda46af
Show file tree
Hide file tree
Showing 7 changed files with 105 additions and 8 deletions.
2 changes: 1 addition & 1 deletion config/dpkg/changelog
Original file line number Diff line number Diff line change
Expand Up @@ -2,4 +2,4 @@ python-plaso (1.2.1-1) unstable; urgency=low

* Auto-generated

-- Log2Timeline <log2timeline-dev@googlegroups.com> Mon, 16 Mar 2015 07:06:53 +0100
-- Log2Timeline <log2timeline-dev@googlegroups.com> Mon, 16 Mar 2015 18:52:41 +0100
Binary file modified data/winevt-rc.db
Binary file not shown.
83 changes: 79 additions & 4 deletions plaso/formatters/winevt_rc.py
Original file line number Diff line number Diff line change
Expand Up @@ -152,7 +152,7 @@ def Open(self, filename):
Returns:
A boolean containing True if successful or False if not.
"""
self._database_file.Open(filename, read_only=True)
return self._database_file.Open(filename, read_only=True)


class WinevtResourcesSqlite3DatabaseReader(Sqlite3DatabaseReader):
Expand All @@ -162,9 +162,16 @@ class WinevtResourcesSqlite3DatabaseReader(Sqlite3DatabaseReader):
_WHITE_SPACE_SPECIFIER_RE = re.compile(r'(%[0b]|[\r\n])')
# Message string specifiers that expand to text.
_TEXT_SPECIFIER_RE = re.compile(r'%([ .!%nrt])')
# Curly brackets in a message string.
_CURLY_BRACKETS = re.compile(r'([\{\}])')
# Message string specifiers that expand to a variable place holder.
_PLACE_HOLDER_SPECIFIER_RE = re.compile(r'%([1-9][0-9]?)[!]?[s]?[!]?')

def __init__(self):
"""Initializes the database reader object."""
super(WinevtResourcesSqlite3DatabaseReader, self).__init__()
self._string_format = u'wrc'

def _GetEventLogProviderKey(self, log_source):
"""Retrieves the Event Log provider key.
Expand Down Expand Up @@ -257,7 +264,7 @@ def _ReformatMessageString(self, message_string):
message_string: the message string.
Returns:
The message string in Python format() style.
The message string in Python format() (PEP 3101) style.
"""
def place_holder_specifier_replacer(match_object):
"""Replaces message string place holders into Python format() style."""
Expand All @@ -278,6 +285,7 @@ def place_holder_specifier_replacer(match_object):

message_string = self._WHITE_SPACE_SPECIFIER_RE.sub(r'', message_string)
message_string = self._TEXT_SPECIFIER_RE.sub(r'\\\1', message_string)
message_string = self._CURLY_BRACKETS.sub(r'\1\1', message_string)
return self._PLACE_HOLDER_SPECIFIER_RE.sub(
place_holder_specifier_replacer, message_string)

Expand All @@ -300,7 +308,7 @@ def GetMessage(self, log_source, lcid, message_identifier):
if not generator:
return

# TODO: cache a number of reformatted message strings.
# TODO: cache a number of message strings.
message_string = None
for message_file_key in generator:
message_string = self._GetMessage(
Expand All @@ -309,4 +317,71 @@ def GetMessage(self, log_source, lcid, message_identifier):
if message_string:
break

return self._ReformatMessageString(message_string)
if self._string_format == u'wrc':
message_string = self._ReformatMessageString(message_string)

return message_string

def GetMetadataAttribute(self, attribute_name):
"""Retrieves the metadata attribute.
Args:
attribute_name: the name of the metadata attribute.
Returns:
The value of the metadata attribute or None.
Raises:
RuntimeError: if more than one value is found in the database.
"""
table_name = u'metadata'

has_table = self._database_file.HasTable(table_name)
if not has_table:
return

column_names = [u'value']
condition = u'name == "{0:s}"'.format(attribute_name)

values = list(self._database_file.GetValues(
[table_name], column_names, condition))

number_of_values = len(values)
if number_of_values == 0:
return

elif number_of_values == 1:
return values[0][u'value']

raise RuntimeError(u'More than one value found in database.')

def Open(self, filename):
"""Opens the database reader object.
Args:
filename: the filename of the database.
Returns:
A boolean containing True if successful or False if not.
Raises:
RuntimeError: if the version or string format of the database
is not supported.
"""
if not super(WinevtResourcesSqlite3DatabaseReader, self).Open(filename):
return False

version = self.GetMetadataAttribute(u'version')
if not version or version not in [u'20150315']:
raise RuntimeError(u'Unsupported version: {0:s}'.format(version))

string_format = self.GetMetadataAttribute(u'string_format')
if not string_format:
string_format = u'wrc'

if string_format not in [u'pep3101', u'wrc']:
raise RuntimeError(u'Unsupported string format: {0:s}'.format(
string_format))

self._string_format = string_format
return True
3 changes: 2 additions & 1 deletion plaso/formatters/winevt_rc_test.py
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,8 @@ class WinevtResourcesSqlite3DatabaseReaderTest(unittest.TestCase):

def setUp(self):
"""Sets up the needed objects used throughout the test."""
self._database_path = os.path.join(os.getcwd(), u'data', u'winevt-rc.db')
self._database_path = os.path.join(
os.getcwd(), u'test_data', u'winevt-rc.db')

def testGetMessage(self):
"""Tests the GetMessage function."""
Expand Down
10 changes: 8 additions & 2 deletions plaso/frontend/image_export.py
Original file line number Diff line number Diff line change
Expand Up @@ -1074,13 +1074,19 @@ def Main():
logging.basicConfig(level=logging.INFO, format=format_str)

if not getattr(options, u'data_location', None):
# TODO: improve handling of data location, for now default to:
# <path image_export.py> .. .. data
# Determine if we are running from the source directory.
options.data_location = os.path.dirname(__file__)
options.data_location = os.path.dirname(options.data_location)
options.data_location = os.path.dirname(options.data_location)
options.data_location = os.path.join(options.data_location, u'data')

if not os.path.exists(options.data_location):
# Otherwise determine if there is shared plaso data location.
options.data_location = os.path.join(sys.prefix, u'share', u'plaso')

if not os.path.exists(options.data_location):
logging.warning(u'Unable to automatically determine data location.')

if getattr(options, u'signature_identifiers', u'') == u'list':
front_end.ListSignatureIdentifiers(options)
return True
Expand Down
15 changes: 15 additions & 0 deletions plaso/frontend/psort.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@
import time
import multiprocessing
import logging
import os
import pdb
import sys

Expand Down Expand Up @@ -722,6 +723,20 @@ def Main(arguments=None):
front_end.ListOutputModules()
return True

if not getattr(options, u'data_location', None):
# Determine if we are running from the source directory.
options.data_location = os.path.dirname(__file__)
options.data_location = os.path.dirname(options.data_location)
options.data_location = os.path.dirname(options.data_location)
options.data_location = os.path.join(options.data_location, u'data')

if not os.path.exists(options.data_location):
# Otherwise determine if there is shared plaso data location.
options.data_location = os.path.join(sys.prefix, u'share', u'plaso')

if not os.path.exists(options.data_location):
logging.warning(u'Unable to automatically determine data location.')

try:
front_end.ParseOptions(options)
except errors.BadConfigOption as exception:
Expand Down
Binary file added test_data/winevt-rc.db
Binary file not shown.

0 comments on commit bda46af

Please sign in to comment.