Skip to content

Commit

Permalink
Worked on MRU script
Browse files Browse the repository at this point in the history
  • Loading branch information
joachimmetz committed Mar 1, 2024
1 parent c9f03b8 commit 29c98d7
Show file tree
Hide file tree
Showing 9 changed files with 268 additions and 110 deletions.
2 changes: 1 addition & 1 deletion config/dpkg/control
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ Homepage: https://github.com/libyal/winreg-kb

Package: python3-winregrc
Architecture: all
Depends: libbde-python3 (>= 20220121), libcaes-python3 (>= 20240114), libcreg-python3 (>= 20200725), libewf-python3 (>= 20131210), libfcrypto-python3 (>= 20240114), libfsapfs-python3 (>= 20220709), libfsext-python3 (>= 20220829), libfsfat-python3 (>= 20220925), libfshfs-python3 (>= 20220831), libfsntfs-python3 (>= 20211229), libfsxfs-python3 (>= 20220829), libfvde-python3 (>= 20220121), libfwnt-python3 (>= 20210717), libfwps-python3 (>= 20230131), libfwsi-python3 (>= 20240224), libhmac-python3 (>= 20230205), libluksde-python3 (>= 20220121), libmodi-python3 (>= 20210405), libphdi-python3 (>= 20220228), libqcow-python3 (>= 20201213), libregf-python3 (>= 20201002), libsigscan-python3 (>= 20230109), libsmdev-python3 (>= 20140529), libsmraw-python3 (>= 20140612), libvhdi-python3 (>= 20201014), libvmdk-python3 (>= 20140421), libvsapm-python3 (>= 20230506), libvsgpt-python3 (>= 20211115), libvshadow-python3 (>= 20160109), libvslvm-python3 (>= 20160109), python3-acstore (>= 20230101), python3-artifacts (>= 20220219), python3-cffi-backend (>= 1.9.1), python3-dfdatetime (>= 20221112), python3-dfimagetools (>= 20220129), python3-dfvfs (>= 20240115), python3-dfwinreg (>= 20211207), python3-dtfabric (>= 20230518), python3-idna (>= 2.5), python3-pytsk3 (>= 20210419), python3-xattr (>= 0.7.2), python3-yaml (>= 3.10), ${misc:Depends}
Depends: libbde-python3 (>= 20220121), libcaes-python3 (>= 20240114), libcreg-python3 (>= 20200725), libewf-python3 (>= 20131210), libfcrypto-python3 (>= 20240114), libfsapfs-python3 (>= 20220709), libfsext-python3 (>= 20220829), libfsfat-python3 (>= 20220925), libfshfs-python3 (>= 20220831), libfsntfs-python3 (>= 20211229), libfsxfs-python3 (>= 20220829), libfvde-python3 (>= 20220121), libfwnt-python3 (>= 20210717), libfwps-python3 (>= 20240225), libfwsi-python3 (>= 20240225), libhmac-python3 (>= 20230205), libluksde-python3 (>= 20220121), libmodi-python3 (>= 20210405), libphdi-python3 (>= 20220228), libqcow-python3 (>= 20201213), libregf-python3 (>= 20201002), libsigscan-python3 (>= 20230109), libsmdev-python3 (>= 20140529), libsmraw-python3 (>= 20140612), libvhdi-python3 (>= 20201014), libvmdk-python3 (>= 20140421), libvsapm-python3 (>= 20230506), libvsgpt-python3 (>= 20211115), libvshadow-python3 (>= 20160109), libvslvm-python3 (>= 20160109), python3-acstore (>= 20230101), python3-artifacts (>= 20220219), python3-cffi-backend (>= 1.9.1), python3-dfdatetime (>= 20221112), python3-dfimagetools (>= 20240301), python3-dfvfs (>= 20240115), python3-dfwinreg (>= 20240229), python3-dtfabric (>= 20230518), python3-idna (>= 2.5), python3-pytsk3 (>= 20210419), python3-xattr (>= 0.7.2), python3-yaml (>= 3.10), ${misc:Depends}
Description: Python 3 module of Windows Registry resources (winregrc)
winregrc is a Python module part of winreg-kb to allow reuse of
Windows Registry resources.
Expand Down
8 changes: 4 additions & 4 deletions dependencies.ini
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ version_property: __version__

