Skip to content

Commit b09f13a

Browse files
authored
Merge pull request #54 from mrexodia/registry
Initial registry support (`ZwOpenKey` and `ZwQueryValueKey`)
2 parents e1c43c8 + d5eaa58 commit b09f13a

File tree

3 files changed

+82
-2
lines changed

3 files changed

+82
-2
lines changed

src/dumpulator/dumpulator.py

Lines changed: 14 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -292,7 +292,9 @@ def __init__(self, minidump_file, *, trace=False, quiet=False, thread_id=None, d
292292
self.syscalls = []
293293
self._setup_syscalls()
294294
self._setup_emulator(thread)
295+
self.handles = HandleManager()
295296
self._setup_handles()
297+
self._setup_registry()
296298
self.kill_me = None
297299
self.exit_code = None
298300
self.exports = self._all_exports()
@@ -519,9 +521,19 @@ def _setup_pebteb(self, thread):
519521
self.memory.set_region_info(default_activation_context_data, "Default activation context data")
520522
self.memory.set_region_info(leap_second_data, "Leap second data")
521523

522-
def _setup_handles(self):
523-
self.handles = HandleManager()
524+
def _setup_registry(self):
525+
self.handles.create_key(r"\Registry\Machine\System\CurrentControlSet\Control\Nls\Sorting\Versions", {
526+
"": "00060305",
527+
"000601xx": "SortWindows61.dll",
528+
"000602xx": "SortWindows62.dll",
529+
"000603xx": "kernel32.dll",
530+
"FF0000xx": "SortServer2003Compat.dll",
531+
"FF0406xx": "SortWindows6Compat.dll",
532+
"FF0502xx": "SortWindows6Compat.dll",
533+
"000604xx": "SortWindows64.dll",
534+
})
524535

536+
def _setup_handles(self):
525537
import dumpulator.ntdevices as ntdevices
526538
self.console = ntdevices.ConsoleDeviceObject(R"\Device\ConDrv")
527539
self.stdin = ConsoleFileObject(ConsoleType.In)

src/dumpulator/native.py

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -81,6 +81,22 @@
8181
IMAGE_SCN_MEM_READ = 0x40000000
8282
IMAGE_SCN_MEM_WRITE = 0x80000000
8383

84+
# Registry value types
85+
REG_NONE = 0 # No value type
86+
REG_SZ = 1 # Unicode nul terminated string
87+
REG_EXPAND_SZ = 2 # Unicode nul terminated string (with environment variable references)
88+
REG_BINARY = 3 # Free form binary
89+
REG_DWORD = 4 # 32-bit number
90+
REG_DWORD_LITTLE_ENDIAN = 4 # 32-bit number (same as REG_DWORD)
91+
REG_DWORD_BIG_ENDIAN = 5 # 32-bit number
92+
REG_LINK = 6 # Symbolic Link (unicode)
93+
REG_MULTI_SZ = 7 # Multiple Unicode strings
94+
REG_RESOURCE_LIST = 8 # Resource list in the resource map
95+
REG_FULL_RESOURCE_DESCRIPTOR = 9 # Resource list in the hardware description
96+
REG_RESOURCE_REQUIREMENTS_LIST = 10 # Resource requirements list
97+
REG_QWORD = 11 # 64-bit number
98+
REG_QWORD_LITTLE_ENDIAN = 11 # 64-bit number (same as REG_QWORD)
99+
84100
def round_to_pages(size):
85101
return (size + 0xFFF) & 0xFFFFFFFFFFFFF000
86102

@@ -561,3 +577,12 @@ def __init__(self, ptr, mem_read):
561577
super().__init__(ptr, mem_read)
562578
self.type = t
563579
return P
580+
581+
class KEY_VALUE_FULL_INFORMATION(ctypes.Structure):
582+
_fields_ = [
583+
("TitleIndex", ctypes.c_uint32),
584+
("Type", ctypes.c_uint32),
585+
("DataOffset", ctypes.c_uint32),
586+
("DataLength", ctypes.c_uint32),
587+
("NameLength", ctypes.c_uint32),
588+
]

src/dumpulator/ntsyscalls.py

Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3280,6 +3280,49 @@ def ZwQueryValueKey(dp: Dumpulator,
32803280
Length: Annotated[ULONG, SAL("_In_")],
32813281
ResultLength: Annotated[P(ULONG), SAL("_Out_")]
32823282
):
3283+
key = dp.handles.get(KeyHandle, RegistryKeyObject)
3284+
name = ValueName[0].read_str()
3285+
if KeyValueInformationClass == KEY_VALUE_INFORMATION_CLASS.KeyValueFullInformation:
3286+
value = key.values.get(name.lower(), None)
3287+
assert value is not None, "value not found"
3288+
info = KEY_VALUE_FULL_INFORMATION()
3289+
info.TitleIndex = 0
3290+
3291+
if len(name) == 0:
3292+
info.NameLength = 0
3293+
appended_data = b""
3294+
else:
3295+
name_data = name.encode("utf-16-le")
3296+
info.NameLength = len(name_data)
3297+
appended_data = name_data
3298+
3299+
# Align to 4 bytes
3300+
remain = 4 - len(appended_data) % 4
3301+
if remain > 0:
3302+
appended_data += b"\0" * remain
3303+
assert (len(appended_data) % 4) == 0
3304+
3305+
if isinstance(value, str):
3306+
info.Type = REG_SZ
3307+
value_data = value.encode("utf-16-le") + b"\0\0"
3308+
elif isinstance(value, int):
3309+
info.Type = REG_DWORD
3310+
value_data = struct.pack("<I", value)
3311+
else:
3312+
raise NotImplementedError()
3313+
3314+
info.DataLength = len(value_data)
3315+
info.DataOffset = ctypes.sizeof(info) + len(appended_data)
3316+
appended_data += value_data
3317+
3318+
final_data = bytes(info) + appended_data
3319+
assert len(final_data) <= Length
3320+
if ResultLength != 0:
3321+
dp.write_ulong(ResultLength, len(final_data))
3322+
KeyValueInformation.write(final_data)
3323+
3324+
return STATUS_SUCCESS
3325+
32833326
raise NotImplementedError()
32843327

32853328
@syscall

0 commit comments

Comments
 (0)