Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Added tests for PR plugins #254 #275

Merged
merged 4 commits into from
Aug 13, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
14 changes: 14 additions & 0 deletions regipy/plugins/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -37,3 +37,17 @@
from .usrclass.shellbags_usrclass import ShellBagUsrclassPlugin
from .ntuser.classes_installer import NtuserClassesInstallerPlugin
from .system.network_data import NetworkDataPlugin
from .software.winver import WinVersionPlugin
from .system.previous_winver import PreviousWinVersionPlugin
from .system.shutdown import ShutdownPlugin
from .system.processor_architecture import ProcessorArchitecturePlugin
from .system.crash_dump import CrashDumpPlugin
from .software.susclient import SusclientPlugin
from .system.disablelastaccess import DisableLastAccessPlugin
from .system.codepage import CodepagePlugin
from .software.disablesr import DisableSRPlugin
from .system.diag_sr import DiagSRPlugin
from .software.spp_clients import SppClientsPlugin
from .system.backuprestore import BackupRestorePlugin
from .system.timezone_data2 import TimezoneDataPlugin2

37 changes: 37 additions & 0 deletions regipy/plugins/software/disablesr.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
import logging

from regipy.hive_types import SOFTWARE_HIVE_TYPE
from regipy.plugins.plugin import Plugin
from regipy.utils import convert_wintime
from regipy.exceptions import RegistryKeyNotFoundException

logger = logging.getLogger(__name__)


SYS_RESTORE_PATH = r"\Microsoft\Windows NT\CurrentVersion\SystemRestore"
value_list = ("DisableSR")


class DisableSRPlugin(Plugin):
NAME = 'disablesr_plugin'
DESCRIPTION = 'Gets the value that turns System Restore either on or off'
COMPATIBLE_HIVE = SOFTWARE_HIVE_TYPE

def can_run(self):
# TODO: Choose the relevant condition - to determine if the plugin is relevant for the given hive
return self.registry_hive.hive_type == SOFTWARE_HIVE_TYPE

def run(self):
logger.info("Started disablesr Plugin...")

try:
key = self.registry_hive.get_key(SYS_RESTORE_PATH)
except RegistryKeyNotFoundException as ex:
logger.error(f'Could not find {self.NAME} subkey at {SYS_RESTORE_PATH}: {ex}')
return None

self.entries = {SYS_RESTORE_PATH: {'last_write': convert_wintime(key.header.last_modified).isoformat()}}

for val in key.iter_values():
if val.name in value_list:
self.entries[SYS_RESTORE_PATH][val.name] = val.value
40 changes: 40 additions & 0 deletions regipy/plugins/software/spp_clients.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
import logging

from regipy.hive_types import SOFTWARE_HIVE_TYPE
from regipy.plugins.plugin import Plugin
from regipy.utils import convert_wintime
from regipy.exceptions import RegistryKeyNotFoundException

logger = logging.getLogger(__name__)


SPP_CLIENT_PATH = r"\Microsoft\Windows NT\CurrentVersion\SPP\Clients"
value_list = ("{09F7EDC5-294E-4180-AF6A-FB0E6A0E9513}")


class SppClientsPlugin(Plugin):
NAME = 'spp_clients_plugin'
DESCRIPTION = 'Determines volumes monitored by VSS'
COMPATIBLE_HIVE = SOFTWARE_HIVE_TYPE

def can_run(self):
# TODO: Choose the relevant condition - to determine if the plugin is relevant for the given hive
return self.registry_hive.hive_type == SOFTWARE_HIVE_TYPE

def run(self):
logger.info("Started spp_clients Plugin...")

try:
key = self.registry_hive.get_key(SPP_CLIENT_PATH)
except RegistryKeyNotFoundException as ex:
logger.error(f'Could not find {self.NAME} subkey at {SPP_CLIENT_PATH}: {ex}')
return None

self.entries = {SPP_CLIENT_PATH: {'last_write': convert_wintime(key.header.last_modified).isoformat()}}

