diff --git a/regipy/__init__.py b/regipy/__init__.py index 0fbd458..07890f5 100644 --- a/regipy/__init__.py +++ b/regipy/__init__.py @@ -1,4 +1,5 @@ + # flake8: noqa from .registry import * __title__ = "regipy" -__version__ = "4.3.1" +__version__ = "4.9.0" diff --git a/regipy/cli.py b/regipy/cli.py index ca829c1..b3f2fd5 100644 --- a/regipy/cli.py +++ b/regipy/cli.py @@ -1,22 +1,19 @@ -import binascii import csv import json import logging import os import time -from typing import Generator, Iterator import attr import click -import pytz from tabulate import tabulate from regipy.plugins.plugin import PLUGINS from regipy.recovery import apply_transaction_logs from regipy.regdiff import compare_hives from regipy.plugins.utils import run_relevant_plugins -from regipy.registry import NKRecord, RegistryHive +from regipy.registry import RegistryHive from regipy.exceptions import RegistryKeyNotFoundException from regipy.utils import calculate_xor32_checksum, _setup_logging from regipy.cli_utils import get_filtered_subkeys, _normalize_subkey_fields diff --git a/regipy/cli_utils.py b/regipy/cli_utils.py index feee7bf..073f1d7 100644 --- a/regipy/cli_utils.py +++ b/regipy/cli_utils.py @@ -25,8 +25,10 @@ def get_filtered_subkeys( Get records filtered by the specified timestamps :param registry_hive: A RegistryHive object :param name_key_entry: A list of paths as strings - :param start_date: Include only subkeys modified after the specified date, in isoformat UTC, for example: 2020-02-18T14:15:00.000000 - :param end_date: Include only subkeys modified before the specified date, in isoformat UTC, for example: 2020-02-20T14:15:00.000000 + :param start_date: Include only subkeys modified after the specified date + in isoformat UTC, for example: 2020-02-18T14:15:00.000000 + :param end_date: Include only subkeys modified before the specified date + in isoformat UTC, for example: 2020-02-20T14:15:00.000000 """ skipped_entries_count = 0 if start_date: diff --git a/regipy/exceptions.py b/regipy/exceptions.py index c858fde..11249e8 100644 --- a/regipy/exceptions.py +++ b/regipy/exceptions.py @@ -44,9 +44,3 @@ class RegistryParsingException(RegipyException): """ pass - - -class NtSidDecodingException(RegipyException): - """ - Raised when the binary Windows NT SID representation can not be decoded - """ diff --git a/regipy/plugins/__init__.py b/regipy/plugins/__init__.py index 9e957c2..3424f87 100644 --- a/regipy/plugins/__init__.py +++ b/regipy/plugins/__init__.py @@ -1,3 +1,4 @@ +# flake8: noqa from .amcache.amcache import AmCachePlugin from .bcd.boot_entry_list import BootEntryListPlugin from .ntuser.installed_programs_ntuser import InstalledProgramsNTUserPlugin diff --git a/regipy/plugins/ntuser/shellbags_ntuser.py b/regipy/plugins/ntuser/shellbags_ntuser.py index 140d2fc..db51c5c 100644 --- a/regipy/plugins/ntuser/shellbags_ntuser.py +++ b/regipy/plugins/ntuser/shellbags_ntuser.py @@ -35,9 +35,9 @@ def _get_shell_item_type(shell_item): import pyfwsi except ModuleNotFoundError as ex: logger.exception( - f"Plugin `shellbag_plugin` has missing modules, install regipy using" - f" `pip install regipy[full]` in order to install plugin dependencies. " - f"This might take some time... " + "Plugin `shellbag_plugin` has missing modules, install regipy using" + " `pip install regipy[full]` in order to install plugin dependencies. " + "This might take some time... " ) raise ex @@ -319,12 +319,13 @@ def iter_sk(self, key, reg_path, codepage=DEFAULT_CODEPAGE, base_path="", path=" def run(self, codepage=DEFAULT_CODEPAGE): try: + # flake8: noqa import pyfwsi except ModuleNotFoundError as ex: logger.exception( - f"Plugin `shellbag_plugin` has missing modules, install regipy using" - f" `pip install regipy[full]` in order to install plugin dependencies. " - f"This might take some time... " + "Plugin `shellbag_plugin` has missing modules, install regipy using" + " `pip install regipy[full]` in order to install plugin dependencies. " + "This might take some time... " ) raise ex diff --git a/regipy/plugins/ntuser/user_assist.py b/regipy/plugins/ntuser/user_assist.py index d943b67..4ef8e26 100644 --- a/regipy/plugins/ntuser/user_assist.py +++ b/regipy/plugins/ntuser/user_assist.py @@ -1,9 +1,8 @@ -import binascii import codecs import logging -from construct import * +from construct import Bytes, Const, ConstError, Int32ul, Int64ul, Struct from regipy.exceptions import RegistryKeyNotFoundException from regipy.hive_types import NTUSER_HIVE_TYPE diff --git a/regipy/plugins/ntuser/winscp_saved_sessions.py b/regipy/plugins/ntuser/winscp_saved_sessions.py index 7b16019..5499f3c 100644 --- a/regipy/plugins/ntuser/winscp_saved_sessions.py +++ b/regipy/plugins/ntuser/winscp_saved_sessions.py @@ -1,7 +1,5 @@ import logging -from inflection import underscore - from regipy import RegistryKeyNotFoundException from regipy.hive_types import NTUSER_HIVE_TYPE from regipy.plugins.plugin import Plugin diff --git a/regipy/plugins/ntuser/word_wheel_query.py b/regipy/plugins/ntuser/word_wheel_query.py index c52ee3c..b255ec3 100644 --- a/regipy/plugins/ntuser/word_wheel_query.py +++ b/regipy/plugins/ntuser/word_wheel_query.py @@ -1,9 +1,6 @@ -import binascii -import codecs - import logging -from construct import * +from construct import CString, GreedyRange, Int32ul from regipy.exceptions import RegistryKeyNotFoundException from regipy.hive_types import NTUSER_HIVE_TYPE diff --git a/regipy/plugins/plugin.py b/regipy/plugins/plugin.py index 8abfb95..72aa1ed 100644 --- a/regipy/plugins/plugin.py +++ b/regipy/plugins/plugin.py @@ -1,6 +1,6 @@ import logging -from typing import Any, Dict, List, Optional +from typing import Any, Dict, List from regipy.registry import RegistryHive diff --git a/regipy/plugins/plugin_template.py b/regipy/plugins/plugin_template.py index f0470e6..d2e02c9 100644 --- a/regipy/plugins/plugin_template.py +++ b/regipy/plugins/plugin_template.py @@ -2,7 +2,6 @@ from regipy.hive_types import NTUSER_HIVE_TYPE from regipy.plugins.plugin import Plugin -from regipy.utils import get_subkey_values_from_list logger = logging.getLogger(__name__) diff --git a/regipy/plugins/software/image_file_execution_options.py b/regipy/plugins/software/image_file_execution_options.py index 72dee0a..c414da5 100644 --- a/regipy/plugins/software/image_file_execution_options.py +++ b/regipy/plugins/software/image_file_execution_options.py @@ -2,7 +2,7 @@ from regipy.hive_types import SOFTWARE_HIVE_TYPE from regipy.plugins.plugin import Plugin -from regipy.utils import get_subkey_values_from_list, convert_wintime +from regipy.utils import convert_wintime logger = logging.getLogger(__name__) diff --git a/regipy/plugins/software/profilelist.py b/regipy/plugins/software/profilelist.py index aa3c823..c2c8516 100644 --- a/regipy/plugins/software/profilelist.py +++ b/regipy/plugins/software/profilelist.py @@ -1,11 +1,8 @@ -import pytz -import datetime import logging -from regipy.exceptions import RegistryKeyNotFoundException, NoRegistryValuesException +from regipy.exceptions import RegistryKeyNotFoundException from regipy.hive_types import SOFTWARE_HIVE_TYPE from regipy.plugins.plugin import Plugin -from regipy.utils import get_subkey_values_from_list from regipy.utils import convert_wintime, convert_filetime diff --git a/regipy/plugins/system/computer_name.py b/regipy/plugins/system/computer_name.py index 320d349..c557995 100644 --- a/regipy/plugins/system/computer_name.py +++ b/regipy/plugins/system/computer_name.py @@ -1,5 +1,4 @@ import logging -import attr from regipy.exceptions import RegistryValueNotFoundException from regipy.hive_types import SYSTEM_HIVE_TYPE @@ -12,7 +11,7 @@ class ComputerNamePlugin(Plugin): - NAME = "computer_name" + NAME: str = "computer_name" DESCRIPTION = "Get the computer name" COMPATIBLE_HIVE = SYSTEM_HIVE_TYPE @@ -31,5 +30,6 @@ def run(self): ), } ) - except RegistryValueNotFoundException as ex: + except RegistryValueNotFoundException: + logger.exception("Could not get computer name") continue diff --git a/regipy/plugins/system/external/ShimCacheParser.py b/regipy/plugins/system/external/ShimCacheParser.py index abea5a8..821e5c3 100755 --- a/regipy/plugins/system/external/ShimCacheParser.py +++ b/regipy/plugins/system/external/ShimCacheParser.py @@ -195,10 +195,10 @@ def get_shimcache_entries(cachebin, as_json=False): # This is a Windows 7/2k8-R2 Shim Cache. elif magic == CACHE_MAGIC_NT6_1: test_size = struct.unpack( - " WIN8_STATS_SIZE - and cachebin[WIN8_STATS_SIZE : WIN8_STATS_SIZE + 4] == WIN8_MAGIC + and cachebin[WIN8_STATS_SIZE: WIN8_STATS_SIZE + 4] == WIN8_MAGIC ): logger.debug("[+] Found Windows 8/2k12 Apphelp Cache data...") yield from read_win8_entries(cachebin, WIN8_MAGIC, as_json=as_json) @@ -236,7 +236,7 @@ def get_shimcache_entries(cachebin, as_json=False): # Windows 8.1 will use a different magic dword, check for it elif ( len(cachebin) > WIN8_STATS_SIZE - and cachebin[WIN8_STATS_SIZE : WIN8_STATS_SIZE + 4] == WIN81_MAGIC + and cachebin[WIN8_STATS_SIZE: WIN8_STATS_SIZE + 4] == WIN81_MAGIC ): logger.debug("[+] Found Windows 8.1 Apphelp Cache data...") yield from read_win8_entries(cachebin, WIN81_MAGIC, as_json=as_json) @@ -244,7 +244,7 @@ def get_shimcache_entries(cachebin, as_json=False): # Windows 10 will use a different magic dword, check for it elif ( len(cachebin) > WIN10_STATS_SIZE - and cachebin[WIN10_STATS_SIZE : WIN10_STATS_SIZE + 4] == WIN10_MAGIC + and cachebin[WIN10_STATS_SIZE: WIN10_STATS_SIZE + 4] == WIN10_MAGIC ): logger.debug("[+] Found Windows 10 Apphelp Cache data...") yield from read_win10_entries(cachebin, WIN10_MAGIC, as_json=as_json) @@ -252,7 +252,7 @@ def get_shimcache_entries(cachebin, as_json=False): # Windows 10 creators update moved the damn magic 4 bytes forward... elif ( len(cachebin) > WIN10_STATS_SIZE - and cachebin[WIN10_STATS_SIZE + 4 : WIN10_STATS_SIZE + 8] == WIN10_MAGIC + and cachebin[WIN10_STATS_SIZE + 4: WIN10_STATS_SIZE + 8] == WIN10_MAGIC ): logger.debug("[+] Found Windows 10 Apphelp Cache data... (creators update)") yield from read_win10_entries( @@ -269,7 +269,6 @@ def get_shimcache_entries(cachebin, as_json=False): def read_win8_entries(bin_data, ver_magic, as_json=False): entry_meta_len = 12 - entry_list = [] # Skip past the stats in the header cache_data = bin_data[WIN8_STATS_SIZE:] @@ -328,11 +327,10 @@ def read_win8_entries(bin_data, ver_magic, as_json=False): def read_win10_entries(bin_data, ver_magic, creators_update=False, as_json=False): entry_meta_len = 12 - entry_list = [] # Skip past the stats in the header if creators_update: - cache_data = bin_data[WIN10_STATS_SIZE + 4 :] + cache_data = bin_data[WIN10_STATS_SIZE + 4:] else: cache_data = bin_data[WIN10_STATS_SIZE:] @@ -377,7 +375,6 @@ def read_win10_entries(bin_data, ver_magic, creators_update=False, as_json=False # Read Windows 2k3/Vista/2k8 Shim Cache entry formats. def read_nt5_entries(bin_data, entry, as_json=False): - entry_list = [] contains_file_size = False entry_size = entry.size() @@ -394,7 +391,7 @@ def read_nt5_entries(bin_data, entry, as_json=False): entry_size, ): - entry.update(bin_data[offset : offset + entry_size]) + entry.update(bin_data[offset: offset + entry_size]) if entry.dw_file_size_low > 3: contains_file_size = True @@ -407,12 +404,12 @@ def read_nt5_entries(bin_data, entry, as_json=False): entry_size, ): - entry.update(bin_data[offset : offset + entry_size]) + entry.update(bin_data[offset: offset + entry_size]) last_mod_date = convert_filetime( entry.dw_low_date_time, entry.dw_high_date_time ) - path = bin_data[entry.offset : entry.offset + entry.w_length].decode( + path = bin_data[entry.offsets: entry.offset + entry.w_length].decode( "utf-16le", "replace" ) @@ -460,11 +457,11 @@ def read_nt6_entries(bin_data, entry, as_json=False): entry_size, ): - entry.update(bin_data[offset : offset + entry_size]) + entry.update(bin_data[offset: offset + entry_size]) last_mod_date = convert_filetime( entry.dw_low_date_time, entry.dw_high_date_time ) - path = bin_data[entry.offset : entry.offset + entry.w_length].decode( + path = bin_data[entry.offset: entry.offset + entry.w_length].decode( "utf-16le", "replace" ) @@ -484,7 +481,6 @@ def read_nt6_entries(bin_data, entry, as_json=False): # Read the WinXP Shim Cache data. Some entries can be missing data but still # contain useful information, so try to get as much as we can. def read_winxp_entries(bin_data, as_json=False): - entry_list = [] num_entries = struct.unpack(" str: diff --git a/regipy/structs.py b/regipy/structs.py index fe78f0a..da704b9 100644 --- a/regipy/structs.py +++ b/regipy/structs.py @@ -1,4 +1,17 @@ -from construct import * +from construct import ( + Array, + Bytes, + Const, + Enum, + FlagsEnum, + Int8ul, + Int16ul, + Int32ul, + Int64ul, + PaddedString, + Struct, + this, +) REGF_HEADER = Struct( "signature" / Const(b"regf"), diff --git a/regipy/utils.py b/regipy/utils.py index 493cdc8..0fe411d 100644 --- a/regipy/utils.py +++ b/regipy/utils.py @@ -196,7 +196,8 @@ def try_decode_binary(data, as_json=False, max_len=MAX_LEN, trim_values=True): except UnicodeDecodeError: try: value = data.decode().rstrip("\x00") - except: + except Exception as ex: + logger.warning(f"Could not parse data as string, formating to hex: {ex}") value = binascii.b2a_hex(data).decode() if as_json else data if trim_values: @@ -212,6 +213,8 @@ def _setup_logging(verbose): ) -def trim_registry_data_for_error_msg(s: str, max_len: int = MAX_LEN_ERR_MSG_REGVALUE) -> str: +def trim_registry_data_for_error_msg( + s: str, max_len: int = MAX_LEN_ERR_MSG_REGVALUE +) -> str: # Registry values included in Registry expections might be arbitrarly large, - return s[:max_len] + f'... (trimmed original value from {len(s)} length)' + return s[:max_len] + f"... (trimmed original value from {len(s)} length)" diff --git a/regipy_tests/__init__.py b/regipy_tests/__init__.py index 7bd66ec..8264303 100644 --- a/regipy_tests/__init__.py +++ b/regipy_tests/__init__.py @@ -1,3 +1,4 @@ +# flake8: noqa from .validation.validation_tests import shimcache_validation from .validation.validation_tests import ntuser_persistence_validation from .validation.validation_tests import software_persistence_validation @@ -30,3 +31,4 @@ from .validation.validation_tests import shell_bag_ntuser_plugin_validation from .validation.validation_tests import shell_bag_usrclass_plugin_validation from .validation.validation_tests import network_data_plugin_validation +from .validation.validation_tests import active_control_set_validation diff --git a/regipy_tests/conftest.py b/regipy_tests/conftest.py index 1f40fb7..da65e91 100644 --- a/regipy_tests/conftest.py +++ b/regipy_tests/conftest.py @@ -1,6 +1,5 @@ import lzma import os -from contextlib import contextmanager from pathlib import Path from tempfile import mktemp diff --git a/regipy_tests/plugin_tests.py b/regipy_tests/plugin_tests.py index 3c64403..dd61e9e 100644 --- a/regipy_tests/plugin_tests.py +++ b/regipy_tests/plugin_tests.py @@ -1,53 +1,50 @@ -import pytest import datetime as dt -from regipy.plugins import ( - NTUserPersistencePlugin, - UserAssistPlugin, - AmCachePlugin, - WordWheelQueryPlugin, - UACStatusPlugin, - LastLogonPlugin, - SoftwareClassesInstallerPlugin, - InstalledProgramsSoftwarePlugin, - RASTracingPlugin, - PrintDemonPlugin, - ServicesPlugin, - NtuserClassesInstallerPlugin, -) -from regipy.registry import RegistryHive -from regipy.plugins.ntuser.typed_urls import TypedUrlsPlugin -from regipy.plugins.ntuser.typed_paths import TypedPathsPlugin -from regipy.plugins.software.profilelist import ProfileListPlugin -from regipy.plugins.software.persistence import SoftwarePersistencePlugin -from regipy.plugins.system.computer_name import ComputerNamePlugin -from regipy.plugins.system.shimcache import ShimCachePlugin -from regipy.plugins.system.bootkey import BootKeyPlugin -from regipy.plugins.system.host_domain_name import HostDomainNamePlugin -from regipy.plugins.sam.local_sid import LocalSidPlugin -from regipy.plugins.security.domain_sid import DomainSidPlugin + +from regipy.plugins.amcache.amcache import AmCachePlugin from regipy.plugins.bcd.boot_entry_list import BootEntryListPlugin -from regipy.plugins.system.wdigest import WDIGESTPlugin -from regipy.plugins.system.usbstor import USBSTORPlugin -from regipy.plugins.ntuser.winrar import WinRARPlugin +from regipy.plugins.ntuser.classes_installer import NtuserClassesInstallerPlugin from regipy.plugins.ntuser.network_drives import NetworkDrivesPlugin +from regipy.plugins.ntuser.persistence import NTUserPersistencePlugin from regipy.plugins.ntuser.shellbags_ntuser import ShellBagNtuserPlugin +from regipy.plugins.ntuser.typed_paths import TypedPathsPlugin +from regipy.plugins.ntuser.typed_urls import TypedUrlsPlugin +from regipy.plugins.ntuser.user_assist import UserAssistPlugin +from regipy.plugins.ntuser.winrar import WinRARPlugin from regipy.plugins.ntuser.winscp_saved_sessions import WinSCPSavedSessionsPlugin -from regipy.plugins.system.network_data import NetworkDataPlugin -from regipy.plugins.usrclass.shellbags_usrclass import ShellBagUsrclassPlugin -from regipy.plugins.software.winver import WinVersionPlugin -from regipy.plugins.system.previous_winver import PreviousWinVersionPlugin -from regipy.plugins.system.shutdown import ShutdownPlugin -from regipy.plugins.system.processor_architecture import ProcessorArchitecturePlugin -from regipy.plugins.system.crash_dump import CrashDumpPlugin -from regipy.plugins.software.susclient import SusclientPlugin -from regipy.plugins.system.disablelastaccess import DisableLastAccessPlugin -from regipy.plugins.system.codepage import CodepagePlugin +from regipy.plugins.ntuser.word_wheel_query import WordWheelQueryPlugin +from regipy.plugins.sam.local_sid import LocalSidPlugin +from regipy.plugins.security.domain_sid import DomainSidPlugin from regipy.plugins.software.disablesr import DisableSRPlugin -from regipy.plugins.system.diag_sr import DiagSRPlugin +from regipy.plugins.software.installed_programs import InstalledProgramsSoftwarePlugin +from regipy.plugins.software.last_logon import LastLogonPlugin +from regipy.plugins.software.persistence import SoftwarePersistencePlugin +from regipy.plugins.software.printdemon import PrintDemonPlugin +from regipy.plugins.software.profilelist import ProfileListPlugin from regipy.plugins.software.spp_clients import SppClientsPlugin +from regipy.plugins.software.susclient import SusclientPlugin +from regipy.plugins.software.tracing import RASTracingPlugin +from regipy.plugins.software.uac import UACStatusPlugin +from regipy.plugins.software.winver import WinVersionPlugin from regipy.plugins.system.backuprestore import BackupRestorePlugin +from regipy.plugins.system.bootkey import BootKeyPlugin +from regipy.plugins.system.codepage import CodepagePlugin +from regipy.plugins.system.computer_name import ComputerNamePlugin +from regipy.plugins.system.crash_dump import CrashDumpPlugin +from regipy.plugins.system.diag_sr import DiagSRPlugin +from regipy.plugins.system.disablelastaccess import DisableLastAccessPlugin +from regipy.plugins.system.host_domain_name import HostDomainNamePlugin +from regipy.plugins.system.network_data import NetworkDataPlugin +from regipy.plugins.system.previous_winver import PreviousWinVersionPlugin +from regipy.plugins.system.processor_architecture import ProcessorArchitecturePlugin +from regipy.plugins.system.services import ServicesPlugin +from regipy.plugins.system.shimcache import ShimCachePlugin +from regipy.plugins.system.shutdown import ShutdownPlugin from regipy.plugins.system.timezone_data2 import TimezoneDataPlugin2 -from regipy.plugins.system.bam import BAMPlugin +from regipy.plugins.system.usbstor import USBSTORPlugin +from regipy.plugins.system.wdigest import WDIGESTPlugin +from regipy.plugins.usrclass.shellbags_usrclass import ShellBagUsrclassPlugin +from regipy.registry import RegistryHive + def test_shimcache_plugin(system_hive): registry_hive = RegistryHive(system_hive) @@ -56,23 +53,20 @@ def test_shimcache_plugin(system_hive): assert len(plugin_instance.entries) == 660 assert plugin_instance.entries[0] == { - 'last_mod_date': '2011-01-12T12:08:00+00:00', - 'path': '\\??\\C:\\Program Files\\McAfee\\VirusScan Enterprise\\mfeann.exe', - 'exec_flag': 'True' + "last_mod_date": "2011-01-12T12:08:00+00:00", + "path": "\\??\\C:\\Program Files\\McAfee\\VirusScan Enterprise\\mfeann.exe", + "exec_flag": "True", } + def test_computer_name_plugin(system_hive): registry_hive = RegistryHive(system_hive) plugin_instance = ComputerNamePlugin(registry_hive, as_json=True) plugin_instance.run() assert plugin_instance.entries == [ - {'name': 'WKS-WIN732BITA', - 'timestamp': '2010-11-10T17:18:08.718750+00:00' - }, - {'name': 'WIN-V5T3CSP8U4H', - 'timestamp': '2010-11-10T18:17:36.968750+00:00' - } + {"name": "WKS-WIN732BITA", "timestamp": "2010-11-10T17:18:08.718750+00:00"}, + {"name": "WIN-V5T3CSP8U4H", "timestamp": "2010-11-10T18:17:36.968750+00:00"}, ] @@ -82,14 +76,16 @@ def test_persistence_plugin_ntuser(ntuser_hive): plugin_instance.run() assert plugin_instance.entries == { - '\\Software\\Microsoft\\Windows\\CurrentVersion\\Run': { - 'timestamp': '2012-04-03T21:19:54.837716+00:00', - 'values': [ - {'name': 'Sidebar', - 'value_type': 'REG_EXPAND_SZ', - 'value': '%ProgramFiles%\\Windows Sidebar\\Sidebar.exe /autoRun', 'is_corrupted': False - } - ] + "\\Software\\Microsoft\\Windows\\CurrentVersion\\Run": { + "timestamp": "2012-04-03T21:19:54.837716+00:00", + "values": [ + { + "name": "Sidebar", + "value_type": "REG_EXPAND_SZ", + "value": "%ProgramFiles%\\Windows Sidebar\\Sidebar.exe /autoRun", + "is_corrupted": False, + } + ], } } @@ -100,53 +96,53 @@ def test_persistence_plugin_software(software_hive): plugin_instance.run() assert plugin_instance.entries == { - '\\Microsoft\\Windows\\CurrentVersion\\Run': - {'timestamp': '2012-04-04T01:54:23.669836+00:00', - 'values': [ - { - 'name': 'VMware Tools', - 'value_type': 'REG_SZ', - 'value': '"C:\\Program Files\\VMware\\VMware Tools\\VMwareTray.exe"', - 'is_corrupted': False - }, - { - 'name': 'VMware User Process', - 'value_type': 'REG_SZ', - 'value': '"C:\\Program Files\\VMware\\VMware Tools\\VMwareUser.exe"', - 'is_corrupted': False - }, - { - 'name': 'Adobe ARM', - 'value_type': 'REG_SZ', - 'value': '"C:\\Program Files\\Common Files\\Adobe\\ARM\\1.0\\AdobeARM.exe"', - 'is_corrupted': False - }, - { - 'name': 'McAfeeUpdaterUI', - 'value_type': 'REG_SZ', - 'value': '"C:\\Program Files\\McAfee\\Common Framework\\udaterui.exe" /StartedFromRunKey', - 'is_corrupted': False - }, - { - 'name': 'ShStatEXE', - 'value_type': 'REG_SZ', - 'value': '"C:\\Program Files\\McAfee\\VirusScan Enterprise\\SHSTAT.EXE" /STANDALONE', - 'is_corrupted': False - }, - { - 'name': 'McAfee Host Intrusion Prevention Tray', - 'value_type': 'REG_SZ', - 'value': '"C:\\Program Files\\McAfee\\Host Intrusion Prevention\\FireTray.exe"', - 'is_corrupted': False - }, - { - 'name': 'svchost', - 'value_type': 'REG_SZ', - 'value': 'c:\\windows\\system32\\dllhost\\svchost.exe', - 'is_corrupted': False - } - ] - } + "\\Microsoft\\Windows\\CurrentVersion\\Run": { + "timestamp": "2012-04-04T01:54:23.669836+00:00", + "values": [ + { + "name": "VMware Tools", + "value_type": "REG_SZ", + "value": '"C:\\Program Files\\VMware\\VMware Tools\\VMwareTray.exe"', + "is_corrupted": False, + }, + { + "name": "VMware User Process", + "value_type": "REG_SZ", + "value": '"C:\\Program Files\\VMware\\VMware Tools\\VMwareUser.exe"', + "is_corrupted": False, + }, + { + "name": "Adobe ARM", + "value_type": "REG_SZ", + "value": '"C:\\Program Files\\Common Files\\Adobe\\ARM\\1.0\\AdobeARM.exe"', + "is_corrupted": False, + }, + { + "name": "McAfeeUpdaterUI", + "value_type": "REG_SZ", + "value": '"C:\\Program Files\\McAfee\\Common Framework\\udaterui.exe" /StartedFromRunKey', + "is_corrupted": False, + }, + { + "name": "ShStatEXE", + "value_type": "REG_SZ", + "value": '"C:\\Program Files\\McAfee\\VirusScan Enterprise\\SHSTAT.EXE" /STANDALONE', + "is_corrupted": False, + }, + { + "name": "McAfee Host Intrusion Prevention Tray", + "value_type": "REG_SZ", + "value": '"C:\\Program Files\\McAfee\\Host Intrusion Prevention\\FireTray.exe"', + "is_corrupted": False, + }, + { + "name": "svchost", + "value_type": "REG_SZ", + "value": "c:\\windows\\system32\\dllhost\\svchost.exe", + "is_corrupted": False, + }, + ], + } } @@ -157,21 +153,21 @@ def test_user_assist_plugin_ntuser(ntuser_hive): assert len(plugin_instance.entries) == 62 assert plugin_instance.entries[-1] == { - 'focus_count': 1, - 'name': '%PROGRAMFILES(X86)%\\Microsoft Office\\Office14\\EXCEL.EXE', - 'run_counter': 4, - 'session_id': 0, - 'timestamp': '2012-04-04T15:43:14.785000+00:00', - 'total_focus_time_ms': 47673 + "focus_count": 1, + "name": "%PROGRAMFILES(X86)%\\Microsoft Office\\Office14\\EXCEL.EXE", + "run_counter": 4, + "session_id": 0, + "timestamp": "2012-04-04T15:43:14.785000+00:00", + "total_focus_time_ms": 47673, } assert plugin_instance.entries[50] == { - 'focus_count': 9, - 'name': 'Microsoft.Windows.RemoteDesktop', - 'run_counter': 8, - 'session_id': 0, - 'timestamp': '2012-04-03T22:06:58.124282+00:00', - 'total_focus_time_ms': 180000 + "focus_count": 9, + "name": "Microsoft.Windows.RemoteDesktop", + "run_counter": 8, + "session_id": 0, + "timestamp": "2012-04-03T22:06:58.124282+00:00", + "total_focus_time_ms": 180000, } @@ -182,11 +178,11 @@ def test_plugin_amcache(amcache_hive): assert len(plugin_instance.entries) == 1367 assert plugin_instance.entries[100] == { - 'full_path': 'C:\\Windows\\system32\\TPVMMondeu.dll', - 'last_modified_timestamp_2': '2017-03-17T05:06:04.002722+00:00', - 'program_id': '75a010066bb612ca7357ce31df8e9f0300000904', - 'sha1': '056f4b9d9ec9b5dc548e1b460da889e44089d76f', - 'timestamp': '2017-08-03T11:34:02.263418+00:00' + "full_path": "C:\\Windows\\system32\\TPVMMondeu.dll", + "last_modified_timestamp_2": "2017-03-17T05:06:04.002722+00:00", + "program_id": "75a010066bb612ca7357ce31df8e9f0300000904", + "sha1": "056f4b9d9ec9b5dc548e1b460da889e44089d76f", + "timestamp": "2017-08-03T11:34:02.263418+00:00", } @@ -197,10 +193,10 @@ def test_word_wheel_query_plugin_ntuser(ntuser_hive): assert len(plugin_instance.entries) == 6 assert plugin_instance.entries[0] == { - 'last_write': '2012-04-04T15:45:18.551340+00:00', - 'mru_id': 1, - 'name': 'alloy', - 'order': 0 + "last_write": "2012-04-04T15:45:18.551340+00:00", + "mru_id": 1, + "name": "alloy", + "order": 0, } @@ -210,12 +206,12 @@ def test_uac_status_plugin_software(software_hive): plugin_instance.run() assert plugin_instance.entries == { - 'consent_prompt_admin': 5, - 'consent_prompt_user': 3, - 'enable_limited_user_accounts': 1, - 'enable_virtualization': 1, - 'filter_admin_token': 0, - 'last_write': '2011-08-30T18:47:10.734144+00:00' + "consent_prompt_admin": 5, + "consent_prompt_user": 3, + "enable_limited_user_accounts": 1, + "enable_virtualization": 1, + "filter_admin_token": 0, + "last_write": "2011-08-30T18:47:10.734144+00:00", } @@ -225,13 +221,13 @@ def test_classes_installer_plugin_ntuser(ntuser_hive_2): plugin_instance.run() assert plugin_instance.entries[0] == { - 'identifier': '8A4152964845CF540BEAEBD27F7A8519', - 'timestamp': '2022-02-15T07:00:07.245646+00:00', - 'product_name': 'Microsoft Visual C++ Compiler Package for Python 2.7', - 'is_hidden': False + "identifier": "8A4152964845CF540BEAEBD27F7A8519", + "timestamp": "2022-02-15T07:00:07.245646+00:00", + "product_name": "Microsoft Visual C++ Compiler Package for Python 2.7", + "is_hidden": False, } - assert not any([x['is_hidden'] for x in plugin_instance.entries]) + assert not any([x["is_hidden"] for x in plugin_instance.entries]) def test_ras_tracing_plugin_software(software_hive): @@ -889,8 +885,10 @@ def test_network_data_plugin(system_hive): registry_hive = RegistryHive(system_hive) plugin_instance = NetworkDataPlugin(registry_hive, as_json=True) plugin_instance.run() - - assert plugin_instance.entries["\\ControlSet001\\Services\\Tcpip\\Parameters\\Interfaces"]["interfaces"][0] == { + + assert plugin_instance.entries[ + "\\ControlSet001\\Services\\Tcpip\\Parameters\\Interfaces" + ]["interfaces"][0] == { "interface_name": "{698E50A9-4F58-4D86-B61D-F42E58DCACF6}", "last_modified": "2011-09-17T13:43:23.770078+00:00", "dhcp_enabled": False, @@ -907,7 +905,7 @@ def test_win_version_plugin(software_hive): plugin_instance = WinVersionPlugin(registry_hive, as_json=True) plugin_instance.run() - assert plugin_instance.entries['\\Microsoft\\Windows NT\\CurrentVersion'] == { + assert plugin_instance.entries["\\Microsoft\\Windows NT\\CurrentVersion"] == { "BuildLab": "7601.win7sp1_gdr.111118-2330", "BuildLabEx": "7601.17727.x86fre.win7sp1_gdr.111118-2330", "CSDVersion": "Service Pack 1", @@ -921,14 +919,15 @@ def test_win_version_plugin(software_hive): "ProductId": "00426-067-1817155-86250", "ProductName": "Windows 7 Ultimate", "RegisteredOrganization": 0, - "RegisteredOwner": "Windows User" - } + "RegisteredOwner": "Windows User", + } + def test_previous_win_version_plugin(system_hive_with_filetime): registry_hive = RegistryHive(system_hive_with_filetime) plugin_instance = PreviousWinVersionPlugin(registry_hive, as_json=True) plugin_instance.run() - + # work with SYSTEM_WIN_10_1709 HIVE assert plugin_instance.entries == [ { @@ -946,7 +945,7 @@ def test_previous_win_version_plugin(system_hive_with_filetime): "ProductName": "Windows 10 Pro", "RegisteredOrganization": 0, "RegisteredOwner": "Windows User", - "update_date": "2019-01-06 02:18:37" + "update_date": "2019-01-06 02:18:37", }, { "BuildLab": "17134.rs4_release.180410-1804", @@ -963,10 +962,11 @@ def test_previous_win_version_plugin(system_hive_with_filetime): "ProductName": "Windows 10 Pro", "RegisteredOrganization": 0, "RegisteredOwner": "Windows User", - "update_date": "2019-05-16 00:55:20" - } + "update_date": "2019-05-16 00:55:20", + }, ] + def test_shutdown_plugin(system_hive): registry_hive = RegistryHive(system_hive) plugin_instance = ShutdownPlugin(registry_hive, as_json=True) @@ -975,75 +975,85 @@ def test_shutdown_plugin(system_hive): assert plugin_instance.entries == { "\\ControlSet001\\Control\\Windows": { "date": "2012-04-04 01:58:40", - "last_write": "2012-04-04T01:58:40.839250+00:00" + "last_write": "2012-04-04T01:58:40.839250+00:00", }, "\\ControlSet002\\Control\\Windows": { "date": "2012-04-04 01:58:40", - "last_write": "2012-04-04T01:58:40.839250+00:00" - } + "last_write": "2012-04-04T01:58:40.839250+00:00", + }, } + def test_processor_architecture_plugin(system_hive): registry_hive = RegistryHive(system_hive) plugin_instance = ProcessorArchitecturePlugin(registry_hive, as_json=True) plugin_instance.run() - assert plugin_instance.entries['\\ControlSet001\\Control\\Session Manager\\Environment'] == { + assert plugin_instance.entries[ + "\\ControlSet001\\Control\\Session Manager\\Environment" + ] == { "NUMBER_OF_PROCESSORS": 49, "PROCESSOR_ARCHITECTURE": "x86", "PROCESSOR_IDENTIFIER": "x86 Family 16 Model 8 Stepping 0, AuthenticAMD", - "PROCESSOR_REVISION": "0800" + "PROCESSOR_REVISION": "0800", } - + + def test_crash_dump_plugin(system_hive): registry_hive = RegistryHive(system_hive) plugin_instance = CrashDumpPlugin(registry_hive, as_json=True) plugin_instance.run() - assert plugin_instance.entries['\\ControlSet001\\Control\\CrashControl'] == { + assert plugin_instance.entries["\\ControlSet001\\Control\\CrashControl"] == { "CrashDumpEnabled": 2, "CrashDumpEnabledStr": "Kernel memory dump", "DumpFile": "%SystemRoot%\\MEMORY.DMP", "last_write": "2012-04-04T11:47:36.984376+00:00", "LogEvent": 1, - "MinidumpDir": "%SystemRoot%\\Minidump" + "MinidumpDir": "%SystemRoot%\\Minidump", } - + + def test_susclient_plugin(software_hive): registry_hive = RegistryHive(software_hive) plugin_instance = SusclientPlugin(registry_hive, as_json=True) plugin_instance.run() - assert plugin_instance.entries['\\Microsoft\\Windows\\CurrentVersion\\WindowsUpdate'] == { + assert plugin_instance.entries[ + "\\Microsoft\\Windows\\CurrentVersion\\WindowsUpdate" + ] == { "last_write": "2012-03-14T07:05:41.719626+00:00", "LastRestorePointSetTime": "2012-03-14 07:05:41", "SusClientId": "50df98f2-964a-496d-976d-d95296e13929", - "SusClientIdValidation": "" + "SusClientIdValidation": "", } - + + def test_disable_last_access_plugin(system_hive_with_filetime): registry_hive = RegistryHive(system_hive_with_filetime) plugin_instance = DisableLastAccessPlugin(registry_hive, as_json=True) plugin_instance.run() # work with SYSTEM_WIN_10_1709 HIVE - assert plugin_instance.entries['\\ControlSet001\\Control\\FileSystem'] == { + assert plugin_instance.entries["\\ControlSet001\\Control\\FileSystem"] == { "last_write": "2020-02-13T11:59:20.987114+00:00", "NtfsDisableLastAccessUpdate": "80000003", - "NtfsDisableLastAccessUpdateStr": "(System Managed, Updates Disabled)" + "NtfsDisableLastAccessUpdateStr": "(System Managed, Updates Disabled)", } - + + def test_code_page_plugin(system_hive_with_filetime): registry_hive = RegistryHive(system_hive_with_filetime) plugin_instance = CodepagePlugin(registry_hive, as_json=True) plugin_instance.run() # work with SYSTEM_WIN_10_1709 HIVE - assert plugin_instance.entries['\\ControlSet001\\Control\\Nls\\CodePage'] == { + assert plugin_instance.entries["\\ControlSet001\\Control\\Nls\\CodePage"] == { "ACP": "1252", - "last_write": "2019-05-16T08:22:00.160628+00:00" + "last_write": "2019-05-16T08:22:00.160628+00:00", } - + + def test_disable_sr_plugin(software_hive): registry_hive = RegistryHive(software_hive) plugin_instance = DisableSRPlugin(registry_hive, as_json=True) @@ -1054,18 +1064,22 @@ def test_disable_sr_plugin(software_hive): "last_write": "2012-03-31T04:00:23.006648+00:00" } } - + + def test_diag_sr_plugin(system_hive): registry_hive = RegistryHive(system_hive) plugin_instance = DiagSRPlugin(registry_hive, as_json=True) plugin_instance.run() - assert plugin_instance.entries['\\ControlSet001\\Services\\VSS\\Diag\\SystemRestore'] == { + assert plugin_instance.entries[ + "\\ControlSet001\\Services\\VSS\\Diag\\SystemRestore" + ] == { "last_write": "2012-03-31T04:00:22.998834+00:00", "SrCreateRp (Enter)": "2012-03-31 04:00:01", - "SrCreateRp (Leave)": "2012-03-31 04:00:22" + "SrCreateRp (Leave)": "2012-03-31 04:00:22", } - + + def test_spp_clients_plugin(software_hive): registry_hive = RegistryHive(software_hive) plugin_instance = SppClientsPlugin(registry_hive, as_json=True) @@ -1076,10 +1090,11 @@ def test_spp_clients_plugin(software_hive): "{09F7EDC5-294E-4180-AF6A-FB0E6A0E9513}": [ "\\\\?\\Volume{656b1715-ecf6-11df-92e6-806e6f6e6963}\\:(C:)" ], - "last_write": "2012-03-15T22:32:18.089574+00:00" + "last_write": "2012-03-15T22:32:18.089574+00:00", } } - + + def test_backup_restore_plugin(system_hive_with_filetime): registry_hive = RegistryHive(system_hive_with_filetime) plugin_instance = BackupRestorePlugin(registry_hive, as_json=True) @@ -1088,12 +1103,8 @@ def test_backup_restore_plugin(system_hive_with_filetime): # work with SYSTEM_WIN_10_1709 HIVE assert plugin_instance.entries == { "\\ControlSet001\\Control\\BackupRestore\\FilesNotToBackup": { - "BITS_metadata": [ - "%ProgramData%\\Microsoft\\Network\\Downloader\\* /s" - ], - "ETW": [ - "%SystemRoot%\\system32\\LogFiles\\WMI\\RtBackup\\*.*" - ], + "BITS_metadata": ["%ProgramData%\\Microsoft\\Network\\Downloader\\* /s"], + "ETW": ["%SystemRoot%\\system32\\LogFiles\\WMI\\RtBackup\\*.*"], "FVE_Control": [ "\\System Volume Information\\FVE.{e40ad34d-dae9-4bc7-95bd-b16218c10f72}.*" ], @@ -1121,36 +1132,24 @@ def test_backup_restore_plugin(system_hive_with_filetime): "FVE2_WipeX": [ "\\System Volume Information\\FVE2.{9ef82dfa-1239-4a30-83e6-3b3e9b8fed08}.*" ], - "Internet Explorer": [ - "%UserProfile%\\index.dat /s" - ], + "Internet Explorer": ["%UserProfile%\\index.dat /s"], "Kernel Dumps": [ "%systemroot%\\Minidump\\* /s", - "%systemroot%\\memory.dmp" + "%systemroot%\\memory.dmp", ], "last_write": "2019-05-16T08:21:59.973146+00:00", - "Memory Page File": [ - "\\Pagefile.sys" - ], + "Memory Page File": ["\\Pagefile.sys"], "Mount Manager": [ "\\System Volume Information\\MountPointManagerRemoteDatabase" ], "MS Distributed Transaction Coordinator": [ "C:\\Windows\\system32\\MSDtc\\MSDTC.LOG", - "C:\\Windows\\system32\\MSDtc\\trace\\dtctrace.log" - ], - "Netlogon": [ - "%SystemRoot%\\netlogon.chg" - ], - "Power Management": [ - "\\hiberfil.sys" - ], - "Storage Tiers Management": [ - "\\System Volume Information\\Heat\\*.* /s" - ], - "Temporary Files": [ - "%TEMP%\\* /s" + "C:\\Windows\\system32\\MSDtc\\trace\\dtctrace.log", ], + "Netlogon": ["%SystemRoot%\\netlogon.chg"], + "Power Management": ["\\hiberfil.sys"], + "Storage Tiers Management": ["\\System Volume Information\\Heat\\*.* /s"], + "Temporary Files": ["%TEMP%\\* /s"], "VSS Default Provider": [ "\\System Volume Information\\*{3808876B-C176-4e48-B7AE-04046E6CC752} /s" ], @@ -1160,12 +1159,8 @@ def test_backup_restore_plugin(system_hive_with_filetime): "VSS Service DB": [ "\\System Volume Information\\*.{7cc467ef-6865-4831-853f-2a4817fd1bca}DB" ], - "WER": [ - "%ProgramData%\\Microsoft\\Windows\\WER\\* /s" - ], - "WUA": [ - "%windir%\\softwaredistribution\\*.* /s" - ] + "WER": ["%ProgramData%\\Microsoft\\Windows\\WER\\* /s"], + "WUA": ["%windir%\\softwaredistribution\\*.* /s"], }, "\\ControlSet001\\Control\\BackupRestore\\FilesNotToSnapshot": { "FVE": [ @@ -1179,29 +1174,21 @@ def test_backup_restore_plugin(system_hive_with_filetime): ], "last_write": "2020-02-13T08:47:50.455600+00:00", "ModernOutlookOAB": [ - "$UserProfile$\\AppData\\Local\\Packages\\Microsoft.Office.Desktop_8wekyb3d8bbwe\\LocalCache\\Local\\Microsoft\\Outlook\\*.oab /s" + "$UserProfile$\\AppData\\Local\\Packages\\Microsoft.Office." + "Desktop_8wekyb3d8bbwe\\LocalCache\\Local\\Microsoft\\Outlook\\*.oab /s" ], "ModernOutlookOST": [ - "$UserProfile$\\AppData\\Local\\Packages\\Microsoft.Office.Desktop_8wekyb3d8bbwe\\LocalCache\\Local\\Microsoft\\Outlook\\*.ost /s" - ], - "OutlookOST": [ - "$UserProfile$\\AppData\\Local\\Microsoft\\Outlook\\*.ost" + "$UserProfile$\\AppData\\Local\\Packages\\Microsoft.Office." + "Desktop_8wekyb3d8bbwe\\LocalCache\\Local\\Microsoft\\Outlook\\*.ost /s" ], - "Storage Tiers Management": [ - "\\System Volume Information\\Heat\\*.* /s" - ], - "TSBACKUP": [ - "C:\\ProgramData\\FLEXnet\\*.* /s" - ], - "WUA": [ - "%windir%\\softwaredistribution\\*.* /s" - ] + "OutlookOST": ["$UserProfile$\\AppData\\Local\\Microsoft\\Outlook\\*.ost"], + "Storage Tiers Management": ["\\System Volume Information\\Heat\\*.* /s"], + "TSBACKUP": ["C:\\ProgramData\\FLEXnet\\*.* /s"], + "WUA": ["%windir%\\softwaredistribution\\*.* /s"], }, "\\ControlSet001\\Control\\BackupRestore\\KeysNotToRestore": { "last_write": "2019-05-16T08:21:59.973146+00:00", - "Mount Manager": [ - "MountedDevices\\" - ], + "Mount Manager": ["MountedDevices\\"], "MS Distributed Transaction Coordinator": [ "CurrentControlSet\\Control\\MSDTC\\ASR\\" ], @@ -1213,17 +1200,18 @@ def test_backup_restore_plugin(system_hive_with_filetime): ], "Session Manager": [ "CurrentControlSet\\Control\\Session Manager\\AllowProtectedRenames" - ] - } + ], + }, } - + + def test_timezone_data2_plugin(system_hive_with_filetime): registry_hive = RegistryHive(system_hive_with_filetime) plugin_instance = TimezoneDataPlugin2(registry_hive, as_json=True) plugin_instance.run() # work with SYSTEM_WIN_10_1709 HIVE - assert plugin_instance.entries['\\ControlSet001\\Control\\TimeZoneInformation'] == { + assert plugin_instance.entries["\\ControlSet001\\Control\\TimeZoneInformation"] == { "ActiveTimeBias": 420, "Bias": 480, "DaylightBias": -60, @@ -1234,6 +1222,5 @@ def test_timezone_data2_plugin(system_hive_with_filetime): "StandardBias": 0, "StandardName": "@tzres.dll,-212", "StandardStart": "00000b00010002000000000000000000", - "TimeZoneKeyName": "Pacific Standard Time" + "TimeZoneKeyName": "Pacific Standard Time", } - \ No newline at end of file diff --git a/regipy_tests/profiling.py b/regipy_tests/profiling.py index 79505be..d30b035 100644 --- a/regipy_tests/profiling.py +++ b/regipy_tests/profiling.py @@ -1,3 +1,4 @@ +# flake8: noqa import cProfile import io import lzma diff --git a/regipy_tests/tests.py b/regipy_tests/tests.py index 1ffc787..f6e047e 100644 --- a/regipy_tests/tests.py +++ b/regipy_tests/tests.py @@ -2,7 +2,6 @@ import os from tempfile import mkdtemp -import pytest from regipy import NoRegistrySubkeysException from regipy.hive_types import NTUSER_HIVE_TYPE @@ -99,12 +98,6 @@ def test_find_keys_partial_ntuser_hive(ntuser_software_partial): assert values[0].value_type == "REG_SZ" -def test_ntuser_timeline(ntuser_hive): - registry_hive = RegistryHive(ntuser_hive) - # TODO - pass - - def test_regdiff(ntuser_hive, second_hive_path): found_differences = compare_hives(ntuser_hive, second_hive_path, verbose=True) assert len(found_differences) == 7 @@ -364,7 +357,8 @@ def test_parse_security_info(ntuser_hive): def test_parse_filetime_value(system_hive_with_filetime): registry_hive = RegistryHive(system_hive_with_filetime) subkey = registry_hive.get_key( - r"\ControlSet001\Enum\USBSTOR\Disk&Ven_SanDisk&Prod_Cruzer&Rev_1.20\200608767007B7C08A6A&0\Properties\{83da6326-97a6-4088-9453-a1923f573b29}\0064" + r"\ControlSet001\Enum\USBSTOR\Disk&Ven_SanDisk&Prod_Cruzer&Rev_1.2" + r"0\200608767007B7C08A6A&0\Properties\{83da6326-97a6-4088-9453-a1923f573b29}\0064" ) val = subkey.get_value("(default)", as_json=True) assert val == "2020-03-17T14:02:38.955490+00:00" diff --git a/regipy_tests/validation/plugin_validation.md b/regipy_tests/validation/plugin_validation.md index cf92ad6..1b36a2d 100644 --- a/regipy_tests/validation/plugin_validation.md +++ b/regipy_tests/validation/plugin_validation.md @@ -3,51 +3,64 @@ ## Plugins with validation -| plugin_name | plugin_class_name | test_case_name | success | -|-------------------------------|---------------------------------|-----------------------------------------------|-----------| -| amcache | AmCachePlugin | AmCachePluginValidationCase | True | -| background_activity_moderator | BAMPlugin | BamValidationCase | True | -| boot_entry_list | BootEntryListPlugin | BootEntryListPluginValidationCase | True | -| bootkey | BootKeyPlugin | BootKeyPluginValidationCase | True | -| computer_name | ComputerNamePlugin | ComputerNamePluginValidationCase | True | -| domain_sid | DomainSidPlugin | DomainSidPluginValidationCase | True | -| host_domain_name | HostDomainNamePlugin | HostDomainNamePluginValidationCase | True | -| installed_programs_software | InstalledProgramsSoftwarePlugin | InstalledProgramsSoftwarePluginValidationCase | True | -| last_logon_plugin | LastLogonPlugin | LastLogonPluginValidationCase | True | -| local_sid | LocalSidPlugin | LocalSidPluginValidationCase | True | -| network_data | NetworkDataPlugin | NetworkDataPluginValidationCase | True | -| network_drives_plugin | NetworkDrivesPlugin | NetworkDrivesPluginValidationCase | True | -| ntuser_classes_installer | NtuserClassesInstallerPlugin | NtuserClassesInstallerPluginValidationCase | True | -| ntuser_persistence | NTUserPersistencePlugin | NTUserPersistenceValidationCase | True | -| ntuser_shellbag_plugin | ShellBagNtuserPlugin | ShellBagNtuserPluginValidationCase | True | -| print_demon_plugin | PrintDemonPlugin | PrintDemonPluginValidationCase | True | -| profilelist_plugin | ProfileListPlugin | ProfileListPluginValidationCase | True | -| ras_tracing | RASTracingPlugin | RASTracingPluginValidationCase | True | -| services | ServicesPlugin | ServicesPluginValidationCase | True | -| shimcache | ShimCachePlugin | AmCacheValidationCase | True | -| software_classes_installer | SoftwareClassesInstallerPlugin | SoftwareClassesInstallerPluginValidationCase | True | -| software_plugin | SoftwarePersistencePlugin | SoftwarePersistenceValidationCase | True | -| typed_paths | TypedPathsPlugin | TypedPathsPluginValidationCase | True | -| typed_urls | TypedUrlsPlugin | TypedUrlsPluginValidationCase | True | -| uac_plugin | UACStatusPlugin | UACStatusPluginValidationCase | True | -| usbstor_plugin | USBSTORPlugin | USBSTORPluginValidationCase | True | -| user_assist | UserAssistPlugin | NTUserUserAssistValidationCase | True | -| usrclass_shellbag_plugin | ShellBagUsrclassPlugin | ShellBagUsrclassPluginValidationCase | True | -| wdigest | WDIGESTPlugin | WDIGESTPluginValidationCase | True | -| winrar_plugin | WinRARPlugin | WinRARPluginValidationCase | True | -| winscp_saved_sessions | WinSCPSavedSessionsPlugin | WinSCPSavedSessionsPluginValidationCase | True | -| word_wheel_query | WordWheelQueryPlugin | WordWheelQueryPluginValidationCase | True | +| plugin_name | plugin_description | plugin_class_name | test_case_name | success | +|-------------------------------|-----------------------------------------------------------------------------------|---------------------------------|-----------------------------------------------|-----------| +| active_control_set | Get information on SYSTEM hive control sets | ActiveControlSetPlugin | ActiveControlSetPluginValidationCase | True | +| amcache | Parse Amcache | AmCachePlugin | AmCachePluginValidationCase | True | +| background_activity_moderator | Get the computer name | BAMPlugin | BamValidationCase | True | +| boot_entry_list | List the Windows BCD boot entries | BootEntryListPlugin | BootEntryListPluginValidationCase | True | +| bootkey | Get the Windows boot key | BootKeyPlugin | BootKeyPluginValidationCase | True | +| computer_name | Get the computer name | ComputerNamePlugin | ComputerNamePluginValidationCase | True | +| domain_sid | Get the machine domain name and SID | DomainSidPlugin | DomainSidPluginValidationCase | True | +| host_domain_name | Get the computer host and domain names | HostDomainNamePlugin | HostDomainNamePluginValidationCase | True | +| installed_programs_software | Retrieve list of installed programs and their install date from the SOFTWARE Hive | InstalledProgramsSoftwarePlugin | InstalledProgramsSoftwarePluginValidationCase | True | +| last_logon_plugin | Get the last logged on username | LastLogonPlugin | LastLogonPluginValidationCase | True | +| local_sid | Get the machine local SID | LocalSidPlugin | LocalSidPluginValidationCase | True | +| network_data | Get network data from many interfaces | NetworkDataPlugin | NetworkDataPluginValidationCase | True | +| network_drives_plugin | Parse the user's mapped network drives | NetworkDrivesPlugin | NetworkDrivesPluginValidationCase | True | +| ntuser_classes_installer | List of installed software from NTUSER hive | NtuserClassesInstallerPlugin | NtuserClassesInstallerPluginValidationCase | True | +| ntuser_persistence | Retrieve values from known persistence subkeys in NTUSER hive | NTUserPersistencePlugin | NTUserPersistenceValidationCase | True | +| ntuser_shellbag_plugin | Parse NTUSER Shellbag items | ShellBagNtuserPlugin | ShellBagNtuserPluginValidationCase | True | +| print_demon_plugin | Get list of installed printer ports, as could be taken advantage by cve-2020-1048 | PrintDemonPlugin | PrintDemonPluginValidationCase | True | +| profilelist_plugin | Parses information about user profiles found in the ProfileList key | ProfileListPlugin | ProfileListPluginValidationCase | True | +| ras_tracing | Retrieve list of executables using ras | RASTracingPlugin | RASTracingPluginValidationCase | True | +| services | Enumerate the services in the SYSTEM hive | ServicesPlugin | ServicesPluginValidationCase | True | +| shimcache | Parse Shimcache artifact | ShimCachePlugin | AmCacheValidationCase | True | +| software_classes_installer | List of installed software from SOFTWARE hive | SoftwareClassesInstallerPlugin | SoftwareClassesInstallerPluginValidationCase | True | +| software_plugin | Retrieve values from known persistence subkeys in Software hive | SoftwarePersistencePlugin | SoftwarePersistenceValidationCase | True | +| typed_paths | Retrieve the typed Paths from the history | TypedPathsPlugin | TypedPathsPluginValidationCase | True | +| typed_urls | Retrieve the typed URLs from IE history | TypedUrlsPlugin | TypedUrlsPluginValidationCase | True | +| uac_plugin | Get the status of User Access Control | UACStatusPlugin | UACStatusPluginValidationCase | True | +| usbstor_plugin | Parse the connected USB devices history | USBSTORPlugin | USBSTORPluginValidationCase | True | +| user_assist | Parse User Assist artifact | UserAssistPlugin | NTUserUserAssistValidationCase | True | +| usrclass_shellbag_plugin | Parse USRCLASS Shellbag items | ShellBagUsrclassPlugin | ShellBagUsrclassPluginValidationCase | True | +| wdigest | Get WDIGEST configuration | WDIGESTPlugin | WDIGESTPluginValidationCase | True | +| winrar_plugin | Parse the WinRAR archive history | WinRARPlugin | WinRARPluginValidationCase | True | +| winscp_saved_sessions | Retrieve list of WinSCP saved sessions | WinSCPSavedSessionsPlugin | WinSCPSavedSessionsPluginValidationCase | True | +| word_wheel_query | Parse the word wheel query artifact | WordWheelQueryPlugin | WordWheelQueryPluginValidationCase | True | ## Plugins without validation **Please note that in the future, this check will be enforced for all plugins** -| plugin_name | plugin_class_name | test_case_name | success | -|------------------------------|-------------------------------|------------------|-----------| -| active_control_set | ActiveControlSetPlugin | | False | -| image_file_execution_options | ImageFileExecutionOptions | | False | -| installed_programs_ntuser | InstalledProgramsNTUserPlugin | | False | -| routes | RoutesPlugin | | False | -| safeboot_configuration | SafeBootConfigurationPlugin | | False | -| terminal_services_history | TSClientPlugin | | False | -| timezone_data | TimezoneDataPlugin | | False | +| plugin_name | plugin_description | plugin_class_name | test_case_name | success | +|------------------------------|------------------------------------------------------------------------------------------|-------------------------------|------------------|-----------| +| backuprestore_plugin | Gets the contents of the FilesNotToSnapshot, KeysNotToRestore, and FilesNotToBackup keys | BackupRestorePlugin | | False | +| codepage | Get codepage value | CodepagePlugin | | False | +| crash_dump | Get crash control information | CrashDumpPlugin | | False | +| diag_sr | Get Diag\SystemRestore values and data | DiagSRPlugin | | False | +| disable_last_access | Get NTFSDisableLastAccessUpdate value | DisableLastAccessPlugin | | False | +| disablesr_plugin | Gets the value that turns System Restore either on or off | DisableSRPlugin | | False | +| image_file_execution_options | Retrieve image file execution options - a persistence method | ImageFileExecutionOptions | | False | +| installed_programs_ntuser | Retrieve list of installed programs and their install date from the NTUSER Hive | InstalledProgramsNTUserPlugin | | False | +| previous_winver_plugin | Get previous relevant OS information | PreviousWinVersionPlugin | | False | +| processor_architecture | Get processor architecture info from the System's environment key | ProcessorArchitecturePlugin | | False | +| routes | Get list of routes | RoutesPlugin | | False | +| safeboot_configuration | Get safeboot configuration | SafeBootConfigurationPlugin | | False | +| shutdown | Get shutdown data | ShutdownPlugin | | False | +| spp_clients_plugin | Determines volumes monitored by VSS | SppClientsPlugin | | False | +| susclient_plugin | Extracts SusClient* info, including HDD SN | SusclientPlugin | | False | +| terminal_services_history | Retrieve history of RDP connections | TSClientPlugin | | False | +| timezone_data | Get timezone data | TimezoneDataPlugin | | False | +| timezone_data2 | Get timezone data | TimezoneDataPlugin2 | | False | +| winver_plugin | Get relevant OS information | WinVersionPlugin | | False | \ No newline at end of file diff --git a/regipy_tests/validation/plugin_validation.py b/regipy_tests/validation/plugin_validation.py index e96f094..be2a292 100644 --- a/regipy_tests/validation/plugin_validation.py +++ b/regipy_tests/validation/plugin_validation.py @@ -1,7 +1,8 @@ from collections import defaultdict -from dataclasses import dataclass, asdict +from dataclasses import asdict from contextlib import contextmanager +import sys from tabulate import tabulate import os @@ -83,6 +84,20 @@ def main(): print(f"[*] Loaded {len(validation_cases)} validation cases") + # TODO: Move this to Click, understand how we can skip installation in setup.py, as the tests are not part of the package. + # Possibly we should need to creae an additional regipy-tests package + # which will be installed during the validation step in github/workflows/python-package.yml + if len(sys.argv) == 2: + plugin_name = sys.argv[1] + if plugin_name in validation_cases.keys(): + print(f"Running validation for plugin {plugin_name}") + validation_case: ValidationCase = validation_cases[plugin_name] + with load_hive(validation_case.test_hive_file_name) as registry_hive: + validate_case(validation_case, registry_hive) + return + print(f"No ValidationCase for {plugin_name}") + return + # Map all plugins according to registry hive test file, for performance. # Also, warn about plugins without validation, this will be enforced in the future. registry_hive_map = defaultdict(list) @@ -134,6 +149,7 @@ def main(): asdict( ValidationResult( plugin_name=p.NAME, + plugin_description=p.DESCRIPTION, plugin_class_name=p.__name__, test_case_name=None, success=False, @@ -154,7 +170,8 @@ def main(): if plugins_without_validation: # fmt: off raise PluginValidationCaseFailureException( - f"{len(plugins_without_validation)} plugins are missing validation: {[p.__name__ for p in PLUGINS if p.NAME in plugins_without_validation]}" + f"{len(plugins_without_validation)} plugins are missing validation:" + f" {[p.__name__ for p in PLUGINS if p.NAME in plugins_without_validation]}" ) # fmt: on diff --git a/regipy_tests/validation/validation.py b/regipy_tests/validation/validation.py index d714c3f..32f2bb1 100644 --- a/regipy_tests/validation/validation.py +++ b/regipy_tests/validation/validation.py @@ -11,6 +11,7 @@ @dataclass class ValidationResult: plugin_name: str + plugin_description: Optional[str] plugin_class_name: str test_case_name: Optional[str] success: bool @@ -85,6 +86,7 @@ def validate(self): print(f"\tValidation passed for {self.plugin.NAME}") return ValidationResult( plugin_name=self.plugin.NAME, + plugin_description=self.plugin.DESCRIPTION, plugin_class_name=self.plugin.__name__, test_case_name=self.__class__.__name__, success=True, diff --git a/regipy_tests/validation/validation_tests/active_control_set_validation.py b/regipy_tests/validation/validation_tests/active_control_set_validation.py new file mode 100644 index 0000000..31eab6b --- /dev/null +++ b/regipy_tests/validation/validation_tests/active_control_set_validation.py @@ -0,0 +1,34 @@ +from regipy.plugins.system.active_controlset import ActiveControlSetPlugin +from regipy_tests.validation.validation import ValidationCase + + +class ActiveControlSetPluginValidationCase(ValidationCase): + plugin = ActiveControlSetPlugin + test_hive_file_name = "SYSTEM_WIN_10_1709.xz" + + exact_expected_result = [ + { + "name": "Current", + "value": 1, + "value_type": "REG_DWORD", + "is_corrupted": False, + }, + { + "name": "Default", + "value": 1, + "value_type": "REG_DWORD", + "is_corrupted": False, + }, + { + "name": "Failed", + "value": 0, + "value_type": "REG_DWORD", + "is_corrupted": False, + }, + { + "name": "LastKnownGood", + "value": 1, + "value_type": "REG_DWORD", + "is_corrupted": False, + }, + ] diff --git a/regipy_tests/validation/validation_tests/services_plugin_validation.py b/regipy_tests/validation/validation_tests/services_plugin_validation.py index 99d8ac9..3cfe8a7 100644 --- a/regipy_tests/validation/validation_tests/services_plugin_validation.py +++ b/regipy_tests/validation/validation_tests/services_plugin_validation.py @@ -1,5 +1,3 @@ -from typing import Dict - from regipy.plugins.system.services import ServicesPlugin from regipy_tests.validation.validation import ValidationCase