Exemple #1
0
    def find_suitable_requirements(self, context: interfaces.context.ContextInterface, config_path: str,
                                   requirement: interfaces.configuration.RequirementInterface,
                                   stacked_layers: List[str]) -> Optional[Tuple[str, str]]:
        """Looks for translation layer requirements and attempts to apply the
        stacked layers to it.  If it succeeds it returns the configuration path
        and layer name where the stacked nodes were spliced into the tree.

        Returns:
            A tuple of a configuration path and layer name for the top of the stacked layers
                or None if suitable requirements are not found
        """
        child_config_path = interfaces.configuration.path_join(config_path, requirement.name)
        if isinstance(requirement, requirements.TranslationLayerRequirement):
            if requirement.unsatisfied(context, config_path):
                original_setting = context.config.get(child_config_path, None)
                for layer_name in stacked_layers:
                    context.config[child_config_path] = layer_name
                    if not requirement.unsatisfied(context, config_path):
                        return child_config_path, layer_name
                else:
                    # Clean-up to restore the config
                    if original_setting:
                        context.config[child_config_path] = original_setting
                    else:
                        del context.config[child_config_path]
            else:
                return child_config_path, context.config.get(child_config_path, None)
        for req_name, req in requirement.requirements.items():
            result = self.find_suitable_requirements(context, child_config_path, req, stacked_layers)
            if result:
                return result
        return None
Exemple #2
0
 def __call__(self,
              context: interfaces.context.ContextInterface,
              config_path: str,
              requirement: interfaces.configuration.RequirementInterface,
              progress_callback: constants.ProgressCallback = None) -> None:
     if requirement.unsatisfied(context, config_path):
         if "pdbscan" not in context.symbol_space:
             context.symbol_space.append(
                 native.NativeTable("pdbscan", native.std_ctypes))
         # TODO: check if this is a windows symbol requirement, otherwise ignore it
         self._symbol_requirements = self.find_requirements(
             context, config_path, requirement,
             requirements.SymbolTableRequirement)
         potential_layers = self.find_virtual_layers_from_req(
             context=context,
             config_path=config_path,
             requirement=requirement)
         for sub_config_path, symbol_req in self._symbol_requirements:
             parent_path = interfaces.configuration.parent_path(
                 sub_config_path)
             if symbol_req.unsatisfied(context, parent_path):
                 valid_kernels = self.determine_valid_kernels(
                     context, potential_layers, progress_callback)
                 if valid_kernels:
                     self.recurse_symbol_fulfiller(context, valid_kernels,
                                                   progress_callback)
                     self.set_kernel_virtual_offset(context, valid_kernels)
Exemple #3
0
    def __call__(
        self,
        context: interfaces.context.ContextInterface,
        config_path: str,
        requirement: interfaces.configuration.RequirementInterface,
        progress_callback: constants.ProgressCallback = None
    ) -> Optional[List[str]]:
        """Runs the automagic over the configurable."""

        framework.import_files(sys.modules['volatility.framework.layers'])

        # Quick exit if we're not needed
        if not requirement.unsatisfied(context, config_path):
            return None

        # Bow out quickly if the UI hasn't provided a single_location
        unsatisfied = self.unsatisfied(self.context, self.config_path)
        if unsatisfied:
            vollog.info(
                "Unable to run LayerStacker, unsatisfied requirement: {}".
                format(unsatisfied))
            return list(unsatisfied)
        if not self.config or not self.config.get('single_location', None):
            raise ValueError(
                "Unable to run LayerStacker, single_location parameter not provided"
            )

        # Search for suitable requirements
        self.stack(context, config_path, requirement, progress_callback)

        if progress_callback is not None:
            progress_callback(100, "Stacking attempts finished")
        return None
Exemple #4
0
    def find_requirements(self,
                          context: interfaces.context.ContextInterface,
                          config_path: str,
                          requirement_root: interfaces.configuration.RequirementInterface,
                          requirement_type: Union[Tuple[Type[interfaces.configuration.RequirementInterface], ...],
                                                  Type[interfaces.configuration.RequirementInterface]],
                          shortcut: bool = True) -> List[Tuple[str, interfaces.configuration.RequirementInterface]]:
        """Determines if there is actually an unfulfilled `Requirement`
        waiting.

        This ensures we do not carry out an expensive search when there is no need for a particular `Requirement`

        Args:
            context: Context on which to operate
            config_path: Configuration path of the top-level requirement
            requirement_root: Top-level requirement whose subrequirements will all be searched
            requirement_type: Type of requirement to find
            shortcut: Only returns requirements that live under unsatisfied requirements

        Returns:
            A list of tuples containing the config_path, sub_config_path and requirement identifying the unsatisfied `Requirements`
        """
        sub_config_path = interfaces.configuration.path_join(config_path, requirement_root.name)
        results = []  # type: List[Tuple[str, interfaces.configuration.RequirementInterface]]
        recurse = not shortcut
        if isinstance(requirement_root, requirement_type):
            if recurse or requirement_root.unsatisfied(context, config_path):
                results.append((sub_config_path, requirement_root))
        else:
            recurse = True
        if recurse:
            for subreq in requirement_root.requirements.values():
                results += self.find_requirements(context, sub_config_path, subreq, requirement_type, shortcut)
        return results