for val in key.iter_values():
if val.name in value_list:
aux_list = []
for value in val.value:
aux_list.append(value.replace("%3A", ":"))
self.entries[SPP_CLIENT_PATH][val.name] = aux_list
45 changes: 45 additions & 0 deletions regipy/plugins/software/susclient.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
import logging

from regipy.hive_types import SOFTWARE_HIVE_TYPE
from regipy.plugins.plugin import Plugin
from regipy.utils import convert_wintime
from regipy.exceptions import RegistryKeyNotFoundException

logger = logging.getLogger(__name__)


WIN_VER_PATH = r"\Microsoft\Windows\CurrentVersion\WindowsUpdate"
value_list = ("LastRestorePointSetTime", "SusClientId")


class SusclientPlugin(Plugin):
NAME = 'susclient_plugin'
DESCRIPTION = 'Extracts SusClient* info, including HDD SN'
COMPATIBLE_HIVE = SOFTWARE_HIVE_TYPE

def can_run(self):
# TODO: Choose the relevant condition - to determine if the plugin is relevant for the given hive
return self.registry_hive.hive_type == SOFTWARE_HIVE_TYPE

def run(self):
logger.info("Started susclient Plugin...")

try:
key = self.registry_hive.get_key(WIN_VER_PATH)
except RegistryKeyNotFoundException as ex:
logger.error(f'Could not find {self.NAME} subkey at {WIN_VER_PATH}: {ex}')
return None

self.entries = {WIN_VER_PATH: {'last_write': convert_wintime(key.header.last_modified).isoformat()}}

for val in key.iter_values():
if val.name == "SusClientIdValidation":
self.entries[WIN_VER_PATH][val.name] = get_SN(val.value)
elif val.name in value_list:
self.entries[WIN_VER_PATH][val.name] = val.value


def get_SN(data):
offset = int(data[:2], 16)
length = int(data[4:6], 16)
return bytes.fromhex(data[2 * offset:2 * (length + offset)]).decode('utf-16le')
42 changes: 42 additions & 0 deletions regipy/plugins/software/winver.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
import logging

from regipy.hive_types import SOFTWARE_HIVE_TYPE
from regipy.plugins.plugin import Plugin
from regipy.utils import convert_wintime
from regipy.exceptions import RegistryKeyNotFoundException
import datetime

logger = logging.getLogger(__name__)


WIN_VER_PATH = r"\Microsoft\Windows NT\CurrentVersion"
os_list = ("ProductName", "ReleaseID", "CSDVersion", "CurrentVersion", "CurrentBuild", "CurrentBuildNumber", "InstallationType", "EditionID",
"ProductName", "ProductId", "BuildLab", "BuildLabEx", "CompositionEditionID", "RegisteredOrganization", "RegisteredOwner", "InstallDate")


class WinVersionPlugin(Plugin):
NAME = 'winver_plugin'
DESCRIPTION = 'Get relevant OS information'
COMPATIBLE_HIVE = SOFTWARE_HIVE_TYPE

def can_run(self):
# TODO: Choose the relevant condition - to determine if the plugin is relevant for the given hive
return self.registry_hive.hive_type == SOFTWARE_HIVE_TYPE

def run(self):
logger.info("Started winver Plugin...")

try:
key = self.registry_hive.get_key(WIN_VER_PATH)
except RegistryKeyNotFoundException as ex:
logger.error(f'Could not find {self.NAME} subkey at {WIN_VER_PATH}: {ex}')
return None

self.entries = {WIN_VER_PATH: {'last_write': convert_wintime(key.header.last_modified).isoformat()}}

for val in key.iter_values():
if val.name in os_list:
if val.name == "InstallDate":
self.entries[WIN_VER_PATH][val.name] = datetime.datetime.utcfromtimestamp(val.value).strftime("%Y-%m-%d %H:%M:%S")
else:
self.entries[WIN_VER_PATH][val.name] = val.value
36 changes: 36 additions & 0 deletions regipy/plugins/system/backuprestore.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
import logging

from regipy.hive_types import SYSTEM_HIVE_TYPE
from regipy.plugins.plugin import Plugin
from regipy.utils import convert_wintime
from regipy.exceptions import RegistryKeyNotFoundException


logger = logging.getLogger(__name__)


