Skip to content

Commit

Permalink
add support in additional shell items
Browse files Browse the repository at this point in the history
  • Loading branch information
lotansery7 committed Mar 19, 2024
1 parent eb900c4 commit 5027eb5
Show file tree
Hide file tree
Showing 6 changed files with 235 additions and 9 deletions.
40 changes: 37 additions & 3 deletions regipy/constants.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
# ShellBags Known GUIDs
KNOWN_GUIDS = {
"008ca0b1-55b4-4c56-b8a8-4de4b299d3bE": "Account Pictures",
"008ca0b1-55b4-4c56-b8a8-4de4b299d3be": "Account Pictures",
"00bcfc5a-ed94-4e48-96a1-3f6217f21990": "RoamingTiles",
"00c6d95f-329c-409a-81d7-c46c66ea7f33": "Default Location",
"00f2886f-cd64-4fc9-8ec5-30ef6cdbe8c3": "Scanners and Cameras",
Expand Down Expand Up @@ -162,7 +162,7 @@
"6c8eec18-8d75-41b2-a177-8831d59d2d50": "Mouse",
"6dfd7c5c-2451-11d3-a299-00c04f8ef6af": "Folder Options",
"6f0cd92b-2e97-45d1-88ff-b0d186b8dedd": "Network Connections",
"7007acc7-3202-11d1-aad2-00805fc1270e": "Network Connections (Network and Dial-up Connections)",
"7007acc7-3202-11d1-aad2-00805fc1270e": "Network Connections",
"708e1662-b832-42a8-bbe1-0a77121e3908": "Tree property value folder",
"71689ac1-cc88-45d0-8a22-2943c3e7dfb3": "Music Search Results",
"71d99464-3b6b-475c-b241-e15883207529": "Sync Results Folder",
Expand Down Expand Up @@ -275,7 +275,7 @@
"b7bede81-df94-4682-a7d8-57a52620b86f": "Screenshots",
"b94237e7-57ac-4347-9151-b08c6c32d1f7": "CommonTemplates",
"b97d20bb-f46a-4c97-ba10-5e3608430854": "Startup",
"b98a2bea-7d42-4558-8bd1-832f41bac6fd": "Backup And Restore (Backup and Restore Center)",
"b98a2bea-7d42-4558-8bd1-832f41bac6fd": "Backup And Restore (Windows 7)",
"bb06c0e4-d293-4f75-8a90-cb05b6477eee": "System",
"bb64f8a7-bee7-4e1a-ab8d-7d8273f7fdb6": "Action Center Control Panel",
"bc476f4c-d9d7-4100-8d4e-e043f6dec409": "Microsoft Browser Architecture",
Expand Down Expand Up @@ -388,4 +388,38 @@
"fbf23b42-e3f0-101b-8488-00aa003e56f8": "Internet Explorer",
"00020d75-0000-0000-c000-000000000046": "Inbox",
"00020d76-0000-0000-c000-000000000046": "Inbox",
"0": "All Control Panel Items",
"1": "Appearance and Personalization",
"2": "Hardware and Sound",
"3": "Network and Internet",
"4": "Sounds, Speech, and Audio Devices",
"5": "System and Security",
"6": "Clock, Language, and Region",
"7": "Ease of Access",
"8": "Programs",
"9": "User Accounts",
"10": "Security Center",
"11": "Mobile PC",
"0ddd015d-b06c-45d5-8c4c-f59713854639": "Local Pictures",
"a0c69a99-21c8-4671-8703-7934162fcf1d": "Local Music",
"7d83ee9b-2244-4e70-b1f5-5393042af1e4": "Local Downloads",
"35286a68-3c57-41a1-bbb1-0eae73d76c95": "Local Videos",
"f42ee2d3-909f-4907-8871-4c22fc0bf756": "Local Documents",
"5ed4f38c-d3ff-4d61-b506-6820320aebfe": "All Settings",
"1bef2128-2f96-4500-ba7c-098dc0049cb2": "CLSID_DBFolderBoth",
"00021400-0000-0000-c000-000000000046": "Desktop",
"3936e9e4-d92c-4eee-a85a-bc16d5ea0819": "Frequent folders",
"45e8e0e8-7ae9-41ad-a9e8-594972716684": "Pictures",
"f5fb2c77-0e2f-4a16-a381-3e560c68bc83": "Removable Drives",
"0e5aae11-a475-4c5b-ab00-c66de400274e": "Shell File System Folder",
"f3364ba0-65b9-11ce-a9ba-00aa004ae837": "Shell File System Folder",
"5e5f29ce-e0a8-49d3-af32-7a7bdc173478": "This PC",
"e44e5d18-0652-4508-a4e2-8a090067bcb0": "Default Programs",
"e88865ea-0e1c-4e20-9aa6-edcd0212c87c": "Gallery",
"b2b4a4d1-2754-4140-a2eb-9a76d9d7cdc6": "Linux",
"2559a1f8-21d7-11d4-bdaf-00c04f60b9f0": "Windows Search",
"e342f0fe-ff1c-4c41-be37-a0271fc90396": "Intel Rapid Storage Technology",
"0bbca823-e77d-419e-9a44-5adec2c8eeb0": "NVIDIA Control Panel",
"8e0c279d-0bd1-43c3-9ebd-31c3dc5b8a77": "Windows To Go",
"00028b00-0000-0000-c000-000000000046": "Microsoft Network",
}
97 changes: 95 additions & 2 deletions regipy/plugins/ntuser/shellbags_ntuser.py
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,15 @@ def _get_shell_item_type(shell_item):
elif isinstance(shell_item, pyfwsi.root_folder):
item_type = "Root Folder"

