def _generator(self): kernel = self.context.modules[self.config['kernel']] try: list_head = kernel.object_from_symbol(symbol_name="ifnet_head") except exceptions.SymbolError: list_head = kernel.object_from_symbol( symbol_name="dlil_ifnet_head") for ifnet in mac.MacUtilities.walk_tailq(list_head, "if_link"): name = utility.pointer_to_string(ifnet.if_name, 32) unit = ifnet.if_unit prom = ifnet.if_flags & 0x100 == 0x100 # IFF_PROMISC sock_addr_dl = ifnet.sockaddr_dl() if sock_addr_dl is None: mac_addr = renderers.UnreadableValue() else: mac_addr = str(sock_addr_dl) for ifaddr in mac.MacUtilities.walk_tailq(ifnet.if_addrhead, "ifa_link"): ip = ifaddr.ifa_addr.get_address() yield (0, (f"{name}{unit}", ip, mac_addr, prom))
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 environment_variables(self): """Generator for environment variables. The PEB points to our env block - a series of null-terminated unicode strings. Each string cannot be more than 0x7FFF chars. End of the list is a quad-null. """ context = self._context process_space = self.add_process_layer() try: block = self.get_peb().ProcessParameters.Environment try: block_size = self.get_peb().ProcessParameters.EnvironmentSize except AttributeError: # Windows XP block_size = self.get_peb().ProcessParameters.Length envars = context.layers[process_space].read( block, block_size).decode("utf-16-le", errors='replace').split('\x00')[:-1] except exceptions.InvalidAddressException: return renderers.UnreadableValue() for envar in envars: split_index = envar.find('=') env = envar[:split_index] var = envar[split_index + 1:] # Exlude parse problem with some types of env if env and var: yield env, var
def _generator(self): kernel = contexts.Module(self._context, self.config['darwin'], self.config['primary'], 0) try: list_head = kernel.object_from_symbol(symbol_name="ifnet_head") except exceptions.SymbolError: list_head = kernel.object_from_symbol( symbol_name="dlil_ifnet_head") for ifnet in mac.MacUtilities.walk_tailq(list_head, "if_link"): name = utility.pointer_to_string(ifnet.if_name, 32) unit = ifnet.if_unit prom = ifnet.if_flags & 0x100 == 0x100 # IFF_PROMISC sock_addr_dl = ifnet.sockaddr_dl() if sock_addr_dl is None: mac_addr = renderers.UnreadableValue() else: mac_addr = str(sock_addr_dl) for ifaddr in mac.MacUtilities.walk_tailq(ifnet.if_addrhead, "ifa_link"): ip = ifaddr.ifa_addr.get_address() yield (0, ("{0}{1}".format(name, unit), ip, mac_addr, prom))
def get_display(self) -> Union[str, interfaces.renderers.BaseAbsentValue]: """Returns the service display.""" try: return self.DisplayName.dereference().cast("string", encoding="utf-16", errors="replace", max_length=512) except exceptions.InvalidAddressException: return renderers.UnreadableValue()
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 _registry_walker(self, layer_name: str, symbol_table: str, hive_offsets: List[int] = None, key: str = None, recurse: bool = False): for hive in hivelist.HiveList.list_hives(self.context, self.config_path, layer_name=layer_name, symbol_table=symbol_table, hive_offsets=hive_offsets): try: # Walk it if key is not None: node_path = hive.get_key(key, return_list=True) else: node_path = [hive.get_node(hive.root_cell_offset)] for (x, y) in self._printkey_iterator(hive, node_path, recurse=recurse): yield (x - len(node_path), y) except (exceptions.InvalidAddressException, KeyError, RegistryFormatException) as excp: if isinstance(excp, KeyError): vollog.debug( f"Key '{key}' not found in Hive at offset {hex(hive.hive_offset)}." ) elif isinstance(excp, RegistryFormatException): vollog.debug(excp) elif isinstance(excp, exceptions.InvalidAddressException): vollog.debug( f"Invalid address identified in Hive: {hex(excp.invalid_address)}" ) result = (0, (renderers.UnreadableValue(), format_hints.Hex(hive.hive_offset), "Key", '?\\' + (key or ''), renderers.UnreadableValue(), renderers.UnreadableValue(), renderers.UnreadableValue())) yield result
def get_handle_count(self): try: if self.has_member("ObjectTable"): if self.ObjectTable.has_member("HandleCount"): return self.ObjectTable.HandleCount except exceptions.InvalidAddressException: vollog.log( constants.LOGLEVEL_VVV, f"Cannot access _EPROCESS.ObjectTable.HandleCount at {self.vol.offset:#x}" ) return renderers.UnreadableValue()
def list_bugcheck_reason_callbacks( cls, context: interfaces.context.ContextInterface, layer_name: str, symbol_table: str, callback_table_name: str) -> Iterable[Tuple[str, int, str]]: """Lists all kernel bugcheck reason callbacks. Args: context: The context to retrieve required elements (layers, symbol tables) from layer_name: The name of the layer on which to operate symbol_table: The name of the table containing the kernel symbols callback_table_name: The nae of the table containing the callback symbols Yields: A name, location and optional detail string """ kvo = context.layers[layer_name].config['kernel_virtual_offset'] ntkrnlmp = context.module(symbol_table, layer_name=layer_name, offset=kvo) try: list_offset = ntkrnlmp.get_symbol( "KeBugCheckReasonCallbackListHead").address except exceptions.SymbolError: vollog.debug("Cannot find KeBugCheckReasonCallbackListHead") return full_type_name = callback_table_name + constants.BANG + "_KBUGCHECK_REASON_CALLBACK_RECORD" callback_record = context.object(object_type=full_type_name, offset=kvo + list_offset, layer_name=layer_name) for callback in callback_record.Entry: if not context.layers[layer_name].is_valid( callback.CallbackRoutine, 64): continue try: component: Union[ interfaces.renderers.BaseAbsentValue, interfaces.objects.ObjectInterface] = ntkrnlmp.object( "string", absolute=True, offset=callback.Component, max_length=64, errors="replace") except exceptions.InvalidAddressException: component = renderers.UnreadableValue() yield "KeBugCheckReasonCallbackListHead", callback.CallbackRoutine, component
def file_name_with_device( self) -> Union[str, interfaces.renderers.BaseAbsentValue]: name: Union[str, interfaces.renderers. BaseAbsentValue] = renderers.UnreadableValue() # this pointer needs to be checked against native_layer_name because the object may # be instantiated from a primary (virtual) layer or a memory (physical) layer. if self._context.layers[self.vol.native_layer_name].is_valid( self.DeviceObject): try: name = f"\\Device\\{self.DeviceObject.get_device_name()}" except ValueError: pass try: name += self.FileName.String except (TypeError, exceptions.InvalidAddressException): pass return name
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, show_corrupt_results: Optional[bool] = None): """ Generates the network objects for use in rendering. """ kernel = self.context.modules[self.config['kernel']] netscan_symbol_table = netscan.NetScan.create_netscan_symbol_table( self.context, kernel.layer_name, kernel.symbol_table_name, self.config_path) tcpip_module = self.get_tcpip_module(self.context, kernel.layer_name, kernel.symbol_table_name) try: tcpip_symbol_table = pdbutil.PDBUtility.symbol_table_from_pdb( self.context, interfaces.configuration.path_join(self.config_path, 'tcpip'), kernel.layer_name, "tcpip.pdb", tcpip_module.DllBase, tcpip_module.SizeOfImage) except exceptions.VolatilityException: vollog.warning( "Unable to locate symbols for the memory image's tcpip module") for netw_obj in self.list_sockets(self.context, kernel.layer_name, kernel.symbol_table_name, netscan_symbol_table, tcpip_module.DllBase, tcpip_symbol_table): # objects passed pool header constraints. check for additional constraints if strict flag is set. if not show_corrupt_results and not netw_obj.is_valid(): continue if isinstance(netw_obj, network._UDP_ENDPOINT): vollog.debug( f"Found UDP_ENDPOINT @ 0x{netw_obj.vol.offset:2x}") # For UdpA, the state is always blank and the remote end is asterisks for ver, laddr, _ in netw_obj.dual_stack_sockets(): yield (0, (format_hints.Hex(netw_obj.vol.offset), "UDP" + ver, laddr, netw_obj.Port, "*", 0, "", netw_obj.get_owner_pid() or renderers.UnreadableValue(), netw_obj.get_owner_procname() or renderers.UnreadableValue(), netw_obj.get_create_time() or renderers.UnreadableValue())) elif isinstance(netw_obj, network._TCP_ENDPOINT): vollog.debug( f"Found _TCP_ENDPOINT @ 0x{netw_obj.vol.offset:2x}") if netw_obj.get_address_family() == network.AF_INET: proto = "TCPv4" elif netw_obj.get_address_family() == network.AF_INET6: proto = "TCPv6" else: vollog.debug( "TCP Endpoint @ 0x{:2x} has unknown address family 0x{:x}" .format(netw_obj.vol.offset, netw_obj.get_address_family())) proto = "TCPv?" try: state = netw_obj.State.description except ValueError: state = renderers.UnreadableValue() yield (0, (format_hints.Hex(netw_obj.vol.offset), proto, netw_obj.get_local_address() or renderers.UnreadableValue(), netw_obj.LocalPort, netw_obj.get_remote_address() or renderers.UnreadableValue(), netw_obj.RemotePort, state, netw_obj.get_owner_pid() or renderers.UnreadableValue(), netw_obj.get_owner_procname() or renderers.UnreadableValue(), netw_obj.get_create_time() or renderers.UnreadableValue())) # check for isinstance of tcp listener last, because all other objects are inherited from here elif isinstance(netw_obj, network._TCP_LISTENER): vollog.debug( f"Found _TCP_LISTENER @ 0x{netw_obj.vol.offset:2x}") # For TcpL, the state is always listening and the remote port is zero for ver, laddr, raddr in netw_obj.dual_stack_sockets(): yield (0, (format_hints.Hex(netw_obj.vol.offset), "TCP" + ver, laddr, netw_obj.Port, raddr, 0, "LISTENING", netw_obj.get_owner_pid() or renderers.UnreadableValue(), netw_obj.get_owner_procname() or renderers.UnreadableValue(), netw_obj.get_create_time() or renderers.UnreadableValue())) else: # this should not happen therefore we log it. vollog.debug( f"Found network object unsure of its type: {netw_obj} of type {type(netw_obj)}" )
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 _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, show_corrupt_results: Optional[bool] = None): """ Generates the network objects for use in rendering. """ kernel = self.context.modules[self.config['kernel']] netscan_symbol_table = self.create_netscan_symbol_table( self.context, kernel.layer_name, kernel.symbol_table_name, self.config_path) for netw_obj in self.scan(self.context, kernel.layer_name, kernel.symbol_table_name, netscan_symbol_table): vollog.debug( f"Found netw obj @ 0x{netw_obj.vol.offset:2x} of assumed type {type(netw_obj)}" ) # objects passed pool header constraints. check for additional constraints if strict flag is set. if not show_corrupt_results and not netw_obj.is_valid(): continue if isinstance(netw_obj, network._UDP_ENDPOINT): vollog.debug( f"Found UDP_ENDPOINT @ 0x{netw_obj.vol.offset:2x}") # For UdpA, the state is always blank and the remote end is asterisks for ver, laddr, _ in netw_obj.dual_stack_sockets(): yield (0, (format_hints.Hex(netw_obj.vol.offset), "UDP" + ver, laddr, netw_obj.Port, "*", 0, "", netw_obj.get_owner_pid() or renderers.UnreadableValue(), netw_obj.get_owner_procname() or renderers.UnreadableValue(), netw_obj.get_create_time() or renderers.UnreadableValue())) elif isinstance(netw_obj, network._TCP_ENDPOINT): vollog.debug( f"Found _TCP_ENDPOINT @ 0x{netw_obj.vol.offset:2x}") if netw_obj.get_address_family() == network.AF_INET: proto = "TCPv4" elif netw_obj.get_address_family() == network.AF_INET6: proto = "TCPv6" else: proto = "TCPv?" try: state = netw_obj.State.description except ValueError: state = renderers.UnreadableValue() yield (0, (format_hints.Hex(netw_obj.vol.offset), proto, netw_obj.get_local_address() or renderers.UnreadableValue(), netw_obj.LocalPort, netw_obj.get_remote_address() or renderers.UnreadableValue(), netw_obj.RemotePort, state, netw_obj.get_owner_pid() or renderers.UnreadableValue(), netw_obj.get_owner_procname() or renderers.UnreadableValue(), netw_obj.get_create_time() or renderers.UnreadableValue())) # check for isinstance of tcp listener last, because all other objects are inherited from here elif isinstance(netw_obj, network._TCP_LISTENER): vollog.debug( f"Found _TCP_LISTENER @ 0x{netw_obj.vol.offset:2x}") # For TcpL, the state is always listening and the remote port is zero for ver, laddr, raddr in netw_obj.dual_stack_sockets(): yield (0, (format_hints.Hex(netw_obj.vol.offset), "TCP" + ver, laddr, netw_obj.Port, raddr, 0, "LISTENING", netw_obj.get_owner_pid() or renderers.UnreadableValue(), netw_obj.get_owner_procname() or renderers.UnreadableValue(), netw_obj.get_create_time() or renderers.UnreadableValue())) else: # this should not happen therefore we log it. vollog.debug( f"Found network object unsure of its type: {netw_obj} of type {type(netw_obj)}" )
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): hive_offsets = None if self.config.get('offset', None) is not None: hive_offsets = [self.config.get('offset', None)] # get all the user hive offsets or use the one specified for hive in hivelist.HiveList.list_hives( context=self.context, base_config_path=self.config_path, layer_name=self.config['primary'], symbol_table=self.config['nt_symbols'], filter_string='ntuser.dat', hive_offsets=hive_offsets): try: yield from self.list_userassist(hive) continue except exceptions.PagedInvalidAddressException as excp: vollog.debug("Invalid address identified in Hive: {}".format( hex(excp.invalid_address))) except exceptions.InvalidAddressException as excp: vollog.debug( "Invalid address identified in lower layer {}: {}".format( excp.layer_name, excp.invalid_address)) except KeyError: vollog.debug("Key '{}' not found in Hive at offset {}.".format( "software\\microsoft\\windows\\currentversion\\explorer\\userassist", hex(hive.hive_offset))) # yield UnreadableValues when an exception occurs for a given hive_offset result = ( 0, (renderers.format_hints.Hex(hive.hive_offset), hive.name if hive.name else renderers.UnreadableValue(), renderers.UnreadableValue(), renderers.UnreadableValue(), renderers.UnreadableValue(), renderers.UnreadableValue(), renderers.UnreadableValue(), renderers.UnreadableValue(), renderers.UnreadableValue(), renderers.UnreadableValue(), renderers.UnreadableValue(), renderers.UnreadableValue())) yield result