def _generator(self): kernel = self.context.modules[self.config['kernel']] for driver in self.scan_drivers(self.context, kernel.layer_name, kernel.symbol_table_name): try: driver_name = driver.get_driver_name() except (ValueError, exceptions.InvalidAddressException): driver_name = renderers.NotApplicableValue() try: service_key = driver.DriverExtension.ServiceKeyName.String except exceptions.InvalidAddressException: service_key = renderers.NotApplicableValue() try: name = driver.DriverName.String except exceptions.InvalidAddressException: name = renderers.NotApplicableValue() yield (0, (format_hints.Hex(driver.vol.offset), format_hints.Hex(driver.DriverStart), format_hints.Hex(driver.DriverSize), service_key, driver_name, name))
def parse_userassist_data(self, reg_val): """Reads the raw data of a _CM_KEY_VALUE and returns a dict of userassist fields.""" item = { "id": renderers.UnparsableValue(), "count": renderers.UnparsableValue(), "focus": renderers.UnparsableValue(), "time": renderers.UnparsableValue(), "lastupdated": renderers.UnparsableValue(), "rawdata": renderers.UnparsableValue(), } userassist_data = reg_val.decode_data() if userassist_data is None: return item item["rawdata"] = userassist_data if self._win7 is None: # if OS is still unknown at this point, return the default item which just has the rawdata return item if len(userassist_data) < self._userassist_size: return item userassist_layer_name = self.context.layers.free_layer_name( "userassist_buffer") buffer = BufferDataLayer(self.context, self._config_path, userassist_layer_name, userassist_data) self.context.add_layer(buffer) userassist_obj = self.context.object(object_type=self._reg_table_name + constants.BANG + self._userassist_type_name, layer_name=userassist_layer_name, offset=0) if self._win7: item["id"] = renderers.NotApplicableValue() item["count"] = int(userassist_obj.Count) seconds = (userassist_obj.FocusTime + 500) / 1000.0 time = datetime.timedelta( seconds=seconds) if seconds > 0 else userassist_obj.FocusTime item["focus"] = int(userassist_obj.FocusCount) item["time"] = str(time) else: item["id"] = int(userassist_obj.ID) item["count"] = int(userassist_obj.CountStartingAtFive if userassist_obj.CountStartingAtFive < 5 else userassist_obj.CountStartingAtFive - 5) item["focus"] = renderers.NotApplicableValue() item["time"] = renderers.NotApplicableValue() item["lastupdated"] = conversion.wintime_to_datetime( userassist_obj.LastUpdated.QuadPart) return item
def _generator(self, runable_plugins: List[TimeLinerInterface]) -> Optional[Iterable[Tuple[int, Tuple]]]: """Takes a timeline, sorts it and output the data from each relevant row from each plugin.""" # Generate the results for each plugin data = [] # Open the bodyfile now, so we can start outputting to it immediately if self.config.get('create-bodyfile', True): file_data = self.open("volatility.body") fp = io.TextIOWrapper(file_data, write_through = True) else: file_data = None fp = None for plugin in runable_plugins: plugin_name = plugin.__class__.__name__ self._progress_callback((runable_plugins.index(plugin) * 100) // len(runable_plugins), f"Running plugin {plugin_name}...") try: vollog.log(logging.INFO, f"Running {plugin_name}") for (item, timestamp_type, timestamp) in plugin.generate_timeline(): times = self.timeline.get((plugin_name, item), {}) if times.get(timestamp_type, None) is not None: vollog.debug("Multiple timestamps for the same plugin/file combination found: {} {}".format( plugin_name, item)) times[timestamp_type] = timestamp self.timeline[(plugin_name, item)] = times data.append((0, [ plugin_name, item, times.get(TimeLinerType.CREATED, renderers.NotApplicableValue()), times.get(TimeLinerType.MODIFIED, renderers.NotApplicableValue()), times.get(TimeLinerType.ACCESSED, renderers.NotApplicableValue()), times.get(TimeLinerType.CHANGED, renderers.NotApplicableValue()) ])) # Write each entry because the body file doesn't need to be sorted if fp: times = self.timeline[(plugin_name, item)] # Body format is: MD5|name|inode|mode_as_string|UID|GID|size|atime|mtime|ctime|crtime if self._any_time_present(times): fp.write("|{} - {}|0|0|0|0|0|{}|{}|{}|{}\n".format( plugin_name, self._sanitize_body_format(item), self._text_format(times.get(TimeLinerType.ACCESSED, "")), self._text_format(times.get(TimeLinerType.MODIFIED, "")), self._text_format(times.get(TimeLinerType.CHANGED, "")), self._text_format(times.get(TimeLinerType.CREATED, "")))) except Exception: vollog.log(logging.INFO, f"Exception occurred running plugin: {plugin_name}") vollog.log(logging.DEBUG, traceback.format_exc()) for data_item in sorted(data, key = self._sort_function): yield data_item # Write out a body file if necessary if self.config.get('create-bodyfile', True): if fp: fp.close() file_data.close()
def _generator(self): kernel = self.context.modules[self.config['kernel']] collection = ssdt.SSDT.build_module_collection(self.context, kernel.layer_name, kernel.symbol_table_name) for driver in driverscan.DriverScan.scan_drivers(self.context, kernel.layer_name, kernel.symbol_table_name): try: driver_name = driver.get_driver_name() except (ValueError, exceptions.InvalidAddressException): driver_name = renderers.NotApplicableValue() for i, address in enumerate(driver.MajorFunction): module_symbols = collection.get_module_symbols_by_absolute_location(address) for module_name, symbol_generator in module_symbols: symbols_found = False for symbol in symbol_generator: symbols_found = True yield (0, (format_hints.Hex(driver.vol.offset), driver_name, MAJOR_FUNCTIONS[i], format_hints.Hex(address), module_name, symbol.split(constants.BANG)[1])) if not symbols_found: yield (0, (format_hints.Hex(driver.vol.offset), driver_name, MAJOR_FUNCTIONS[i], format_hints.Hex(address), module_name, renderers.NotAvailableValue()))
def get_number_of_bytes(self) -> Union[int, interfaces.renderers.BaseAbsentValue]: """Returns the NumberOfBytes value on applicable systems""" # Not applicable until Vista try: return self.NumberOfBytes except AttributeError: return renderers.NotApplicableValue()
def get_session_id(self): try: if self.has_member("Session"): if self.Session == 0: return renderers.NotApplicableValue() symbol_table_name = self.get_symbol_table_name() kvo = self._context.layers[ self.vol.native_layer_name].config['kernel_virtual_offset'] ntkrnlmp = self._context.module( symbol_table_name, layer_name=self.vol.native_layer_name, offset=kvo, native_layer_name=self.vol.native_layer_name) session = ntkrnlmp.object(object_type="_MM_SESSION_SPACE", offset=self.Session, absolute=True) if session.has_member("SessionId"): return session.SessionId except exceptions.InvalidAddressException: vollog.log( constants.LOGLEVEL_VVV, f"Cannot access _EPROCESS.Session.SessionId at {self.vol.offset:#x}" ) return renderers.UnreadableValue()
def get_pool_type(self) -> Union[str, interfaces.renderers.BaseAbsentValue]: """Returns the enum name for the PoolType value on applicable systems""" # Not applicable until Vista if hasattr(self, 'PoolType'): if not self.pool_type_lookup: self._generate_pool_type_lookup() return self.pool_type_lookup.get(self.PoolType, f"Unknown choice {self.PoolType}") else: return renderers.NotApplicableValue()
def wintime_to_datetime(wintime: int) -> Union[interfaces.renderers.BaseAbsentValue, datetime.datetime]: unix_time = wintime // 10000000 if unix_time == 0: return renderers.NotApplicableValue() unix_time = unix_time - 11644473600 try: return datetime.datetime.utcfromtimestamp(unix_time) # Windows sometimes throws OSErrors rather than ValueErrors when it can't convert a value except (ValueError, OSError): return renderers.UnparsableValue()
def get_pid(self) -> Union[int, interfaces.renderers.BaseAbsentValue]: """Return the pid of the process, if any.""" if self.State.description != "SERVICE_RUNNING" or "PROCESS" not in self.get_type( ): return renderers.NotApplicableValue() try: return self.ServiceProcess.ProcessId except exceptions.InvalidAddressException: return renderers.UnreadableValue()
def _generator(self): for mutant in self.scan_mutants(self.context, self.config['primary'], self.config['nt_symbols']): try: name = mutant.get_name() except (ValueError, exceptions.InvalidAddressException): name = renderers.NotApplicableValue() yield (0, (format_hints.Hex(mutant.vol.offset), name))
def _generator(self): for driver in self.scan_drivers(self.context, self.config['primary'], self.config['nt_symbols']): try: driver_name = driver.get_driver_name() except (ValueError, exceptions.InvalidAddressException): driver_name = renderers.NotApplicableValue() try: service_key = driver.DriverExtension.ServiceKeyName.String except exceptions.InvalidAddressException: service_key = renderers.NotApplicableValue() try: name = driver.DriverName.String except exceptions.InvalidAddressException: name = renderers.NotApplicableValue() yield (0, (format_hints.Hex(driver.vol.offset), format_hints.Hex(driver.DriverStart), format_hints.Hex(driver.DriverSize), service_key, driver_name, name))
def _generator(self): kernel = self.context.modules[self.config['kernel']] callback_table_name = self.create_callback_table( self.context, kernel.symbol_table_name, self.config_path) collection = ssdt.SSDT.build_module_collection( self.context, kernel.layer_name, kernel.symbol_table_name) callback_methods = (self.list_notify_routines, self.list_bugcheck_callbacks, self.list_bugcheck_reason_callbacks, self.list_registry_callbacks) for callback_method in callback_methods: for callback_type, callback_address, callback_detail in callback_method( self.context, kernel.layer_name, kernel.symbol_table_name, callback_table_name): if callback_detail is None: detail = renderers.NotApplicableValue() else: detail = callback_detail module_symbols = list( collection.get_module_symbols_by_absolute_location( callback_address)) if module_symbols: for module_name, symbol_generator in module_symbols: symbols_found = False # we might have multiple symbols pointing to the same location for symbol in symbol_generator: symbols_found = True yield (0, (callback_type, format_hints.Hex(callback_address), module_name, symbol.split(constants.BANG)[1], detail)) # no symbols, but we at least can report the module name if not symbols_found: yield (0, (callback_type, format_hints.Hex(callback_address), module_name, renderers.NotAvailableValue(), detail)) else: # no module was found at the absolute location yield (0, (callback_type, format_hints.Hex(callback_address), renderers.NotAvailableValue(), renderers.NotAvailableValue(), detail))
def _generator(self): kernel = self.context.modules[self.config['kernel']] for mutant in self.scan_mutants(self.context, kernel.layer_name, kernel.symbol_table_name): try: name = mutant.get_name() except (ValueError, exceptions.InvalidAddressException): name = renderers.NotApplicableValue() yield (0, (format_hints.Hex(mutant.vol.offset), name))
def get_state(self) -> str: dictState = { 0: 'Initialized', 1: 'Ready', 2: 'Running', 3: 'Standby', 4: 'Terminated', 5: 'Waiting', 6: 'Transition', 7: 'DeferredReady', 8: 'GateWait' } return dictState.get(self.State, renderers.NotApplicableValue())
def get_file_name(self): """Get the name of the file mapped into the memory range (if any)""" file_name = renderers.NotApplicableValue() try: # this is for xp and 2003 if self.has_member("ControlArea"): file_name = self.ControlArea.FilePointer.FileName.get_string() # this is for vista through windows 7 else: file_name = self.Subsection.ControlArea.FilePointer.dereference( ).cast("_FILE_OBJECT").FileName.get_string() except exceptions.InvalidAddressException: pass return file_name
def get_wait_reason(self) -> str: dictWaitReason = { 0: 'Executive', 1: 'FreePage', 2: 'PageIn', 3: 'PoolAllocation', 4: 'DelayExecution', 5: 'Suspended', 6: 'UserRequest', 7: 'WrExecutive', 8: 'WrFreePage', 9: 'WrPageIn', 10: 'WrPoolAllocation', 11: 'WrDelayExecution', 12: 'WrSuspended', 13: 'WrUserRequest', 14: 'WrEventPair', 15: 'WrQueue', 16: 'WrLpcReceive', 17: 'WrLpcReply', 18: 'WrVirtualMemory', 19: 'WrPageOut', 20: 'WrRendezvous', 21: 'Spare2', 22: 'Spare3', 23: 'Spare4', 24: 'Spare5', 25: 'Spare6', 26: 'WrKernel', 27: 'WrResource', 28: 'WrPushLock', 29: 'WrMutex', 30: 'WrQuantumEnd', 31: 'WrDispatchInt', 32: 'WrPreempted', 33: 'WrYieldExecution', 34: 'WrFastMutex', 35: 'WrGuardedMutex', 36: 'WrRundown', 37: 'MaximumWaitReason' } return dictWaitReason.get(self.WaitReason, renderers.NotApplicableValue())
def get_binary(self) -> Union[str, interfaces.renderers.BaseAbsentValue]: """Returns the binary associated with the service.""" if self.State.description != "SERVICE_RUNNING": return renderers.NotApplicableValue() # depending on whether the service is for a process # or kernel driver, the binary path is stored differently try: if "PROCESS" in self.get_type(): return self.ServiceProcess.BinaryPath.dereference().cast( "string", encoding="utf-16", errors="replace", max_length=512) else: return self.DriverName.dereference().cast("string", encoding="utf-16", errors="replace", max_length=512) except exceptions.InvalidAddressException: return renderers.UnreadableValue()
def _generator(self, layer: crash.WindowsCrashDump32Layer): header = layer.get_header() uptime = datetime.timedelta(microseconds=int(header.SystemUpTime) / 10) if header.DumpType == 0x1: dump_type = "Full Dump (0x1)" elif header.DumpType == 0x5: dump_type = "Bitmap Dump (0x5)" else: # this should never happen since the crash layer only accepts 0x1 and 0x5 dump_type = "Unknown/Unsupported ({:#x})".format(header.DumpType) if header.DumpType == 0x5: summary_header = layer.get_summary_header() bitmap_header_size = format_hints.Hex(summary_header.HeaderSize) bitmap_size = format_hints.Hex(summary_header.BitmapSize) bitmap_pages = format_hints.Hex(summary_header.Pages) else: bitmap_header_size = bitmap_size = bitmap_pages = renderers.NotApplicableValue( ) yield (0, ( utility.array_to_string(header.Signature), header.MajorVersion, header.MinorVersion, format_hints.Hex(header.DirectoryTableBase), format_hints.Hex(header.PfnDataBase), format_hints.Hex(header.PsLoadedModuleList), format_hints.Hex(header.PsActiveProcessHead), header.MachineImageType, header.NumberProcessors, format_hints.Hex(header.KdDebuggerDataBlock), dump_type, str(uptime), utility.array_to_string(header.Comment), conversion.wintime_to_datetime(header.SystemTime), bitmap_header_size, bitmap_size, bitmap_pages, ))
def _generator(self): symbol_table = self.config["nt_symbols"] constraints = self.builtin_constraints(symbol_table) for constraint, mem_object, header in self.generate_pool_scan(self.context, self.config["primary"], symbol_table, constraints): # generate some type-specific info for sanity checking if constraint.object_type == "Process": name = mem_object.ImageFileName.cast("string", max_length = mem_object.ImageFileName.vol.count, errors = "replace") elif constraint.object_type == "File": try: name = mem_object.FileName.String except exceptions.InvalidAddressException: vollog.log(constants.LOGLEVEL_VVV, "Skipping file at {0:#x}".format(mem_object.vol.offset)) continue else: name = renderers.NotApplicableValue() yield (0, (constraint.type_name, format_hints.Hex(header.vol.offset), header.vol.layer_name, name))
def _generator(self, procs): pe_table_name = intermed.IntermediateSymbolTable.create( self.context, self.config_path, "windows", "pe", class_types=pe.class_types) kuser = info.Info.get_kuser_structure(self.context, self.config['primary'], self.config['nt_symbols']) nt_major_version = int(kuser.NtMajorVersion) nt_minor_version = int(kuser.NtMinorVersion) # LoadTime only applies to versions higher or equal to Window 7 (6.1 and higher) dll_load_time_field = (nt_major_version > 6) or ( nt_major_version == 6 and nt_minor_version >= 1) for proc in procs: proc_id = proc.UniqueProcessId proc_layer_name = proc.add_process_layer() for entry in proc.load_order_modules(): BaseDllName = FullDllName = renderers.UnreadableValue() try: BaseDllName = entry.BaseDllName.get_string() # We assume that if the BaseDllName points to an invalid buffer, so will FullDllName FullDllName = entry.FullDllName.get_string() except exceptions.InvalidAddressException: pass if dll_load_time_field: # Versions prior to 6.1 won't have the LoadTime attribute # and 32bit version shouldn't have the Quadpart according to MSDN try: DllLoadTime = conversion.wintime_to_datetime( entry.LoadTime.QuadPart) except exceptions.InvalidAddressException: DllLoadTime = renderers.UnreadableValue() else: DllLoadTime = renderers.NotApplicableValue() file_output = "Disabled" if self.config['dump']: file_handle = self.dump_pe( self.context, pe_table_name, entry, self.open, proc_layer_name, prefix="pid.{}.".format(proc_id)) file_output = "Error outputting file" if file_handle: file_handle.close() file_output = file_handle.preferred_filename yield (0, (proc.UniqueProcessId, proc.ImageFileName.cast( "string", max_length=proc.ImageFileName.vol.count, errors='replace'), format_hints.Hex(entry.DllBase), format_hints.Hex(entry.SizeOfImage), BaseDllName, FullDllName, DllLoadTime, file_output))
def _generator(self): layer = self.context.layers[self.config['primary']] # Yara Rule to scan for MFT Header Signatures rules = yarascan.YaraScan.process_yara_options( {'yara_rules': '/FILE0|FILE\*|BAAD/'}) # Read in the Symbol File symbol_table = intermed.IntermediateSymbolTable.create( context=self.context, config_path=self.config_path, sub_path="windows", filename="mft", class_types={ 'FILE_NAME_ENTRY': mft.MFTFileName, 'MFT_ENTRY': mft.MFTEntry }) # get each of the individual Field Sets mft_object = symbol_table + constants.BANG + "MFT_ENTRY" attribute_object = symbol_table + constants.BANG + "ATTRIBUTE" header_object = symbol_table + constants.BANG + "ATTR_HEADER" si_object = symbol_table + constants.BANG + "STANDARD_INFORMATION_ENTRY" fn_object = symbol_table + constants.BANG + "FILE_NAME_ENTRY" # Scan the layer for Raw MFT records and parse the fields for offset, _rule_name, _name, _value in layer.scan( context=self.context, scanner=yarascan.YaraScanner(rules=rules)): try: mft_record = self.context.object(mft_object, offset=offset, layer_name=layer.name) # We will update this on each pass in the next loop and use it as the new offset. attr_base_offset = mft_record.FirstAttrOffset attr_header = self.context.object(header_object, offset=offset + attr_base_offset, layer_name=layer.name) # There is no field that has a count of Attributes # Keep Attempting to read attributes until we get an invalid attr_header.AttrType while attr_header.AttrType.is_valid_choice: vollog.debug(f"Attr Type: {attr_header.AttrType.lookup()}") # Offset past the headers to the attribute data attr_data_offset = offset + attr_base_offset + self.context.symbol_space.get_type( attribute_object).relative_child_offset("Attr_Data") # MFT Flags determine the file type or dir # If we don't have a valid enum, coerce to hex so we can keep the record try: mft_flag = mft_record.Flags.lookup() except ValueError: mft_flag = hex(mft_record.Flags) # Standard Information Attribute if attr_header.AttrType.lookup() == 'STANDARD_INFORMATION': attr_data = self.context.object( si_object, offset=attr_data_offset, layer_name=layer.name) yield 0, ( format_hints.Hex(attr_data_offset), mft_record.get_signature(), mft_record.RecordNumber, mft_record.LinkCount, mft_flag, renderers.NotApplicableValue(), attr_header.AttrType.lookup(), conversion.wintime_to_datetime( attr_data.CreationTime), conversion.wintime_to_datetime( attr_data.ModifiedTime), conversion.wintime_to_datetime( attr_data.UpdatedTime), conversion.wintime_to_datetime( attr_data.AccessedTime), renderers.NotApplicableValue(), ) # File Name Attribute if attr_header.AttrType.lookup() == 'FILE_NAME': attr_data = self.context.object( fn_object, offset=attr_data_offset, layer_name=layer.name) file_name = attr_data.get_full_name() # If we don't have a valid enum, coerce to hex so we can keep the record try: permissions = attr_data.Flags.lookup() except ValueError: permissions = hex(attr_data.Flags) yield 1, (format_hints.Hex(attr_data_offset), mft_record.get_signature(), mft_record.RecordNumber, mft_record.LinkCount, mft_flag, permissions, attr_header.AttrType.lookup(), conversion.wintime_to_datetime( attr_data.CreationTime), conversion.wintime_to_datetime( attr_data.ModifiedTime), conversion.wintime_to_datetime( attr_data.UpdatedTime), conversion.wintime_to_datetime( attr_data.AccessedTime), file_name) # If there's no advancement the loop will never end, so break it now if attr_header.Length == 0: break # Update the base offset to point to the next attribute attr_base_offset += attr_header.Length # Get the next attribute attr_header = self.context.object(header_object, offset=offset + attr_base_offset, layer_name=layer.name) except exceptions.PagedInvalidAddressException: pass
def _printkey_iterator(self, hive: RegistryHive, node_path: Sequence[objects.StructType] = None, recurse: bool = False): """Method that wraps the more generic key_iterator, to provide output for printkey specifically. Args: hive: The registry hive to walk node_path: The list of nodes that make up the recurse: Traverse down the node tree or stay only on the same level Yields: The depth, and a tuple of results (last write time, hive offset, type, path, name, data and volatile) """ for depth, is_key, last_write_time, key_path, volatile, node in self.key_iterator( hive, node_path, recurse): if is_key: try: key_node_name = node.get_name() except (exceptions.InvalidAddressException, RegistryFormatException) as excp: vollog.debug(excp) key_node_name = renderers.UnreadableValue() yield (depth, (last_write_time, renderers.format_hints.Hex(hive.hive_offset), "Key", key_path, key_node_name, renderers.NotApplicableValue(), volatile)) else: try: value_node_name = node.get_name() or "(Default)" except (exceptions.InvalidAddressException, RegistryFormatException) as excp: vollog.debug(excp) value_node_name = renderers.UnreadableValue() try: value_type = RegValueTypes(node.Type).name except (exceptions.InvalidAddressException, RegistryFormatException) as excp: vollog.debug(excp) value_type = renderers.UnreadableValue() if isinstance(value_type, renderers.UnreadableValue): vollog.debug( "Couldn't read registry value type, so data is unreadable" ) value_data: Union[interfaces.renderers.BaseAbsentValue, bytes] = renderers.UnreadableValue() else: try: value_data = node.decode_data() if isinstance(value_data, int): value_data = format_hints.MultiTypeData( value_data, encoding='utf-8') elif RegValueTypes( node.Type) == RegValueTypes.REG_BINARY: value_data = format_hints.MultiTypeData( value_data, show_hex=True) elif RegValueTypes( node.Type) == RegValueTypes.REG_MULTI_SZ: value_data = format_hints.MultiTypeData( value_data, encoding='utf-16-le', split_nulls=True) else: value_data = format_hints.MultiTypeData( value_data, encoding='utf-16-le') except (ValueError, exceptions.InvalidAddressException, RegistryFormatException) as excp: vollog.debug(excp) value_data = renderers.UnreadableValue() result = (depth, (last_write_time, renderers.format_hints.Hex(hive.hive_offset), value_type, key_path, value_node_name, value_data, volatile)) yield result
def _generator(self, procs: Generator[interfaces.objects.ObjectInterface, None, None], mods: Generator[interfaces.objects.ObjectInterface, None, None], session_layers: Generator[str, None, None]): """Generates a list of PE file version info for processes, dlls, and modules. Args: procs: <generator> of processes mods: <generator> of modules session_layers: <generator> of layers in the session to be checked """ pe_table_name = intermed.IntermediateSymbolTable.create( self.context, self.config_path, "windows", "pe", class_types=pe.class_types) # TODO: Fix this so it works with more than just intel layers physical_layer_name = self.context.layers[ self.config['primary']].config.get('memory_layer', None) for mod in mods: try: BaseDllName = mod.BaseDllName.get_string() except exceptions.InvalidAddressException: BaseDllName = renderers.UnreadableValue() session_layer_name = modules.Modules.find_session_layer( self.context, session_layers, mod.DllBase) try: (major, minor, product, build) = self.get_version_information( self._context, pe_table_name, session_layer_name, mod.DllBase) except (exceptions.InvalidAddressException, TypeError, AttributeError): (major, minor, product, build) = [renderers.UnreadableValue()] * 4 if (not isinstance(BaseDllName, renderers.UnreadableValue) and physical_layer_name is not None and self.config['extensive']): result = self.find_version_info(self._context, physical_layer_name, BaseDllName) if result is not None: (major, minor, product, build) = result # the pid and process are not applicable for kernel modules yield (0, (renderers.NotApplicableValue(), renderers.NotApplicableValue(), format_hints.Hex(mod.DllBase), BaseDllName, major, minor, product, build)) # now go through the process and dll lists for proc in procs: proc_id = "Unknown" try: proc_id = proc.UniqueProcessId proc_layer_name = proc.add_process_layer() except exceptions.InvalidAddressException as excp: vollog.debug( "Process {}: invalid address {} in layer {}".format( proc_id, excp.invalid_address, excp.layer_name)) continue for entry in proc.load_order_modules(): try: BaseDllName = entry.BaseDllName.get_string() except exceptions.InvalidAddressException: BaseDllName = renderers.UnreadableValue() try: DllBase = format_hints.Hex(entry.DllBase) except exceptions.InvalidAddressException: DllBase = renderers.UnreadableValue() try: (major, minor, product, build) = self.get_version_information( self._context, pe_table_name, proc_layer_name, entry.DllBase) except (exceptions.InvalidAddressException, ValueError, AttributeError): (major, minor, product, build) = [renderers.UnreadableValue()] * 4 yield (0, (proc.UniqueProcessId, proc.ImageFileName.cast( "string", max_length=proc.ImageFileName.vol.count, errors="replace"), DllBase, BaseDllName, major, minor, product, build))
def list_userassist( self, hive: RegistryHive) -> Generator[Tuple[int, Tuple], None, None]: """Generate userassist data for a registry hive.""" hive_name = hive.hive.cast(self.config["nt_symbols"] + constants.BANG + "_CMHIVE").get_name() if self._win7 is None: try: self._win7 = self._win7_or_later() except exceptions.SymbolError: # self._win7 will be None and only registry value rawdata will be output pass self._determine_userassist_type() userassist_node_path = hive.get_key( "software\\microsoft\\windows\\currentversion\\explorer\\userassist", return_list=True) if not userassist_node_path: vollog.warning( "list_userassist did not find a valid node_path (or None)") return if not isinstance(userassist_node_path, list): vollog.warning( "userassist_node_path did not return a list as expected") return userassist_node = userassist_node_path[-1] # iterate through the GUIDs under the userassist key for guidkey in userassist_node.get_subkeys(): # each guid key should have a Count key in it for countkey in guidkey.get_subkeys(): countkey_path = countkey.get_key_path() countkey_last_write_time = conversion.wintime_to_datetime( countkey.LastWriteTime.QuadPart) # output the parent Count key result = ( 0, (renderers.format_hints.Hex(hive.hive_offset), hive_name, countkey_path, countkey_last_write_time, "Key", renderers.NotApplicableValue(), renderers.NotApplicableValue(), renderers.NotApplicableValue(), renderers.NotApplicableValue(), renderers.NotApplicableValue(), renderers.NotApplicableValue(), renderers.NotApplicableValue()) ) # type: Tuple[int, Tuple[format_hints.Hex, Any, Any, Any, Any, Any, Any, Any, Any, Any, Any, Any]] yield result # output any subkeys under Count for subkey in countkey.get_subkeys(): subkey_name = subkey.get_name() result = (1, ( renderers.format_hints.Hex(hive.hive_offset), hive_name, countkey_path, countkey_last_write_time, "Subkey", subkey_name, renderers.NotApplicableValue(), renderers.NotApplicableValue(), renderers.NotApplicableValue(), renderers.NotApplicableValue(), renderers.NotApplicableValue(), renderers.NotApplicableValue(), )) yield result # output any values under Count for value in countkey.get_values(): value_name = value.get_name() try: value_name = codecs.encode(value_name, "rot_13") except UnicodeDecodeError: pass if self._win7: guid = value_name.split("\\")[0] if guid in self._folder_guids: value_name = value_name.replace( guid, self._folder_guids[guid]) userassist_data_dict = self.parse_userassist_data(value) result = (1, ( renderers.format_hints.Hex(hive.hive_offset), hive_name, countkey_path, countkey_last_write_time, "Value", value_name, userassist_data_dict["id"], userassist_data_dict["count"], userassist_data_dict["focus"], userassist_data_dict["time"], userassist_data_dict["lastupdated"], format_hints.HexBytes(userassist_data_dict["rawdata"]), )) yield result
def _generator(self) -> Iterator[Tuple]: kernel = self.context.modules[self.config["kernel"]] # Scan the Layer for drivers for driver in driverscan.DriverScan.scan_drivers( self.context, kernel.layer_name, kernel.symbol_table_name): try: try: driver_name = driver.get_driver_name() except (ValueError, exceptions.PagedInvalidAddressException): vollog.log( constants.LOGLEVEL_VVVV, f"Failed to get Driver name : {driver.vol.offset:x}") driver_name = renderers.UnparsableValue() yield (0, (format_hints.Hex(driver.vol.offset), "DRV", driver_name, renderers.NotApplicableValue(), renderers.NotApplicableValue(), renderers.NotApplicableValue())) # Scan to get the device information of driver. for device in driver.get_devices(): try: device_name = device.get_device_name() except (ValueError, exceptions.PagedInvalidAddressException): vollog.log( constants.LOGLEVEL_VVVV, f"Failed to get Device name : {device.vol.offset:x}" ) device_name = renderers.UnparsableValue() device_type = DEVICE_CODES.get(device.DeviceType, "UNKNOWN") yield (1, (format_hints.Hex(driver.vol.offset), "DEV", driver_name, device_name, renderers.NotApplicableValue(), device_type)) # Scan to get the attached devices information of device. for level, attached_device in enumerate( device.get_attached_devices(), start=2): try: device_name = attached_device.get_device_name() except (ValueError, exceptions.PagedInvalidAddressException): vollog.log( constants.LOGLEVEL_VVVV, f"Failed to get Attached Device Name: {attached_device.vol.offset:x}" ) device_name = renderers.UnparsableValue() attached_device_driver_name = attached_device.DriverObject.DriverName.get_string( ) attached_device_type = DEVICE_CODES.get( attached_device.DeviceType, "UNKNOWN") yield (level, (format_hints.Hex(driver.vol.offset), "ATT", driver_name, device_name, attached_device_driver_name, attached_device_type)) except (exceptions.PagedInvalidAddressException): vollog.log( constants.LOGLEVEL_VVVV, f"Invalid address identified in drivers and devices: {driver.vol.offset:x}" ) continue
def get_file_name(self): """Only long(er) vads have mapped files.""" return renderers.NotApplicableValue()
def _generator(self) -> Iterator[Tuple]: kernel = self.context.modules[self.config['kernel']] physical_layer_name = self.context.layers[ kernel.layer_name].config.get('memory_layer', None) # Decide of Memory Dump Architecture layer = self.context.layers[physical_layer_name] architecture = "intel" if not symbols.symbol_table_is_64bit( self.context, kernel.symbol_table_name) else "intel64" # Read in the Symbol File symbol_table = intermed.IntermediateSymbolTable.create( context=self.context, config_path=self.config_path, sub_path="windows", filename="mbr", class_types={ 'PARTITION_TABLE': mbr.PARTITION_TABLE, 'PARTITION_ENTRY': mbr.PARTITION_ENTRY }) partition_table_object = symbol_table + constants.BANG + "PARTITION_TABLE" # Define Signature and Data Length mbr_signature = b"\x55\xAA" mbr_length = 0x200 bootcode_length = 0x1B8 # Scan the Layer for Raw Master Boot Record (MBR) and parse the fields for offset, _value in layer.scan( context=self.context, scanner=scanners.MultiStringScanner(patterns=[mbr_signature])): try: mbr_start_offset = offset - (mbr_length - len(mbr_signature)) partition_table = self.context.object(partition_table_object, offset=mbr_start_offset, layer_name=layer.name) # Extract only BootCode full_mbr = layer.read(mbr_start_offset, mbr_length, pad=True) bootcode = full_mbr[:bootcode_length] all_zeros = None if bootcode: all_zeros = bootcode.count(b"\x00") == len(bootcode) if not all_zeros: partition_entries = [ partition_table.FirstEntry, partition_table.SecondEntry, partition_table.ThirdEntry, partition_table.FourthEntry ] if not self.config.get("full", True): yield (0, (format_hints.Hex(offset), partition_table.get_disk_signature(), self.get_hash(bootcode), self.get_hash(full_mbr), renderers.NotApplicableValue(), renderers.NotApplicableValue(), renderers.NotApplicableValue(), renderers.NotApplicableValue(), interfaces.renderers.Disassembly( bootcode, 0, architecture))) else: yield (0, (format_hints.Hex(offset), partition_table.get_disk_signature(), self.get_hash(bootcode), self.get_hash(full_mbr), renderers.NotApplicableValue(), renderers.NotApplicableValue(), renderers.NotApplicableValue(), renderers.NotApplicableValue(), renderers.NotApplicableValue(), renderers.NotApplicableValue(), renderers.NotApplicableValue(), renderers.NotApplicableValue(), renderers.NotApplicableValue(), renderers.NotApplicableValue(), renderers.NotApplicableValue(), renderers.NotApplicableValue(), renderers.NotApplicableValue(), interfaces.renderers.Disassembly( bootcode, 0, architecture), format_hints.HexBytes(bootcode))) for partition_index, partition_entry_object in enumerate( partition_entries, start=1): if not self.config.get("full", True): yield (1, ( format_hints.Hex(offset), partition_table.get_disk_signature(), self.get_hash(bootcode), self.get_hash(full_mbr), partition_index, partition_entry_object.is_bootable(), partition_entry_object.get_partition_type(), format_hints.Hex(partition_entry_object. get_size_in_sectors()), renderers.NotApplicableValue())) else: yield (1, ( format_hints.Hex(offset), partition_table.get_disk_signature(), self.get_hash(bootcode), self.get_hash(full_mbr), partition_index, partition_entry_object.is_bootable(), format_hints.Hex(partition_entry_object. get_bootable_flag()), partition_entry_object.get_partition_type(), format_hints.Hex( partition_entry_object.PartitionType), format_hints.Hex( partition_entry_object.get_starting_lba()), partition_entry_object.get_starting_cylinder(), partition_entry_object.get_starting_chs(), partition_entry_object.get_starting_sector(), partition_entry_object.get_ending_cylinder(), partition_entry_object.get_ending_chs(), partition_entry_object.get_ending_sector(), format_hints.Hex(partition_entry_object. get_size_in_sectors()), renderers.NotApplicableValue(), renderers.NotApplicableValue())) else: vollog.log( constants.LOGLEVEL_VVVV, f"Not a valid MBR: Data all zeroed out : {format_hints.Hex(offset)}" ) continue except exceptions.PagedInvalidAddressException as excp: vollog.log( constants.LOGLEVEL_VVVV, f"Invalid address identified in guessed MBR: {hex(excp.invalid_address)}" ) continue