def render(self, renderer): if self.plugin_args.converter: cls = ProfileConverter.classes.get(self.plugin_args.converter) if not cls: raise IOError("Unknown converter %s" % self.plugin_args.converter) return cls(self.plugin_args.source, profile_class=self.plugin_args.profile_class).Convert() try: input = io_manager.Factory(self.plugin_args.source, session=self.session, mode="r") except IOError: self.session.logging.critical( "Input profile file %s could not be opened.", self.plugin_args.source) return with input: profile = self.ConvertProfile(input) if profile: with renderer.open(filename=self.plugin_args.out_file, mode="wt") as output: output.write(utils.PPrint(profile)) self.session.logging.info("Converted %s to %s", input, output.name)
def Build(self, renderer): """Linux profile location""" convert_profile = self.session.plugins.convert_profile( session=self.session, source="/dev/null", out_file="dummy file") # We don't really output the profile. changed_files = False total_profiles = 0 new_profiles = 0 for source_profile in self.args.repository.ListFiles(): # Find all source profiles. if (source_profile.startswith("src/Linux") and source_profile.endswith(".zip")): total_profiles += 1 profile_id = source_profile.lstrip("src/").rstrip(".zip") # Skip already built profiles. if self.args.repository.Metadata(profile_id): continue # Convert the profile self.session.report_progress( "Found new raw Linux profile %s. Converting...", profile_id) self.session.logging.info("Found new raw Linux profile %s", profile_id) profile_fullpath = self.args.repository.GetAbsolutePathName( source_profile) profile = convert_profile.ConvertProfile( io_manager.Factory(profile_fullpath, session=self.session, mode="r")) if not profile: self.session.logging.info( "Skipped %s, Unable to convert to a Rekall profile.", profile_fullpath) continue # Add profile to the repository and the inventory self.args.repository.StoreData(profile_id, profile) new_profiles += 1 changed_files = True self.session.logging.info("Found %d profiles. %d are new.", total_profiles, new_profiles) # Now rebuild the index if changed_files and self.args.index or self.args.force_build_index: self.BuildIndex()
def repository_managers(self): """The IO managers that are used to fetch profiles from the profile repository. """ if self._repository_managers: return self._repository_managers # The profile path is specified in search order. repository_path = (self.state.Get("repository_path") or self.state.Get("profile_path") or []) for path in repository_path: self._repository_managers.append( (path, io_manager.Factory(path, session=self))) return self._repository_managers
def repository_managers(self): """The IO managers that are used to fetch profiles from the profile repository. """ if self._repository_managers: return self._repository_managers # The profile path is specified in search order. repository_path = (self.GetParameter("repository_path") or self.GetParameter("profile_path") or []) for path in repository_path: # TODO(scudette): remove this hack for 1.6 release. Github has # changed their static URL access. If the user is using an old URL # we warn and correct it. if path in constants.OLD_DEPRECATED_URLS: self.logging.warn( "Rekall's profile repository is pointing to deprecated URL " "(%s). Please update your ~/.rekallrc file.", path) path = constants.PROFILE_REPOSITORIES[0] try: self._repository_managers.append( (path, io_manager.Factory(path, session=self))) except ValueError: pass if not self._repository_managers: try: self.logging.warn( "No usable repositories were found. " "Rekall Will attempt to use the local cache. " "This is likely to fail if profiles are missing locally!") self._repository_managers = [ (None, io_manager.DirectoryIOManager(urn=cache.GetCacheDir(self), session=self)) ] except IOError: self._repository_managers = [] return self._repository_managers
def render(self, renderer): if self.converter: cls = ProfileConverter.classes.get(self.converter) if not cls: raise IOError("Unknown converter %s" % self.converter) return cls(self.source, self.output, profile_class=self.profile_class).Convert() try: input = io_manager.Factory(self.source, mode="r") except IOError: logging.critical("Input profile file %s could not be opened.", self.source) return with input, self.output: self.ConvertProfile(input, self.output)
def render_profile_info(self, renderer): for path in self.session.state.profile_path: manager = io_manager.Factory(path) renderer.section() renderer.format("Profile Repository {0}\n\n", path) renderer.table_header([('Profile', 'profile', "40"), ('Docs', 'docs', '[wrap:70]'), ]) try: # If the repository contains a proper metadata list we show it. repository_metadata = manager.GetData("metadata") if repository_metadata: for name, profile_metadata in sorted( repository_metadata.get("inventory", {}).items()): renderer.table_row( name, profile_metadata.get("description", "")) except IOError: # Otherwise we just list the files in the repository. for name in sorted(manager.ListFiles()): renderer.table_row(name)
def LoadProfile(self, filename, use_cache=True): """Try to load a profile directly from a filename. Args: filename: A string which will be used to get an io_manager container. If it contains a path sepearator we open the file directly, otherwise we search in the profile_path specification. Returns: a Profile() instance or a NoneObject() """ if not filename: return if isinstance(filename, obj.Profile): return filename # We only want to deal with unix paths. filename = filename.replace("\\", "/") canonical_name = os.path.splitext(filename)[0] try: if use_cache: cached_profile = self.profile_cache[canonical_name] if cached_profile: return cached_profile.copy() else: raise ValueError( "Unable to load profile %s from any repository." % filename) except KeyError: pass # If the filename is a path we try to open it directly: if os.access(filename, os.R_OK): container = io_manager.Factory(os.path.dirname(filename)) result = obj.Profile.LoadProfileFromData(container.GetData( os.path.basename(filename)), self, name=canonical_name) # Traverse the profile path until one works. else: result = None # The profile path is specified in search order. profile_path = self.state.Get("profile_path") or [] # Add the last supported repository as the last fallback path. for path in profile_path: path = "%s/%s" % (path, constants.PROFILE_REPOSITORY_VERSION) try: manager = io_manager.Factory(path) try: # The inventory allows us to fail fetching the profile # quickly - without making the round trip. if path not in self.inventories: # Fetch the profile inventory. self.inventories[path] = manager.GetData( "inventory") inventory = self.inventories[path]["$INVENTORY"] if (filename not in inventory and filename + ".gz" not in inventory): continue # No inventory in that repository - just try anyway. except IOError: pass result = obj.Profile.LoadProfileFromData( manager.GetData(filename), self, name=canonical_name) logging.info("Loaded profile %s from %s", filename, manager) break except (IOError, KeyError) as e: result = obj.NoneObject(e) logging.debug("Could not find profile %s in %s", filename, path) continue # Cache it for later. Note that this also caches failures so we do not # retry again. self.profile_cache[canonical_name] = result if result == None: raise ValueError("Unable to load profile %s from any repository." % filename) return result
def LoadProfile(self, name, use_cache=True): """Try to load a profile directly by its name. Args: name: A string which represents the canonical name for the profile. We ask all repositories in the repository_path to resolve this name into a profile. Returns: a Profile() instance or a NoneObject() """ if not name: return obj.NoneObject("No filename") if isinstance(name, obj.Profile): return name # We only want to deal with unix paths. name = name.replace("\\", "/") try: if use_cache: cached_profile = self.profile_cache[name] if cached_profile: return cached_profile else: return obj.NoneObject( "Unable to load profile %s from any repository." % name) except KeyError: pass result = None try: # If the name is a path we try to open it directly: container = io_manager.DirectoryIOManager(os.path.dirname(name), version=None) result = obj.Profile.LoadProfileFromData(container.GetData( os.path.basename(name)), self, name=name) except IOError: pass # Traverse the profile path until one works. if not result: # The profile path is specified in search order. repository_path = (self.state.Get("repository_path") or self.state.Get("profile_path") or []) # Add the last supported repository as the last fallback path. for path in repository_path: try: if path not in self.repository_managers: self.repository_managers[path] = io_manager.Factory( path, session=self) manager = self.repository_managers[path] # The inventory allows us to fail fetching the profile # quickly - without making the round trip. if not manager.CheckInventory(name): logging.debug( "Skipped profile %s from %s (Not in inventory)", name, path) continue result = obj.Profile.LoadProfileFromData( manager.GetData(name), self, name=name) logging.info("Loaded profile %s from %s", name, manager) break except (IOError, KeyError) as e: result = obj.NoneObject(e) logging.debug("Could not find profile %s in %s: %s", name, path, e) continue # Cache it for later. Note that this also caches failures so we do not # retry again. self.profile_cache[name] = result if result == None: return obj.NoneObject( "Unable to load profile %s from any repository." % name) return result
def LoadProfile(self, filename, use_cache=True): """Try to load a profile directly from a filename. Args: filename: A string which will be used to get an io_manager container. If it contains a path sepearator we open the file directly, otherwise we search in the profile_path specification. Returns: a Profile() instance or a NoneObject() """ if not filename: return if isinstance(filename, obj.Profile): return filename # We only want to deal with unix paths. filename = filename.replace("\\", "/") # Only strip the extension if it is one of the recognized # extensions. Otherwise ignore it - this allows the profile name to have # . characters in it (e.g. Linux-3.1.13). canonical_name, extension = os.path.splitext(filename) if extension not in [".gz", ".json"]: canonical_name = filename try: if use_cache: cached_profile = self.profile_cache[canonical_name] if cached_profile: return cached_profile else: return obj.NoneObject( "Unable to load profile %s from any repository." % filename) except KeyError: pass # If the filename is a path we try to open it directly: if os.access(filename, os.R_OK): container = io_manager.Factory(os.path.dirname(filename)) result = obj.Profile.LoadProfileFromData( container.GetData(os.path.basename(filename)), self, name=canonical_name) # Traverse the profile path until one works. else: result = None # The profile path is specified in search order. profile_path = self.state.Get("profile_path") or [] # Add the last supported repository as the last fallback path. for path in profile_path: path = "%s/%s" % (path, constants.PROFILE_REPOSITORY_VERSION) # For now, print a warning when the user has an out of date # config file. TODO: Remove this in a future version. if "profiles.rekall.googlecode.com" in path: logging.warn( "Rekall profiles have moved to %s, but your .rekallrc " "file still points to %s. You should update your " "config file.", constants.PROFILE_REPOSITORIES[0], path) try: manager = io_manager.Factory(path) try: # The inventory allows us to fail fetching the profile # quickly - without making the round trip. if path not in self.inventories: # Fetch the profile inventory. self.inventories[path] = manager.GetData( "inventory") inventory = self.inventories[path]["$INVENTORY"] if (filename not in inventory and filename + ".gz" not in inventory): logging.debug( "Skipped profile %s from %s (Not in inventory)", filename, path) continue # No inventory in that repository - just try anyway. except IOError: pass result = obj.Profile.LoadProfileFromData( manager.GetData(filename), self, name=canonical_name) logging.info( "Loaded profile %s from %s", filename, manager) break except (IOError, KeyError) as e: result = obj.NoneObject(e) logging.debug("Could not find profile %s in %s", filename, path) continue # Cache it for later. Note that this also caches failures so we do not # retry again. self.profile_cache[canonical_name] = result if result == None: return obj.NoneObject( "Unable to load profile %s from any repository." % filename) return result