elif isinstance(shell_item, pyfwsi.control_panel_category):
item_type = "Control Panel Category"

elif isinstance(shell_item, pyfwsi.control_panel_item):
item_type = "Control Panel Item"

elif isinstance(shell_item, pyfwsi.users_property_view):
item_type = "Users Property View"

else:
item_type = 'unknown'

Expand All @@ -67,13 +76,16 @@ def _parse_shell_item_path_segment(self, shell_item):

try:
import pyfwsi
import pyfwps
except ModuleNotFoundError as ex:
logger.exception(f"Plugin `shellbag_plugin` has missing modules, install regipy using"
f" `pip install regipy[full]` in order to install plugin dependencies. "
f"This might take some time... ")
raise ex

path_segment = None
full_path = None
location_description = None

if isinstance(shell_item, pyfwsi.volume):
if shell_item.name:
Expand All @@ -98,6 +110,10 @@ def _parse_shell_item_path_segment(self, shell_item):
elif isinstance(shell_item, pyfwsi.network_location):
if shell_item.location:
path_segment = shell_item.location
if shell_item.description:
location_description = shell_item.description
if shell_item.comments:
location_description += f', {shell_item.comments}'

elif isinstance(shell_item, pyfwsi.root_folder):
if shell_item.shell_folder_identifier in KNOWN_GUIDS:
Expand All @@ -107,10 +123,85 @@ def _parse_shell_item_path_segment(self, shell_item):
else:
path_segment = '{{{0:s}}}'.format(shell_item.shell_folder_identifier)

elif isinstance(shell_item, pyfwsi.users_property_view):
# Users property view
if shell_item.delegate_folder_identifier in KNOWN_GUIDS:
path_segment = KNOWN_GUIDS[shell_item.delegate_folder_identifier]
elif hasattr(shell_item, 'identifier') and shell_item.identifier in KNOWN_GUIDS:
path_segment = KNOWN_GUIDS[shell_item.identifier]

# Variable: Users property view
elif shell_item.property_store_data:
fwps_store = pyfwps.store()
fwps_store.copy_from_byte_stream(shell_item.property_store_data)

for fwps_set in iter(fwps_store.sets):
if fwps_set.identifier == 'b725f130-47ef-101a-a5f1-02608c9eebac':
for fwps_record in iter(fwps_set.records):

if fwps_record.entry_name:
entry_string = fwps_record.entry_name
else:
entry_string = f'{fwps_record.entry_type:d}'

property_key = f'{{{fwps_set.identifier:s}}}/{entry_string:s}'

# PKEY_DisplayName
if property_key == '{b725f130-47ef-101a-a5f1-02608c9eebac}/10':
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 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 == 0x0048:
value_string = fwps_record.get_data_as_guid()
elif fwps_record.value_type & 0xf000 == 0x1000:
# TODO: add support
value_string = '<VT_VECTOR>'
else:
value_string = None

path_segment = value_string

elif fwps_set.identifier == '28636aa6-953d-11d2-b5d6-00c04fd918d0':
for fwps_record in iter(fwps_set.records):

if fwps_record.entry_name:
entry_string = fwps_record.entry_name
else:
entry_string = f'{fwps_record.entry_type:d}'

