Ejemplo n.º 1
0
    def parse_userassist_data(self, reg_val):
        """Reads the raw data of a _CM_KEY_VALUE and returns a dict of
        userassist fields."""

        item = {
            "id": renderers.UnparsableValue(),
            "count": renderers.UnparsableValue(),
            "focus": renderers.UnparsableValue(),
            "time": renderers.UnparsableValue(),
            "lastupdated": renderers.UnparsableValue(),
            "rawdata": renderers.UnparsableValue(),
        }

        userassist_data = reg_val.decode_data()

        if userassist_data is None:
            return item

        item["rawdata"] = userassist_data

        if self._win7 is None:
            # if OS is still unknown at this point, return the default item which just has the rawdata
            return item

        if len(userassist_data) < self._userassist_size:
            return item

        userassist_layer_name = self.context.layers.free_layer_name(
            "userassist_buffer")
        buffer = BufferDataLayer(self.context, self._config_path,
                                 userassist_layer_name, userassist_data)
        self.context.add_layer(buffer)
        userassist_obj = self.context.object(object_type=self._reg_table_name +
                                             constants.BANG +
                                             self._userassist_type_name,
                                             layer_name=userassist_layer_name,
                                             offset=0)

        if self._win7:
            item["id"] = renderers.NotApplicableValue()
            item["count"] = int(userassist_obj.Count)

            seconds = (userassist_obj.FocusTime + 500) / 1000.0
            time = datetime.timedelta(
                seconds=seconds) if seconds > 0 else userassist_obj.FocusTime
            item["focus"] = int(userassist_obj.FocusCount)
            item["time"] = str(time)

        else:
            item["id"] = int(userassist_obj.ID)
            item["count"] = int(userassist_obj.CountStartingAtFive
                                if userassist_obj.CountStartingAtFive < 5 else
                                userassist_obj.CountStartingAtFive - 5)
            item["focus"] = renderers.NotApplicableValue()
            item["time"] = renderers.NotApplicableValue()

        item["lastupdated"] = conversion.wintime_to_datetime(
            userassist_obj.LastUpdated.QuadPart)

        return item
Ejemplo n.º 2
0
    def _generator(self):

        symbol_table = self.config["nt_symbols"]
        constraints = self.builtin_constraints(symbol_table)

        for constraint, mem_object, header in self.generate_pool_scan(
                self.context, self.config["primary"], symbol_table,
                constraints):
            # generate some type-specific info for sanity checking
            if constraint.object_type == "Process":
                name = mem_object.ImageFileName.cast(
                    "string",
                    max_length=mem_object.ImageFileName.vol.count,
                    errors="replace")
            elif constraint.object_type == "File":
                try:
                    name = mem_object.FileName.String
                except exceptions.InvalidAddressException:
                    vollog.log(
                        constants.LOGLEVEL_VVV,
                        "Skipping file at {0:#x}".format(
                            mem_object.vol.offset))
                    continue
            else:
                name = renderers.NotApplicableValue()

            yield (0,
                   (constraint.type_name, format_hints.Hex(header.vol.offset),
                    header.vol.layer_name, name))
Ejemplo n.º 3
0
 def get_number_of_bytes(self) -> Union[int, interfaces.renderers.BaseAbsentValue]:
     """Returns the NumberOfBytes value on applicable systems"""
     # Not applicable until Vista
     try:
         return self.NumberOfBytes
     except AttributeError:
         return renderers.NotApplicableValue()
    def _generator(self):

        collection = ssdt.SSDT.build_module_collection(
            self.context, self.config['primary'], self.config['nt_symbols'])

        for driver in driverscan.DriverScan.scan_drivers(
                self.context, self.config['primary'],
                self.config['nt_symbols']):

            try:
                driver_name = driver.get_driver_name()
            except exceptions.InvalidAddressException:
                driver_name = renderers.NotApplicableValue()

            for i, address in enumerate(driver.MajorFunction):
                module_symbols = collection.get_module_symbols_by_absolute_location(
                    address)

                for module_name, symbol_generator in module_symbols:
                    symbols_found = False

                    for symbol in symbol_generator:
                        symbols_found = True
                        yield (0, (format_hints.Hex(driver.vol.offset),
                                   driver_name, MAJOR_FUNCTIONS[i],
                                   format_hints.Hex(address), module_name,
                                   symbol.split(constants.BANG)[1]))

                    if not symbols_found:
                        yield (0, (format_hints.Hex(driver.vol.offset),
                                   driver_name, MAJOR_FUNCTIONS[i],
                                   format_hints.Hex(address), module_name,
                                   renderers.NotAvailableValue()))
