예제 #1
0
    def _generator(self, tasks):
        vmlinux = self.context.modules[self.config["kernel"]]
        is_32bit = not symbols.symbol_table_is_64bit(self.context,
                                                     vmlinux.symbol_table_name)
        if is_32bit:
            pack_format = "I"
            bash_json_file = "bash32"
        else:
            pack_format = "Q"
            bash_json_file = "bash64"

        bash_table_name = BashIntermedSymbols.create(self.context,
                                                     self.config_path, "linux",
                                                     bash_json_file)

        ts_offset = self.context.symbol_space.get_type(
            bash_table_name + constants.BANG +
            "hist_entry").relative_child_offset("timestamp")

        for task in tasks:
            task_name = utility.array_to_string(task.comm)
            if task_name not in ["bash", "sh", "dash"]:
                continue

            proc_layer_name = task.add_process_layer()
            if not proc_layer_name:
                continue

            proc_layer = self.context.layers[proc_layer_name]

            bang_addrs = []

            # find '#' values on the heap
            for address in proc_layer.scan(
                    self.context,
                    scanners.BytesScanner(b"#"),
                    sections=task.get_process_memory_sections(heap_only=True)):
                bang_addrs.append(struct.pack(pack_format, address))

            history_entries = []

            if bang_addrs:
                for address, _ in proc_layer.scan(
                        self.context,
                        scanners.MultiStringScanner(bang_addrs),
                        sections=task.get_process_memory_sections(
                            heap_only=True)):
                    hist = self.context.object(bash_table_name +
                                               constants.BANG + "hist_entry",
                                               offset=address - ts_offset,
                                               layer_name=proc_layer_name)

                    if hist.is_valid():
                        history_entries.append(hist)

            for hist in sorted(history_entries,
                               key=lambda x: x.get_time_as_integer()):
                yield (0, (task.pid, task_name, hist.get_time_object(),
                           hist.get_command()))
예제 #2
0
    def __init__(self, module: interfaces.context.ModuleInterface, constraint_lookup: Dict[bytes, PoolConstraint],
                 alignment: int):
        super().__init__()
        self._module = module
        self._constraint_lookup = constraint_lookup
        self._alignment = alignment

        header_type = self._module.get_type('_POOL_HEADER')
        self._header_offset = header_type.relative_child_offset('PoolTag')
        self._subscanner = scanners.MultiStringScanner([c for c in constraint_lookup.keys()])
예제 #3
0
파일: linux.py 프로젝트: XZVB12/volatility3
    def stack(cls,
              context: interfaces.context.ContextInterface,
              layer_name: str,
              progress_callback: constants.ProgressCallback = None) -> Optional[interfaces.layers.DataLayerInterface]:
        """Attempts to identify linux within this layer."""
        # Bail out by default unless we can stack properly
        layer = context.layers[layer_name]
        join = interfaces.configuration.path_join

        # Never stack on top of an intel layer
        # FIXME: Find a way to improve this check
        if isinstance(layer, intel.Intel):
            return None

        linux_banners = LinuxBannerCache.load_banners()
        # If we have no banners, don't bother scanning
        if not linux_banners:
            vollog.info("No Linux banners found - if this is a linux plugin, please check your symbol files location")
            return None

        mss = scanners.MultiStringScanner([x for x in linux_banners if x is not None])
        for _, banner in layer.scan(context = context, scanner = mss, progress_callback = progress_callback):
            dtb = None
            vollog.debug("Identified banner: {}".format(repr(banner)))

            symbol_files = linux_banners.get(banner, None)
            if symbol_files:
                isf_path = symbol_files[0]
                table_name = context.symbol_space.free_table_name('LintelStacker')
                table = linux.LinuxKernelIntermedSymbols(context,
                                                         'temporary.' + table_name,
                                                         name = table_name,
                                                         isf_url = isf_path)
                context.symbol_space.append(table)
                kaslr_shift, aslr_shift = cls.find_aslr(context,
                                                        table_name,
                                                        layer_name,
                                                        progress_callback = progress_callback)

                layer_class = intel.Intel  # type: Type
                if 'init_top_pgt' in table.symbols:
                    layer_class = intel.Intel32e
                    dtb_symbol_name = 'init_top_pgt'
                elif 'init_level4_pgt' in table.symbols:
                    layer_class = intel.Intel32e
                    dtb_symbol_name = 'init_level4_pgt'
                else:
                    dtb_symbol_name = 'swapper_pg_dir'

                dtb = cls.virtual_to_physical_address(table.get_symbol(dtb_symbol_name).address + kaslr_shift)

                # Build the new layer
                new_layer_name = context.layers.free_layer_name("IntelLayer")
                config_path = join("IntelHelper", new_layer_name)
                context.config[join(config_path, "memory_layer")] = layer_name
                context.config[join(config_path, "page_map_offset")] = dtb
                context.config[join(config_path, LinuxSymbolFinder.banner_config_key)] = str(banner, 'latin-1')

                layer = layer_class(context,
                                    config_path = config_path,
                                    name = new_layer_name,
                                    metadata = {'kaslr_value': aslr_shift, 'os': 'Linux'})

            if layer and dtb:
                vollog.debug("DTB was found at: 0x{:0x}".format(dtb))
                return layer
        vollog.debug("No suitable linux banner could be matched")
        return None