property_key = f'{{{fwps_set.identifier:s}}}/{entry_string:s}'

# PKEY_ParsingPath
if property_key == '{28636aa6-953d-11d2-b5d6-00c04fd918d0}/30':
full_path = fwps_record.get_data_as_string()

elif isinstance(shell_item, pyfwsi.control_panel_category):
if str(shell_item.identifier) in KNOWN_GUIDS:
path_segment = KNOWN_GUIDS[str(shell_item.identifier)]
else:
path_segment = '{{{0:s}}}'.format(shell_item.identifier)

elif isinstance(shell_item, pyfwsi.control_panel_item):
if shell_item.identifier in KNOWN_GUIDS:
path_segment = KNOWN_GUIDS[shell_item.identifier]
else:
path_segment = '{{{0:s}}}'.format(shell_item.identifier)

if path_segment is None:
path_segment = '<UNKNOWN: 0x{0:02x}>'.format(shell_item.class_type)

return path_segment
return path_segment, full_path, location_description

def iter_sk(self, key, reg_path, base_path='', path=''):
try:
Expand Down Expand Up @@ -140,7 +231,7 @@ def iter_sk(self, key, reg_path, base_path='', path=''):
shell_items.copy_from_byte_stream(byte_stream, ascii_codepage=CODEPAGE)
for item in shell_items.items:
shell_type = self._get_shell_item_type(item)
value = self._parse_shell_item_path_segment(self, item)
value, full_path, location_description = self._parse_shell_item_path_segment(self, item)
if not path:
path = value
base_path = ''
Expand Down Expand Up @@ -184,6 +275,8 @@ def iter_sk(self, key, reg_path, base_path='', path=''):
'node_slot': node_slot,
'shell_type': shell_type,
'path': path,
'full path': full_path if full_path else None,
'location description': location_description if location_description else None,
'creation_time': creation_time,
'access_time': access_time,
'modification_time': modification_time,
Expand Down
101 changes: 99 additions & 2 deletions regipy/plugins/usrclass/shellbags_usrclass.py
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,15 @@ def _get_shell_item_type(shell_item):
elif isinstance(shell_item, pyfwsi.root_folder):
item_type = "Root Folder"

elif isinstance(shell_item, pyfwsi.control_panel_category):
item_type = "Control Panel Category"

elif isinstance(shell_item, pyfwsi.control_panel_item):
item_type = "Control Panel Item"

elif isinstance(shell_item, pyfwsi.users_property_view):
item_type = "Users Property View"

else:
item_type = 'unknown'

Expand All @@ -67,13 +76,16 @@ def _parse_shell_item_path_segment(self, shell_item):

try:
import pyfwsi
import pyfwps
except ModuleNotFoundError as ex:
logger.exception(f"Plugin `shellbag_plugin` has missing modules, install regipy using"
f" `pip install regipy[full]` in order to install plugin dependencies. "
f"This might take some time... ")
raise ex

path_segment = None
full_path = None
location_description = None

if isinstance(shell_item, pyfwsi.volume):
if shell_item.name:
Expand All @@ -98,6 +110,10 @@ def _parse_shell_item_path_segment(self, shell_item):
elif isinstance(shell_item, pyfwsi.network_location):
if shell_item.location:
path_segment = shell_item.location
if shell_item.description:
location_description = shell_item.description
if shell_item.comments:
location_description += f', {shell_item.comments}'

elif isinstance(shell_item, pyfwsi.root_folder):
if shell_item.shell_folder_identifier in KNOWN_GUIDS:
Expand All @@ -107,10 +123,89 @@ def _parse_shell_item_path_segment(self, shell_item):
else:
path_segment = '{{{0:s}}}'.format(shell_item.shell_folder_identifier)

elif isinstance(shell_item, pyfwsi.users_property_view):
# Users property view
if shell_item.delegate_folder_identifier in KNOWN_GUIDS:
path_segment = KNOWN_GUIDS[shell_item.delegate_folder_identifier]
elif hasattr(shell_item, 'identifier') and shell_item.identifier in KNOWN_GUIDS:
path_segment = KNOWN_GUIDS[shell_item.identifier]

# Variable
elif hasattr(shell_item, 'known_folder_identifier') and shell_item.known_folder_identifier in KNOWN_GUIDS:
path_segment = KNOWN_GUIDS[shell_item.known_folder_identifier]