Ejemplo n.º 5
0
    def _generator(self, procs):
        pe_table_name = intermed.IntermediateSymbolTable.create(
            self.context,
            self.config_path,
            "windows",
            "pe",
            class_types=pe.class_types)

        kuser = info.Info.get_kuser_structure(self.context,
                                              self.config['primary'],
                                              self.config['nt_symbols'])
        nt_major_version = int(kuser.NtMajorVersion)
        nt_minor_version = int(kuser.NtMinorVersion)
        # LoadTime only applies to versions higher or equal to Window 7 (6.1 and higher)
        dll_load_time_field = (nt_major_version > 6) or (
            nt_major_version == 6 and nt_minor_version >= 1)
        for proc in procs:

            proc_id = proc.UniqueProcessId
            proc_layer_name = proc.add_process_layer()

            for entry in proc.load_order_modules():

                BaseDllName = FullDllName = renderers.UnreadableValue()
                try:
                    BaseDllName = entry.BaseDllName.get_string()
                    # We assume that if the BaseDllName points to an invalid buffer, so will FullDllName
                    FullDllName = entry.FullDllName.get_string()
                except exceptions.InvalidAddressException:
                    pass

                if dll_load_time_field:
                    # Versions prior to 6.1 won't have the LoadTime attribute
                    # and 32bit version shouldn't have the Quadpart according to MSDN
                    try:
                        DllLoadTime = conversion.wintime_to_datetime(
                            entry.LoadTime.QuadPart)
                    except exceptions.InvalidAddressException:
                        DllLoadTime = renderers.UnreadableValue()
                else:
                    DllLoadTime = renderers.NotApplicableValue()

                dumped = False
                if self.config['dump']:
                    filedata = self.dump_pe(self.context, pe_table_name, entry,
                                            proc_layer_name)
                    if filedata:
                        filedata.preferred_filename = "pid.{0}.".format(
                            proc_id) + filedata.preferred_filename
                        dumped = True
                        self.produce_file(filedata)

                yield (0, (proc.UniqueProcessId,
                           proc.ImageFileName.cast(
                               "string",
                               max_length=proc.ImageFileName.vol.count,
                               errors='replace'),
                           format_hints.Hex(entry.DllBase),
                           format_hints.Hex(entry.SizeOfImage), BaseDllName,
                           FullDllName, DllLoadTime, dumped))
Ejemplo n.º 6
0
    def get_session_id(self):
        try:
            if self.has_member("Session"):
                if self.Session == 0:
                    return renderers.NotApplicableValue()

                symbol_table_name = self.get_symbol_table_name()
                kvo = self._context.layers[
                    self.vol.native_layer_name].config['kernel_virtual_offset']
                ntkrnlmp = self._context.module(
                    symbol_table_name,
                    layer_name=self.vol.native_layer_name,
                    offset=kvo,
                    native_layer_name=self.vol.native_layer_name)
                session = ntkrnlmp.object(object_type="_MM_SESSION_SPACE",
                                          offset=self.Session,
                                          absolute=True)

                if session.has_member("SessionId"):
                    return session.SessionId

        except exceptions.InvalidAddressException:
            vollog.log(
                constants.LOGLEVEL_VVV,
                "Cannot access _EPROCESS.Session.SessionId at {0:#x}".format(
                    self.vol.offset))

        return renderers.UnreadableValue()
