예제 #1
0
    def run(self):
        offset = self.config.get('offset', None)

        syshive = sechive = None

        for hive in hivelist.HiveList.list_hives(
                self.context,
                self.config_path,
                self.config['primary'],
                self.config['nt_symbols'],
                hive_offsets=None if offset is None else [offset]):

            if hive.get_name().split('\\')[-1].upper() == 'SYSTEM':
                syshive = hive
            if hive.get_name().split('\\')[-1].upper() == 'SECURITY':
                sechive = hive

        if syshive is None:
            raise exceptions.VolatilityException(
                'Unable to locate SYSTEM hive')
        if sechive is None:
            raise exceptions.VolatilityException(
                'Unable to locate SECURITY hive')

        return renderers.TreeGrid([("Username", str), ("Domain", str),
                                   ("Domain name", str), ('Hashh', bytes)],
                                  self._generator(syshive, sechive))
예제 #2
0
    def add_module(self, module: ModuleInterface) -> None:
        """Adds a module to the module collection

        This will throw an exception if the required dependencies are not met

        Args:
            module: the module to add to the list of modules (based on module.name)
        """
        if module.name in self._modules:
            raise exceptions.VolatilityException(f"Module already exists: {module.name}")
        self._modules[module.name] = module
예제 #3
0
    def create_tcpip_symbol_table(cls,
                                  context: interfaces.context.ContextInterface,
                                  config_path: str, layer_name: str,
                                  tcpip_module_offset: int,
                                  tcpip_module_size: int) -> str:
        """Creates symbol table for the current image's tcpip.sys driver.

        Searches the memory section of the loaded tcpip.sys module for its PDB GUID
        and loads the associated symbol table into the symbol space.

        Args:
            context: The context to retrieve required elements (layers, symbol tables) from
            config_path: The config path where to find symbol files
            layer_name: The name of the layer on which to operate
            tcpip_module_offset: This memory dump's tcpip.sys image offset
            tcpip_module_size: The size of `tcpip.sys` for this dump

        Returns:
            The name of the constructed and loaded symbol table
        """

        guids = list(
            pdbutil.PDBUtility.pdbname_scan(
                context,
                layer_name,
                context.layers[layer_name].page_size, [b"tcpip.pdb"],
                start=tcpip_module_offset,
                end=tcpip_module_offset + tcpip_module_size))

        if not guids:
            raise exceptions.VolatilityException(
                "Did not find GUID of tcpip.pdb in tcpip.sys module @ 0x{:x}!".
                format(tcpip_module_offset))

        guid = guids[0]

        vollog.debug("Found {}: {}-{}".format(guid["pdb_name"], guid["GUID"],
                                              guid["age"]))

        return pdbutil.PDBUtility.load_windows_symbol_table(
            context,
            guid["GUID"],
            guid["age"],
            guid["pdb_name"],
            "volatility3.framework.symbols.intermed.IntermediateSymbolTable",
            config_path="tcpip")
예제 #4
0
    def symbol_table_from_pdb(cls,
                              context: interfaces.context.ContextInterface,
                              config_path: str, layer_name: str, pdb_name: str,
                              module_offset: int, module_size: int) -> str:
        """Creates symbol table for a module in the specified layer_name.

        Searches the memory section of the loaded module for its PDB GUID
        and loads the associated symbol table into the symbol space.

        Args:
            context: The context to retrieve required elements (layers, symbol tables) from
            config_path: The config path where to find symbol files
            layer_name: The name of the layer on which to operate
            module_offset: This memory dump's module image offset
            module_size: The size of the module for this dump

        Returns:
            The name of the constructed and loaded symbol table
        """

        guids = list(
            cls.pdbname_scan(context,
                             layer_name,
                             context.layers[layer_name].page_size,
                             [bytes(pdb_name, 'latin-1')],
                             start=module_offset,
                             end=module_offset + module_size))

        if not guids:
            raise exceptions.VolatilityException(
                "Did not find GUID of {} in module @ 0x{:x}!".format(
                    pdb_name, module_offset))

        guid = guids[0]

        vollog.debug("Found {}: {}-{}".format(guid["pdb_name"], guid["GUID"],
                                              guid["age"]))

        return cls.load_windows_symbol_table(
            context,
            guid["GUID"],
            guid["age"],
            guid["pdb_name"],
            "volatility3.framework.symbols.intermed.IntermediateSymbolTable",
            config_path=config_path)
