def _generator(self, syshive: registry.RegistryHive, samhive: registry.RegistryHive): if syshive is None: vollog.debug("SYSTEM address is None: Did you use the correct profile?") yield (0, (renderers.NotAvailableValue(), renderers.NotAvailableValue(), renderers.NotAvailableValue(), renderers.NotAvailableValue())) if samhive is None: vollog.debug("SAM address is None: Did you use the correct profile?") yield (0, (renderers.NotAvailableValue(), renderers.NotAvailableValue(), renderers.NotAvailableValue(), renderers.NotAvailableValue())) bootkey = self.get_bootkey(syshive) hbootkey = self.get_hbootkey(samhive, bootkey) if hbootkey: for user in self.get_user_keys(samhive): ret = self.get_user_hashes(user, samhive, hbootkey) if ret: lmhash, nthash = ret ## temporary fix to prevent UnicodeDecodeError backtraces ## however this can cause truncated user names as a result name = self.get_user_name(user, samhive) if name is None: name = renderers.NotAvailableValue() else: name = str(name, 'utf-16-le', errors = 'ignore') lmout = str(binascii.hexlify(lmhash or self.empty_lm), 'latin-1') ntout = str(binascii.hexlify(nthash or self.empty_nt), 'latin-1') rid = int(str(user.get_name()), 16) yield (0, (name, rid, lmout, ntout)) else: raise ValueError("Hbootkey is not valid")
def parse_data(self, data: bytes) -> Tuple[str, bytes]: name = renderers.NotAvailableValue() certificate_data = renderers.NotAvailableValue() while len(data) > 12: ctype, clength = struct.unpack("<QI", data[0:12]) cvalue, data = data[12:12 + clength], data[12 + clength:] if ctype == 0x10000000b: name = str(cvalue, 'utf-16').strip("\x00") elif ctype == 0x100000020: certificate_data = cvalue return (name, certificate_data)
def _generator(self): callback_table_name = self.create_callback_table( self.context, self.config["nt_symbols"], self.config_path) collection = ssdt.SSDT.build_module_collection( self.context, self.config['primary'], self.config['nt_symbols']) 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, self.config['primary'], self.config['nt_symbols'], 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 find_sid_re( sid_string, sid_re_list) -> Union[str, interfaces.renderers.BaseAbsentValue]: for reg, name in sid_re_list: if reg.search(sid_string): return name return renderers.NotAvailableValue()
def _generator(self): collection = ssdt.SSDT.build_module_collection( self.context, self.config['primary'], self.config['nt_symbols']) for driver in driverscan.DriverScan.scan_drivers( self.context, self.config['primary'], self.config['nt_symbols']): try: driver_name = driver.get_driver_name() except 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_banner(self, clazz: Type[symbol_cache.SymbolBannerCache], data: Any) -> str: """Gets a banner from an ISF file""" banner_symbol = data.get('symbols', {}).get(clazz.symbol_name, {}).get('constant_data', renderers.NotAvailableValue()) if not isinstance(banner_symbol, interfaces.renderers.BaseAbsentValue): banner_symbol = str(base64.b64decode(banner_symbol), encoding='latin-1') return banner_symbol
def _generator(self): if self.config.get('isf', None) is not None: file_list = [self.config['isf']] else: file_list = list(self.list_all_isf_files()) # Filter the files filtered_list = [] if not len(self.config['filter']): filtered_list = file_list else: for isf_file in file_list: for filter_item in self.config['filter']: if filter_item in isf_file: filtered_list.append(isf_file) try: import jsonschema if not self.config['validate']: raise ImportError # Act as if we couldn't import if validation is turned off def check_valid(data): return "True" if schemas.validate(data, True) else "False" except ImportError: def check_valid(data): return "Unknown" # Process the filtered list for entry in filtered_list: num_types = num_enums = num_bases = num_symbols = 0 windows_info = linux_banner = mac_banner = renderers.NotAvailableValue( ) valid = "Unknown" with resources.ResourceAccessor().open(url=entry) as fp: try: data = json.load(fp) num_symbols = len(data.get('symbols', [])) num_types = len(data.get('user_types', [])) num_enums = len(data.get('enums', [])) num_bases = len(data.get('base_types', [])) linux_banner = self._get_banner(linux.LinuxBannerCache, data) mac_banner = self._get_banner(mac.MacBannerCache, data) if not linux_banner and not mac_banner: windows_info = os.path.splitext( os.path.basename(entry))[0] valid = check_valid(data) except (UnicodeDecodeError, json.decoder.JSONDecodeError): vollog.warning("Invalid ISF: {}".format(entry)) yield (0, (entry, valid, num_bases, num_types, num_symbols, num_enums, windows_info, linux_banner, mac_banner))
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) 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) (major, minor, product, build) = [ renderers.NotAvailableValue() ] * 4 # type: Tuple[Union[int, interfaces.renderers.BaseAbsentValue],Union[int, interfaces.renderers.BaseAbsentValue],Union[int, interfaces.renderers.BaseAbsentValue],Union[int, interfaces.renderers.BaseAbsentValue]] 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 # 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 _generator(self) -> Iterator[Tuple[int, Tuple[int, int, Any, Any]]]: layer_name = self.config['primary'] collection = self.build_module_collection(self.context, self.config["primary"], self.config["nt_symbols"]) kvo = self.context.layers[layer_name].config['kernel_virtual_offset'] ntkrnlmp = self.context.module(self.config["nt_symbols"], layer_name=layer_name, offset=kvo) # this is just one way to enumerate the native (NT) service table. # to do the same thing for the Win32K service table, we would need Win32K.sys symbol support ## we could also find nt!KeServiceDescriptorTable (NT) and KeServiceDescriptorTableShadow (NT, Win32K) service_table_address = ntkrnlmp.get_symbol("KiServiceTable").address service_limit_address = ntkrnlmp.get_symbol("KiServiceLimit").address service_limit = ntkrnlmp.object(object_type="int", offset=service_limit_address) # on 32-bit systems the table indexes are 32-bits and contain pointers (unsigned) # on 64-bit systems the indexes are also 32-bits but they're offsets from the # base address of the table and can be negative, so we need a signed data type is_kernel_64 = symbols.symbol_table_is_64bit(self.context, self.config["nt_symbols"]) if is_kernel_64: array_subtype = "long" def kvo_calulator(func: int) -> int: return kvo + service_table_address + (func >> 4) find_address = kvo_calulator else: array_subtype = "unsigned long" def passthrough(func: int) -> int: return func find_address = passthrough functions = ntkrnlmp.object(object_type="array", offset=service_table_address, subtype=ntkrnlmp.get_type(array_subtype), count=service_limit) for idx, function_obj in enumerate(functions): function = find_address(function_obj) module_symbols = collection.get_module_symbols_by_absolute_location( function) for module_name, symbol_generator in module_symbols: symbols_found = False for symbol in symbol_generator: symbols_found = True yield (0, (idx, format_hints.Hex(function), module_name, symbol.split(constants.BANG)[1])) if not symbols_found: yield (0, (idx, format_hints.Hex(function), module_name, renderers.NotAvailableValue()))