예제 #4
0
    def _banner_scan(
            self,
            context: interfaces.context.ContextInterface,
            config_path: str,
            requirement: interfaces.configuration.
        ConstructableRequirementInterface,
            layer_name: str,
            progress_callback: constants.ProgressCallback = None) -> None:
        """Accepts a context, config_path and SymbolTableRequirement, with a
        constructed layer_name and scans the layer for banners."""

        # Bomb out early if there's no banners
        if not self.banners:
            return

        mss = scanners.MultiStringScanner(
            [x for x in self.banners if x is not None])

        layer = context.layers[layer_name]

        # Check if the Stacker has already found what we're looking for
        if layer.config.get(self.banner_config_key, None):
            banner_list = [(0,
                            bytes(layer.config[self.banner_config_key],
                                  'raw_unicode_escape'))
                           ]  # type: Iterable[Any]
        else:
            # Swap to the physical layer for scanning
            # TODO: Fix this so it works for layers other than just Intel
            layer = context.layers[layer.config['memory_layer']]
            banner_list = layer.scan(context=context,
                                     scanner=mss,
                                     progress_callback=progress_callback)

        for _, banner in banner_list:
            vollog.debug("Identified banner: {}".format(repr(banner)))
            symbol_files = self.banners.get(banner, None)
            if symbol_files:
                isf_path = symbol_files[0]
                vollog.debug("Using symbol library: {}".format(
                    symbol_files[0]))
                clazz = self.symbol_class
                # Set the discovered options
                path_join = interfaces.configuration.path_join
                context.config[path_join(config_path, requirement.name,
                                         "class")] = clazz
                context.config[path_join(config_path, requirement.name,
                                         "isf_url")] = isf_path
                context.config[path_join(config_path, requirement.name,
                                         "symbol_mask")] = layer.address_mask

                # Set a default symbol_shift when attempt to determine it,
                # so we can create the symbols which are used in finding the aslr_shift anyway
                if not context.config.get(
                        path_join(config_path, requirement.name,
                                  "symbol_shift"), None):
                    # Don't overwrite it if it's already been set, it will be manually refound if not present
                    prefound_kaslr_value = context.layers[
                        layer_name].metadata.get('kaslr_value', 0)
                    context.config[path_join(
                        config_path, requirement.name,
                        "symbol_shift")] = prefound_kaslr_value
                # Construct the appropriate symbol table
                requirement.construct(context, config_path)

                # Apply the ASLR masking (only if we're not already shifted)
                if self.find_aslr and not context.config.get(
                        path_join(config_path, requirement.name,
                                  "symbol_shift"), None):
                    unmasked_symbol_table_name = context.config.get(
                        path_join(config_path, requirement.name), None)
                    if not unmasked_symbol_table_name:
                        raise exceptions.SymbolSpaceError(
                            "Symbol table could not be constructed")
                    if not isinstance(layer, layers.intel.Intel):
                        raise TypeError("Layer name {} is not an intel space")
                    aslr_shift = self.find_aslr(context,
                                                unmasked_symbol_table_name,
                                                layer.config['memory_layer'])
                    context.config[path_join(config_path, requirement.name,
                                             "symbol_shift")] = aslr_shift
                    context.symbol_space.clear_symbol_cache(
                        unmasked_symbol_table_name)

                break
            else:
                if symbol_files:
                    vollog.debug("Symbol library path not found: {}".format(
                        symbol_files[0]))
                    # print("Kernel", banner, hex(banner_offset))
        else:
            vollog.debug("No existing banners found")