Exemple #5
0
    def __call__(self,
                 context: interfaces.context.ContextInterface,
                 config_path: str,
                 requirement: interfaces.configuration.RequirementInterface,
                 progress_callback: constants.ProgressCallback = None) -> None:
        useful = []
        sub_config_path = interfaces.configuration.path_join(
            config_path, requirement.name)
        if (isinstance(requirement, requirements.TranslationLayerRequirement)
                and requirement.requirements.get("class", False)
                and requirement.unsatisfied(context, config_path)):
            class_req = requirement.requirements["class"]

            for test in self.tests:
                if (test.layer_type.__module__ + "." +
                        test.layer_type.__name__ == class_req.config_value(
                            context, sub_config_path)):
                    useful.append(test)

            # Determine if a class has been chosen
            # Once an appropriate class has been chosen, attempt to determine the page_map_offset value
            if ("memory_layer" in requirement.requirements and
                    not requirement.requirements["memory_layer"].unsatisfied(
                        context, sub_config_path)):
                # Only bother getting the DTB if we don't already have one
                page_map_offset_path = interfaces.configuration.path_join(
                    sub_config_path, "page_map_offset")
                if not context.config.get(page_map_offset_path, None):
                    physical_layer_name = requirement.requirements[
                        "memory_layer"].config_value(context, sub_config_path)
                    if not isinstance(physical_layer_name, str):
                        raise TypeError(
                            "Physical layer name is not a string: {}".format(
                                sub_config_path))
                    physical_layer = context.layers[physical_layer_name]
                    # Check lower layer metadata first
                    if physical_layer.metadata.get('page_map_offset', None):
                        context.config[
                            page_map_offset_path] = physical_layer.metadata[
                                'page_map_offset']
                    else:
                        hits = physical_layer.scan(context,
                                                   PageMapScanner(useful),
                                                   progress_callback)
                        for test, dtb in hits:
                            context.config[page_map_offset_path] = dtb
                            break
                        else:
                            return None
                if isinstance(
                        requirement, interfaces.configuration.
                        ConstructableRequirementInterface):
                    requirement.construct(context, config_path)
        else:
            for subreq in requirement.requirements.values():
                self(context, sub_config_path, subreq)
Exemple #6
0
    def __call__(self,
                 context: interfaces.context.ContextInterface,
                 config_path: str,
                 requirement: interfaces.configuration.RequirementInterface,
                 progress_callback=None,
                 optional=False) -> List[str]:

        # Make sure we import the layers, so they can reconstructed
        framework.import_files(sys.modules['volatility.framework.layers'])

        result = []  # type: List[str]
        if requirement.unsatisfied(context, config_path):
            # Having called validate at the top level tells us both that we need to dig deeper
            # but also ensures that TranslationLayerRequirements have got the correct subrequirements if their class is populated

            subreq_config_path = interfaces.configuration.path_join(
                config_path, requirement.name)
            for subreq in requirement.requirements.values():
                try:
                    self(context,
                         subreq_config_path,
                         subreq,
                         optional=optional or subreq.optional)
                except Exception as e:
                    # We don't really care if this fails, it tends to mean the configuration isn't complete for that item
                    vollog.log(constants.LOGLEVEL_VVVV,
                               "Construction Exception occurred: {}".format(e))
                invalid = subreq.unsatisfied(context, subreq_config_path)
                # We want to traverse optional paths, so don't check until we've tried to validate
                # We also don't want to emit a debug message when a parent is optional, hence the optional parameter
                if invalid and not (optional or subreq.optional):
                    vollog.log(
                        constants.LOGLEVEL_V,
                        "Failed on requirement: {}".format(subreq_config_path))
                    result.append(
                        interfaces.configuration.path_join(
                            subreq_config_path, subreq.name))
            if result:
                return result
            elif isinstance(
                    requirement, interfaces.configuration.
                    ConstructableRequirementInterface):
                # We know all the subrequirements are filled, so let's populate
                requirement.construct(context, config_path)

        if progress_callback is not None:
            progress_callback(100, "Reconstruction finished")

        return []
    def __call__(self,
                 context: interfaces.context.ContextInterface,
                 config_path: str,
                 requirement: interfaces.configuration.RequirementInterface,
                 progress_callback: constants.ProgressCallback = None) -> None:
        """Searches for SymbolTableRequirements and attempt to populate
        them."""

        # Bomb out early if our details haven't been configured
        if self.symbol_class is None:
            return

        self._requirements = self.find_requirements(
            context,
            config_path,
            requirement, (requirements.TranslationLayerRequirement,
                          requirements.SymbolTableRequirement),
            shortcut=False)

        for (sub_path, requirement) in self._requirements:
            parent_path = interfaces.configuration.parent_path(sub_path)

            if (isinstance(requirement, requirements.SymbolTableRequirement)
                    and requirement.unsatisfied(context, parent_path)):
                for (tl_sub_path, tl_requirement) in self._requirements:
                    tl_parent_path = interfaces.configuration.parent_path(
                        tl_sub_path)
                    # Find the TranslationLayer sibling to the SymbolTableRequirement
                    if (isinstance(tl_requirement,
                                   requirements.TranslationLayerRequirement)
                            and tl_parent_path == parent_path):
                        if context.config.get(tl_sub_path, None):
                            self._banner_scan(context, parent_path,
                                              requirement,
                                              context.config[tl_sub_path],
                                              progress_callback)
                            break