BACKUPRESTORE_PATH = [r"Control\BackupRestore\FilesNotToSnapshot", r"Control\BackupRestore\FilesNotToBackup", r"Control\BackupRestore\KeysNotToRestore"]


class BackupRestorePlugin(Plugin):
NAME = 'backuprestore_plugin'
DESCRIPTION = "Gets the contents of the FilesNotToSnapshot, KeysNotToRestore, and FilesNotToBackup keys"
COMPATIBLE_HIVE = SYSTEM_HIVE_TYPE

def can_run(self):
# TODO: Choose the relevant condition - to determine if the plugin is relevant for the given hive
return self.registry_hive.hive_type == SYSTEM_HIVE_TYPE

def run(self):
self.entries = {}
for br_path in BACKUPRESTORE_PATH:
br_subkeys = self.registry_hive.get_control_sets(br_path)
for br_subkey in br_subkeys:
try:
backuprestore = self.registry_hive.get_key(br_subkey)
except RegistryKeyNotFoundException as ex:
logger.error(f'Could not find {self.NAME} subkey at {br_subkey}: {ex}')
continue
self.entries[br_subkey] = {'last_write': convert_wintime(backuprestore.header.last_modified).isoformat()}
for val in backuprestore.iter_values():
self.entries[br_subkey][val.name] = val.value
37 changes: 37 additions & 0 deletions regipy/plugins/system/codepage.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
import logging

from regipy.hive_types import SYSTEM_HIVE_TYPE
from regipy.plugins.plugin import Plugin
from regipy.utils import convert_wintime
from regipy.exceptions import RegistryKeyNotFoundException


logger = logging.getLogger(__name__)


PROCESSOR_PATH = r"Control\Nls\CodePage"
crash_items = ("ACP")


class CodepagePlugin(Plugin):
NAME = 'codepage'
DESCRIPTION = "Get codepage value"
COMPATIBLE_HIVE = SYSTEM_HIVE_TYPE

def can_run(self):
# TODO: Choose the relevant condition - to determine if the plugin is relevant for the given hive
return self.registry_hive.hive_type == SYSTEM_HIVE_TYPE

def run(self):
self.entries = {}
codepage_subkeys = self.registry_hive.get_control_sets(PROCESSOR_PATH)
for codepage_subkey in codepage_subkeys:
try:
codepage = self.registry_hive.get_key(codepage_subkey)
except RegistryKeyNotFoundException as ex:
logger.error(f'Could not find {self.NAME} subkey at {codepage_subkey}: {ex}')
continue
self.entries[codepage_subkey] = {'last_write': convert_wintime(codepage.header.last_modified).isoformat()}
for val in codepage.iter_values():
if val.name in crash_items:
self.entries[codepage_subkey][val.name] = val.value
43 changes: 43 additions & 0 deletions regipy/plugins/system/crash_dump.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
import logging

from regipy.hive_types import SYSTEM_HIVE_TYPE
from regipy.plugins.plugin import Plugin
from regipy.utils import convert_wintime
from regipy.exceptions import RegistryKeyNotFoundException

logger = logging.getLogger(__name__)


PROCESSOR_PATH = r"Control\CrashControl"
crash_items = ("CrashDumpEnabled", "DumpFile", "MinidumpDir", "LogEvent")
dump_enabled = {"0": "None",
"1": "Complete memory dump",
"2": "Kernel memory dump",
"3": "Small memory dump (64 KB)",
"7": "Automatic memory dump"}


class CrashDumpPlugin(Plugin):
NAME = 'crash_dump'
DESCRIPTION = "Get crash control information"
COMPATIBLE_HIVE = SYSTEM_HIVE_TYPE

def can_run(self):
# TODO: Choose the relevant condition - to determine if the plugin is relevant for the given hive
return self.registry_hive.hive_type == SYSTEM_HIVE_TYPE

