1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
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
|