summaryrefslogtreecommitdiffstats
path: root/src/utils/winreg.py
diff options
context:
space:
mode:
Diffstat (limited to 'src/utils/winreg.py')
-rw-r--r--src/utils/winreg.py114
1 files changed, 114 insertions, 0 deletions
diff --git a/src/utils/winreg.py b/src/utils/winreg.py
new file mode 100644
index 0000000..ed2d5c6
--- /dev/null
+++ b/src/utils/winreg.py
@@ -0,0 +1,114 @@
+#
+# Copyright (C) 2022 Soleta Networks <info@soleta.eu>
+#
+# This program is free software: you can redistribute it and/or modify it under
+# the terms of the GNU Affero General Public License as published by the
+# Free Software Foundation; either version 3 of the License, or
+# (at your option) any later version.
+
+import libhivexmod
+import hivex
+from enum import Enum
+from src.log import OgError
+from uuid import UUID
+
+
+WINDOWS_HIVES_PATH = '/Windows/System32/config'
+WINDOWS_HIVE_SOFTWARE = f'{WINDOWS_HIVES_PATH}/SOFTWARE'
+WINDOWS_HIVE_SYSTEM = f'{WINDOWS_HIVES_PATH}/SYSTEM'
+
+WINDOWS_HIVE_ENCODING = 'utf-16-le'
+
+
+class RegistryType(Enum):
+ NONE = 0
+ SZ = 1
+ EXPAND_SZ = 2
+ BINARY = 3
+ DWORD = 4
+ DWORD_BIG_ENDIAN = 5
+ LINK = 6
+ MULTI_SZ = 7
+ RESOURCE_LIST = 8
+ FULL_RESOURCE_DESCRIPTIOR = 9
+ RESOURCE_REQUIREMENTS_LISTS = 10
+ QWORD = 11
+
+
+def get_value_from_node(hive, node, value):
+ type_node_value = hive.node_get_value(node, value)
+
+ val = None
+
+ val_type = hive.value_type(type_node_value)[0]
+ rtype = RegistryType(val_type)
+
+ if rtype == RegistryType.SZ:
+ val = hive.value_string(type_node_value)
+ elif rtype == RegistryType.MULTI_SZ:
+ val = hive.value_multiple_strings(type_node_value)
+ elif rtype == RegistryType.DWORD:
+ val = hive.value_dword(type_node_value)
+ elif rtype == RegistryType.QWORD:
+ val = hive.value_qword(type_node_value)
+ elif rtype == RegistryType.BINARY:
+ _, val = hive.value_value(type_node_value)
+
+ if not val:
+ raise OgError(f'No valid value found for the node {hive.node_name(node)}')
+
+ return val
+
+
+def check_hive_consistency(hive_path):
+ """
+ The Hivex class tries to call libhivexmod.close in the __del__ method.
+ That is not reliable as trying to free resources from a corrupted hivex
+ file will not work, we first check if the hivex can be loaded.
+ """
+ try:
+ h = libhivexmod.open(hive_path, 0)
+ libhivexmod.close(h)
+ except RuntimeError as e:
+ raise OgError(f'Unable to load the registry hive at {hive_path}: {e}') from e
+
+
+def hive_handler_open(hive_path, write):
+ check_hive_consistency(hive_path)
+
+ h = hivex.Hivex(hive_path, write = write)
+
+ if not h.root():
+ raise OgError(f'Unable to find the root node for hive at {hive_path}') from e
+ return h
+
+
+def get_node_child(hive, node, name):
+ child_node = hive.node_get_child(node, name)
+
+ if not child_node:
+ raise OgError(f'Could not find child node {name} in {hive.node_name(node)}')
+
+ return child_node
+
+
+def get_node_child_from_path(hive, node, path):
+ path_components = path.split('/')
+
+ child_node = node
+ for node_name in path_components:
+ child_node = get_node_child(hive, child_node, node_name)
+
+ return child_node
+
+
+def uuid_to_bytes(uuid):
+ uuid = uuid.replace('-', '')
+
+ group0 = f'{uuid[6:8]}{uuid[4:6]}{uuid[2:4]}{uuid[0:2]}'
+ group1 = f'{uuid[10:12]}{uuid[8:10]}'
+ group2 = f'{uuid[14:16]}{uuid[12:14]}'
+ group3 = uuid[16:20]
+ group4 = uuid[20:32]
+ res = f'{group0}-{group1}-{group2}-{group3}-{group4}'
+ return UUID(res).bytes