[dfimagetools]
dpkg_name: python3-dfimagetools
minimum_version: 20220129
minimum_version: 20240301
rpm_name: python3-dfimagetools
version_property: __version__

Expand All @@ -37,7 +37,7 @@ version_property: __version__

[dfwinreg]
dpkg_name: python3-dfwinreg
minimum_version: 20211207
minimum_version: 20240229
rpm_name: python3-dfwinreg
version_property: __version__

Expand Down Expand Up @@ -162,15 +162,15 @@ version_property: get_version()
[pyfwps]
dpkg_name: libfwps-python3
l2tbinaries_name: libfwps
minimum_version: 20240224
minimum_version: 20240225
pypi_name: libfwps-python
rpm_name: libfwps-python3
version_property: get_version()

[pyfwsi]
dpkg_name: libfwsi-python3
l2tbinaries_name: libfwsi
minimum_version: 20240224
minimum_version: 20240225
pypi_name: libfwsi-python
rpm_name: libfwsi-python3
version_property: get_version()
Expand Down
16 changes: 13 additions & 3 deletions docs/sources/windows-registry/Files.md
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,7 @@ SOFTWARE | %SystemRoot%\System32\config | Software specific part of the Registry
Syscache.hve | System Volume Information | *TODO* | | 7, 2008
SYSTEM | %SystemRoot%\System32\config | System specific part of the Registry | `HKEY_LOCAL_MACHINE\System` | NT 4 and later
userdiff | %SystemRoot%\System32\config | *TODO* | | NT 4 and later
UsrClass.dat | %UserProfile%\Local Settings\Application Data\Microsoft\Windows | File associations and COM Registry entries | | 2000, XP, 2003
UsrClass.dat | %UserProfile%\Local Settings\Application Data\Microsoft\Windows | `HKEY_CURRENT_USER\Software\Classes` | | 2000, XP, 2003
UsrClass.dat | %UserProfile%\AppData\Local\Microsoft\Windows | File associations and COM Registry entries | `HKEY_CURRENT_USER\Software\Classes` | Vista and later

*TODO Windows NT 3.1 user specific file under %SystemRoot%\System32\config*
Expand Down Expand Up @@ -165,7 +165,17 @@ Vista, 7 | %SID%_Classes, where %SID%_Classes is a string of the SID of the user
8 | *TODO*
10 | %SID%_Classes, where %SID%_Classes is a string of the SID of the user

## Notes

*TODO what about earlier versions of Windows?*
### Virtual keys

Windows version | Key path | Description
--- | --- | ---
2000 and later | `HKEY_LOCAL_MACHINE\System\CurrentControlSet` | See [Current control set](../system-keys/Current-control-set.html)
2000 and later | `HKEY_CURRENT_USER\Software\Classes` | Maps to UsrClass.dat
2000 and later | `HKEY_CLASSES_ROOT` | Combination of system (`HKEY_LOCAL_MACHINE\Software\Classes`) and user-specific (`HKEY_CURRENT_USER\Software\Classes`) settings
Vista and later | `HKEY_CURRENT_USER\Software\Classes\VirtualStore\Machine\Software` | User-specific changes to `HKEY_LOCAL_MACHINE\Software`

## External Links