def run(self):
self.entries = {}
architecture_subkeys = self.registry_hive.get_control_sets(PROCESSOR_PATH)
for architecture_subkey in architecture_subkeys:
try:
architecture = self.registry_hive.get_key(architecture_subkey)
except RegistryKeyNotFoundException as ex:
logger.error(f'Could not find {self.NAME} subkey at {architecture_subkey}: {ex}')
continue
self.entries[architecture_subkey] = {'last_write': convert_wintime(architecture.header.last_modified).isoformat()}
for val in architecture.iter_values():
if val.name in crash_items:
self.entries[architecture_subkey][val.name] = val.value
if val.name == "CrashDumpEnabled":
self.entries[architecture_subkey]["CrashDumpEnabledStr"] = dump_enabled.get(str(val.value), "")
38 changes: 38 additions & 0 deletions regipy/plugins/system/diag_sr.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
import logging
import struct

from regipy.hive_types import SYSTEM_HIVE_TYPE
from regipy.plugins.plugin import Plugin
from regipy.utils import convert_wintime
from regipy.utils import convert_filetime2
from regipy.exceptions import RegistryKeyNotFoundException


logger = logging.getLogger(__name__)


DIAGSR_PATH = r"Services\VSS\Diag\SystemRestore"
crash_items = ("CrashDumpEnabled", "DumpFile", "MinidumpDir", "LogEvent")


class DiagSRPlugin(Plugin):
NAME = 'diag_sr'
DESCRIPTION = "Get Diag\\SystemRestore values and data"
COMPATIBLE_HIVE = SYSTEM_HIVE_TYPE

def can_run(self):
# TODO: Choose the relevant condition - to determine if the plugin is relevant for the given hive
return self.registry_hive.hive_type == SYSTEM_HIVE_TYPE

def run(self):
self.entries = {}
diagsr_subkeys = self.registry_hive.get_control_sets(DIAGSR_PATH)
for diagsr_subkey in diagsr_subkeys:
try:
diagsr = self.registry_hive.get_key(diagsr_subkey)
except RegistryKeyNotFoundException as ex:
logger.error(f'Could not find {self.NAME} subkey at {diagsr_subkey}: {ex}')
continue
self.entries[diagsr_subkey] = {'last_write': convert_wintime(diagsr.header.last_modified).isoformat()}
for val in diagsr.iter_values():
self.entries[diagsr_subkey][val.name] = convert_filetime2(val.value[16:32])
42 changes: 42 additions & 0 deletions regipy/plugins/system/disablelastaccess.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
import logging

from regipy.hive_types import SYSTEM_HIVE_TYPE
from regipy.plugins.plugin import Plugin
from regipy.utils import convert_wintime
from regipy.exceptions import RegistryKeyNotFoundException


logger = logging.getLogger(__name__)


LAST_ACCESS_PATH = r"Control\FileSystem"
crash_items = ("NtfsDisableLastAccessUpdate", "NtfsDisableLastAccessUpdate")
last_acc = {"80000000": "(User Managed, Updates Enabled)",
"80000001": "(User Managed, Updates Disabled)",
"80000002": "(System Managed, Updates Enabled)",
"80000003": "(System Managed, Updates Disabled)"}


class DisableLastAccessPlugin(Plugin):
NAME = 'disable_last_access'
DESCRIPTION = "Get NTFSDisableLastAccessUpdate value"
COMPATIBLE_HIVE = SYSTEM_HIVE_TYPE

def can_run(self):
# TODO: Choose the relevant condition - to determine if the plugin is relevant for the given hive
return self.registry_hive.hive_type == SYSTEM_HIVE_TYPE

def run(self):
self.entries = {}
access_subkeys = self.registry_hive.get_control_sets(LAST_ACCESS_PATH)
for access_subkey in access_subkeys:
try:
access = self.registry_hive.get_key(access_subkey)
except RegistryKeyNotFoundException as ex:
logger.error(f'Could not find {self.NAME} subkey at {access_subkey}: {ex}')
continue
self.entries[access_subkey] = {'last_write': convert_wintime(access.header.last_modified).isoformat()}
for val in access.iter_values():
if val.name in crash_items:
self.entries[access_subkey][val.name] = f'{val.value:0x}'
self.entries[access_subkey][f'{val.name}Str'] = last_acc.get(f'{val.value:0x}', '')
Loading
Loading