Ejemplo n.º 7
0
    def _generator(self, runable_plugins: List[TimeLinerInterface]) -> Optional[Iterable[Tuple[int, Tuple]]]:
        """Takes a timeline, sorts it and output the data from each relevant
        row from each plugin."""
        # Generate the results for each plugin
        data = []
        for plugin in runable_plugins:
            plugin_name = plugin.__class__.__name__
            self._progress_callback((runable_plugins.index(plugin) * 100) // len(runable_plugins),
                                    "Running plugin {}...".format(plugin_name))
            try:
                vollog.log(logging.INFO, "Running {}".format(plugin_name))
                for (item, timestamp_type, timestamp) in plugin.generate_timeline():
                    times = self.timeline.get((plugin_name, item), {})
                    if times.get(timestamp_type, None) is not None:
                        vollog.debug("Multiple timestamps for the same plugin/file combination found: {} {}".format(
                            plugin_name, item))
                    times[timestamp_type] = timestamp
                    self.timeline[(plugin_name, item)] = times
                    data.append((0, [
                        plugin_name, item,
                        times.get(TimeLinerType.CREATED, renderers.NotApplicableValue()),
                        times.get(TimeLinerType.MODIFIED, renderers.NotApplicableValue()),
                        times.get(TimeLinerType.ACCESSED, renderers.NotApplicableValue()),
                        times.get(TimeLinerType.CHANGED, renderers.NotApplicableValue())
                    ]))
            except Exception:
                vollog.log(logging.INFO, "Exception occurred running plugin: {}".format(plugin_name))
                vollog.log(logging.DEBUG, traceback.format_exc())
        for data_item in sorted(data, key = self._sort_function):
            yield data_item

        # Write out a body file if necessary
        if self.config.get('create-bodyfile', True):
            with self.open("volatility.body") as file_data:
                with io.TextIOWrapper(file_data, write_through = True) as fp:
                    for (plugin_name, item) in self.timeline:
                        times = self.timeline[(plugin_name, item)]
                        # Body format is: MD5|name|inode|mode_as_string|UID|GID|size|atime|mtime|ctime|crtime

                        if self._any_time_present(times):
                            fp.write("|{} - {}||||||{}|{}|{}|{}\n".format(
                                plugin_name, self._sanitize_body_format(item),
                                self._text_format(times.get(TimeLinerType.ACCESSED, "")),
                                self._text_format(times.get(TimeLinerType.MODIFIED, "")),
                                self._text_format(times.get(TimeLinerType.CHANGED, "")),
                                self._text_format(times.get(TimeLinerType.CREATED, ""))))
    def _generator(
        self, runable_plugins: List[TimeLinerInterface]
    ) -> Optional[Iterable[Tuple[int, Tuple]]]:
        """Takes a timeline, sorts it and output the data from each relevant
        row from each plugin."""
        # Generate the results for each plugin
        for plugin in runable_plugins:
            plugin_name = plugin.__class__.__name__
            self._progress_callback(
                (runable_plugins.index(plugin) * 100) // len(runable_plugins),
                "Running plugin {}...".format(plugin_name))
            try:
                vollog.log(logging.INFO, "Running {}".format(plugin_name))
                for (item, timestamp_type,
                     timestamp) in plugin.generate_timeline():
                    times = self.timeline.get((plugin_name, item), {})
                    if times.get(timestamp_type, None) is not None:
                        vollog.debug(
                            "Multiple timestamps for the same plugin/file combination found: {} {}"
                            .format(plugin_name, item))
                    times[timestamp_type] = timestamp
                    self.timeline[(plugin_name, item)] = times
            except Exception:
                # FIXME: traceback shouldn't be printed directly, but logged instead
                traceback.print_exc()
                vollog.log(
                    logging.INFO,
                    "Exception occurred running plugin: {}".format(
                        plugin_name))

        for (plugin_name, item) in self.timeline:
            times = self.timeline[(plugin_name, item)]
            data = (0,
                    [
                        plugin_name, item,
                        times.get(TimeLinerType.CREATED,
                                  renderers.NotApplicableValue()),
                        times.get(TimeLinerType.MODIFIED,
                                  renderers.NotApplicableValue()),
                        times.get(TimeLinerType.ACCESSED,
                                  renderers.NotApplicableValue()),
                        times.get(TimeLinerType.CHANGED,
                                  renderers.NotApplicableValue())
                    ])
            yield data
Ejemplo n.º 9
0
 def get_pool_type(self) -> Union[str, interfaces.renderers.BaseAbsentValue]:
     """Returns the enum name for the PoolType value on applicable systems"""
     # Not applicable until Vista
     if hasattr(self, 'PoolType'):
         if not self.pool_type_lookup:
             self._generate_pool_type_lookup()
         return self.pool_type_lookup.get(self.PoolType, "Unknown choice {}".format(self.PoolType))
     else:
         return renderers.NotApplicableValue()