* [HKEY_CLASSES_ROOT Key](https://learn.microsoft.com/en-us/windows/win32/sysinfo/hkey-classes-root-key)
* [Registry Virtualization](https://learn.microsoft.com/en-us/windows/win32/sysinfo/registry-virtualization)
4 changes: 2 additions & 2 deletions docs/sources/windows-registry/MUI-form.md
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,6 @@ Yet another variation seen in Windows 2000.

## External Links

* [MSDN: Multilingual User Interface](https://learn.microsoft.com/en-us/windows/win32/intl/multilingual-user-interface)
* [MSDN: Using Registry String Redirection](https://learn.microsoft.com/en-us/windows/win32/intl/using-registry-string-redirection)
* [Multilingual User Interface](https://learn.microsoft.com/en-us/windows/win32/intl/multilingual-user-interface)
* [Using Registry String Redirection](https://learn.microsoft.com/en-us/windows/win32/intl/using-registry-string-redirection)

8 changes: 4 additions & 4 deletions requirements.txt
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,9 @@ acstore >= 20230101
artifacts >= 20220219
cffi >= 1.9.1
dfdatetime >= 20221112
dfimagetools >= 20220129
dfimagetools >= 20240301
dfvfs >= 20240115
dfwinreg >= 20211207
dfwinreg >= 20240229
dtfabric >= 20230518
libbde-python >= 20220121
libcaes-python >= 20240114
Expand All @@ -20,8 +20,8 @@ libfsntfs-python >= 20211229
libfsxfs-python >= 20220829
libfvde-python >= 20220121
libfwnt-python >= 20210717
libfwps-python >= 20230131
libfwsi-python >= 20240224
libfwps-python >= 20240225
libfwsi-python >= 20240225
libhmac-python >= 20230205
libluksde-python >= 20220121
libmodi-python >= 20210405
Expand Down
135 changes: 96 additions & 39 deletions scripts/mru.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
import logging
import sys

from dfvfs.helpers import volume_scanner as dfvfs_volume_scanner
from dfvfs.lib import errors as dfvfs_errors

import pyfwps
import pyfwsi
Expand All @@ -19,6 +19,15 @@
class StdoutWriter(output_writers.StdoutOutputWriter):
"""Stdout output writer."""

_SHELL_PROPERTY_KEYS = {
'{b725f130-47ef-101a-a5f1-02608c9eebac}/4': 'PKEY_ItemTypeText',
'{b725f130-47ef-101a-a5f1-02608c9eebac}/10': 'PKEY_ItemNameDisplay',
'{b725f130-47ef-101a-a5f1-02608c9eebac}/12': 'PKEY_Size',
'{b725f130-47ef-101a-a5f1-02608c9eebac}/14': 'PKEY_DateModified',
'{dabd30ed-0043-4789-a7f8-d013a4736622}/100': (
'PKEY_ItemFolderPathDisplayNarrow'),
}

def _WriteShellItemControlPanelCategory(self, shell_item):
"""Writes a control panel category shell item to stdout.
Expand Down Expand Up @@ -80,18 +89,23 @@ def _WriteShellItemUsersPropertyView(self, shell_item):

for fwps_set in iter(fwps_store.sets):
for fwps_record in iter(fwps_set.records):
if fwps_record.value_type == 0x000b:
value_string = str(fwps_record.get_data_as_boolean())
elif fwps_record.value_type in (0x0013, 0x0014):
if fwps_record.value_type == 0x0001:
value_string = '<VT_NULL>'
elif fwps_record.value_type in (0x0003, 0x0013, 0x0014, 0x0015):
value_string = str(fwps_record.get_data_as_integer())
elif fwps_record.value_type == 0x001f:
elif fwps_record.value_type in (0x0008, 0x001e, 0x001f):
value_string = fwps_record.get_data_as_string()
elif fwps_record.value_type == 0x000b:
value_string = str(fwps_record.get_data_as_boolean())
elif fwps_record.value_type == 0x0040:
filetime = fwps_record.get_data_as_integer()
value_string = self._FormatFiletimeValue(filetime)
elif fwps_record.value_type == 0x0042:
# TODO: add support
value_string = '<VT_STREAM>'
elif fwps_record.value_type & 0xf000 == 0x1000:
# TODO: add support
value_string = '<VT_VECTOR>'
else:
raise RuntimeError(
f'Unsupported value type: 0x{fwps_record.value_type:04x}')
Expand All @@ -101,9 +115,12 @@ def _WriteShellItemUsersPropertyView(self, shell_item):
else:
entry_string = f'{fwps_record.entry_type:d}'

# TODO: print PKEY_ name
property_key = f'{{{fwps_set.identifier:s}}}/{entry_string:s}'
shell_property_key = self._SHELL_PROPERTY_KEYS.get(
property_key, 'Unknown')
self.WriteText(
f'\tProperty: {{{fwps_set.identifier:s}}}/{entry_string:s}\n')
f'\tProperty: {property_key:s} ({shell_property_key:s})\n')

self.WriteValue(
f'\t\tValue (0x{fwps_record.value_type:04x})', value_string)

Expand All @@ -130,7 +147,24 @@ def WriteShellItem(self, shell_item):
Args:
shell_item (pyfwsi.item): Shell item.
"""
self.WriteValue('Shell item', f'0x{shell_item.class_type:02x}')
if isinstance(shell_item, pyfwsi.control_panel_category):
shell_item_type = 'Control Panel Category'
elif isinstance(shell_item, pyfwsi.control_panel_item):
shell_item_type = 'Control Panel Item'
elif isinstance(shell_item, pyfwsi.file_entry):
shell_item_type = 'File Entry'
elif isinstance(shell_item, pyfwsi.network_location):
shell_item_type = 'Network Location'
elif isinstance(shell_item, pyfwsi.root_folder):
shell_item_type = 'Root Folder'
elif isinstance(shell_item, pyfwsi.users_property_view):
shell_item_type = 'User Property View'
elif isinstance(shell_item, pyfwsi.volume):
shell_item_type = 'Volume'
else:
shell_item_type = f'Unknown (0x{shell_item.class_type:02x})'

self.WriteValue('Shell item', shell_item_type)

if shell_item.delegate_folder_identifier:
self.WriteValue(
Expand Down Expand Up @@ -196,17 +230,21 @@ def WriteShellItem(self, shell_item):

self.WriteValue('\t\tFile reference', file_reference)

# TODO: add support for 0xbeef0000
# TODO: add support for 0xbeef0019
# TODO: add support for 0xbeef0025

self.WriteText('\n')
elif extension_block.signature not in (
0xbeef0000, 0xbeef0013, 0xbeef0019, 0xbeef0025, 0xbeef0026,
0xbeef0029):
self.WriteText('MARKER2\n')


def Main():
"""The main program function.
"""Entry point of console script to extract Most Recently Used information.
Returns:
bool: True if successful or False if not.
int: exit code that is provided to sys.exit().
"""
argument_parser = argparse.ArgumentParser(description=(
'Extracts Most Recently Used information from a NTUSER.DAT Registry '
Expand All @@ -216,12 +254,16 @@ def Main():
'-d', '--debug', dest='debug', action='store_true', default=False,
help='enable debug output.')

argument_parser.add_argument(
'-u', '--username', dest='username', action='store', metavar='USERNAME',
default=None, help='username within a storage media image.')

argument_parser.add_argument(
'source', nargs='?', action='store', metavar='PATH', default=None,
help=(
'path of the volume containing C:\\Windows, the filename of '
'a storage media image containing the C:\\Windows directory, '
'or the path of a NTUSER.DAT Registry file.'))
'or the path of a NTUSER.DAT or UsrClass.dat Registry file.'))

options = argument_parser.parse_args()

Expand All @@ -230,7 +272,7 @@ def Main():
print('')
argument_parser.print_help()
print('')
return False
return 1

logging.basicConfig(
level=logging.INFO, format='[%(levelname)s] %(message)s')
Expand All @@ -240,22 +282,36 @@ def Main():
if not output_writer.Open():
print('Unable to open output writer.')
print('')
return False
return 1

mediator = volume_scanner.WindowsRegistryVolumeScannerMediator()
scanner = volume_scanner.WindowsRegistryVolumeScanner(mediator=mediator)

volume_scanner_options = dfvfs_volume_scanner.VolumeScannerOptions()
volume_scanner_options = volume_scanner.VolumeScannerOptions()
volume_scanner_options.partitions = ['all']
volume_scanner_options.snapshots = ['none']
volume_scanner_options.username = options.username
volume_scanner_options.volumes = ['none']

if not scanner.ScanForWindowsVolume(
options.source, options=volume_scanner_options):
try:
result = scanner.ScanForWindowsVolume(
options.source, options=volume_scanner_options)

except dfvfs_errors.ScannerError as exception:
print(f'[ERROR] {exception!s}', file=sys.stderr)
print('')
return 1

except KeyboardInterrupt:
print('Aborted by user.', file=sys.stderr)
print('')
return 1

if not result:
print((f'Unable to retrieve the volume with the Windows directory from: '
f'{options.source:s}.'))
print('')
return False
return 1

collector_object = mru.MostRecentlyUsedCollector(
debug=options.debug, output_writer=output_writer)
Expand All @@ -264,36 +320,37 @@ def Main():
result = collector_object.Collect(scanner.registry)
if not result:
print('No Most Recently Used key found.')
else:
for mru_entry in collector_object.mru_entries:
output_writer.WriteValue('Key path', mru_entry.key_path)
output_writer.WriteValue('Value name', mru_entry.value_name)
return 0

if mru_entry.string:
output_writer.WriteValue('String', mru_entry.string)
for mru_entry in collector_object.mru_entries:
output_writer.WriteValue('Key path', mru_entry.key_path)
output_writer.WriteValue('Value name', mru_entry.value_name)

if mru_entry.shell_item_data:
shell_item = pyfwsi.item()
shell_item.copy_from_byte_stream(mru_entry.shell_item_data)
if mru_entry.string:
output_writer.WriteValue('String', mru_entry.string)

output_writer.WriteShellItem(shell_item)
if mru_entry.shell_item_data:
shell_item = pyfwsi.item()
shell_item.copy_from_byte_stream(mru_entry.shell_item_data)

output_writer.WriteShellItem(shell_item)

elif mru_entry.shell_item_list_data:
shell_item_list = pyfwsi.item_list()
shell_item_list.copy_from_byte_stream(mru_entry.shell_item_list_data)
elif mru_entry.shell_item_list_data:
shell_item_list = pyfwsi.item_list()
shell_item_list.copy_from_byte_stream(mru_entry.shell_item_list_data)

for shell_item in iter(shell_item_list.items):
output_writer.WriteShellItem(shell_item)
for index, shell_item in enumerate(shell_item_list.items):
if index > 1:
output_writer.WriteText('\n')

output_writer.WriteShellItem(shell_item)

output_writer.WriteText('')
output_writer.WriteText('\n')

output_writer.Close()

return True
return 0


if __name__ == '__main__':
if not Main():
sys.exit(1)
else:
sys.exit(0)
sys.exit(Main())
11 changes: 6 additions & 5 deletions setup.cfg
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[metadata]
name = winregrc
version = 20240224
version = 20240301
description = Windows Registry resources (winregrc)
long_description = winregrc is a Python module part of winreg-kb to allow reuse of Windows Registry resources.
long_description_content_type = text/plain
Expand Down Expand Up @@ -28,6 +28,7 @@ scripts =
scripts/application_identifiers.py
scripts/cached_credentials.py
scripts/catalog.py
scripts/delegatefolders.py
scripts/environment_variables.py
scripts/eventlog_providers.py
scripts/knownfolders.py
Expand Down Expand Up @@ -92,8 +93,8 @@ requires =
libfsxfs-python3 >= 20220829
libfvde-python3 >= 20220121
libfwnt-python3 >= 20210717
libfwps-python3 >= 20230131
libfwsi-python3 >= 20240224
libfwps-python3 >= 20240225
libfwsi-python3 >= 20240225
libhmac-python3 >= 20230205
libluksde-python3 >= 20220121
libmodi-python3 >= 20210405
Expand All @@ -113,9 +114,9 @@ requires =
python3-artifacts >= 20220219
python3-cffi >= 1.9.1
python3-dfdatetime >= 20221112
python3-dfimagetools >= 20220129
python3-dfimagetools >= 20240301
python3-dfvfs >= 20240115
python3-dfwinreg >= 20211207
python3-dfwinreg >= 20240229
python3-dtfabric >= 20230518
python3-idna >= 2.5
python3-pytsk3 >= 20210419
Expand Down
Loading

0 comments on commit 29c98d7

Please sign in to comment.