Skip to content

Commit

Permalink
Merge pull request #275 from ZarKyo/master
Browse files Browse the repository at this point in the history
Added tests for PR plugins #254
  • Loading branch information
mkorman90 authored Aug 13, 2024
2 parents ae14551 + 15fab78 commit d84c307
Show file tree
Hide file tree
Showing 16 changed files with 1,047 additions and 26 deletions.
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

0 comments on commit d84c307

Please sign in to comment.