Ejemplo n.º 10
0
    def _generator(self):
        for mutant in self.scan_mutants(self.context, self.config['primary'],
                                        self.config['nt_symbols']):

            try:
                name = mutant.get_name()
            except (ValueError, exceptions.InvalidAddressException):
                name = renderers.NotApplicableValue()

            yield (0, (format_hints.Hex(mutant.vol.offset), name))
Ejemplo n.º 11
0
    def get_pid(self) -> Union[int, interfaces.renderers.BaseAbsentValue]:
        """Return the pid of the process, if any."""
        if self.State.description != "SERVICE_RUNNING" or "PROCESS" not in self.get_type(
        ):
            return renderers.NotApplicableValue()

        try:
            return self.ServiceProcess.ProcessId
        except exceptions.InvalidAddressException:
            return renderers.UnreadableValue()
Ejemplo n.º 12
0
 def get_wait_reason(self) -> str:
     dictWaitReason = {0: 'Executive', 1: 'FreePage', 2: 'PageIn', 3: 'PoolAllocation',
                       4: 'DelayExecution', 5: 'Suspended', 6: 'UserRequest', 7: 'WrExecutive',
                       8: 'WrFreePage', 9: 'WrPageIn', 10: 'WrPoolAllocation', 11: 'WrDelayExecution',
                       12: 'WrSuspended', 13: 'WrUserRequest', 14: 'WrEventPair', 15: 'WrQueue',
                       16: 'WrLpcReceive', 17: 'WrLpcReply', 18: 'WrVirtualMemory', 19: 'WrPageOut',
                       20: 'WrRendezvous', 21: 'Spare2', 22: 'Spare3', 23: 'Spare4', 24: 'Spare5',
                       25: 'Spare6', 26: 'WrKernel', 27: 'WrResource', 28: 'WrPushLock', 29: 'WrMutex',
                       30: 'WrQuantumEnd', 31: 'WrDispatchInt', 32: 'WrPreempted',33: 'WrYieldExecution', 34: 'WrFastMutex', 35: 'WrGuardedMutex',
                       36: 'WrRundown', 37: 'MaximumWaitReason'}
     return dictWaitReason.get(self.WaitReason, renderers.NotApplicableValue())
def wintime_to_datetime(
    wintime: int
) -> Union[interfaces.renderers.BaseAbsentValue, datetime.datetime]:
    unix_time = wintime // 10000000
    if unix_time == 0:
        return renderers.NotApplicableValue()
    unix_time = unix_time - 11644473600
    try:
        return datetime.datetime.utcfromtimestamp(unix_time)
        # Windows sometimes throws OSErrors rather than ValueErrors when it can't convert a value
    except (ValueError, OSError):
        return renderers.UnparsableValue()
Ejemplo n.º 14
0
    def _generator(self):

        callback_table_name = self.create_callback_table(
            self.context, self.config["nt_symbols"], self.config_path)

        collection = ssdt.SSDT.build_module_collection(
            self.context, self.config['primary'], self.config['nt_symbols'])

        callback_methods = (self.list_notify_routines,
                            self.list_bugcheck_callbacks,
                            self.list_bugcheck_reason_callbacks,
                            self.list_registry_callbacks)

        for callback_method in callback_methods:
            for callback_type, callback_address, callback_detail in callback_method(
                    self.context, self.config['primary'],
                    self.config['nt_symbols'], callback_table_name):

                if callback_detail is None:
                    detail = renderers.NotApplicableValue()
                else:
                    detail = callback_detail

                module_symbols = list(
                    collection.get_module_symbols_by_absolute_location(
                        callback_address))

                if module_symbols:
                    for module_name, symbol_generator in module_symbols:
                        symbols_found = False

                        # we might have multiple symbols pointing to the same location
                        for symbol in symbol_generator:
                            symbols_found = True
                            yield (0,
                                   (callback_type,
                                    format_hints.Hex(callback_address),
                                    module_name,
                                    symbol.split(constants.BANG)[1], detail))

                        # no symbols, but we at least can report the module name
                        if not symbols_found:
                            yield (0, (callback_type,
                                       format_hints.Hex(callback_address),
                                       module_name,
                                       renderers.NotAvailableValue(), detail))
                else:
                    # no module was found at the absolute location
                    yield (0, (callback_type,
                               format_hints.Hex(callback_address),
                               renderers.NotAvailableValue(),
                               renderers.NotAvailableValue(), detail))
