From b1a65b6ed0fb0bcc388b38bf17bd65c1353121b1 Mon Sep 17 00:00:00 2001 From: Joachim Metz Date: Sun, 31 Dec 2023 11:39:28 +0100 Subject: [PATCH] Changes to handling message file resource paths #4259 (#4773) --- plaso/helpers/windows/eventlog_providers.py | 37 ++++++++-- tests/helpers/windows/eventlog_providers.py | 75 +++++++++++++++++++++ 2 files changed, 106 insertions(+), 6 deletions(-) create mode 100644 tests/helpers/windows/eventlog_providers.py diff --git a/plaso/helpers/windows/eventlog_providers.py b/plaso/helpers/windows/eventlog_providers.py index 50759e4691..73a133c0b3 100644 --- a/plaso/helpers/windows/eventlog_providers.py +++ b/plaso/helpers/windows/eventlog_providers.py @@ -15,6 +15,7 @@ def _GetNormalizedPath(self, path): str: normalized path of a message file. """ path_segments = path.split('\\') + filename = path_segments.pop() if path_segments: # Check if the first path segment is a drive letter or "%SystemDrive%". @@ -23,6 +24,30 @@ def _GetNormalizedPath(self, path): first_path_segment == '%systemdrive%'): path_segments[0] = '' + path_segments_lower = [ + path_segment.lower() for path_segment in path_segments] + + if not path_segments_lower: + # If the path is a filename assume the file is stored in: + # "%SystemRoot%\System32". + path_segments = ['%SystemRoot%', 'System32'] + + elif path_segments_lower[0] in ('system32', '$(runtime.system32)'): + # Note that the path can be relative so if it starts with "System32" + # asume this represents "%SystemRoot%\System32". + path_segments = ['%SystemRoot%', 'System32'] + path_segments[1:] + + elif path_segments_lower[0] in ( + '%systemroot%', '%windir%', '$(runtime.windows)'): + path_segments = ['%SystemRoot%'] + path_segments[1:] + + # Check if path starts with "\SystemRoot\", "\Windows\" or "\WinNT\" for + # example: "\SystemRoot\system32\drivers\SerCx.sys" + elif not path_segments_lower[0] and path_segments_lower[1] in ( + 'systemroot', 'windows', 'winnt'): + path_segments = ['%SystemRoot%'] + path_segments[2:] + + path_segments.append(filename) return '\\'.join(path_segments) or '\\' def Merge(self, first_event_log_provider, second_event_log_provider): @@ -50,17 +75,17 @@ def Merge(self, first_event_log_provider, second_event_log_provider): first_event_log_provider.log_types.append(log_type) for path in second_event_log_provider.category_message_files: - path = self._GetNormalizedPath(path.lower()) + path = self._GetNormalizedPath(path) if path not in first_event_log_provider.category_message_files: first_event_log_provider.category_message_files.append(path) for path in second_event_log_provider.event_message_files: - path = self._GetNormalizedPath(path.lower()) + path = self._GetNormalizedPath(path) if path not in first_event_log_provider.event_message_files: first_event_log_provider.event_message_files.append(path) for path in second_event_log_provider.parameter_message_files: - path = self._GetNormalizedPath(path.lower()) + path = self._GetNormalizedPath(path) if path not in first_event_log_provider.parameter_message_files: first_event_log_provider.parameter_message_files.append(path) @@ -71,13 +96,13 @@ def NormalizeMessageFiles(self, event_log_provider): event_log_provider (EventLogProvider): Event Log provider. """ event_log_provider.category_message_files = [ - self._GetNormalizedPath(path.lower()) + self._GetNormalizedPath(path) for path in event_log_provider.category_message_files] event_log_provider.event_message_files = [ - self._GetNormalizedPath(path.lower()) + self._GetNormalizedPath(path) for path in event_log_provider.event_message_files] event_log_provider.parameter_message_files = [ - self._GetNormalizedPath(path.lower()) + self._GetNormalizedPath(path) for path in event_log_provider.parameter_message_files] diff --git a/tests/helpers/windows/eventlog_providers.py b/tests/helpers/windows/eventlog_providers.py new file mode 100644 index 0000000000..c83d257377 --- /dev/null +++ b/tests/helpers/windows/eventlog_providers.py @@ -0,0 +1,75 @@ +#!/usr/bin/env python3 +# -*- coding: utf-8 -*- +"""Tests for the Windows EventLog providers helper.""" + +import unittest + +from plaso.helpers.windows import eventlog_providers + +from tests import test_lib as shared_test_lib + + +class WindowsEventLogProvidersHelperTest(shared_test_lib.BaseTestCase): + """Tests for the Windows EventLog providers helper.""" + + # pylint: disable=protected-access + + def testGetNormalizedPath(self): + """Tests the _GetNormalizedPath function.""" + test_helper = eventlog_providers.WindowsEventLogProvidersHelper() + + normalized_path = test_helper._GetNormalizedPath( + '%SystemRoot%\\System32\\IoLogMsg.dll') + self.assertEqual(normalized_path, '%SystemRoot%\\System32\\IoLogMsg.dll') + + normalized_path = test_helper._GetNormalizedPath( + '%windir%\\System32\\lsasrv.dll') + self.assertEqual(normalized_path, '%SystemRoot%\\System32\\lsasrv.dll') + + normalized_path = test_helper._GetNormalizedPath( + 'C:\\Windows\\System32\\mscoree.dll') + self.assertEqual(normalized_path, '%SystemRoot%\\System32\\mscoree.dll') + + normalized_path = test_helper._GetNormalizedPath( + 'werfault.exe') + self.assertEqual(normalized_path, '%SystemRoot%\\System32\\werfault.exe') + + normalized_path = test_helper._GetNormalizedPath( + 'system32\\drivers\\WdFilter.sys') + self.assertEqual(normalized_path, ( + '%SystemRoot%\\System32\\drivers\\WdFilter.sys')) + + normalized_path = test_helper._GetNormalizedPath( + 'C:\\Program Files (x86)\\Microsoft\\Edge\\Application\\84.0.522.52\\' + 'eventlog_provider.dll') + self.assertEqual(normalized_path, ( + '\\Program Files (x86)\\Microsoft\\Edge\\Application\\84.0.522.52\\' + 'eventlog_provider.dll')) + + normalized_path = test_helper._GetNormalizedPath( + '%ProgramFiles%\\Windows Defender\\MpClient.dll') + self.assertEqual(normalized_path, ( + '%ProgramFiles%\\Windows Defender\\MpClient.dll')) + + normalized_path = test_helper._GetNormalizedPath( + '%programdata%\\Microsoft\\Windows Defender\\Definition Updates\\' + 'Default\\MpEngine.dll') + self.assertEqual(normalized_path, ( + '%programdata%\\Microsoft\\Windows Defender\\Definition Updates\\' + 'Default\\MpEngine.dll')) + + normalized_path = test_helper._GetNormalizedPath( + '$(runtime.system32)\\WinML.dll') + self.assertEqual(normalized_path, '%SystemRoot%\\System32\\WinML.dll') + + normalized_path = test_helper._GetNormalizedPath( + '$(runtime.windows)\\immersivecontrolpanel\\systemsettings.exe') + self.assertEqual(normalized_path, ( + '%SystemRoot%\\immersivecontrolpanel\\systemsettings.exe')) + + # TODO: add tests for Merge + # TODO: add tests for NormalizeMessageFiles + + +if __name__ == '__main__': + unittest.main()