# Variable: Users property view
elif shell_item.property_store_data:
fwps_store = pyfwps.store()
fwps_store.copy_from_byte_stream(shell_item.property_store_data)

for fwps_set in iter(fwps_store.sets):
if fwps_set.identifier == 'b725f130-47ef-101a-a5f1-02608c9eebac':
for fwps_record in iter(fwps_set.records):

if fwps_record.entry_name:
entry_string = fwps_record.entry_name
else:
entry_string = f'{fwps_record.entry_type:d}'

property_key = f'{{{fwps_set.identifier:s}}}/{entry_string:s}'

# PKEY_DisplayName
if property_key == '{b725f130-47ef-101a-a5f1-02608c9eebac}/10':
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 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 == 0x0048:
value_string = fwps_record.get_data_as_guid()
elif fwps_record.value_type & 0xf000 == 0x1000:
# TODO: add support
value_string = '<VT_VECTOR>'
else:
value_string = None

path_segment = value_string

elif fwps_set.identifier == '28636aa6-953d-11d2-b5d6-00c04fd918d0':
for fwps_record in iter(fwps_set.records):

if fwps_record.entry_name:
entry_string = fwps_record.entry_name
else:
entry_string = f'{fwps_record.entry_type:d}'

property_key = f'{{{fwps_set.identifier:s}}}/{entry_string:s}'

# PKEY_ParsingPath
if property_key == '{28636aa6-953d-11d2-b5d6-00c04fd918d0}/30':
full_path = fwps_record.get_data_as_string()

elif isinstance(shell_item, pyfwsi.control_panel_category):
if str(shell_item.identifier) in KNOWN_GUIDS:
path_segment = KNOWN_GUIDS[str(shell_item.identifier)]
else:
path_segment = '{{{0:s}}}'.format(shell_item.identifier)

elif isinstance(shell_item, pyfwsi.control_panel_item):
if shell_item.identifier in KNOWN_GUIDS:
path_segment = KNOWN_GUIDS[shell_item.identifier]
else:
path_segment = '{{{0:s}}}'.format(shell_item.identifier)

if path_segment is None:
path_segment = '<UNKNOWN: 0x{0:02x}>'.format(shell_item.class_type)

return path_segment
return path_segment, full_path, location_description

def iter_sk(self, key, reg_path, base_path='', path=''):
try:
Expand Down Expand Up @@ -140,7 +235,7 @@ def iter_sk(self, key, reg_path, base_path='', path=''):
shell_items.copy_from_byte_stream(byte_stream, ascii_codepage=CODEPAGE)
for item in shell_items.items:
shell_type = self._get_shell_item_type(item)
value = self._parse_shell_item_path_segment(self, item)
value, full_path, location_description = self._parse_shell_item_path_segment(self, item)
if not path:
path = value
base_path = ''
Expand Down Expand Up @@ -184,6 +279,8 @@ def iter_sk(self, key, reg_path, base_path='', path=''):
'node_slot': node_slot,
'shell_type': shell_type,
'path': path,
'full path': full_path if full_path else None,
'location description': location_description if location_description else None,
'creation_time': creation_time,
'access_time': access_time,
'modification_time': modification_time,
Expand Down
2 changes: 2 additions & 0 deletions regipy_tests/plugin_tests.py
Original file line number Diff line number Diff line change
Expand Up @@ -838,9 +838,11 @@ def test_shellbags_plugin_usrclass(transaction_usrclass):
'shell_type': 'Root Folder',
'path': 'Dropbox',
'creation_time': None,
'full path': None,
'access_time': None,
'modification_time': None,
'last_write': '2018-04-05T02:13:26.843024+00:00',
'location description': None,
'mru_order': '4-8-7-6-9-0-1-5-3-2',
'mru_order_location': 4}

Expand Down
1 change: 0 additions & 1 deletion requirements.txt
Original file line number Diff line number Diff line change
Expand Up @@ -5,4 +5,3 @@ inflection==0.5.1
pytz
tabulate==0.8.9
pytest==7.0.1
libfwsi-python==20220123
3 changes: 2 additions & 1 deletion setup.py
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,8 @@ def main():
'full': [
'click>=7.0.0',
'tabulate',
'libfwsi-python>=20220123'
'libfwsi-python>=20240315',
'libfwps-python>=20240310'
],
},
include_package_data=True,
Expand Down

0 comments on commit 5027eb5

Please sign in to comment.