Ejemplo n.º 15
0
 def get_state(self) -> str:
     dictState = {
         0: 'Initialized',
         1: 'Ready',
         2: 'Running',
         3: 'Standby',
         4: 'Terminated',
         5: 'Waiting',
         6: 'Transition',
         7: 'DeferredReady',
         8: 'GateWait'
     }
     return dictState.get(self.State, renderers.NotApplicableValue())
    def _generator(self):
        for driver in self.scan_drivers(self.context, self.config['primary'],
                                        self.config['nt_symbols']):

            try:
                driver_name = driver.get_driver_name()
            except exceptions.InvalidAddressException:
                driver_name = renderers.NotApplicableValue()

            try:
                service_key = driver.DriverExtension.ServiceKeyName.String
            except exceptions.InvalidAddressException:
                service_key = renderers.NotApplicableValue()

            try:
                name = driver.DriverName.String
            except exceptions.InvalidAddressException:
                name = renderers.NotApplicableValue()

            yield (0, (format_hints.Hex(driver.vol.offset),
                       format_hints.Hex(driver.DriverStart),
                       format_hints.Hex(driver.DriverSize), service_key,
                       driver_name, name))
Ejemplo n.º 17
0
    def get_file_name(self):
        """Get the name of the file mapped into the memory range (if any)"""

        file_name = renderers.NotApplicableValue()

        try:
            # this is for xp and 2003
            if self.has_member("ControlArea"):
                file_name = self.ControlArea.FilePointer.FileName.get_string()

            # this is for vista through windows 7
            else:
                file_name = self.Subsection.ControlArea.FilePointer.dereference().cast(
                    "_FILE_OBJECT").FileName.get_string()

        except exceptions.InvalidAddressException:
            pass

        return file_name
Ejemplo n.º 18
0
    def get_binary(self) -> Union[str, interfaces.renderers.BaseAbsentValue]:
        """Returns the binary associated with the service."""
        if self.State.description != "SERVICE_RUNNING":
            return renderers.NotApplicableValue()

        # depending on whether the service is for a process
        # or kernel driver, the binary path is stored differently
        try:
            if "PROCESS" in self.get_type():
                return self.ServiceProcess.BinaryPath.dereference().cast(
                    "string",
                    encoding="utf-16",
                    errors="replace",
                    max_length=512)
            else:
                return self.DriverName.dereference().cast("string",
                                                          encoding="utf-16",
                                                          errors="replace",
                                                          max_length=512)
        except exceptions.InvalidAddressException:
            return renderers.UnreadableValue()
Ejemplo n.º 19
0
 def get_file_name(self):
     """Only long(er) vads have mapped files."""
     return renderers.NotApplicableValue()