예제 #5
0
    def determine_tcpip_version(cls,
                                context: interfaces.context.ContextInterface,
                                layer_name: str,
                                nt_symbol_table: str) -> Tuple[str, Type]:
        """Tries to determine which symbol filename to use for the image's tcpip driver. The logic is partially taken from the info plugin.

        Args:
            context: The context to retrieve required elements (layers, symbol tables) from
            layer_name: The name of the layer on which to operate
            nt_symbol_table: The name of the table containing the kernel symbols

        Returns:
            The filename of the symbol table to use.
        """

        # while the failsafe way to determine the version of tcpip.sys would be to
        # extract the driver and parse its PE header containing the versionstring,
        # unfortunately that header is not guaranteed to persist within memory.
        # therefore we determine the version based on the kernel version as testing
        # with several windows versions has showed this to work out correctly.

        is_64bit = symbols.symbol_table_is_64bit(context, nt_symbol_table)

        is_18363_or_later = versions.is_win10_18363_or_later(
            context=context, symbol_table=nt_symbol_table)

        if is_64bit:
            arch = "x64"
        else:
            arch = "x86"

        vers = info.Info.get_version_structure(context, layer_name,
                                               nt_symbol_table)

        kuser = info.Info.get_kuser_structure(context, layer_name,
                                              nt_symbol_table)

        try:
            vers_minor_version = int(vers.MinorVersion)
            nt_major_version = int(kuser.NtMajorVersion)
            nt_minor_version = int(kuser.NtMinorVersion)
        except ValueError:
            # vers struct exists, but is not an int anymore?
            raise NotImplementedError(
                "Kernel Debug Structure version format not supported!")
        except:
            # unsure what to raise here. Also, it might be useful to add some kind of fallback,
            # either to a user-provided version or to another method to determine tcpip.sys's version
            raise exceptions.VolatilityException(
                "Kernel Debug Structure missing VERSION/KUSER structure, unable to determine Windows version!"
            )

        vollog.debug("Determined OS Version: {}.{} {}.{}".format(
            kuser.NtMajorVersion, kuser.NtMinorVersion, vers.MajorVersion,
            vers.MinorVersion))

        if nt_major_version == 10 and arch == "x64":
            # win10 x64 has an additional class type we have to include.
            class_types = network.win10_x64_class_types
        else:
            # default to general class types
            class_types = network.class_types

        # these versions are listed explicitly because symbol files differ based on
        # version *and* architecture. this is currently the clearest way to show
        # the differences, even if it introduces a fair bit of redundancy.
        # furthermore, it is easy to append new versions.
        if arch == "x86":
            version_dict = {
                (6, 0, 6000, 0): "netscan-vista-x86",
                (6, 0, 6001, 0): "netscan-vista-x86",
                (6, 0, 6002, 0): "netscan-vista-x86",
                (6, 0, 6003, 0): "netscan-vista-x86",
                (6, 1, 7600, 0): "netscan-win7-x86",
                (6, 1, 7601, 0): "netscan-win7-x86",
                (6, 1, 8400, 0): "netscan-win7-x86",
                (6, 2, 9200, 0): "netscan-win8-x86",
                (6, 3, 9600, 0): "netscan-win81-x86",
                (10, 0, 10240, 0): "netscan-win10-10240-x86",
                (10, 0, 10586, 0): "netscan-win10-10586-x86",
                (10, 0, 14393, 0): "netscan-win10-14393-x86",
                (10, 0, 15063, 0): "netscan-win10-15063-x86",
                (10, 0, 16299, 0): "netscan-win10-15063-x86",
                (10, 0, 17134, 0): "netscan-win10-17134-x86",
                (10, 0, 17763, 0): "netscan-win10-17134-x86",
                (10, 0, 18362, 0): "netscan-win10-17134-x86",
                (10, 0, 18363, 0): "netscan-win10-17134-x86"
            }
        else:
            version_dict = {
                (6, 0, 6000, 0): "netscan-vista-x64",
                (6, 0, 6001, 0): "netscan-vista-sp12-x64",
                (6, 0, 6002, 0): "netscan-vista-sp12-x64",
                (6, 0, 6003, 0): "netscan-vista-sp12-x64",
                (6, 1, 7600, 0): "netscan-win7-x64",
                (6, 1, 7601, 0): "netscan-win7-x64",
                (6, 1, 8400, 0): "netscan-win7-x64",
                (6, 2, 9200, 0): "netscan-win8-x64",
                (6, 3, 9600, 0): "netscan-win81-x64",
                (6, 3, 9600, 19935): "netscan-win81-19935-x64",
                (10, 0, 10240, 0): "netscan-win10-x64",
                (10, 0, 10586, 0): "netscan-win10-x64",
                (10, 0, 14393, 0): "netscan-win10-x64",
                (10, 0, 15063, 0): "netscan-win10-15063-x64",
                (10, 0, 16299, 0): "netscan-win10-16299-x64",
                (10, 0, 17134, 0): "netscan-win10-17134-x64",
                (10, 0, 17763, 0): "netscan-win10-17763-x64",
                (10, 0, 18362, 0): "netscan-win10-18362-x64",
                (10, 0, 18363, 0): "netscan-win10-18363-x64",
                (10, 0, 19041, 0): "netscan-win10-19041-x64"
            }

        # we do not need to check for tcpip's specific FileVersion in every case
        tcpip_mod_version = 0  # keep it 0 as a default

        # special use cases

        # Win10_18363 is not recognized by windows.info as 18363
        # because all kernel file headers and debug structures report 18363 as
        # "10.0.18362.1198" with the last part being incremented. However, we can use
        # os_distinguisher to differentiate between 18362 and 18363
        if vers_minor_version == 18362 and is_18363_or_later:
            vollog.debug(
                "Detected 18363 data structures: working with 18363 symbol table."
            )
            vers_minor_version = 18363

        # we need to define additional version numbers (which are then found via tcpip.sys's FileVersion header) in case there is
        # ambiguity _within_ an OS version. If such a version number (last number of the tuple) is defined for the current OS
        # we need to inspect tcpip.sys's headers to see if we can grab the precise version
        if [(a, b, c, d) for a, b, c, d in version_dict
                if (a, b, c) == (nt_major_version, nt_minor_version,
                                 vers_minor_version) and d != 0]:
            vollog.debug(
                "Requiring further version inspection due to OS version by checking tcpip.sys's FileVersion header"
            )
            # the following is IntelLayer specific and might need to be adapted to other architectures.
            physical_layer_name = context.layers[layer_name].config.get(
                'memory_layer', None)
            if physical_layer_name:
                ver = verinfo.VerInfo.find_version_info(
                    context, physical_layer_name, "tcpip.sys")
                if ver:
                    tcpip_mod_version = ver[3]
                    vollog.debug(
                        "Determined tcpip.sys's FileVersion: {}".format(
                            tcpip_mod_version))
                else:
                    vollog.debug(
                        "Could not determine tcpip.sys's FileVersion.")
            else:
                vollog.debug(
                    "Unable to retrieve physical memory layer, skipping FileVersion check."
                )

        # when determining the symbol file we have to consider the following cases:
        # the determined version's symbol file is found by intermed.create -> proceed
        # the determined version's symbol file is not found by intermed -> intermed will throw an exc and abort
        # the determined version has no mapped symbol file -> if win10 use latest, otherwise throw exc
        # windows version cannot be determined -> throw exc

        filename = version_dict.get((nt_major_version, nt_minor_version,
                                     vers_minor_version, tcpip_mod_version))
        if not filename:
            # no match on filename means that we possibly have a version newer than those listed here.
            # try to grab the latest supported version of the current image NT version. If that symbol
            # version does not work, support has to be added manually.
            current_versions = [
                (nt_maj, nt_min, vers_min, tcpip_ver)
                for nt_maj, nt_min, vers_min, tcpip_ver in version_dict
                if nt_maj == nt_major_version and nt_min == nt_minor_version
                and tcpip_ver <= tcpip_mod_version
            ]
            current_versions.sort()

            if current_versions:
                latest_version = current_versions[-1]

                filename = version_dict.get(latest_version)

                vollog.debug(
                    f"Unable to find exact matching symbol file, going with latest: {filename}"
                )

            else:
                raise NotImplementedError(
                    "This version of Windows is not supported: {}.{} {}.{}!".
                    format(nt_major_version, nt_minor_version,
                           vers.MajorVersion, vers_minor_version))

        vollog.debug(f"Determined symbol filename: {filename}")

        return filename, class_types
