def GetRegistryValue(self, source): """Retrieve directly specified registry values, returning Stat objects.""" new_paths = set() has_glob = False for kvdict in source.attributes["key_value_pairs"]: if "*" in kvdict["key"] or rdf_paths.GROUPING_PATTERN.search( kvdict["key"]): has_glob = True if kvdict["value"]: # This currently only supports key value pairs specified using forward # slash. path = "\\".join((kvdict["key"], kvdict["value"])) else: # If value is not set, we want to get the default value. In # GRR this is done by specifying the key only, so this is what # we do here. path = kvdict["key"] expanded_paths = artifact_utils.InterpolateKbAttributes( path, self.state.knowledge_base, ignore_errors=self.args.ignore_interpolation_errors) new_paths.update(expanded_paths) if has_glob: self.CallFlow(filesystem.Glob.__name__, paths=new_paths, pathtype=rdf_paths.PathSpec.PathType.REGISTRY, request_data={ "artifact_name": self.current_artifact_name, "source": source.ToPrimitiveDict() }, next_state="ProcessCollected") else: # We call statfile directly for keys that don't include globs because it # is faster and some artifacts rely on getting an IOError to trigger # fallback processing. for new_path in new_paths: pathspec = rdf_paths.PathSpec( path=new_path, pathtype=rdf_paths.PathSpec.PathType.REGISTRY) # TODO(hanuszczak): Support for old clients ends on 2021-01-01. # This conditional should be removed after that date. if self.client_version >= 3221: stub = server_stubs.GetFileStat request = rdf_client.GetFileStatRequest(pathspec=pathspec) else: stub = server_stubs.StatFile request = rdf_client.ListDirRequest(pathspec=pathspec) self.CallClient(stub, request, request_data={ "artifact_name": self.current_artifact_name, "source": source.ToPrimitiveDict() }, next_state="ProcessCollectedRegistryStatEntry")
def _ProcessRegistryValueSource(self, args): new_paths = set() has_glob = False for kvdict in args.base_source.attributes["key_value_pairs"]: if "*" in kvdict["key"] or rdf_paths.GROUPING_PATTERN.search( kvdict["key"]): has_glob = True if kvdict["value"]: path = "\\".join((kvdict["key"], kvdict["value"])) else: path = kvdict["key"] expanded_paths = artifact_utils.InterpolateKbAttributes( path, self.knowledge_base, ignore_errors=self.ignore_interpolation_errors) new_paths.update(expanded_paths) if has_glob: # TODO(user): If a path has a wildcard we need to glob the filesystem # for patterns to collect matching files. The corresponding flow is # filesystem.Glob. pass else: action = standard.GetFileStat response_field = "file_stat" for new_path in new_paths: pathspec = rdf_paths.PathSpec( path=new_path, pathtype=rdf_paths.PathSpec.PathType.REGISTRY) request = rdf_client.GetFileStatRequest(pathspec=pathspec) yield action, request, response_field
def _InterpolatePaths(self, globs): client = aff4.FACTORY.Open(self.client_id, token=self.token) kb = client.Get(client.Schema.KNOWLEDGE_BASE) for glob in globs: param_path = glob.SerializeToString() for path in artifact_utils.InterpolateKbAttributes(param_path, kb): yield path
def Interpolate(self, client=None): kb = client.Get(client.Schema.KNOWLEDGE_BASE) patterns = artifact_utils.InterpolateKbAttributes(self._value, kb) for pattern in patterns: # Normalize the component path (this allows us to resolve ../ # sequences). pattern = utils.NormalizePath(pattern.replace("\\", "/")) for pattern in self.InterpolateGrouping(pattern): yield pattern
def _GetSingleExpansion(self, value): results = list( artifact_utils.InterpolateKbAttributes( value, self.state.knowledge_base, ignore_errors=self.args.ignore_interpolation_errors)) if len(results) > 1: raise ValueError( "Interpolation generated multiple results, use a" " list for multi-value expansions. %s yielded: %s" % (value, results)) return results[0]
def testInterpolation(self): """Check we can interpolate values from the knowledge base.""" kb = rdf_client.KnowledgeBase() # No users yet, this should raise self.assertRaises( artifact_utils.KnowledgeBaseInterpolationError, list, artifact_utils.InterpolateKbAttributes("test%%users.username%%test", kb)) # Now we have two users kb.users.Append(rdf_client.User(username="******", uid=1)) kb.users.Append(rdf_client.User(username="******", uid=2)) kb.Set("environ_allusersprofile", "c:\\programdata") paths = artifact_utils.InterpolateKbAttributes("test%%users.username%%test", kb) paths = list(paths) self.assertEqual(len(paths), 2) self.assertItemsEqual(paths, ["testjoetest", "testjimtest"]) paths = artifact_utils.InterpolateKbAttributes( "%%environ_allusersprofile%%\\a", kb) self.assertEqual(list(paths), ["c:\\programdata\\a"]) # Check a bad attribute raises self.assertRaises( artifact_utils.KnowledgeBaseInterpolationError, list, artifact_utils.InterpolateKbAttributes("%%nonexistent%%\\a", kb)) # Empty values should also raise kb.Set("environ_allusersprofile", "") self.assertRaises( artifact_utils.KnowledgeBaseInterpolationError, list, artifact_utils.InterpolateKbAttributes("%%environ_allusersprofile%%\\a", kb)) # No users have temp defined, so this should raise self.assertRaises( artifact_utils.KnowledgeBaseInterpolationError, list, artifact_utils.InterpolateKbAttributes("%%users.temp%%\\a", kb)) # One user has users.temp defined, the others do not. This is common on # windows where users have been created but have never logged in. We should # get just one value back. kb.users.Append( rdf_client.User( username="******", uid=1, temp="C:\\Users\\jason\\AppData\\Local\\Temp")) paths = artifact_utils.InterpolateKbAttributes(r"%%users.temp%%\abcd", kb) self.assertItemsEqual(paths, ["C:\\Users\\jason\\AppData\\Local\\Temp\\abcd"])
def WMIQuery(self, source): """Run a Windows WMI Query.""" query = source.attributes["query"] queries = artifact_utils.InterpolateKbAttributes( query, self.state.knowledge_base, ignore_errors=self.args.ignore_interpolation_errors) base_object = source.attributes.get("base_object") for query in queries: self.CallClient(server_stubs.WmiQuery, query=query, base_object=base_object, request_data={ "artifact_name": self.current_artifact_name, "source": source.ToPrimitiveDict() }, next_state="ProcessCollected")
def InterpolateList(self, input_list): """Interpolate all items from a given source array. Args: input_list: list of values to interpolate Returns: original list of values extended with strings interpolated """ new_args = [] for value in input_list: if isinstance(value, basestring): results = list( artifact_utils.InterpolateKbAttributes( value, self.state.knowledge_base, ignore_errors=self.args.ignore_interpolation_errors)) new_args.extend(results) else: new_args.extend(value) return new_args
def GetFiles(self, source, path_type, max_size): """Get a set of files.""" new_path_list = [] for path in source.attributes["paths"]: # Interpolate any attributes from the knowledgebase. new_path_list.extend( artifact_utils.InterpolateKbAttributes( path, self.state.knowledge_base, ignore_errors=self.args.ignore_interpolation_errors)) action = rdf_file_finder.FileFinderAction.Download(max_size=max_size) self.CallFlow(file_finder.FileFinder.__name__, paths=new_path_list, pathtype=path_type, action=action, request_data={ "artifact_name": self.current_artifact_name, "source": source.ToPrimitiveDict() }, next_state="ProcessFileFinderResults")