Ejemplo n.º 20
0
    def _printkey_iterator(self,
                           hive: RegistryHive,
                           node_path: Sequence[objects.StructType] = None,
                           recurse: bool = False):
        """Method that wraps the more generic key_iterator, to provide output
        for printkey specifically.

        Args:
            hive: The registry hive to walk
            node_path: The list of nodes that make up the
            recurse: Traverse down the node tree or stay only on the same level

        Yields:
            The depth, and a tuple of results (last write time, hive offset, type, path, name, data and volatile)
        """
        for depth, is_key, last_write_time, key_path, volatile, node in self.key_iterator(
                hive, node_path, recurse):
            if is_key:
                try:
                    key_node_name = node.get_name()
                except (exceptions.InvalidAddressException,
                        RegistryFormatException) as excp:
                    vollog.debug(excp)
                    key_node_name = renderers.UnreadableValue()

                yield (depth, (last_write_time,
                               renderers.format_hints.Hex(hive.hive_offset),
                               "Key", key_path, key_node_name,
                               renderers.NotApplicableValue(), volatile))
            else:
                try:
                    value_node_name = node.get_name() or "(Default)"
                except (exceptions.InvalidAddressException,
                        RegistryFormatException) as excp:
                    vollog.debug(excp)
                    value_node_name = renderers.UnreadableValue()

                try:
                    value_type = RegValueTypes.get(node.Type).name
                except (exceptions.InvalidAddressException,
                        RegistryFormatException) as excp:
                    vollog.debug(excp)
                    value_type = renderers.UnreadableValue()

                if isinstance(value_type, renderers.UnreadableValue):
                    vollog.debug(
                        "Couldn't read registry value type, so data is unreadable"
                    )
                    value_data = renderers.UnreadableValue()
                else:
                    try:
                        value_data = node.decode_data(
                        )  # type: Union[interfaces.renderers.BaseAbsentValue, bytes]

                        if isinstance(value_data, int):
                            value_data = format_hints.MultiTypeData(
                                value_data, encoding='utf-8')
                        elif RegValueTypes.get(
                                node.Type) == RegValueTypes.REG_BINARY:
                            value_data = format_hints.MultiTypeData(
                                value_data, show_hex=True)
                        elif RegValueTypes.get(
                                node.Type) == RegValueTypes.REG_MULTI_SZ:
                            value_data = format_hints.MultiTypeData(
                                value_data,
                                encoding='utf-16-le',
                                split_nulls=True)
                        else:
                            value_data = format_hints.MultiTypeData(
                                value_data, encoding='utf-16-le')
                    except (ValueError, exceptions.InvalidAddressException,
                            RegistryFormatException) as excp:
                        vollog.debug(excp)
                        value_data = renderers.UnreadableValue()

                result = (depth, (last_write_time,
                                  renderers.format_hints.Hex(hive.hive_offset),
                                  value_type, key_path, value_node_name,
                                  value_data, volatile))
                yield result
Ejemplo n.º 21
0
    def _generator(self, procs: Generator[interfaces.objects.ObjectInterface, None, None],
                   mods: Generator[interfaces.objects.ObjectInterface, None, None], session_layers: Generator[str, None,
                                                                                                              None]):
        """Generates a list of PE file version info for processes, dlls, and
        modules.

        Args:
            procs: <generator> of processes
            mods: <generator> of modules
            session_layers: <generator> of layers in the session to be checked
        """

        pe_table_name = intermed.IntermediateSymbolTable.create(self.context,
                                                                self.config_path,
                                                                "windows",
                                                                "pe",
                                                                class_types = pe.class_types)

        for mod in mods:
            try:
                BaseDllName = mod.BaseDllName.get_string()
            except exceptions.InvalidAddressException:
                BaseDllName = renderers.UnreadableValue()

            session_layer_name = modules.Modules.find_session_layer(self.context, session_layers, mod.DllBase)
            (major, minor, product, build) = [
                renderers.NotAvailableValue()
            ] * 4  # type: Tuple[Union[int, interfaces.renderers.BaseAbsentValue],Union[int, interfaces.renderers.BaseAbsentValue],Union[int, interfaces.renderers.BaseAbsentValue],Union[int, interfaces.renderers.BaseAbsentValue]]
            try:
                (major, minor, product, build) = self.get_version_information(self._context, pe_table_name,
                                                                              session_layer_name, mod.DllBase)
            except (exceptions.InvalidAddressException, TypeError, AttributeError):
                (major, minor, product, build) = [renderers.UnreadableValue()] * 4

            # the pid and process are not applicable for kernel modules
            yield (0, (renderers.NotApplicableValue(), renderers.NotApplicableValue(), format_hints.Hex(mod.DllBase),
                       BaseDllName, major, minor, product, build))

        # now go through the process and dll lists
        for proc in procs:
            proc_id = "Unknown"
            try:
                proc_id = proc.UniqueProcessId
                proc_layer_name = proc.add_process_layer()
            except exceptions.InvalidAddressException as excp:
                vollog.debug("Process {}: invalid address {} in layer {}".format(proc_id, excp.invalid_address,
                                                                                 excp.layer_name))
                continue

            for entry in proc.load_order_modules():

                try:
                    BaseDllName = entry.BaseDllName.get_string()
                except exceptions.InvalidAddressException:
                    BaseDllName = renderers.UnreadableValue()

                try:
                    DllBase = format_hints.Hex(entry.DllBase)
                except exceptions.InvalidAddressException:
                    DllBase = renderers.UnreadableValue()

                try:
                    (major, minor, product, build) = self.get_version_information(self._context, pe_table_name,
                                                                                  proc_layer_name, entry.DllBase)
                except (exceptions.InvalidAddressException, ValueError, AttributeError):
                    (major, minor, product, build) = [renderers.UnreadableValue()] * 4

                yield (0, (proc.UniqueProcessId,
                           proc.ImageFileName.cast("string",
                                                   max_length = proc.ImageFileName.vol.count,
                                                   errors = "replace"), DllBase, BaseDllName, major, minor, product,
                           build))