예제 #5
0
    def stack(
        cls,
        context: interfaces.context.ContextInterface,
        layer_name: str,
        progress_callback: constants.ProgressCallback = None
    ) -> Optional[interfaces.layers.DataLayerInterface]:
        """Attempts to identify mac within this layer."""
        # Bail out by default unless we can stack properly
        layer = context.layers[layer_name]
        new_layer = None
        join = interfaces.configuration.path_join

        # Never stack on top of an intel layer
        # FIXME: Find a way to improve this check
        if isinstance(layer, intel.Intel):
            return None

        mac_banners = MacBannerCache.load_banners()
        # If we have no banners, don't bother scanning
        if not mac_banners:
            vollog.info(
                "No Mac banners found - if this is a mac plugin, please check your symbol files location"
            )
            return None

        mss = scanners.MultiStringScanner([x for x in mac_banners if x])
        for banner_offset, banner in layer.scan(
                context=context, scanner=mss,
                progress_callback=progress_callback):
            dtb = None
            vollog.debug(f"Identified banner: {repr(banner)}")

            symbol_files = mac_banners.get(banner, None)
            if symbol_files:
                isf_path = symbol_files[0]
                table_name = context.symbol_space.free_table_name(
                    'MacintelStacker')
                table = mac.MacKernelIntermedSymbols(context=context,
                                                     config_path=join(
                                                         'temporary',
                                                         table_name),
                                                     name=table_name,
                                                     isf_url=isf_path)
                context.symbol_space.append(table)
                kaslr_shift = cls.find_aslr(
                    context=context,
                    symbol_table=table_name,
                    layer_name=layer_name,
                    compare_banner=banner,
                    compare_banner_offset=banner_offset,
                    progress_callback=progress_callback)

                if kaslr_shift == 0:
                    vollog.log(
                        constants.LOGLEVEL_VVV,
                        f"Invalid kalsr_shift found at offset: {banner_offset}"
                    )
                    continue

                bootpml4_addr = cls.virtual_to_physical_address(
                    table.get_symbol("BootPML4").address + kaslr_shift)

                new_layer_name = context.layers.free_layer_name(
                    "MacDTBTempLayer")
                config_path = join("automagic", "MacIntelHelper",
                                   new_layer_name)
                context.config[join(config_path, "memory_layer")] = layer_name
                context.config[join(config_path,
                                    "page_map_offset")] = bootpml4_addr

                layer = layers.intel.Intel32e(context,
                                              config_path=config_path,
                                              name=new_layer_name,
                                              metadata={'os': 'Mac'})

                idlepml4_ptr = table.get_symbol(
                    "IdlePML4").address + kaslr_shift
                try:
                    idlepml4_str = layer.read(idlepml4_ptr, 4)
                except exceptions.InvalidAddressException:
                    vollog.log(
                        constants.LOGLEVEL_VVVV,
                        f"Skipping invalid idlepml4_ptr: 0x{idlepml4_ptr:0x}")
                    continue

                idlepml4_addr = struct.unpack("<I", idlepml4_str)[0]

                tmp_dtb = idlepml4_addr

                if tmp_dtb % 4096:
                    vollog.log(
                        constants.LOGLEVEL_VVV,
                        f"Skipping non-page aligned DTB: 0x{tmp_dtb:0x}")
                    continue

                dtb = tmp_dtb

                # Build the new layer
                new_layer_name = context.layers.free_layer_name("IntelLayer")
                config_path = join("automagic", "MacIntelHelper",
                                   new_layer_name)
                context.config[join(config_path, "memory_layer")] = layer_name
                context.config[join(config_path, "page_map_offset")] = dtb
                context.config[join(config_path,
                                    MacSymbolFinder.banner_config_key)] = str(
                                        banner, 'latin-1')

                new_layer = intel.Intel32e(context,
                                           config_path=config_path,
                                           name=new_layer_name,
                                           metadata={'os': 'mac'})
                new_layer.config['kernel_virtual_offset'] = kaslr_shift

            if new_layer and dtb:
                vollog.debug(f"DTB was found at: 0x{dtb:0x}")
                return new_layer
        vollog.debug("No suitable mac banner could be matched")
        return None
