mirror of https://git.48k.eu/ogclient
115 lines
3.1 KiB
Python
115 lines
3.1 KiB
Python
#
|
|
# 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
|