Ejemplo n.º 22
0
    def list_userassist(
            self,
            hive: RegistryHive) -> Generator[Tuple[int, Tuple], None, None]:
        """Generate userassist data for a registry hive."""

        hive_name = hive.hive.cast(self.config["nt_symbols"] + constants.BANG +
                                   "_CMHIVE").get_name()

        if self._win7 is None:
            try:
                self._win7 = self._win7_or_later()
            except exceptions.SymbolError:
                # self._win7 will be None and only registry value rawdata will be output
                pass

        self._determine_userassist_type()

        userassist_node_path = hive.get_key(
            "software\\microsoft\\windows\\currentversion\\explorer\\userassist",
            return_list=True)

        if not userassist_node_path:
            vollog.warning(
                "list_userassist did not find a valid node_path (or None)")
            return

        if not isinstance(userassist_node_path, list):
            vollog.warning(
                "userassist_node_path did not return a list as expected")
            return
        userassist_node = userassist_node_path[-1]
        # iterate through the GUIDs under the userassist key
        for guidkey in userassist_node.get_subkeys():
            # each guid key should have a Count key in it
            for countkey in guidkey.get_subkeys():
                countkey_path = countkey.get_key_path()
                countkey_last_write_time = conversion.wintime_to_datetime(
                    countkey.LastWriteTime.QuadPart)

                # output the parent Count key
                result = (
                    0, (renderers.format_hints.Hex(hive.hive_offset),
                        hive_name, countkey_path, countkey_last_write_time,
                        "Key", renderers.NotApplicableValue(),
                        renderers.NotApplicableValue(),
                        renderers.NotApplicableValue(),
                        renderers.NotApplicableValue(),
                        renderers.NotApplicableValue(),
                        renderers.NotApplicableValue(),
                        renderers.NotApplicableValue())
                )  # type: Tuple[int, Tuple[format_hints.Hex, Any, Any, Any, Any, Any, Any, Any, Any, Any, Any, Any]]
                yield result

                # output any subkeys under Count
                for subkey in countkey.get_subkeys():

                    subkey_name = subkey.get_name()
                    result = (1, (
                        renderers.format_hints.Hex(hive.hive_offset),
                        hive_name,
                        countkey_path,
                        countkey_last_write_time,
                        "Subkey",
                        subkey_name,
                        renderers.NotApplicableValue(),
                        renderers.NotApplicableValue(),
                        renderers.NotApplicableValue(),
                        renderers.NotApplicableValue(),
                        renderers.NotApplicableValue(),
                        renderers.NotApplicableValue(),
                    ))
                    yield result

                # output any values under Count
                for value in countkey.get_values():

                    value_name = value.get_name()
                    try:
                        value_name = codecs.encode(value_name, "rot_13")
                    except UnicodeDecodeError:
                        pass

                    if self._win7:
                        guid = value_name.split("\\")[0]
                        if guid in self._folder_guids:
                            value_name = value_name.replace(
                                guid, self._folder_guids[guid])

                    userassist_data_dict = self.parse_userassist_data(value)
                    result = (1, (
                        renderers.format_hints.Hex(hive.hive_offset),
                        hive_name,
                        countkey_path,
                        countkey_last_write_time,
                        "Value",
                        value_name,
                        userassist_data_dict["id"],
                        userassist_data_dict["count"],
                        userassist_data_dict["focus"],
                        userassist_data_dict["time"],
                        userassist_data_dict["lastupdated"],
                        format_hints.HexBytes(userassist_data_dict["rawdata"]),
                    ))
                    yield result