예제 #6
0
    def _generator(self) -> Iterator[Tuple]:
        kernel = self.context.modules[self.config['kernel']]
        physical_layer_name = self.context.layers[
            kernel.layer_name].config.get('memory_layer', None)

        # Decide of Memory Dump Architecture
        layer = self.context.layers[physical_layer_name]
        architecture = "intel" if not symbols.symbol_table_is_64bit(
            self.context, kernel.symbol_table_name) else "intel64"

        # Read in the Symbol File
        symbol_table = intermed.IntermediateSymbolTable.create(
            context=self.context,
            config_path=self.config_path,
            sub_path="windows",
            filename="mbr",
            class_types={
                'PARTITION_TABLE': mbr.PARTITION_TABLE,
                'PARTITION_ENTRY': mbr.PARTITION_ENTRY
            })

        partition_table_object = symbol_table + constants.BANG + "PARTITION_TABLE"

        # Define Signature and Data Length
        mbr_signature = b"\x55\xAA"
        mbr_length = 0x200
        bootcode_length = 0x1B8

        # Scan the Layer for Raw Master Boot Record (MBR) and parse the fields
        for offset, _value in layer.scan(
                context=self.context,
                scanner=scanners.MultiStringScanner(patterns=[mbr_signature])):
            try:
                mbr_start_offset = offset - (mbr_length - len(mbr_signature))
                partition_table = self.context.object(partition_table_object,
                                                      offset=mbr_start_offset,
                                                      layer_name=layer.name)

                # Extract only BootCode
                full_mbr = layer.read(mbr_start_offset, mbr_length, pad=True)
                bootcode = full_mbr[:bootcode_length]

                all_zeros = None

                if bootcode:
                    all_zeros = bootcode.count(b"\x00") == len(bootcode)

                if not all_zeros:

                    partition_entries = [
                        partition_table.FirstEntry,
                        partition_table.SecondEntry,
                        partition_table.ThirdEntry, partition_table.FourthEntry
                    ]

                    if not self.config.get("full", True):
                        yield (0, (format_hints.Hex(offset),
                                   partition_table.get_disk_signature(),
                                   self.get_hash(bootcode),
                                   self.get_hash(full_mbr),
                                   renderers.NotApplicableValue(),
                                   renderers.NotApplicableValue(),
                                   renderers.NotApplicableValue(),
                                   renderers.NotApplicableValue(),
                                   interfaces.renderers.Disassembly(
                                       bootcode, 0, architecture)))
                    else:
                        yield (0, (format_hints.Hex(offset),
                                   partition_table.get_disk_signature(),
                                   self.get_hash(bootcode),
                                   self.get_hash(full_mbr),
                                   renderers.NotApplicableValue(),
                                   renderers.NotApplicableValue(),
                                   renderers.NotApplicableValue(),
                                   renderers.NotApplicableValue(),
                                   renderers.NotApplicableValue(),
                                   renderers.NotApplicableValue(),
                                   renderers.NotApplicableValue(),
                                   renderers.NotApplicableValue(),
                                   renderers.NotApplicableValue(),
                                   renderers.NotApplicableValue(),
                                   renderers.NotApplicableValue(),
                                   renderers.NotApplicableValue(),
                                   renderers.NotApplicableValue(),
                                   interfaces.renderers.Disassembly(
                                       bootcode, 0, architecture),
                                   format_hints.HexBytes(bootcode)))

                    for partition_index, partition_entry_object in enumerate(
                            partition_entries, start=1):

                        if not self.config.get("full", True):
                            yield (1, (
                                format_hints.Hex(offset),
                                partition_table.get_disk_signature(),
                                self.get_hash(bootcode),
                                self.get_hash(full_mbr), partition_index,
                                partition_entry_object.is_bootable(),
                                partition_entry_object.get_partition_type(),
                                format_hints.Hex(partition_entry_object.
                                                 get_size_in_sectors()),
                                renderers.NotApplicableValue()))
                        else:
                            yield (1, (
                                format_hints.Hex(offset),
                                partition_table.get_disk_signature(),
                                self.get_hash(bootcode),
                                self.get_hash(full_mbr), partition_index,
                                partition_entry_object.is_bootable(),
                                format_hints.Hex(partition_entry_object.
                                                 get_bootable_flag()),
                                partition_entry_object.get_partition_type(),
                                format_hints.Hex(
                                    partition_entry_object.PartitionType),
                                format_hints.Hex(
                                    partition_entry_object.get_starting_lba()),
                                partition_entry_object.get_starting_cylinder(),
                                partition_entry_object.get_starting_chs(),
                                partition_entry_object.get_starting_sector(),
                                partition_entry_object.get_ending_cylinder(),
                                partition_entry_object.get_ending_chs(),
                                partition_entry_object.get_ending_sector(),
                                format_hints.Hex(partition_entry_object.
                                                 get_size_in_sectors()),
                                renderers.NotApplicableValue(),
                                renderers.NotApplicableValue()))
                else:
                    vollog.log(
                        constants.LOGLEVEL_VVVV,
                        f"Not a valid MBR: Data all zeroed out : {format_hints.Hex(offset)}"
                    )
                    continue

            except exceptions.PagedInvalidAddressException as excp:
                vollog.log(
                    constants.LOGLEVEL_VVVV,
                    f"Invalid address identified in guessed MBR: {hex(excp.invalid_address)}"
                )
                continue
