├── README.md ├── __init__.py ├── __pycache__ ├── AmcacheInventorDriverBinary.cpython-37.pyc ├── AmcacheInventoryApplication.cpython-37.pyc ├── AmcacheInventoryApplicationFile.cpython-37.pyc ├── AmcacheInventoryApplicationShortcut.cpython-37.pyc ├── AmcacheInventoryDeviceContainer.cpython-37.pyc ├── AmcacheInventoryDevicePnp.cpython-37.pyc ├── AmcacheInventoryDriverBinary.cpython-37.pyc ├── MountedDevices.cpython-37.pyc ├── __init__.cpython-37.pyc └── regexplore.cpython-37.pyc ├── regexplore.py └── registryplugins ├── AmcacheInventoryApplication.py ├── AmcacheInventoryApplicationFile.py ├── AmcacheInventoryApplicationShortcut.py ├── AmcacheInventoryDeviceContainer.py ├── AmcacheInventoryDevicePnp.py ├── AmcacheInventoryDriverBinary.py ├── AppCompatCache.py ├── AppCompatCacheDep ├── VistaWin2k3Win2k8.py ├── Windows10.py ├── Windows7.py ├── Windows8.py ├── WindowsXP.py ├── __init__.py └── __pycache__ │ ├── VistaWin2k3Win2k8.cpython-37.pyc │ ├── Windows10.cpython-37.pyc │ ├── Windows7.cpython-37.pyc │ ├── Windows8.cpython-37.pyc │ ├── WindowsXP.cpython-37.pyc │ └── __init__.cpython-37.pyc ├── AppPaths.py ├── BamDam.py ├── CIDSizeMRU.py ├── MountedDevices.py ├── __init__.py └── __pycache__ ├── AmcacheInventoryApplication.cpython-37.pyc ├── AmcacheInventoryApplicationFile.cpython-37.pyc ├── AmcacheInventoryApplicationShortcut.cpython-37.pyc ├── AmcacheInventoryDeviceContainer.cpython-37.pyc ├── AmcacheInventoryDevicePnp.cpython-37.pyc ├── AmcacheInventoryDriverBinary.cpython-37.pyc ├── AppCompatCache.cpython-37.pyc ├── AppPaths.cpython-37.pyc ├── BamDam.cpython-37.pyc ├── CIDSizeMRU.cpython-37.pyc ├── CacheEntry.cpython-37.pyc ├── MountedDevices.cpython-37.pyc ├── Windows10.cpython-37.pyc └── __init__.cpython-37.pyc /README.md: -------------------------------------------------------------------------------- 1 | # Regexplore 2 | 3 | Regexplore is a Volatility plugin designed to mimic the functionality of the Registry Explorer plugins in EZsuite and regripper plugins in volatility. It allows users to list different types of registry information in memory, such as runkeys, connected devices, and more. 4 | 5 | ## Usage 6 | 7 | 1. Place the plugin folder in Volatility `volatility3/volatility3/framework/plugins/windows/registry`. 8 | 9 | 2. Run the plugin using the command `python vol.py windows.registry.regexplore -h` to display the available options and commands. 10 | 11 | ![image](https://user-images.githubusercontent.com/51376376/227634534-0801b47a-95be-45a9-ba1b-20e8954da444.png) 12 | 13 | ## Available Commands 14 | 15 | ### regplg parameter 16 | - `run_all`: export all information in csv files to be feed to splunk, or TimeLineExplorer 17 | - `MountedDevices`: Displays mounted devices including GUIDs and device information 18 | - `AmcacheInventoryApplication`: Amcache-InventoryApplication 19 | - `AmcacheInventoryApplicationFile`: Amcache-InventoryApplicationFile 20 | - `AmcacheInventoryApplicationShortcut`: Amcache-InventoryApplicationShortcut 21 | - `AmcacheInventoryDeviceContainer`: Amcache-InventoryApplicationDeviceContainer 22 | - `AmcacheInventoryDevicePnp`: Amcache-InventoryApplicationDevicePnp 23 | - `AmcacheInventoryDriverBinary`: Amcache-InventoryApplicationDriverBinary 24 | - `AppCompatCache`: Tracks application compatibility. The cache data tracks file path, size, and last modified time. In some cases, an executed flag is also available. 25 | - `AppPaths`: AppPaths Information 26 | - `BamDam`: Extracts program information and last run times from bam and dam keys 27 | - `services`: Lists the services that are automatically started when the system boots up (to-do) 28 | - `devices`: Lists the connected devices on the system (to-do) 29 | - `userassist`: Lists the programs that have been run by the user (to-do) 30 | - `mru`: Lists the most recently used files and applications (to-do) 31 | - `uninstall`: Lists the programs that have been uninstalled on the system (to-do) 32 | - `network`: Lists the network information and connections on the system (to-do) 33 | - `html`: html output (to-do) 34 | 35 | ### hive parameter 36 | - `SYSTEM`: run all plugins related to SYSTEM hive and extract information in respective csv files. 37 | - `SOFTWARE`: run all plugins related to SOFTWARE hive and extract information in respective csv files. 38 | - `Amcache`: run all plugins related to Amcache hive and extract information in respective csv files. 39 | - `NTUSER`: run all plugins related to NTUSER.dat hive and extract information in respective csv files. 40 | 41 | ## Contributing 42 | 43 | If you find any issues or have suggestions for new features, please feel free to create an issue or submit a pull request. We appreciate your contributions and recommendations to improve the Regexplore plugin! 44 | -------------------------------------------------------------------------------- /__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/0xHasanM/regexplore/8c0a95fd2444c356a5627f7a4b0b4a53aa1e9c01/__init__.py -------------------------------------------------------------------------------- /__pycache__/AmcacheInventorDriverBinary.cpython-37.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/0xHasanM/regexplore/8c0a95fd2444c356a5627f7a4b0b4a53aa1e9c01/__pycache__/AmcacheInventorDriverBinary.cpython-37.pyc -------------------------------------------------------------------------------- /__pycache__/AmcacheInventoryApplication.cpython-37.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/0xHasanM/regexplore/8c0a95fd2444c356a5627f7a4b0b4a53aa1e9c01/__pycache__/AmcacheInventoryApplication.cpython-37.pyc -------------------------------------------------------------------------------- /__pycache__/AmcacheInventoryApplicationFile.cpython-37.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/0xHasanM/regexplore/8c0a95fd2444c356a5627f7a4b0b4a53aa1e9c01/__pycache__/AmcacheInventoryApplicationFile.cpython-37.pyc -------------------------------------------------------------------------------- /__pycache__/AmcacheInventoryApplicationShortcut.cpython-37.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/0xHasanM/regexplore/8c0a95fd2444c356a5627f7a4b0b4a53aa1e9c01/__pycache__/AmcacheInventoryApplicationShortcut.cpython-37.pyc -------------------------------------------------------------------------------- /__pycache__/AmcacheInventoryDeviceContainer.cpython-37.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/0xHasanM/regexplore/8c0a95fd2444c356a5627f7a4b0b4a53aa1e9c01/__pycache__/AmcacheInventoryDeviceContainer.cpython-37.pyc -------------------------------------------------------------------------------- /__pycache__/AmcacheInventoryDevicePnp.cpython-37.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/0xHasanM/regexplore/8c0a95fd2444c356a5627f7a4b0b4a53aa1e9c01/__pycache__/AmcacheInventoryDevicePnp.cpython-37.pyc -------------------------------------------------------------------------------- /__pycache__/AmcacheInventoryDriverBinary.cpython-37.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/0xHasanM/regexplore/8c0a95fd2444c356a5627f7a4b0b4a53aa1e9c01/__pycache__/AmcacheInventoryDriverBinary.cpython-37.pyc -------------------------------------------------------------------------------- /__pycache__/MountedDevices.cpython-37.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/0xHasanM/regexplore/8c0a95fd2444c356a5627f7a4b0b4a53aa1e9c01/__pycache__/MountedDevices.cpython-37.pyc -------------------------------------------------------------------------------- /__pycache__/__init__.cpython-37.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/0xHasanM/regexplore/8c0a95fd2444c356a5627f7a4b0b4a53aa1e9c01/__pycache__/__init__.cpython-37.pyc -------------------------------------------------------------------------------- /__pycache__/regexplore.cpython-37.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/0xHasanM/regexplore/8c0a95fd2444c356a5627f7a4b0b4a53aa1e9c01/__pycache__/regexplore.cpython-37.pyc -------------------------------------------------------------------------------- /regexplore.py: -------------------------------------------------------------------------------- 1 | # This file is Copyright 2019 Volatility Foundation and licensed under the Volatility Software License 1.0 2 | # which is available at https://www.volatilityfoundation.org/license/vsl-v1.0 3 | # 4 | 5 | import datetime 6 | import logging 7 | from typing import List, Sequence, Iterable, Tuple, Union 8 | 9 | from volatility3.framework import objects, renderers, exceptions, interfaces, constants 10 | from volatility3.framework.configuration import requirements 11 | from volatility3.framework.layers.registry import RegistryHive, RegistryFormatException 12 | from volatility3.framework.renderers import TreeGrid, conversion, format_hints 13 | from volatility3.framework.symbols.windows.extensions.registry import RegValueTypes 14 | from volatility3.plugins.windows.registry import hivelist 15 | from volatility3.plugins.windows.registry.regexplore.registryplugins import * 16 | 17 | vollog = logging.getLogger(__name__) 18 | hive_list = [] 19 | 20 | class regexplore(interfaces.plugins.PluginInterface): 21 | """Registry Explorer plugins from EZsuite to volatility3""" 22 | 23 | _required_framework_version = (2, 0, 0) 24 | _version = (1, 0, 0) 25 | 26 | @classmethod 27 | def get_requirements(cls) -> List[interfaces.configuration.RequirementInterface]: 28 | return [ 29 | requirements.ModuleRequirement( 30 | name="kernel", 31 | description="Windows kernel", 32 | architectures=["Intel32", "Intel64"], 33 | ), 34 | requirements.StringRequirement( 35 | name="regplg", description="Specify plugin to run {run_all, MountedDevices, AmcacheInventoryApplication" 36 | "AmcacheInventoryDeviceContainer, AmcacheInventoryApplicationFile, AmcacheInventoryApplicationShortcut," 37 | "AmcacheInventoryInventoryDevicePnp, AppCompatCache, AppPaths, BamDam, CIDSizeMRU}" 38 | , default=None, optional=True 39 | ), 40 | requirements.StringRequirement( 41 | name="hive", description="Specify hive to run all plugins related to that hive {SYSTEM, AMCACHE, NTUSER, SOFTWARE}" 42 | , default=None, optional=True 43 | ) 44 | ] 45 | 46 | @classmethod 47 | def key_iterator( 48 | cls, 49 | hive: RegistryHive, 50 | node_path: Sequence[objects.StructType] = None, 51 | recurse: bool = False, 52 | ) -> Iterable[ 53 | Tuple[ 54 | int, bool, datetime.datetime, str, bool, interfaces.objects.ObjectInterface 55 | ] 56 | ]: 57 | """Walks through a set of nodes from a given node (last one in 58 | node_path). Avoids loops by not traversing into nodes already present 59 | in the node_path. 60 | 61 | Args: 62 | hive: The registry hive to walk 63 | node_path: The list of nodes that make up the 64 | recurse: Traverse down the node tree or stay only on the same level 65 | 66 | Yields: 67 | A tuple of results (depth, is_key, last write time, path, volatile, and the node). 68 | """ 69 | if not node_path: 70 | node_path = [hive.get_node(hive.root_cell_offset)] 71 | if not isinstance(node_path, list) or len(node_path) < 1: 72 | vollog.warning("Hive walker was not passed a valid node_path (or None)") 73 | return 74 | node = node_path[-1] 75 | key_path_items = [hive] + node_path[1:] 76 | if node.vol.type_name.endswith(constants.BANG + "_CELL_DATA"): 77 | raise RegistryFormatException( 78 | hive.name, "Encountered _CELL_DATA instead of _CM_KEY_NODE" 79 | ) 80 | last_write_time = conversion.wintime_to_datetime(node.LastWriteTime.QuadPart) 81 | 82 | for key_node in node.get_subkeys(): 83 | result = ( 84 | len(node_path), 85 | True, 86 | last_write_time, 87 | key_node, 88 | ) 89 | yield result 90 | 91 | if recurse: 92 | if key_node.vol.offset not in [x.vol.offset for x in node_path]: 93 | try: 94 | key_node.get_name() 95 | except exceptions.InvalidAddressException as excp: 96 | vollog.debug(excp) 97 | continue 98 | 99 | yield from cls.key_iterator( 100 | hive, node_path + [key_node], recurse=recurse 101 | ) 102 | 103 | for value_node in node.get_values(): 104 | result = ( 105 | len(node_path), 106 | False, 107 | last_write_time, 108 | value_node, 109 | ) 110 | yield result 111 | 112 | def _printkey_iterator( 113 | self, 114 | hive: RegistryHive, 115 | node_path: Sequence[objects.StructType] = None, 116 | recurse: bool = False, 117 | ): 118 | """Method that wraps the more generic key_iterator, to provide output 119 | for printkey specifically. 120 | 121 | Args: 122 | hive: The registry hive to walk 123 | node_path: The list of nodes that make up the 124 | recurse: Traverse down the node tree or stay only on the same level 125 | 126 | Yields: 127 | The depth, and a tuple of results (last write time, hive offset, type, path, name, data and volatile) 128 | """ 129 | for ( 130 | depth, 131 | is_key, 132 | last_write_time, 133 | node, 134 | ) in self.key_iterator(hive, node_path, recurse): 135 | if is_key: 136 | try: 137 | key_node_name = node.get_name() 138 | except ( 139 | exceptions.InvalidAddressException, 140 | RegistryFormatException, 141 | ) as excp: 142 | vollog.debug(excp) 143 | key_node_name = renderers.UnreadableValue() 144 | 145 | yield ( 146 | depth, 147 | ( 148 | last_write_time, 149 | renderers.format_hints.Hex(hive.hive_offset), 150 | "Key", 151 | key_node_name, 152 | renderers.NotApplicableValue(), 153 | ), 154 | ) 155 | else: 156 | try: 157 | value_node_name = node.get_name() or "(Default)" 158 | except ( 159 | exceptions.InvalidAddressException, 160 | RegistryFormatException, 161 | ) as excp: 162 | vollog.debug(excp) 163 | value_node_name = renderers.UnreadableValue() 164 | 165 | try: 166 | value_type = RegValueTypes(node.Type).name 167 | except ( 168 | exceptions.InvalidAddressException, 169 | RegistryFormatException, 170 | ) as excp: 171 | vollog.debug(excp) 172 | value_type = renderers.UnreadableValue() 173 | 174 | if isinstance(value_type, renderers.UnreadableValue): 175 | vollog.debug( 176 | "Couldn't read registry value type, so data is unreadable" 177 | ) 178 | value_data: Union[ 179 | interfaces.renderers.BaseAbsentValue, bytes 180 | ] = renderers.UnreadableValue() 181 | else: 182 | try: 183 | value_data = node.decode_data() 184 | 185 | if isinstance(value_data, int): 186 | value_data = format_hints.MultiTypeData( 187 | value_data, encoding="utf-8" 188 | ) 189 | elif RegValueTypes(node.Type) == RegValueTypes.REG_BINARY: 190 | value_data = format_hints.MultiTypeData( 191 | value_data, show_hex=True 192 | ) 193 | elif RegValueTypes(node.Type) == RegValueTypes.REG_MULTI_SZ: 194 | value_data = format_hints.MultiTypeData( 195 | value_data, encoding="utf-16-le", split_nulls=True 196 | ) 197 | else: 198 | value_data = format_hints.MultiTypeData( 199 | value_data, encoding="utf-16-le" 200 | ) 201 | except ( 202 | ValueError, 203 | exceptions.InvalidAddressException, 204 | RegistryFormatException, 205 | ) as excp: 206 | vollog.debug(excp) 207 | value_data = renderers.UnreadableValue() 208 | 209 | result = ( 210 | depth, 211 | ( 212 | last_write_time, 213 | key_node_name if 'key_node_name' in locals() else renderers.UnreadableValue(), 214 | value_node_name, 215 | value_data 216 | ), 217 | ) 218 | yield result 219 | 220 | def _hives_walker( 221 | self, 222 | kernel, 223 | ): 224 | hives = {} 225 | for hive in hivelist.HiveList.list_hives( 226 | self.context, 227 | self.config_path, 228 | layer_name=kernel.layer_name, 229 | symbol_table=kernel.symbol_table_name 230 | ): 231 | hives[hive.get_name()] = hive 232 | return hives 233 | 234 | def _registry_walker( 235 | self, 236 | layer_name: str, 237 | symbol_table: str, 238 | hive_list: List[hivelist.HiveList], 239 | key: str = None, 240 | hive_name: str = None, 241 | recurse: bool = False, 242 | ): 243 | 244 | for hive_path in [hive for hive in hive_list.keys() if hive_name.lower() in hive.split('\\')[-1].lower()]: 245 | try: 246 | try: 247 | node_path = hive_list[hive_path].get_key(key, return_list=True) if key else [hive_list[hive_path].get_node(hive.root_cell_offset)] 248 | except Exception as e: 249 | continue 250 | for x, y in self._printkey_iterator(hive_list[hive_path], node_path, recurse=recurse): 251 | yield (x - len(node_path), y, hive_path) 252 | except (exceptions.InvalidAddressException, KeyError, RegistryFormatException) as excp: 253 | self.handle_exceptions(excp, key, hive_list[hive_path]) 254 | 255 | @staticmethod 256 | def handle_exceptions(exception: Exception, key: str, hive: hivelist.HiveList) -> None: 257 | if isinstance(exception, KeyError): 258 | vollog.debug(f"Key '{key}' not found in Hive at offset {hex(hive.hive_offset)}.") 259 | elif isinstance(exception, RegistryFormatException): 260 | vollog.debug(exception) 261 | elif isinstance(exception, exceptions.InvalidAddressException): 262 | vollog.debug(f"Invalid address identified in Hive: {hex(exception.invalid_address)}") 263 | 264 | yield (0, (renderers.UnreadableValue(),) * 4) 265 | 266 | def run_all( 267 | self, 268 | module_mapping, 269 | _registry_walker, 270 | kernel, 271 | hive_list: List[hivelist.HiveList], 272 | hive, 273 | ): 274 | progress = 0 275 | for module_name, module_function in module_mapping.items(): 276 | progress += 1 277 | module_function(_registry_walker, kernel, hive_list=hive_list, hive=hive, file_output=True) 278 | yield (0, (module_name, f'regexplore/{module_name}.csv', f'{progress}/{len(module_mapping)}')) 279 | 280 | def run(self): 281 | kernel = self.context.modules[self.config["kernel"]] 282 | regplg = self.config.get("regplg", None) 283 | hive = self.config.get("hive", None) 284 | 285 | # Define module and hive mappings 286 | module_mapping = { 287 | "mounteddevices": MountedDevices.MountedDevices, 288 | "amcacheinventoryapplication": AmcacheInventoryApplication.AmcacheInventoryApplication, 289 | "amcacheinventoryapplicationfile": AmcacheInventoryApplicationFile.AmcacheInventoryApplicationFile, 290 | "amcacheinventoryapplicationshortcut": AmcacheInventoryApplicationShortcut.AmcacheInventoryApplicationShortcut, 291 | "amcacheinventorydevicecontainer": AmcacheInventoryDeviceContainer.AmcacheInventoryDeviceContainer, 292 | "amcacheinventorydevicepnp": AmcacheInventoryDevicePnp.AmcacheInventoryDevicePnp, 293 | "amcacheinventorydriverbinary": AmcacheInventoryDriverBinary.AmcacheInventoryDriverBinary, 294 | "appcompatcache": AppCompatCache.AppCompatCache, 295 | "apppaths": AppPaths.AppPaths, 296 | "bamdam": BamDam.BamDam, 297 | "cidsizemru": CIDSizeMRU.CIDSizeMRU 298 | } 299 | 300 | hive_mapping = { 301 | "system": { 302 | "mounteddevices": module_mapping["mounteddevices"], 303 | "appcompatcache": module_mapping["appcompatcache"], 304 | "bamdam": module_mapping["bamdam"] 305 | }, 306 | "software": { 307 | "apppaths": module_mapping["apppaths"], 308 | }, 309 | "amcache": { 310 | "amcacheinventoryapplication": module_mapping["amcacheinventoryapplication"], 311 | "amcacheinventoryapplicationfile": module_mapping["amcacheinventoryapplicationfile"], 312 | "amcacheinventoryapplicationshortcut": module_mapping["amcacheinventoryapplicationshortcut"], 313 | "amcacheinventorydevicecontainer": module_mapping["amcacheinventorydevicecontainer"], 314 | "amcacheinventorydevicepnp": module_mapping["amcacheinventorydevicepnp"], 315 | "amcacheinventorydriverbinary": module_mapping["amcacheinventorydriverbinary"], 316 | }, 317 | "ntuser": { 318 | "apppaths": module_mapping["apppaths"], 319 | "cidsizemru": module_mapping["cidsizemru"] 320 | } 321 | } 322 | 323 | # Get the list of hives using the generator function 324 | hive_list = self._hives_walker(kernel) 325 | # Check if either hive or regplg is specified 326 | if regplg and not hive: 327 | if regplg.lower() == 'run_all': 328 | return TreeGrid( 329 | columns=[ 330 | ("Module name", str), 331 | ("Output path", str), 332 | ("Progress", str), 333 | ], 334 | generator=self.run_all(module_mapping, self._registry_walker, kernel, hive_list, hive), 335 | ) 336 | else: 337 | if regplg.lower() not in module_mapping: 338 | allowed_values = ', '.join(module_mapping.keys()) 339 | raise ValueError(f"Invalid regplg value. Allowed values are {allowed_values}") 340 | 341 | module_function = module_mapping[regplg.lower()] 342 | return module_function(self._registry_walker, kernel, hive_list) 343 | 344 | elif hive and not regplg: 345 | if hive.lower() not in hive_mapping: 346 | allowed_values = ', '.join(hive_mapping.keys()) 347 | raise ValueError(f"Invalid hive value. Allowed values are {allowed_values}") 348 | 349 | return TreeGrid( 350 | columns=[ 351 | ("Module name", str), 352 | ("Output path", str), 353 | ("Progress", str), 354 | ], 355 | generator=self.run_all(hive_mapping[hive.lower()], self._registry_walker, kernel, hive_list, hive), 356 | ) 357 | 358 | else: 359 | raise ValueError(f"You need to specify either hive or regplg") -------------------------------------------------------------------------------- /registryplugins/AmcacheInventoryApplication.py: -------------------------------------------------------------------------------- 1 | import datetime 2 | from volatility3.framework.renderers import TreeGrid, format_hints 3 | from volatility3.framework.interfaces import layers 4 | import os 5 | import codecs 6 | 7 | # Define the columns for the TreeGrid 8 | COLUMNS = [ 9 | ("Timestamp", str), 10 | ("Name", str), 11 | ("Version", str), 12 | ("Publisher", str), 13 | ("Source", str), 14 | ("RootDirPath", str), 15 | ("UninstallString", str) 16 | ] 17 | 18 | def write_result_to_csv( 19 | _registry_walker, 20 | kernel, 21 | hive_list, 22 | key=None, 23 | hive_name=None, 24 | output_path='regexplore/AmcacheInventoryApplication.csv' 25 | ): 26 | 27 | os.makedirs('regexplore', exist_ok=True) 28 | 29 | entries = process_values( 30 | _registry_walker, 31 | kernel, 32 | hive_list, 33 | key, 34 | hive_name 35 | ) 36 | 37 | with open(output_path, 'w', encoding='utf-8') as file_handle: 38 | header = "Timestamp,Name,Version,Publisher,Source,RootDirPath,UninstallString\n" 39 | file_handle.write(header) 40 | for registry_key in entries.keys(): 41 | if entries[registry_key].get("Name", "") == "": 42 | continue 43 | file_handle.write( 44 | f'{entries[registry_key].get("Timestamp", "")},' 45 | f'{entries[registry_key].get("Name", "").replace(",", ";")},' 46 | f'{entries[registry_key].get("Version", "").replace(",", ";")},' 47 | f'{entries[registry_key].get("Publisher", "").replace(",", ";")},' 48 | f'{entries[registry_key].get("Source", "").replace(",", ";")},' 49 | f'{entries[registry_key].get("RootDirPath", "").replace(",", ";")},' 50 | f'{entries[registry_key].get("UninstallString", "").replace(",", ";")}\n' 51 | ) 52 | 53 | return 54 | def ValuesOut( 55 | _registry_walker, 56 | kernel, 57 | hive_list, 58 | key, 59 | hive_name 60 | ): 61 | 62 | entries = process_values( 63 | _registry_walker, 64 | kernel, 65 | hive_list, 66 | key, 67 | hive_name 68 | ) 69 | 70 | for registry_key in entries.keys(): 71 | if entries[registry_key].get("Name", "") == "": 72 | continue 73 | result = ( 74 | 0, 75 | ( 76 | entries[registry_key].get("Timestamp", ""), 77 | entries[registry_key].get("Name", "").replace(",", ";"), 78 | entries[registry_key].get("Version", "").replace(",", ";"), 79 | entries[registry_key].get("Publisher", "").replace(",", ";"), 80 | entries[registry_key].get("Source", "").replace(",", ";"), 81 | entries[registry_key].get("RootDirPath", "").replace(",", ";"), 82 | entries[registry_key].get("UninstallString", "").replace(",", ";"), 83 | ), 84 | ) 85 | yield result 86 | def process_values( 87 | _registry_walker, 88 | kernel, 89 | hive_list, 90 | key=None, 91 | hive_name=None, 92 | file_output=False 93 | ): 94 | 95 | """ 96 | Process registry values and return Programs data. 97 | """ 98 | # Define options for the registry walker 99 | walker_options = { 100 | "layer_name": kernel.layer_name, 101 | "symbol_table": kernel.symbol_table_name, 102 | "hive_list": hive_list, 103 | "key": key, 104 | "hive_name": hive_name, 105 | "recurse": True, 106 | } 107 | 108 | # Iterate through the registry walker output 109 | entries = {} 110 | for subkey in _registry_walker(**walker_options): 111 | # Only process values, not keys 112 | if str(subkey[1][2]) != 'Key': 113 | registry_key = subkey[1][1] 114 | registry_value = subkey[1][2] 115 | try: 116 | registry_data = codecs.decode(subkey[1][3], "utf-16le") 117 | except: 118 | continue 119 | 120 | # Initialize the registry key entry if it doesn't exist 121 | if registry_key not in entries: 122 | entries[registry_key] = {'Timestamp': str(subkey[1][0])} 123 | 124 | # Store the registry value and data 125 | entries[registry_key][registry_value] = registry_data 126 | return entries 127 | 128 | def AmcacheInventoryApplication( 129 | _registry_walker, 130 | kernel, 131 | hive_list, 132 | hive=None, 133 | file_output=False 134 | ): 135 | """ 136 | Create a TreeGrid with Programs data. 137 | """ 138 | # Define the registry key and hive name to process 139 | key = 'ROOT\InventoryApplication' 140 | hive_name = 'Amcache.hve' 141 | 142 | if file_output: 143 | write_result_to_csv( 144 | _registry_walker, 145 | kernel, 146 | hive_list, 147 | key, 148 | hive_name 149 | ) 150 | return 151 | else: 152 | generator = ValuesOut( 153 | _registry_walker, 154 | kernel, 155 | hive_list, 156 | key, 157 | hive_name, 158 | ) 159 | 160 | return TreeGrid( 161 | columns=COLUMNS, 162 | generator=generator, 163 | ) -------------------------------------------------------------------------------- /registryplugins/AmcacheInventoryApplicationFile.py: -------------------------------------------------------------------------------- 1 | import datetime 2 | from volatility3.framework.renderers import TreeGrid, format_hints 3 | import os 4 | import codecs 5 | # Define the columns for the TreeGrid 6 | COLUMNS = [ 7 | ("Timestamp", str), 8 | ("Path", str), 9 | ("Name", str), 10 | ("Product", str), 11 | ("Publisher", str), 12 | ("Version", str), 13 | ("SHA1", str) 14 | ] 15 | 16 | def write_result_to_csv( 17 | _registry_walker, 18 | kernel, 19 | hive_list, 20 | key=None, 21 | hive_name=None, 22 | output_path='regexplore/AmcacheInventoryApplicationFile.csv' 23 | ): 24 | 25 | os.makedirs('regexplore', exist_ok=True) 26 | 27 | entries = process_values( 28 | _registry_walker, 29 | kernel, 30 | hive_list, 31 | key, 32 | hive_name 33 | ) 34 | 35 | with open(output_path, 'w', encoding='utf-8') as file_handle: 36 | header = "Timestamp,Path,Name,Product,Publisher,Version,SHA1\n" 37 | file_handle.write(header) 38 | 39 | for registry_key in entries.keys(): 40 | if entries[registry_key].get("Name", "") == "": 41 | continue 42 | file_handle.write( 43 | f'{entries[registry_key].get("Timestamp", "")},' 44 | f'{entries[registry_key].get("LowerCaseLongPath", "").replace(",", ";")},' 45 | f'{entries[registry_key].get("Name", "").replace(",", ";")},' 46 | f'{entries[registry_key].get("ProductName", "").replace(",", ";")},' 47 | f'{entries[registry_key].get("Publisher", "").replace(",", ";")},' 48 | f'{entries[registry_key].get("Version", "").replace(",", ";")},' 49 | f'{str(entries[registry_key].get("FileId", "")).lstrip("0000")}\n' 50 | ) 51 | 52 | def ValuesOut( 53 | _registry_walker, 54 | kernel, 55 | hive_list, 56 | key, 57 | hive_name 58 | ): 59 | 60 | entries = process_values( 61 | _registry_walker, 62 | kernel, 63 | hive_list, 64 | key, 65 | hive_name 66 | ) 67 | 68 | for registry_key in entries.keys(): 69 | if entries[registry_key].get("Name", "") == "": 70 | continue 71 | result = ( 72 | 0, 73 | ( 74 | entries[registry_key].get("Timestamp", ""), 75 | entries[registry_key].get("LowerCaseLongPath", "").replace(",", ";"), 76 | entries[registry_key].get("Name", "").replace(",", ";"), 77 | entries[registry_key].get("ProductName", "").replace(",", ";"), 78 | entries[registry_key].get("Publisher", "").replace(",", ";"), 79 | entries[registry_key].get("Version", "").replace(",", ";"), 80 | str(entries[registry_key].get("FileId", "")).lstrip('0000') 81 | ), 82 | ) 83 | yield result 84 | 85 | def process_values( 86 | _registry_walker, 87 | kernel, 88 | hive_list, 89 | key=None, 90 | hive_name=None, 91 | file_output=False 92 | ): 93 | 94 | """ 95 | Process registry values and return Programs data. 96 | """ 97 | # Define options for the registry walker 98 | walker_options = { 99 | "layer_name": kernel.layer_name, 100 | "symbol_table": kernel.symbol_table_name, 101 | "hive_list": hive_list, 102 | "key": key, 103 | "hive_name": hive_name, 104 | "recurse": True, 105 | } 106 | 107 | # Iterate through the registry walker output 108 | entries = {} 109 | for subkey in _registry_walker(**walker_options): 110 | # Only process values, not keys 111 | if str(subkey[1][2]) != 'Key': 112 | registry_key = subkey[1][1] 113 | registry_value = subkey[1][2] 114 | try: 115 | registry_data = codecs.decode(subkey[1][3], "utf-16le") 116 | except: 117 | continue 118 | # Initialize the registry key entry if it doesn't exist 119 | if registry_key not in entries: 120 | entries[registry_key] = {'Timestamp': str(subkey[1][0])} 121 | # Store the registry value and data 122 | entries[registry_key][registry_value] = registry_data 123 | 124 | return entries 125 | 126 | def AmcacheInventoryApplicationFile( 127 | _registry_walker, 128 | kernel, 129 | hive_list, 130 | hive = None, 131 | file_output=False 132 | ): 133 | 134 | """ 135 | Create a TreeGrid with Programs data. 136 | """ 137 | # Define the registry key and hive name to process 138 | key = 'ROOT\InventoryApplicationFile' 139 | hive_name = 'Amcache.hve' 140 | 141 | if file_output: 142 | write_result_to_csv( 143 | _registry_walker, 144 | kernel, 145 | hive_list, 146 | key, 147 | hive_name 148 | ) 149 | return 150 | else: 151 | generator = ValuesOut( 152 | _registry_walker, 153 | kernel, 154 | hive_list, 155 | key, 156 | hive_name, 157 | ) 158 | 159 | return TreeGrid( 160 | columns=COLUMNS, 161 | generator=generator, 162 | ) -------------------------------------------------------------------------------- /registryplugins/AmcacheInventoryApplicationShortcut.py: -------------------------------------------------------------------------------- 1 | import datetime 2 | from volatility3.framework.renderers import TreeGrid, format_hints 3 | from volatility3.framework.interfaces import layers 4 | import os 5 | import codecs 6 | # Define the columns for the TreeGrid 7 | COLUMNS = [ 8 | ("Timestamp", str), 9 | ("Path", str) 10 | ] 11 | 12 | def write_result_to_csv( 13 | _registry_walker, 14 | kernel, 15 | hive_list, 16 | key=None, 17 | hive_name=None, 18 | output_path='regexplore/AmcacheInventoryApplicationShortcut.csv' 19 | ): 20 | 21 | os.makedirs('regexplore', exist_ok=True) 22 | 23 | entries = process_values( 24 | _registry_walker, 25 | kernel, 26 | hive_list, 27 | key, 28 | hive_name 29 | ) 30 | 31 | with open(output_path, 'w', encoding='utf-8') as file_handle: 32 | header = "Timestamp,ShortcutPath\n" 33 | file_handle.write(header) 34 | for registry_key in entries.keys(): 35 | if entries[registry_key].get("ShortcutPath", "") == "": 36 | continue 37 | file_handle.write( 38 | f'{entries[registry_key].get("Timestamp", "")},' 39 | f'{entries[registry_key].get("ShortcutPath", "").replace(",", ";")}\n' 40 | ) 41 | 42 | return 43 | 44 | def ValuesOut( 45 | _registry_walker, 46 | kernel, 47 | hive_list, 48 | key, 49 | hive_name 50 | ): 51 | 52 | entries = process_values( 53 | _registry_walker, 54 | kernel, 55 | hive_list, 56 | key, 57 | hive_name 58 | ) 59 | 60 | for registry_key in entries.keys(): 61 | if entries[registry_key].get("ShortcutPath", "") == "": 62 | continue 63 | result = ( 64 | 0, 65 | ( 66 | entries[registry_key].get("Timestamp", ""), 67 | entries[registry_key].get("ShortcutPath", "").replace(",", ";"), 68 | ), 69 | ) 70 | yield result 71 | 72 | def process_values( 73 | _registry_walker, 74 | kernel, 75 | hive_list, 76 | key=None, 77 | hive_name=None, 78 | file_output=False 79 | ): 80 | 81 | """ 82 | Process registry values and return Programs data. 83 | """ 84 | # Define options for the registry walker 85 | walker_options = { 86 | "layer_name": kernel.layer_name, 87 | "symbol_table": kernel.symbol_table_name, 88 | "hive_list": hive_list, 89 | "key": key, 90 | "hive_name": hive_name, 91 | "recurse": True, 92 | } 93 | 94 | # Iterate through the registry walker output 95 | entries = {} 96 | for subkey in _registry_walker(**walker_options): 97 | # Only process values, not keys 98 | if str(subkey[1][2]) != 'Key': 99 | registry_key = subkey[1][1] 100 | registry_value = subkey[1][2] 101 | try: 102 | registry_data = codecs.decode(subkey[1][3], "utf-16le") 103 | except: 104 | continue 105 | 106 | # Initialize the registry key entry if it doesn't exist 107 | if registry_key not in entries: 108 | entries[registry_key] = {'Timestamp': str(subkey[1][0])} 109 | 110 | # Store the registry value and data 111 | entries[registry_key][registry_value] = registry_data 112 | return entries 113 | 114 | def AmcacheInventoryApplicationShortcut( 115 | _registry_walker, 116 | kernel, 117 | hive_list, 118 | hive = None, 119 | file_output=False 120 | ): 121 | """ 122 | Create a TreeGrid with Programs data. 123 | """ 124 | # Define the registry key and hive name to process 125 | key = 'ROOT\InventoryApplicationShortcut' 126 | hive_name = 'Amcache.hve' 127 | 128 | if file_output: 129 | write_result_to_csv( 130 | _registry_walker, 131 | kernel, 132 | hive_list, 133 | key, 134 | hive_name 135 | ) 136 | return 137 | else: 138 | generator = ValuesOut( 139 | _registry_walker, 140 | kernel, 141 | hive_list, 142 | key, 143 | hive_name, 144 | ) 145 | 146 | return TreeGrid( 147 | columns=COLUMNS, 148 | generator=generator, 149 | ) -------------------------------------------------------------------------------- /registryplugins/AmcacheInventoryDeviceContainer.py: -------------------------------------------------------------------------------- 1 | import datetime 2 | from volatility3.framework.renderers import TreeGrid, format_hints 3 | from volatility3.framework.interfaces import layers 4 | import os 5 | import codecs 6 | # Define the columns for the TreeGrid 7 | COLUMNS = [ 8 | ("Timestamp", str), 9 | ("ModelName", str), 10 | ("FriendlyName", str), 11 | ("ModelNumber", str), 12 | ("Manufacturer", str), 13 | ("PrimaryCategory", str), 14 | ("ModelID", str) 15 | ] 16 | 17 | def write_result_to_csv( 18 | _registry_walker, 19 | kernel, 20 | hive_list, 21 | key=None, 22 | hive_name=None, 23 | output_path='regexplore/AmcacheInventoryDeviceContainer.csv' 24 | ): 25 | 26 | walker_options = { 27 | "layer_name": kernel.layer_name, 28 | "symbol_table": kernel.symbol_table_name, 29 | "hive_list": hive_list, 30 | "key": key, 31 | "hive_name": hive_name, 32 | "recurse": True, 33 | } 34 | 35 | os.makedirs('regexplore', exist_ok=True) 36 | 37 | entries = process_values( 38 | _registry_walker, 39 | kernel, 40 | hive_list, 41 | key, 42 | hive_name 43 | ) 44 | 45 | with open(output_path, 'w', encoding='utf-8') as file_handle: 46 | header = "Timestamp,ModelName,FriendlyName,ModelNumber,Manufacturer,PrimaryCategory,ModelID\n" 47 | file_handle.write(header) 48 | for registry_key in entries.keys(): 49 | if entries[registry_key].get("ModelName", "") == "": 50 | continue 51 | file_handle.write( 52 | f'{entries[registry_key].get("Timestamp", "")},' 53 | f'{entries[registry_key].get("ModelName", "").replace(",", ";")},' 54 | f'{entries[registry_key].get("FriendlyName", "").replace(",", ";")},' 55 | f'{entries[registry_key].get("ModelNumber", "").replace(",", ";")},' 56 | f'{entries[registry_key].get("Manufacturer", "").replace(",", ";")},' 57 | f'{entries[registry_key].get("PrimaryCategory", "").replace(",", ";")},' 58 | f'{entries[registry_key].get("ModelId", "").replace(",", ";")}\n' 59 | ) 60 | 61 | return 62 | 63 | def ValuesOut( 64 | _registry_walker, 65 | kernel, 66 | hive_list, 67 | key, 68 | hive_name 69 | ): 70 | 71 | entries = process_values( 72 | _registry_walker, 73 | kernel, 74 | hive_list, 75 | key, 76 | hive_name 77 | ) 78 | 79 | for registry_key in entries.keys(): 80 | if entries[registry_key].get("ModelName", "") == "": 81 | continue 82 | result = ( 83 | 0, 84 | ( 85 | entries[registry_key].get("Timestamp", ""), 86 | entries[registry_key].get("ModelName", "").replace(",", ";"), 87 | entries[registry_key].get("FriendlyName", "").replace(",", ";"), 88 | entries[registry_key].get("ModelNumber", "").replace(",", ";"), 89 | entries[registry_key].get("Manufacturer", "").replace(",", ";"), 90 | entries[registry_key].get("PrimaryCategory", "").replace(",", ";"), 91 | entries[registry_key].get("ModelId", "").replace(",", ";"), 92 | ), 93 | ) 94 | yield result 95 | 96 | def process_values( 97 | _registry_walker, 98 | kernel, 99 | hive_list, 100 | key=None, 101 | hive_name=None, 102 | file_output=False 103 | ): 104 | 105 | """ 106 | Process registry values and return Programs data. 107 | """ 108 | # Define options for the registry walker 109 | walker_options = { 110 | "layer_name": kernel.layer_name, 111 | "symbol_table": kernel.symbol_table_name, 112 | "hive_list": hive_list, 113 | "key": key, 114 | "hive_name": hive_name, 115 | "recurse": True, 116 | } 117 | 118 | # Iterate through the registry walker output 119 | entries = {} 120 | for subkey in _registry_walker(**walker_options): 121 | # Only process values, not keys 122 | if str(subkey[1][2]) != 'Key': 123 | registry_key = subkey[1][1] 124 | registry_value = subkey[1][2] 125 | try: 126 | registry_data = codecs.decode(subkey[1][3], "utf-16le") 127 | except: 128 | continue 129 | # Initialize the registry key entry if it doesn't exist 130 | if registry_key not in entries: 131 | entries[registry_key] = {'Timestamp': str(subkey[1][0])} 132 | # Store the registry value and data 133 | entries[registry_key][registry_value] = registry_data 134 | return entries 135 | 136 | def AmcacheInventoryDeviceContainer( 137 | _registry_walker, 138 | kernel, 139 | hive_list, 140 | hive=None, 141 | file_output=False 142 | ): 143 | """ 144 | Create a TreeGrid with Programs data. 145 | """ 146 | # Define the registry key and hive name to process 147 | key = 'ROOT\InventoryDeviceContainer' 148 | hive_name = 'Amcache.hve' 149 | 150 | if file_output: 151 | write_result_to_csv( 152 | _registry_walker, 153 | kernel, 154 | hive_list, 155 | key, 156 | hive_name 157 | ) 158 | return 159 | else: 160 | generator = ValuesOut( 161 | _registry_walker, 162 | kernel, 163 | hive_list, 164 | key, 165 | hive_name, 166 | ) 167 | 168 | return TreeGrid( 169 | columns=COLUMNS, 170 | generator=generator, 171 | ) -------------------------------------------------------------------------------- /registryplugins/AmcacheInventoryDevicePnp.py: -------------------------------------------------------------------------------- 1 | import datetime 2 | from volatility3.framework.renderers import TreeGrid, format_hints 3 | from volatility3.framework.interfaces import layers 4 | import os 5 | import codecs 6 | # Define the columns for the TreeGrid 7 | COLUMNS = [ 8 | ("Timestamp", str), 9 | ("Model", str), 10 | ("Manufacturer", str), 11 | ("Description", str), 12 | ("InstallDate", str), 13 | ("ParentId", str), 14 | ("MatchingID", str) 15 | ] 16 | 17 | def write_result_to_csv( 18 | _registry_walker, 19 | kernel, 20 | hive_list, 21 | key=None, 22 | hive_name=None, 23 | output_path='regexplore/AmcacheInventoryDevicePnp.csv' 24 | ): 25 | 26 | 27 | os.makedirs('regexplore', exist_ok=True) 28 | 29 | entries = process_values( 30 | _registry_walker, 31 | kernel, 32 | hive_list, 33 | key, 34 | hive_name 35 | ) 36 | 37 | with open(output_path, 'w', encoding='utf-8') as file_handle: 38 | header = "Timestamp,Model,Manufacturer,Description,InstallDate,ParentId,MatchingID\n" 39 | file_handle.write(header) 40 | for registry_key in entries.keys(): 41 | if entries[registry_key].get("DriverLastWriteTime", "") == "": 42 | continue 43 | file_handle.write( 44 | f'{entries[registry_key].get("Timestamp", "")},' 45 | f'{entries[registry_key].get("Model", "").replace(",", ";")},' 46 | f'{entries[registry_key].get("Manufacturer", "").replace(",", ";")},' 47 | f'{entries[registry_key].get("Description", "").replace(",", ";")},' 48 | f'{entries[registry_key].get("InstallDate", "").replace(",", ";")},' 49 | f'{entries[registry_key].get("ParentId", "").replace(",", ";")},' 50 | f'{entries[registry_key].get("MatchingID", "").replace(",", ";")}\n' 51 | ) 52 | 53 | return 54 | 55 | def ValuesOut( 56 | _registry_walker, 57 | kernel, 58 | hive_list, 59 | key, 60 | hive_name 61 | ): 62 | 63 | entries = process_values( 64 | _registry_walker, 65 | kernel, 66 | hive_list, 67 | key, 68 | hive_name 69 | ) 70 | 71 | for registry_key in entries.keys(): 72 | if entries[registry_key].get("Model", "") == "": 73 | continue 74 | result = ( 75 | 0, 76 | ( 77 | entries[registry_key].get("Timestamp", ""), 78 | entries[registry_key].get("Model", "").replace(",", ";"), 79 | entries[registry_key].get("Manufacturer", "").replace(",", ";"), 80 | entries[registry_key].get("Description", "").replace(",", ";"), 81 | entries[registry_key].get("InstallDate", "").replace(",", ";"), 82 | entries[registry_key].get("ParentId", "").replace(",", ";"), 83 | entries[registry_key].get("MatchingID", "").replace(",", ";") 84 | ), 85 | ) 86 | yield result 87 | 88 | def process_values( 89 | _registry_walker, 90 | kernel, 91 | hive_list, 92 | key=None, 93 | hive_name=None, 94 | file_output=False 95 | ): 96 | 97 | """ 98 | Process registry values and return Programs data. 99 | """ 100 | # Define options for the registry walker 101 | walker_options = { 102 | "layer_name": kernel.layer_name, 103 | "symbol_table": kernel.symbol_table_name, 104 | "hive_list": hive_list, 105 | "key": key, 106 | "hive_name": hive_name, 107 | "recurse": True, 108 | } 109 | 110 | # Iterate through the registry walker output 111 | entries = {} 112 | for subkey in _registry_walker(**walker_options): 113 | # Only process values, not keys 114 | if str(subkey[1][2]) != 'Key': 115 | registry_key = subkey[1][1] 116 | registry_value = subkey[1][2] 117 | try: 118 | registry_data = codecs.decode(subkey[1][3], "utf-16le") 119 | except: 120 | continue 121 | 122 | # Initialize the registry key entry if it doesn't exist 123 | if registry_key not in entries: 124 | entries[registry_key] = {'Timestamp': str(subkey[1][0])} 125 | 126 | # Store the registry value and data 127 | entries[registry_key][registry_value] = registry_data 128 | return entries 129 | 130 | 131 | def AmcacheInventoryDevicePnp( 132 | _registry_walker, 133 | kernel, 134 | hive_list, 135 | hive = None, 136 | file_output=False 137 | ): 138 | """ 139 | Create a TreeGrid with Programs data. 140 | """ 141 | # Define the registry key and hive name to process 142 | key = 'ROOT\InventoryDevicePnp' 143 | hive_name = 'Amcache.hve' 144 | 145 | if file_output: 146 | write_result_to_csv( 147 | _registry_walker, 148 | kernel, 149 | hive_list, 150 | key, 151 | hive_name 152 | ) 153 | return 154 | else: 155 | generator = ValuesOut( 156 | _registry_walker, 157 | kernel, 158 | hive_list, 159 | key, 160 | hive_name, 161 | ) 162 | 163 | return TreeGrid( 164 | columns=COLUMNS, 165 | generator=generator, 166 | ) -------------------------------------------------------------------------------- /registryplugins/AmcacheInventoryDriverBinary.py: -------------------------------------------------------------------------------- 1 | import datetime 2 | from volatility3.framework.renderers import TreeGrid, format_hints 3 | from volatility3.framework.interfaces import layers 4 | import os 5 | import codecs 6 | # Define the columns for the TreeGrid 7 | COLUMNS = [ 8 | ("Timestamp", str), 9 | ("DriverLastWriteTime", str), 10 | ("DriverCompany", str), 11 | ("Product", str), 12 | ("ProductVersion", str), 13 | ("DriverName", str), 14 | ("DriverVersion", str), 15 | ("Path", str), 16 | ("SHA1", str), 17 | ] 18 | 19 | def write_result_to_csv( 20 | _registry_walker, 21 | kernel, 22 | hive_list, 23 | key=None, 24 | hive_name=None, 25 | output_path='regexplore/AmcacheInventoryDriverBinary.csv' 26 | ): 27 | 28 | os.makedirs('regexplore', exist_ok=True) 29 | 30 | entries = process_values( 31 | _registry_walker, 32 | kernel, 33 | hive_list, 34 | key, 35 | hive_name 36 | ) 37 | 38 | with open(output_path, 'w', encoding='utf-8') as file_handle: 39 | header = "Timestamp,DriverLastWriteTime,DriverCompany,DriverName,DriverVersion,Product,ProductVersion,Path,SHA1\n" 40 | file_handle.write(header) 41 | for registry_key in entries.keys(): 42 | if entries[registry_key].get("DriverLastWriteTime", "") == "": 43 | continue 44 | file_handle.write( 45 | f'{entries[registry_key].get("Timestamp", "")},' 46 | f'{entries[registry_key].get("DriverLastWriteTime", "").replace(",", ";")},' 47 | f'{entries[registry_key].get("DriverCompany", "").replace(",", ";")},' 48 | f'{entries[registry_key].get("Product", "").replace(",", ";")},' 49 | f'{entries[registry_key].get("ProductVersion", "").replace(",", ";")},' 50 | f'{entries[registry_key].get("DriverName", "").replace(",", ";")},' 51 | f'{entries[registry_key].get("DriverVersion", "").replace(",", ";")},' 52 | f'{entries[registry_key].get("Path", "").replace(",", ";")},' 53 | f'{entries[registry_key].get("DriverId", "").replace("0000", "")}\n' 54 | ) 55 | 56 | return 57 | 58 | def ValuesOut( 59 | _registry_walker, 60 | kernel, 61 | hive_list, 62 | key, 63 | hive_name 64 | ): 65 | 66 | entries = process_values( 67 | _registry_walker, 68 | kernel, 69 | hive_list, 70 | key, 71 | hive_name 72 | ) 73 | 74 | for registry_key in entries.keys(): 75 | if entries[registry_key].get("DriverLastWriteTime", "") == "": 76 | continue 77 | result = ( 78 | 0, 79 | ( 80 | entries[registry_key].get("Timestamp", ""), 81 | entries[registry_key].get("DriverLastWriteTime", "").replace(",", ";"), 82 | entries[registry_key].get("DriverCompany", "").replace(",", ";"), 83 | entries[registry_key].get("Product", "").replace(",", ";"), 84 | entries[registry_key].get("ProductVersion", "").replace(",", ";"), 85 | entries[registry_key].get("DriverName", "").replace(",", ";"), 86 | entries[registry_key].get("DriverVersion", "").replace(",", ";"), 87 | entries[registry_key].get("Path", "").replace(",", ";"), 88 | entries[registry_key].get("DriverId", "").replace("0000", ""), 89 | ), 90 | ) 91 | yield result 92 | 93 | def process_values( 94 | _registry_walker, 95 | kernel, 96 | hive_list, 97 | key=None, 98 | hive_name=None, 99 | file_output=False 100 | ): 101 | 102 | """ 103 | Process registry values and return Programs data. 104 | """ 105 | # Define options for the registry walker 106 | walker_options = { 107 | "layer_name": kernel.layer_name, 108 | "symbol_table": kernel.symbol_table_name, 109 | "hive_list": hive_list, 110 | "key": key, 111 | "hive_name": hive_name, 112 | "recurse": True, 113 | } 114 | 115 | # Iterate through the registry walker output 116 | entries = {} 117 | for subkey in _registry_walker(**walker_options): 118 | # Only process values, not keys 119 | if str(subkey[1][2]) != 'Key': 120 | registry_key = subkey[1][1] 121 | registry_value = subkey[1][2] 122 | try: 123 | registry_data = codecs.decode(subkey[1][3], "utf-16le") 124 | except: 125 | continue 126 | 127 | # Initialize the registry key entry if it doesn't exist 128 | if registry_key not in entries: 129 | entries[registry_key] = {'Timestamp': str(subkey[1][0])} 130 | 131 | # Store the registry value and data 132 | entries[registry_key]['Path'] = registry_key 133 | entries[registry_key][registry_value] = registry_data 134 | 135 | return entries 136 | 137 | def AmcacheInventoryDriverBinary( 138 | _registry_walker, 139 | kernel, 140 | hive_list, 141 | hive = None, 142 | file_output=False 143 | ): 144 | """ 145 | Create a TreeGrid with Programs data. 146 | """ 147 | # Define the registry key and hive name to process 148 | key = 'ROOT\InventoryDriverBinary' 149 | hive_name = 'Amcache.hve' 150 | 151 | if file_output: 152 | write_result_to_csv( 153 | _registry_walker, 154 | kernel, 155 | hive_list, 156 | key, 157 | hive_name 158 | ) 159 | return 160 | else: 161 | generator = ValuesOut( 162 | _registry_walker, 163 | kernel, 164 | hive_list, 165 | key, 166 | hive_name, 167 | ) 168 | 169 | return TreeGrid( 170 | columns=COLUMNS, 171 | generator=generator, 172 | ) -------------------------------------------------------------------------------- /registryplugins/AppCompatCache.py: -------------------------------------------------------------------------------- 1 | import datetime 2 | from volatility3.framework.renderers import TreeGrid, format_hints 3 | import os 4 | from volatility3.plugins.windows.registry.regexplore.registryplugins.AppCompatCacheDep import * 5 | from enum import Enum, Flag, auto 6 | 7 | COLUMNS = [ 8 | ('ControlSet', int), 9 | ('CacheEntryPosition', int), 10 | ('Path', str), 11 | ('LastModifiedTimeUTC', str), 12 | ('Executed', str), 13 | ('Duplicate', str), 14 | 15 | ] 16 | 17 | def write_result_to_csv( 18 | _registry_walker, 19 | kernel, 20 | hive_list, 21 | key=None, 22 | hive_name=None, 23 | output_path='regexplore/AppCompatCache.csv' 24 | ): 25 | 26 | os.makedirs('regexplore', exist_ok=True) 27 | 28 | with open(output_path, 'w', encoding='utf-8') as file_handle: 29 | header = 'ControlSet,CacheEntryPosition,Path,LastModifiedTimeUTC,Executed,Duplicate\n' 30 | file_handle.write(header) 31 | for result in process_values( 32 | _registry_walker, 33 | kernel, 34 | hive_list, 35 | key, 36 | hive_name 37 | ): 38 | file_handle.write(f'{result[0]},{result[1]},{result[2]},{result[3]},{result[4]},{result[5]}\n') 39 | return 40 | 41 | def ValuesOut( 42 | _registry_walker, 43 | kernel, 44 | hive_list, 45 | key=None, 46 | hive_name=None, 47 | file_output=False 48 | ): 49 | 50 | for result in process_values( 51 | _registry_walker, 52 | kernel, 53 | hive_list, 54 | key, 55 | hive_name 56 | ): 57 | 58 | yield ( 59 | 0, 60 | ( 61 | result 62 | ), 63 | ) 64 | 65 | def process_values( 66 | _registry_walker, 67 | kernel, 68 | hive_list, 69 | key=None, 70 | hive_name=None, 71 | file_output=False 72 | ): 73 | 74 | """ 75 | Process registry values and return device name and data. 76 | """ 77 | paths_set = set() 78 | 79 | for i in range(1,5): 80 | try: 81 | walker_options = { 82 | 'layer_name': kernel.layer_name, 83 | 'symbol_table': kernel.symbol_table_name, 84 | 'hive_list': hive_list, 85 | 'key': key.replace('*', str(i)), 86 | 'hive_name': hive_name, 87 | 'recurse': False, 88 | } 89 | 90 | controlSetId = i 91 | 92 | if kernel.get_type("pointer").size == 4: 93 | is32bit = "x86" 94 | else: 95 | is32bit = False 96 | for value in _registry_walker(**walker_options): 97 | if str(value[1][2]) == "AppCompatCache": 98 | rawBytes = value[1][3] 99 | for result in AppCompatCacheParser(rawBytes, is32bit, controlSetId): 100 | if result[2] in paths_set: 101 | result += ('TRUE', ) 102 | else: 103 | result += ('FALSE', ) 104 | paths_set.add(result[2]) 105 | yield result 106 | except Exception as e: 107 | print(e) 108 | def AppCompatCacheParser(rawBytes, is32bit, controlSetId): 109 | 110 | sigNum = int.from_bytes(rawBytes[:4], byteorder='little', signed=False) 111 | signature = rawBytes[128:132].decode('ascii') 112 | 113 | if sigNum == 0xDEADBEEF and is32bit: #XP 114 | for result in WindowsXP.WindowsXP(rawBytes, is32bit, controlSetId): 115 | yield result 116 | elif sigNum == 0xbadc0ffe: #Win2k3Win2k8 117 | for result in VistaWin2k3Win2k8.VistaWin2k3Win2k8(rawBytes, is32bit, controlSetId): 118 | yield result 119 | elif sigNum == 0xbadc0fee: #7x86 120 | for result in Windows7.Windows7(rawBytes, is32bit, controlSetId): 121 | yield result 122 | elif signature == "00ts" or signature == "10ts" : #8.0, server2012, 8.1, server2012r2 123 | for result in Windows8.Windows8(rawBytes, signature, controlSetId): 124 | yield result 125 | else: #10,11 126 | offsetToEntries = int.from_bytes(rawBytes[:4], byteorder='little') 127 | signature = rawBytes[offsetToEntries:offsetToEntries+4].decode('ascii') 128 | if signature == "10ts": 129 | for result in Windows10.Windows10(rawBytes, controlSetId): 130 | yield result 131 | 132 | def AppCompatCache( 133 | _registry_walker, 134 | kernel, 135 | hive_list, 136 | hive = None, 137 | file_output=False 138 | ): 139 | """ 140 | Create a TreeGrid with device name and data. 141 | """ 142 | key = 'ControlSet00*\Control\Session Manager\AppCompatCache' 143 | hive_name = 'SYSTEM' 144 | 145 | if file_output: 146 | write_result_to_csv( 147 | _registry_walker, 148 | kernel, 149 | hive_list, 150 | key, 151 | hive_name 152 | ) 153 | return 154 | else: 155 | generator = ValuesOut( 156 | _registry_walker, 157 | kernel, 158 | hive_list, 159 | key, 160 | hive_name 161 | ) 162 | 163 | return TreeGrid( 164 | columns=COLUMNS, 165 | generator=generator, 166 | ) 167 | -------------------------------------------------------------------------------- /registryplugins/AppCompatCacheDep/VistaWin2k3Win2k8.py: -------------------------------------------------------------------------------- 1 | import datetime 2 | import logging 3 | import codecs 4 | 5 | def VistaWin2k3Win2k8(raw_bytes, is_32bit, control_set): 6 | # initialize the starting index and control set 7 | index = 4 8 | control_set = control_set 9 | 10 | # get the number of cache entries 11 | entry_count = int.from_bytes(raw_bytes[4:8], byteorder="little") 12 | 13 | # set the starting index and position 14 | index = 8 15 | position = 0 16 | 17 | # set the null date for FILETIME 18 | FILETIME_null_date = datetime.datetime(1601, 1, 1, 0, 0, 0) 19 | 20 | # if there are no cache entries, return None 21 | if entry_count == 0: 22 | return 23 | 24 | # loop through the cache entries 25 | while index < len(raw_bytes): 26 | try: 27 | # initialize the cache entry dictionary 28 | cache_entry = {} 29 | 30 | # get the path size 31 | cache_entry["path_size"] = int.from_bytes(raw_bytes[index:index+2], byteorder="little", signed=False) 32 | index += 2 33 | 34 | # get the max path size 35 | max_path_size = int.from_bytes(raw_bytes[index:index+2], byteorder="little", signed=False) 36 | index += 2 37 | 38 | # get the path offset 39 | if not is_32bit: 40 | index += 4 41 | path_offset = int.from_bytes(raw_bytes[index:index+8], byteorder="little", signed=False) 42 | index += 8 43 | else: 44 | path_offset = int.from_bytes(raw_bytes[index:index+4], byteorder="little") 45 | index += 4 46 | 47 | # get the last modified time 48 | try: 49 | timestamp = int.from_bytes(raw_bytes[index:index + 8], "little") / 10 # divide by 10 to convert 100-nanosecond intervals to microseconds 50 | cache_entry["last_modified_time_utc"] = str(FILETIME_null_date + datetime.timedelta(microseconds=timestamp)) 51 | if '1601' in cache_entry["last_modified_time_utc"]: 52 | cache_entry["last_modified_time_utc"] = "" 53 | except Exception as e: 54 | cache_entry["last_modified_time_utc"] = "" 55 | 56 | index += 8 57 | 58 | # get the insertion flags 59 | cache_entry["insert_flags"] = int.from_bytes(raw_bytes[index:index+4], byteorder="little") 60 | index += 4 61 | 62 | # skip 4 unknown (shim flags?) 63 | index += 4 64 | 65 | # decode the path 66 | cache_entry["path"] = codecs.decode( 67 | raw_bytes[path_offset:path_offset+cache_entry["path_size"]], "utf-16le" 68 | ).replace("\\??\\", "") 69 | 70 | # get the execution flag 71 | if cache_entry["insert_flags"] & 0x01: 72 | cache_entry["executed"] = "Yes" 73 | else: 74 | cache_entry["executed"] = "No" 75 | 76 | cache_entry["cache_entry_position"] = position 77 | cache_entry["control_set"] = control_set 78 | 79 | position += 1 80 | 81 | result = ( 82 | cache_entry.get('control_set', ""), 83 | cache_entry.get('cache_entry_position', ""), 84 | cache_entry.get('path', ""), 85 | cache_entry.get('last_modified_time_utc', ""), 86 | cache_entry.get('executed', ""), 87 | ) 88 | yield result 89 | 90 | if entry_count == position: 91 | break 92 | except Exception as ex: 93 | logging.error( 94 | f"Error parsing cache entry. Position: {position} Index: {index}, Error: {str(ex)}") 95 | if len(entries) < entry_count: 96 | raise 97 | break 98 | -------------------------------------------------------------------------------- /registryplugins/AppCompatCacheDep/Windows10.py: -------------------------------------------------------------------------------- 1 | import datetime 2 | import codecs 3 | 4 | def Windows10(raw_bytes, control_set): 5 | expected_entries = 0 6 | 7 | offset_to_records = int.from_bytes(raw_bytes[:4], "little") 8 | expected_entries = int.from_bytes(raw_bytes[0x24:0x28], "little") 9 | 10 | if offset_to_records == 0x34: 11 | expected_entries = int.from_bytes(raw_bytes[0x28:0x2C], "little") 12 | 13 | index = offset_to_records 14 | 15 | control_set = control_set 16 | 17 | position = 0 18 | 19 | FILETIME_null_date = datetime.datetime(1601, 1, 1, 0, 0, 0) 20 | 21 | 22 | while index < len(raw_bytes): 23 | try: 24 | cache_entry = {} 25 | 26 | cache_entry["signature"] = codecs.decode(raw_bytes[index:index + 4], "ascii") 27 | index += 4 28 | 29 | if cache_entry["signature"] != "10ts": 30 | break 31 | 32 | index += 4 33 | 34 | cache_entry_data_size = int.from_bytes(raw_bytes[index:index + 4], "little", signed=False) 35 | index += 4 36 | 37 | cache_entry["path_size"] = int.from_bytes(raw_bytes[index:index + 2], "little", signed=False) 38 | index += 2 39 | 40 | cache_entry["path"] = codecs.decode( 41 | raw_bytes[index:index + cache_entry["path_size"]], "utf-16le" 42 | ).replace("\\??\\", "") 43 | 44 | index += cache_entry["path_size"] 45 | 46 | try: 47 | timestamp = int.from_bytes(raw_bytes[index:index + 8], "little") / 10 # divide by 10 to convert 100-nanosecond intervals to microseconds 48 | cache_entry["last_modified_time_utc"] = str(FILETIME_null_date + datetime.timedelta(microseconds=timestamp)) 49 | if '1601' in cache_entry["last_modified_time_utc"]: 50 | cache_entry["last_modified_time_utc"] = "" 51 | except: 52 | cache_entry["last_modified_time_utc"] = "" 53 | 54 | index += 8 55 | 56 | cache_entry["data_size"] = int.from_bytes(raw_bytes[index:index + 4], "little") 57 | index += 4 58 | 59 | cache_entry["data"] = raw_bytes[index:index + cache_entry["data_size"]] 60 | index += cache_entry["data_size"] 61 | 62 | # if the last 4 bytes of data is 1, it indicates execution 63 | cache_entry["executed"] = ( 64 | "Yes" 65 | if int.from_bytes(cache_entry["data"][-4:], "little") == 1 66 | else "No" 67 | ) 68 | 69 | cache_entry["control_set"] = control_set 70 | cache_entry["cache_entry_position"] = position 71 | 72 | position += 1 73 | result = ( 74 | cache_entry.get('control_set', ""), 75 | cache_entry.get('cache_entry_position', ""), 76 | cache_entry.get('path', ""), 77 | cache_entry.get('last_modified_time_utc', ""), 78 | cache_entry.get('executed', ""), 79 | ) 80 | yield result 81 | except Exception as ex: 82 | print(f"Error parsing cache entry. Position: {position} Index: {index}, Error: {str(ex)} ") 83 | continue 84 | -------------------------------------------------------------------------------- /registryplugins/AppCompatCacheDep/Windows7.py: -------------------------------------------------------------------------------- 1 | import datetime 2 | import logging 3 | import codecs 4 | 5 | def Windows7(raw_bytes, is_32bit, control_set): 6 | # initialize the starting index and control set 7 | index = 4 8 | control_set = control_set 9 | 10 | # get the number of cache entries 11 | entry_count = int.from_bytes(raw_bytes[4:8], byteorder="little") 12 | 13 | # set the starting index and position 14 | index = 128 15 | position = 0 16 | 17 | # set the null date for FILETIME 18 | FILETIME_null_date = datetime.datetime(1601, 1, 1, 0, 0, 0) 19 | 20 | # if there are no cache entries, return None 21 | if entry_count == 0: 22 | return 23 | 24 | # loop through the cache entries 25 | while index < len(raw_bytes): 26 | try: 27 | # initialize the cache entry dictionary 28 | cache_entry = {} 29 | 30 | # get the path size 31 | cache_entry["path_size"] = int.from_bytes(raw_bytes[index:index+2], byteorder="little", signed=False) 32 | index += 2 33 | 34 | # get the max path size 35 | max_path_size = int.from_bytes(raw_bytes[index:index+2], byteorder="little", signed=False) 36 | index += 2 37 | 38 | # get the path offset 39 | if not is_32bit: 40 | index += 4 41 | path_offset = int.from_bytes(raw_bytes[index:index+8], byteorder="little", signed=False) 42 | index += 8 43 | else: 44 | path_offset = int.from_bytes(raw_bytes[index:index+4], byteorder="little") 45 | index += 4 46 | 47 | # get the last modified time 48 | try: 49 | timestamp = int.from_bytes(raw_bytes[index:index + 8], "little") / 10 # divide by 10 to convert 100-nanosecond intervals to microseconds 50 | cache_entry["last_modified_time_utc"] = str(FILETIME_null_date + datetime.timedelta(microseconds=timestamp)) 51 | if '1601' in cache_entry["last_modified_time_utc"]: 52 | cache_entry["last_modified_time_utc"] = "" 53 | except Exception as e: 54 | cache_entry["last_modified_time_utc"] = "" 55 | 56 | index += 8 57 | 58 | # get the insertion flags 59 | cache_entry["insert_flags"] = int.from_bytes(raw_bytes[index:index+4], byteorder="little") 60 | index += 4 61 | 62 | # skip 4 unknown (shim flags?) 63 | index += 4 64 | 65 | # get the cache entry data size and offset 66 | if not is_32bit: 67 | cache_entry_data_size = int.from_bytes(raw_bytes[index:index+8], byteorder="little", signed=False) 68 | index += 8 69 | data_offset = int.from_bytes(raw_bytes[index:index+8], byteorder="little", signed=False) 70 | index += 8 71 | else: 72 | cache_entry_data_size = int.from_bytes(raw_bytes[index:index+4], byteorder="little", signed=False) 73 | index += 4 74 | data_offset = int.from_bytes(raw_bytes[index:index+4], byteorder="little", signed=False) 75 | index += 4 76 | 77 | # decode the path 78 | cache_entry["path"] = codecs.decode( 79 | raw_bytes[path_offset:path_offset+cache_entry["path_size"]], "utf-16le" 80 | ).replace("\\??\\", "") 81 | 82 | # get the execution flag 83 | if cache_entry["insert_flags"] & 0x01: 84 | cache_entry["executed"] = "Yes" 85 | else: 86 | cache_entry["executed"] = "No" 87 | 88 | cache_entry["cache_entry_position"] = position 89 | cache_entry["control_set"] = control_set 90 | 91 | position += 1 92 | 93 | result = ( 94 | cache_entry.get('control_set', ""), 95 | cache_entry.get('cache_entry_position', ""), 96 | cache_entry.get('path', ""), 97 | cache_entry.get('last_modified_time_utc', ""), 98 | cache_entry.get('executed', ""), 99 | ) 100 | yield result 101 | 102 | if entry_count == position: 103 | break 104 | except Exception as ex: 105 | logging.error( 106 | f"Error parsing cache entry. Position: {position} Index: {index}, Error: {str(ex)}") 107 | if len(entries) < entry_count: 108 | raise 109 | break 110 | -------------------------------------------------------------------------------- /registryplugins/AppCompatCacheDep/Windows8.py: -------------------------------------------------------------------------------- 1 | import datetime 2 | import codecs 3 | 4 | def Windows8(raw_bytes, signature, control_set): 5 | 6 | index = 128 7 | 8 | control_set = control_set 9 | 10 | position = 0 11 | 12 | FILETIME_null_date = datetime.datetime(1601, 1, 1, 0, 0, 0) 13 | 14 | 15 | while index < len(raw_bytes): 16 | try: 17 | cache_entry = {} 18 | 19 | if codecs.decode(raw_bytes[index:index + 4], "ascii") == signature: 20 | break 21 | 22 | index += 4 23 | 24 | index += 4 25 | 26 | cache_entry_data_size = int.from_bytes(raw_bytes[index:index + 4], "little", signed=False) 27 | index += 4 28 | 29 | cache_entry["path_size"] = int.from_bytes(raw_bytes[index:index + 2], "little", signed=False) 30 | index += 2 31 | 32 | cache_entry["path"] = codecs.decode( 33 | raw_bytes[index:index + cache_entry["path_size"]], "utf-16le" 34 | ).replace("\\??\\", "") 35 | 36 | index += cache_entry["path_size"] 37 | 38 | package_len = int.from_bytes(raw_bytes[index:index + 2], "little", signed=False) 39 | 40 | index += 2 41 | 42 | index += package_len 43 | 44 | cache_entry["insert_flags"] = int.from_bytes(raw_bytes[index:index+4], byteorder="little") 45 | index += 4 46 | 47 | index += 4 48 | 49 | try: 50 | timestamp = int.from_bytes(raw_bytes[index:index + 8], "little") / 10 # divide by 10 to convert 100-nanosecond intervals to microseconds 51 | cache_entry["last_modified_time_utc"] = str(FILETIME_null_date + datetime.timedelta(microseconds=timestamp)) 52 | if '1601' in cache_entry["last_modified_time_utc"]: 53 | cache_entry["last_modified_time_utc"] = "" 54 | except: 55 | cache_entry["last_modified_time_utc"] = "" 56 | 57 | index += 8 58 | 59 | cache_entry["data_size"] = int.from_bytes(raw_bytes[index:index + 4], "little") 60 | index += 4 61 | 62 | cache_entry["data"] = raw_bytes[index:index + cache_entry["data_size"]] 63 | index += cache_entry["data_size"] 64 | 65 | # if the last 4 bytes of data is 1, it indicates execution 66 | if cache_entry["insert_flags"] & 0x01: 67 | cache_entry["executed"] = "Yes" 68 | else: 69 | cache_entry["executed"] = "No" 70 | 71 | cache_entry["control_set"] = control_set 72 | cache_entry["cache_entry_position"] = position 73 | 74 | position += 1 75 | result = ( 76 | cache_entry.get('control_set', ""), 77 | cache_entry.get('cache_entry_position', ""), 78 | cache_entry.get('path', ""), 79 | cache_entry.get('last_modified_time_utc', ""), 80 | cache_entry.get('executed', ""), 81 | ) 82 | yield result 83 | except Exception as ex: 84 | print(f"Error parsing cache entry. Position: {position} Index: {index}, Error: {str(ex)} ") 85 | continue 86 | -------------------------------------------------------------------------------- /registryplugins/AppCompatCacheDep/WindowsXP.py: -------------------------------------------------------------------------------- 1 | import datetime 2 | import logging 3 | import codecs 4 | 5 | def WindowsXP(raw_bytes, is_32bit, control_set): 6 | # initialize the starting index and control set 7 | index = 4 8 | control_set = control_set 9 | 10 | # get the number of cache entries 11 | entry_count = int.from_bytes(raw_bytes[4:8], byteorder="little") 12 | 13 | # set the starting index and position 14 | index = 400 15 | position = 0 16 | 17 | # set the null date for FILETIME 18 | FILETIME_null_date = datetime.datetime(1601, 1, 1, 0, 0, 0) 19 | 20 | # if there are no cache entries, return None 21 | if entry_count == 0: 22 | return 23 | 24 | # loop through the cache entries 25 | while index < len(raw_bytes): 26 | try: 27 | # initialize the cache entry dictionary 28 | cache_entry = {} 29 | 30 | # set the path size 31 | cache_entry["path_size"] = 528 32 | 33 | cache_entry['path'] = cache_entry["path"] = codecs.decode( 34 | raw_bytes[index:index + cache_entry["path_size"]], "utf-16le" 35 | ).replace("\\??\\", "") 36 | 37 | index += 528 38 | 39 | try: 40 | timestamp = int.from_bytes(raw_bytes[index:index + 8], "little") / 10 # divide by 10 to convert 100-nanosecond intervals to microseconds 41 | cache_entry["last_modified_time_utc"] = str(FILETIME_null_date + datetime.timedelta(microseconds=timestamp)) 42 | if '1601' in cache_entry["last_modified_time_utc"]: 43 | cache_entry["last_modified_time_utc"] = "" 44 | except: 45 | cache_entry["last_modified_time_utc"] = "" 46 | 47 | index += 8 48 | 49 | cache_entry['file_size'] = int.from_bytes(raw_bytes[index:index + 8], "little", signed=False) 50 | 51 | index += 8 52 | 53 | index += 8 54 | 55 | cache_entry["cache_entry_position"] = position 56 | cache_entry["control_set"] = control_set 57 | 58 | position += 1 59 | 60 | result = ( 61 | cache_entry.get('control_set', ""), 62 | cache_entry.get('cache_entry_position', ""), 63 | cache_entry.get('path', ""), 64 | cache_entry.get('last_modified_time_utc', ""), 65 | cache_entry.get('executed', ""), 66 | ) 67 | yield result 68 | 69 | if entry_count == position: 70 | break 71 | except Exception as ex: 72 | logging.error( 73 | f"Error parsing cache entry. Position: {position} Index: {index}, Error: {str(ex)}") 74 | if len(entries) < entry_count: 75 | raise 76 | break 77 | -------------------------------------------------------------------------------- /registryplugins/AppCompatCacheDep/__init__.py: -------------------------------------------------------------------------------- 1 | from volatility3.plugins.windows.registry.regexplore.registryplugins.AppCompatCacheDep import Windows10 2 | from volatility3.plugins.windows.registry.regexplore.registryplugins.AppCompatCacheDep import Windows7 3 | from volatility3.plugins.windows.registry.regexplore.registryplugins.AppCompatCacheDep import WindowsXP 4 | from volatility3.plugins.windows.registry.regexplore.registryplugins.AppCompatCacheDep import VistaWin2k3Win2k8 5 | from volatility3.plugins.windows.registry.regexplore.registryplugins.AppCompatCacheDep import Windows8 -------------------------------------------------------------------------------- /registryplugins/AppCompatCacheDep/__pycache__/VistaWin2k3Win2k8.cpython-37.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/0xHasanM/regexplore/8c0a95fd2444c356a5627f7a4b0b4a53aa1e9c01/registryplugins/AppCompatCacheDep/__pycache__/VistaWin2k3Win2k8.cpython-37.pyc -------------------------------------------------------------------------------- /registryplugins/AppCompatCacheDep/__pycache__/Windows10.cpython-37.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/0xHasanM/regexplore/8c0a95fd2444c356a5627f7a4b0b4a53aa1e9c01/registryplugins/AppCompatCacheDep/__pycache__/Windows10.cpython-37.pyc -------------------------------------------------------------------------------- /registryplugins/AppCompatCacheDep/__pycache__/Windows7.cpython-37.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/0xHasanM/regexplore/8c0a95fd2444c356a5627f7a4b0b4a53aa1e9c01/registryplugins/AppCompatCacheDep/__pycache__/Windows7.cpython-37.pyc -------------------------------------------------------------------------------- /registryplugins/AppCompatCacheDep/__pycache__/Windows8.cpython-37.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/0xHasanM/regexplore/8c0a95fd2444c356a5627f7a4b0b4a53aa1e9c01/registryplugins/AppCompatCacheDep/__pycache__/Windows8.cpython-37.pyc -------------------------------------------------------------------------------- /registryplugins/AppCompatCacheDep/__pycache__/WindowsXP.cpython-37.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/0xHasanM/regexplore/8c0a95fd2444c356a5627f7a4b0b4a53aa1e9c01/registryplugins/AppCompatCacheDep/__pycache__/WindowsXP.cpython-37.pyc -------------------------------------------------------------------------------- /registryplugins/AppCompatCacheDep/__pycache__/__init__.cpython-37.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/0xHasanM/regexplore/8c0a95fd2444c356a5627f7a4b0b4a53aa1e9c01/registryplugins/AppCompatCacheDep/__pycache__/__init__.cpython-37.pyc -------------------------------------------------------------------------------- /registryplugins/AppPaths.py: -------------------------------------------------------------------------------- 1 | import datetime 2 | from volatility3.framework.renderers import TreeGrid, format_hints 3 | import os 4 | import codecs 5 | COLUMNS = [ 6 | ('Timestamp', str), 7 | ('Hive', str), 8 | ('FileName', str), 9 | ('Path1', str), 10 | ('Path2', str), 11 | ] 12 | 13 | def write_result_to_csv( 14 | _registry_walker, 15 | kernel, 16 | hive_list, 17 | keys_hive_mapping, 18 | output_path='regexplore/AppPaths.csv' 19 | ): 20 | 21 | os.makedirs('regexplore', exist_ok=True) 22 | 23 | entries = process_values( 24 | _registry_walker, 25 | kernel, 26 | hive_list, 27 | keys_hive_mapping 28 | ) 29 | 30 | with open(output_path, 'w', encoding='utf-8') as file_handle: 31 | header = "Timestamp,Hive,FileName,Path1,Path2\n" 32 | file_handle.write(header) 33 | for registry_key in entries.keys(): 34 | file_handle.write( 35 | f'{entries[registry_key].get("Timestamp", "")},' 36 | f'{entries[registry_key].get("hive_path", "")},' 37 | f'{registry_key},' 38 | f'{entries[registry_key].get("(Default)", "")},' 39 | f'{entries[registry_key].get("Path", "")}\n' 40 | ) 41 | return 42 | 43 | def ValuesOut( 44 | _registry_walker, 45 | kernel, 46 | hive_list, 47 | keys_hive_mapping, 48 | file_output=False 49 | ): 50 | 51 | entries = process_values( 52 | _registry_walker, 53 | kernel, 54 | hive_list, 55 | keys_hive_mapping 56 | ) 57 | 58 | for registry_key in entries.keys(): 59 | result = ( 60 | 0, 61 | ( 62 | entries[registry_key].get("Timestamp", ""), 63 | entries[registry_key].get('hive_path', ''), 64 | registry_key, 65 | entries[registry_key].get("(Default)", ""), 66 | entries[registry_key].get("Path", ""), 67 | ), 68 | ) 69 | yield result 70 | 71 | def process_values( 72 | _registry_walker, 73 | kernel, 74 | hive_list, 75 | keys_hive_mapping, 76 | file_output=False 77 | ): 78 | 79 | """ 80 | Process registry values and return device name and data. 81 | """ 82 | entries = {} 83 | for hive_name, key in keys_hive_mapping.items(): 84 | walker_options = { 85 | 'layer_name': kernel.layer_name, 86 | 'symbol_table': kernel.symbol_table_name, 87 | 'hive_list': hive_list, 88 | 'key': key, 89 | 'hive_name': hive_name, 90 | 'recurse': True, 91 | } 92 | for subkey in _registry_walker(**walker_options): 93 | if str(subkey[1][2]) != 'Key': 94 | hive_path = subkey[2] 95 | registry_key = subkey[1][1] 96 | registry_value = subkey[1][2] 97 | try: 98 | registry_data = codecs.decode(subkey[1][3], "utf-16le") 99 | except: 100 | continue 101 | # Initialize the registry key entry if it doesn't exist 102 | if registry_key not in entries: 103 | entries[registry_key] = {'Timestamp': str(subkey[1][0])} 104 | entries[registry_key]['hive_path'] = hive_path 105 | entries[registry_key][registry_value] = registry_data 106 | # Store the registry value and data 107 | return entries 108 | 109 | def AppPaths( 110 | _registry_walker, 111 | kernel, 112 | hive_list, 113 | hive = None, 114 | file_output=False 115 | ): 116 | """ 117 | Create a TreeGrid with device name and data. 118 | """ 119 | if hive != None: 120 | if hive == "SOFTWARE": 121 | keys_hive_mapping = { 122 | 'SOFTWARE':'Microsoft\Windows\CurrentVersion\App Paths' 123 | } 124 | elif hive == "ntuser": 125 | keys_hive_mapping = { 126 | 'ntuser.dat':'SOFTWARE\Microsoft\Windows\CurrentVersion\App Paths' 127 | } 128 | else: 129 | keys_hive_mapping = { 130 | 'SOFTWARE':'Microsoft\Windows\CurrentVersion\App Paths', 131 | 'ntuser.dat':'SOFTWARE\Microsoft\Windows\CurrentVersion\App Paths' 132 | } 133 | 134 | if file_output: 135 | write_result_to_csv( 136 | _registry_walker, 137 | kernel, 138 | hive_list, 139 | keys_hive_mapping 140 | ) 141 | return 142 | else: 143 | generator = ValuesOut( 144 | _registry_walker, 145 | kernel, 146 | hive_list, 147 | keys_hive_mapping 148 | ) 149 | 150 | return TreeGrid( 151 | columns=COLUMNS, 152 | generator=generator, 153 | ) 154 | -------------------------------------------------------------------------------- /registryplugins/BamDam.py: -------------------------------------------------------------------------------- 1 | import datetime 2 | from volatility3.framework.renderers import TreeGrid, format_hints 3 | import os 4 | 5 | COLUMNS = [ 6 | ('Key', str), 7 | ('Program', str), 8 | ('Execution Time', str), 9 | ] 10 | 11 | def write_result_to_csv( 12 | _registry_walker, 13 | kernel, 14 | hive_list, 15 | keys, 16 | hive_name, 17 | output_path='regexplore/BamDam.csv' 18 | ): 19 | 20 | os.makedirs('regexplore', exist_ok=True) 21 | 22 | entries = process_values( 23 | _registry_walker, 24 | kernel, 25 | hive_list, 26 | keys, 27 | hive_name 28 | ) 29 | 30 | with open(output_path, 'w', encoding='utf-8') as file_handle: 31 | header = "Key,Program,Execution Time\n" 32 | file_handle.write(header) 33 | for entries in process_values( 34 | _registry_walker, 35 | kernel, 36 | hive_list, 37 | keys, 38 | hive_name 39 | ): 40 | file_handle.write(f'{entries[0]}, {entries[1]}, {entries[2]}\n') 41 | return 42 | 43 | def ValuesOut( 44 | _registry_walker, 45 | kernel, 46 | hive_list, 47 | keys, 48 | hive_name, 49 | file_output=False 50 | ): 51 | 52 | for entries in process_values( 53 | _registry_walker, 54 | kernel, 55 | hive_list, 56 | keys, 57 | hive_name 58 | ): 59 | yield (0, (entries)) 60 | 61 | def process_values( 62 | _registry_walker, 63 | kernel, 64 | hive_list, 65 | keys, 66 | hive_name, 67 | file_output=False 68 | ): 69 | 70 | """ 71 | Process registry values and return device name and data. 72 | """ 73 | FILETIME_null_date = datetime.datetime(1601, 1, 1, 0, 0, 0) 74 | for i in range(1,5): 75 | for key in keys: 76 | walker_options = { 77 | 'layer_name': kernel.layer_name, 78 | 'symbol_table': kernel.symbol_table_name, 79 | 'hive_list': hive_list, 80 | 'key': key.replace('*', str(i)), 81 | 'hive_name': hive_name, 82 | 'recurse': True, 83 | } 84 | for subkey in _registry_walker(**walker_options): 85 | if subkey[1][2] == "Version" or subkey[1][2] == "SequenceNumber" or str(subkey[1][2]) == 'Key': 86 | continue 87 | registry_key = subkey[1][1] 88 | registry_value = subkey[1][2] 89 | try: 90 | registry_data = subkey[1][3] 91 | timestamp = int.from_bytes(registry_data[:8], "little") / 10 92 | last_execution_time = str(FILETIME_null_date + datetime.timedelta(microseconds=timestamp)) 93 | except Exception as e: 94 | continue 95 | result = ( 96 | f'{key.replace("*", str(i))}\{registry_key}', 97 | registry_value, 98 | last_execution_time, 99 | ) 100 | yield result 101 | 102 | def BamDam( 103 | _registry_walker, 104 | kernel, 105 | hive_list, 106 | hive = None, 107 | file_output=False 108 | ): 109 | """ 110 | Create a TreeGrid with device name and data. 111 | """ 112 | 113 | keys = [r"ControlSet00*\Services\bam\UserSettings" ,r"ControlSet00*\Services\bam\State\UserSettings", r"ControlSet00*\Services\dam\UserSettings"] 114 | hive_name = 'SYSTEM' 115 | 116 | if file_output: 117 | write_result_to_csv( 118 | _registry_walker, 119 | kernel, 120 | hive_list, 121 | keys, 122 | hive_name 123 | ) 124 | return 125 | else: 126 | generator = ValuesOut( 127 | _registry_walker, 128 | kernel, 129 | hive_list, 130 | keys, 131 | hive_name 132 | ) 133 | 134 | return TreeGrid( 135 | columns=COLUMNS, 136 | generator=generator, 137 | ) 138 | -------------------------------------------------------------------------------- /registryplugins/CIDSizeMRU.py: -------------------------------------------------------------------------------- 1 | import datetime 2 | from volatility3.framework.renderers import TreeGrid, format_hints 3 | import os 4 | import codecs 5 | 6 | COLUMNS = [ 7 | ('Executable ', str), 8 | ('MRUPosition', str), 9 | ('OpenedOn', str), 10 | ] 11 | 12 | def write_result_to_csv( 13 | _registry_walker, 14 | kernel, 15 | hive_list, 16 | key, 17 | hive_name, 18 | output_path='regexplore/CIDSizeMRU.csv' 19 | ): 20 | 21 | os.makedirs('regexplore', exist_ok=True) 22 | 23 | with open(output_path, 'w', encoding='utf-8') as file_handle: 24 | header = "Executable,MRUPosition,OpenedOn\n" 25 | file_handle.write(header) 26 | for result in process_values( 27 | _registry_walker, 28 | kernel, 29 | hive_list, 30 | key, 31 | hive_name 32 | ): 33 | file_handle.write(f'{result[0]}, {result[1]}, {result[2]}\n') 34 | return 35 | 36 | def ValuesOut( 37 | _registry_walker, 38 | kernel, 39 | hive_list, 40 | key, 41 | hive_name, 42 | file_output=False 43 | ): 44 | 45 | for result in process_values( 46 | _registry_walker, 47 | kernel, 48 | hive_list, 49 | key, 50 | hive_name 51 | ): 52 | yield (0, (result)) 53 | 54 | def process_values( 55 | _registry_walker, 56 | kernel, 57 | hive_list, 58 | key, 59 | hive_name, 60 | file_output=False 61 | ): 62 | 63 | """ 64 | Process registry values and return device name and data. 65 | """ 66 | walker_options = { 67 | 'layer_name': kernel.layer_name, 68 | 'symbol_table': kernel.symbol_table_name, 69 | 'hive_list': hive_list, 70 | 'key': key, 71 | 'hive_name': hive_name, 72 | 'recurse': False, 73 | } 74 | entries = {} 75 | LastWriteTime = '' 76 | for value in _registry_walker(**walker_options): 77 | entries[value[1][2]] = value[1][3] 78 | LastWriteTime = value[1][0] 79 | for result in process_mru(entries, LastWriteTime): 80 | yield result 81 | 82 | def process_mru(entries, LastWriteTime): 83 | mruList = entries.get('MRUListEx', b'') 84 | mruPositions = {} 85 | i = 0 86 | index = 0 87 | 88 | while index < len(mruList) - 4: 89 | mruPos = int.from_bytes(mruList[index:index+4], byteorder='little', signed=False) 90 | if mruPos == 0xFFFFFFFF: 91 | break 92 | mruPositions[mruPos] = i 93 | i += 1 94 | index += 4 95 | 96 | for value_name, value_data in entries.items(): 97 | if value_name == 'MRUListEx': 98 | continue 99 | 100 | mru = mruPositions.get(int(value_name), -1) 101 | 102 | chunks = value_data.decode('utf-16le').split('\x00') 103 | exeName = chunks[0] 104 | openedOn = LastWriteTime if mru == 0 else 'None' 105 | 106 | yield exeName, str(mru), openedOn 107 | 108 | def CIDSizeMRU( 109 | _registry_walker, 110 | kernel, 111 | hive_list, 112 | hive = None, 113 | file_output=False 114 | ): 115 | """ 116 | Create a TreeGrid with device name and data. 117 | """ 118 | key = "Software\Microsoft\Windows\CurrentVersion\Explorer\ComDlg32\CIDSizeMRU" 119 | hive_name = "NTUSER.DAT" 120 | 121 | if file_output: 122 | write_result_to_csv( 123 | _registry_walker, 124 | kernel, 125 | hive_list, 126 | key, 127 | hive_name 128 | ) 129 | return 130 | else: 131 | generator = ValuesOut( 132 | _registry_walker, 133 | kernel, 134 | hive_list, 135 | key, 136 | hive_name 137 | ) 138 | 139 | return TreeGrid( 140 | columns=COLUMNS, 141 | generator=generator, 142 | ) 143 | -------------------------------------------------------------------------------- /registryplugins/MountedDevices.py: -------------------------------------------------------------------------------- 1 | import datetime 2 | from volatility3.framework.renderers import TreeGrid, format_hints 3 | import os 4 | import codecs 5 | 6 | COLUMNS = [ 7 | ('Device name', str), 8 | ('Device Data', str) 9 | ] 10 | 11 | def write_result_to_csv( 12 | _registry_walker, 13 | kernel, 14 | hive_list, 15 | key=None, 16 | hive_name=None, 17 | output_path='regexplore/MountedDevices.csv' 18 | ): 19 | 20 | walker_options = { 21 | 'layer_name': kernel.layer_name, 22 | 'symbol_table': kernel.symbol_table_name, 23 | 'hive_list': hive_list, 24 | 'key': key, 25 | 'hive_name': hive_name, 26 | 'recurse': False, 27 | } 28 | 29 | os.makedirs('regexplore', exist_ok=True) 30 | 31 | with open(output_path, 'w', encoding='utf-16le') as file_handle: 32 | header = 'Device Name, Device Data\n' 33 | file_handle.write(header) 34 | for value in _registry_walker(**walker_options): 35 | device_name = value[1][2] 36 | try: 37 | device_data = codecs.decode(value[1][3], "utf-16le") 38 | except: 39 | continue 40 | file_handle.write(f'{device_name.replace(",", ";")},{device_data.replace(",", ";")}\n') 41 | return 42 | 43 | def process_values( 44 | _registry_walker, 45 | kernel, 46 | hive_list, 47 | key=None, 48 | hive_name=None, 49 | file_output=False 50 | ): 51 | 52 | """ 53 | Process registry values and return device name and data. 54 | """ 55 | walker_options = { 56 | 'layer_name': kernel.layer_name, 57 | 'symbol_table': kernel.symbol_table_name, 58 | 'hive_list': hive_list, 59 | 'key': key, 60 | 'hive_name': hive_name, 61 | 'recurse': False, 62 | } 63 | 64 | for value in _registry_walker(**walker_options): 65 | device_name = value[1][2] 66 | try: 67 | device_data = codecs.decode(value[1][3], "utf-16le") 68 | except: 69 | continue 70 | result = ( 71 | 0, 72 | ( 73 | device_name, 74 | device_data.replace(",", ";") 75 | ), 76 | ) 77 | yield result 78 | 79 | def MountedDevices( 80 | _registry_walker, 81 | kernel, 82 | hive_list, 83 | hive = None, 84 | file_output=False 85 | ): 86 | """ 87 | Create a TreeGrid with device name and data. 88 | """ 89 | key = 'MountedDevices' 90 | hive_name = 'SYSTEM' 91 | 92 | if file_output: 93 | write_result_to_csv( 94 | _registry_walker, 95 | kernel, 96 | hive_list, 97 | key, 98 | hive_name 99 | ) 100 | return 101 | else: 102 | generator = process_values( 103 | _registry_walker, 104 | kernel, 105 | hive_list, 106 | key, 107 | hive_name 108 | ) 109 | 110 | return TreeGrid( 111 | columns=COLUMNS, 112 | generator=generator, 113 | ) 114 | -------------------------------------------------------------------------------- /registryplugins/__init__.py: -------------------------------------------------------------------------------- 1 | # Import registry plugins 2 | from volatility3.plugins.windows.registry.regexplore.registryplugins import ( 3 | AmcacheInventoryApplication, 4 | AmcacheInventoryApplicationFile, 5 | AmcacheInventoryApplicationShortcut, 6 | AmcacheInventoryDeviceContainer, 7 | AmcacheInventoryDevicePnp, 8 | AmcacheInventoryDriverBinary, 9 | AppCompatCache, 10 | AppPaths, 11 | BamDam, 12 | MountedDevices, 13 | CIDSizeMRU 14 | ) 15 | 16 | # Purpose of each module: 17 | # AmcacheInventoryApplication - retrieve information about installed applications 18 | # AmcacheInventoryApplicationFile - retrieve information about files related to installed applications 19 | # AmcacheInventoryApplicationShortcut - retrieve information about shortcuts related to installed applications 20 | # AmcacheInventoryDeviceContainer - retrieve information about PnP device containers 21 | # AmcacheInventoryDevicePnp - retrieve information about PnP devices 22 | # AmcacheInventoryDriverBinary - retrieve information about installed drivers 23 | # AppCompatCache - retrieve information about application compatibility settings 24 | # AppPaths - retrieve information about registered application paths 25 | # BamDam - retrieve information about Bam and Dam registry keys 26 | # MountedDevices - retrieve information about mounted devices 27 | -------------------------------------------------------------------------------- /registryplugins/__pycache__/AmcacheInventoryApplication.cpython-37.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/0xHasanM/regexplore/8c0a95fd2444c356a5627f7a4b0b4a53aa1e9c01/registryplugins/__pycache__/AmcacheInventoryApplication.cpython-37.pyc -------------------------------------------------------------------------------- /registryplugins/__pycache__/AmcacheInventoryApplicationFile.cpython-37.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/0xHasanM/regexplore/8c0a95fd2444c356a5627f7a4b0b4a53aa1e9c01/registryplugins/__pycache__/AmcacheInventoryApplicationFile.cpython-37.pyc -------------------------------------------------------------------------------- /registryplugins/__pycache__/AmcacheInventoryApplicationShortcut.cpython-37.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/0xHasanM/regexplore/8c0a95fd2444c356a5627f7a4b0b4a53aa1e9c01/registryplugins/__pycache__/AmcacheInventoryApplicationShortcut.cpython-37.pyc -------------------------------------------------------------------------------- /registryplugins/__pycache__/AmcacheInventoryDeviceContainer.cpython-37.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/0xHasanM/regexplore/8c0a95fd2444c356a5627f7a4b0b4a53aa1e9c01/registryplugins/__pycache__/AmcacheInventoryDeviceContainer.cpython-37.pyc -------------------------------------------------------------------------------- /registryplugins/__pycache__/AmcacheInventoryDevicePnp.cpython-37.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/0xHasanM/regexplore/8c0a95fd2444c356a5627f7a4b0b4a53aa1e9c01/registryplugins/__pycache__/AmcacheInventoryDevicePnp.cpython-37.pyc -------------------------------------------------------------------------------- /registryplugins/__pycache__/AmcacheInventoryDriverBinary.cpython-37.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/0xHasanM/regexplore/8c0a95fd2444c356a5627f7a4b0b4a53aa1e9c01/registryplugins/__pycache__/AmcacheInventoryDriverBinary.cpython-37.pyc -------------------------------------------------------------------------------- /registryplugins/__pycache__/AppCompatCache.cpython-37.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/0xHasanM/regexplore/8c0a95fd2444c356a5627f7a4b0b4a53aa1e9c01/registryplugins/__pycache__/AppCompatCache.cpython-37.pyc -------------------------------------------------------------------------------- /registryplugins/__pycache__/AppPaths.cpython-37.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/0xHasanM/regexplore/8c0a95fd2444c356a5627f7a4b0b4a53aa1e9c01/registryplugins/__pycache__/AppPaths.cpython-37.pyc -------------------------------------------------------------------------------- /registryplugins/__pycache__/BamDam.cpython-37.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/0xHasanM/regexplore/8c0a95fd2444c356a5627f7a4b0b4a53aa1e9c01/registryplugins/__pycache__/BamDam.cpython-37.pyc -------------------------------------------------------------------------------- /registryplugins/__pycache__/CIDSizeMRU.cpython-37.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/0xHasanM/regexplore/8c0a95fd2444c356a5627f7a4b0b4a53aa1e9c01/registryplugins/__pycache__/CIDSizeMRU.cpython-37.pyc -------------------------------------------------------------------------------- /registryplugins/__pycache__/CacheEntry.cpython-37.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/0xHasanM/regexplore/8c0a95fd2444c356a5627f7a4b0b4a53aa1e9c01/registryplugins/__pycache__/CacheEntry.cpython-37.pyc -------------------------------------------------------------------------------- /registryplugins/__pycache__/MountedDevices.cpython-37.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/0xHasanM/regexplore/8c0a95fd2444c356a5627f7a4b0b4a53aa1e9c01/registryplugins/__pycache__/MountedDevices.cpython-37.pyc -------------------------------------------------------------------------------- /registryplugins/__pycache__/Windows10.cpython-37.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/0xHasanM/regexplore/8c0a95fd2444c356a5627f7a4b0b4a53aa1e9c01/registryplugins/__pycache__/Windows10.cpython-37.pyc -------------------------------------------------------------------------------- /registryplugins/__pycache__/__init__.cpython-37.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/0xHasanM/regexplore/8c0a95fd2444c356a5627f7a4b0b4a53aa1e9c01/registryplugins/__pycache__/__init__.cpython-37.pyc --------------------------------------------------------------------------------