예제 #6
0
    def determine_tcpip_version(cls,
                                context: interfaces.context.ContextInterface,
                                layer_name: str, nt_symbol_table: str) -> str:
        """Tries to determine which symbol filename to use for the image's tcpip driver. The logic is partially taken from the info plugin.

        Args:
            context: The context to retrieve required elements (layers, symbol tables) from
            layer_name: The name of the layer on which to operate
            nt_symbol_table: The name of the table containing the kernel symbols

        Returns:
            The filename of the symbol table to use.
        """

        # while the failsafe way to determine the version of tcpip.sys would be to
        # extract the driver and parse its PE header containing the versionstring,
        # unfortunately that header is not guaranteed to persist within memory.
        # therefore we determine the version based on the kernel version as testing
        # with several windows versions has showed this to work out correctly.

        is_64bit = symbols.symbol_table_is_64bit(context, nt_symbol_table)

        is_18363_or_later = versions.is_win10_18363_or_later(
            context=context, symbol_table=nt_symbol_table)

        if is_64bit:
            arch = "x64"
        else:
            arch = "x86"

        vers = info.Info.get_version_structure(context, layer_name,
                                               nt_symbol_table)

        kuser = info.Info.get_kuser_structure(context, layer_name,
                                              nt_symbol_table)

        try:
            vers_minor_version = int(vers.MinorVersion)
            nt_major_version = int(kuser.NtMajorVersion)
            nt_minor_version = int(kuser.NtMinorVersion)
        except ValueError:
            # vers struct exists, but is not an int anymore?
            raise NotImplementedError(
                "Kernel Debug Structure version format not supported!")
        except:
            # unsure what to raise here. Also, it might be useful to add some kind of fallback,
            # either to a user-provided version or to another method to determine tcpip.sys's version
            raise exceptions.VolatilityException(
                "Kernel Debug Structure missing VERSION/KUSER structure, unable to determine Windows version!"
            )

        vollog.debug("Determined OS Version: {}.{} {}.{}".format(
            kuser.NtMajorVersion, kuser.NtMinorVersion, vers.MajorVersion,
            vers.MinorVersion))

        if nt_major_version == 10 and arch == "x64":
            # win10 x64 has an additional class type we have to include.
            class_types = network.win10_x64_class_types
        else:
            # default to general class types
            class_types = network.class_types

        # these versions are listed explicitly because symbol files differ based on
        # version *and* architecture. this is currently the clearest way to show
        # the differences, even if it introduces a fair bit of redundancy.
        # furthermore, it is easy to append new versions.
        if arch == "x86":
            version_dict = {
                (6, 0, 6000): "netscan-vista-x86",
                (6, 0, 6001): "netscan-vista-x86",
                (6, 0, 6002): "netscan-vista-x86",
                (6, 0, 6003): "netscan-vista-x86",
                (6, 1, 7600): "netscan-win7-x86",
                (6, 1, 7601): "netscan-win7-x86",
                (6, 1, 8400): "netscan-win7-x86",
                (6, 2, 9200): "netscan-win8-x86",
                (6, 3, 9600): "netscan-win81-x86",
                (10, 0, 10240): "netscan-win10-10240-x86",
                (10, 0, 10586): "netscan-win10-10586-x86",
                (10, 0, 14393): "netscan-win10-14393-x86",
                (10, 0, 15063): "netscan-win10-15063-x86",
                (10, 0, 16299): "netscan-win10-15063-x86",
                (10, 0, 17134): "netscan-win10-17134-x86",
                (10, 0, 17763): "netscan-win10-17134-x86",
                (10, 0, 18362): "netscan-win10-17134-x86",
                (10, 0, 18363): "netscan-win10-17134-x86"
            }
        else:
            version_dict = {
                (6, 0, 6000): "netscan-vista-x64",
                (6, 0, 6001): "netscan-vista-sp12-x64",
                (6, 0, 6002): "netscan-vista-sp12-x64",
                (6, 0, 6003): "netscan-vista-sp12-x64",
                (6, 1, 7600): "netscan-win7-x64",
                (6, 1, 7601): "netscan-win7-x64",
                (6, 1, 8400): "netscan-win7-x64",
                (6, 2, 9200): "netscan-win8-x64",
                (6, 3, 9600): "netscan-win81-x64",
                (10, 0, 10240): "netscan-win10-x64",
                (10, 0, 10586): "netscan-win10-x64",
                (10, 0, 14393): "netscan-win10-x64",
                (10, 0, 15063): "netscan-win10-15063-x64",
                (10, 0, 16299): "netscan-win10-16299-x64",
                (10, 0, 17134): "netscan-win10-17134-x64",
                (10, 0, 17763): "netscan-win10-17763-x64",
                (10, 0, 18362): "netscan-win10-18362-x64",
                (10, 0, 18363): "netscan-win10-18363-x64",
                (10, 0, 19041): "netscan-win10-19041-x64"
            }

        # special use case: Win10_18363 is not recognized by windows.info as 18363
        # because all kernel file headers and debug structures report 18363 as
        # "10.0.18362.1198" with the last part being incremented. However, we can use
        # os_distinguisher to differentiate between 18362 and 18363
        if vers_minor_version == 18362 and is_18363_or_later:
            vollog.debug(
                "Detected 18363 data structures: working with 18363 symbol table."
            )
            vers_minor_version = 18363

        # when determining the symbol file we have to consider the following cases:
        # the determined version's symbol file is found by intermed.create -> proceed
        # the determined version's symbol file is not found by intermed -> intermed will throw an exc and abort
        # the determined version has no mapped symbol file -> if win10 use latest, otherwise throw exc
        # windows version cannot be determined -> throw exc
        filename = version_dict.get(
            (nt_major_version, nt_minor_version, vers_minor_version))
        if not filename:
            # no match on filename means that we possibly have a version newer than those listed here.
            # try to grab the latest supported version of the current image NT version. If that symbol
            # version does not work, support has to be added manually.
            current_versions = [
                key for key in list(version_dict.keys())
                if key[0] == nt_major_version and key[1] == nt_minor_version
            ]
            current_versions.sort()

            if current_versions:
                latest_version = current_versions[-1]

                filename = version_dict.get(latest_version)
                vollog.debug(
                    "Unable to find exact matching symbol file, going with latest: {}"
                    .format(filename))
            else:
                raise NotImplementedError(
                    "This version of Windows is not supported: {}.{} {}.{}!".
                    format(nt_major_version, nt_minor_version,
                           vers.MajorVersion, vers_minor_version))

        vollog.debug("Determined symbol filename: {}".format(filename))

        return filename, class_types