예제 #7
0
    def _banner_scan(
            self,
            context: interfaces.context.ContextInterface,
            config_path: str,
            requirement: interfaces.configuration.
        ConstructableRequirementInterface,
            layer_name: str,
            progress_callback: constants.ProgressCallback = None) -> None:
        """Accepts a context, config_path and SymbolTableRequirement, with a
        constructed layer_name and scans the layer for banners."""

        # Bomb out early if there's no banners
        if not self.banners:
            return

        mss = scanners.MultiStringScanner(
            [x for x in self.banners if x is not None])

        layer = context.layers[layer_name]

        # Check if the Stacker has already found what we're looking for
        if layer.config.get(self.banner_config_key, None):
            banner_list = [(0,
                            bytes(layer.config[self.banner_config_key],
                                  'raw_unicode_escape'))
                           ]  # type: Iterable[Any]
        else:
            # Swap to the physical layer for scanning
            # Only traverse down a layer if it's an intel layer
            # TODO: Fix this so it works for layers other than just Intel
            if isinstance(layer, layers.intel.Intel):
                layer = context.layers[layer.config['memory_layer']]
            banner_list = layer.scan(context=context,
                                     scanner=mss,
                                     progress_callback=progress_callback)

        for _, banner in banner_list:
            vollog.debug(f"Identified banner: {repr(banner)}")
            symbol_files = self.banners.get(banner, None)
            if symbol_files:
                isf_path = symbol_files[0]
                vollog.debug(f"Using symbol library: {symbol_files[0]}")
                clazz = self.symbol_class
                # Set the discovered options
                path_join = interfaces.configuration.path_join
                context.config[path_join(config_path, requirement.name,
                                         "class")] = clazz
                context.config[path_join(config_path, requirement.name,
                                         "isf_url")] = isf_path
                context.config[path_join(config_path, requirement.name,
                                         "symbol_mask")] = layer.address_mask

                # Construct the appropriate symbol table
                requirement.construct(context, config_path)
                break
            else:
                if symbol_files:
                    vollog.debug(
                        f"Symbol library path not found: {symbol_files[0]}")
                    # print("Kernel", banner, hex(banner_offset))
        else:
            vollog.debug("No existing banners found")