Beispiel #1
0
    def _generator(self):
        kernel = self.context.modules[self.config['kernel']]

        for driver in self.scan_drivers(self.context, kernel.layer_name,
                                        kernel.symbol_table_name):

            try:
                driver_name = driver.get_driver_name()
            except (ValueError, 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))
Beispiel #2
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
Beispiel #3
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 = []

        # Open the bodyfile now, so we can start outputting to it immediately
        if self.config.get('create-bodyfile', True):
            file_data = self.open("volatility.body")
            fp = io.TextIOWrapper(file_data, write_through = True)
        else:
            file_data = None
            fp = None

        for plugin in runable_plugins:
            plugin_name = plugin.__class__.__name__
            self._progress_callback((runable_plugins.index(plugin) * 100) // len(runable_plugins),
                                    f"Running plugin {plugin_name}...")
            try:
                vollog.log(logging.INFO, f"Running {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())
                    ]))

                    # Write each entry because the body file doesn't need to be sorted
                    if fp:
                        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("|{} - {}|0|0|0|0|0|{}|{}|{}|{}\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, ""))))
            except Exception:
                vollog.log(logging.INFO, f"Exception occurred running plugin: {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):
            if fp:
                fp.close()
                file_data.close()
Beispiel #4
0
    def _generator(self):
        kernel = self.context.modules[self.config['kernel']]

        collection = ssdt.SSDT.build_module_collection(self.context, kernel.layer_name, kernel.symbol_table_name)

        for driver in driverscan.DriverScan.scan_drivers(self.context, kernel.layer_name, kernel.symbol_table_name):

            try:
                driver_name = driver.get_driver_name()
            except (ValueError, 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()))
Beispiel #5
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()
Beispiel #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,
                f"Cannot access _EPROCESS.Session.SessionId at {self.vol.offset:#x}"
            )

        return renderers.UnreadableValue()
Beispiel #7
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, f"Unknown choice {self.PoolType}")
     else:
         return renderers.NotApplicableValue()
Beispiel #8
0
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()
Beispiel #9
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()
Beispiel #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))
Beispiel #11
0
    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 (ValueError, 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))
Beispiel #12
0
    def _generator(self):

        kernel = self.context.modules[self.config['kernel']]

        callback_table_name = self.create_callback_table(
            self.context, kernel.symbol_table_name, self.config_path)

        collection = ssdt.SSDT.build_module_collection(
            self.context, kernel.layer_name, kernel.symbol_table_name)

        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, kernel.layer_name, kernel.symbol_table_name,
                    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))
Beispiel #13
0
    def _generator(self):
        kernel = self.context.modules[self.config['kernel']]

        for mutant in self.scan_mutants(self.context, kernel.layer_name,
                                        kernel.symbol_table_name):

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

            yield (0, (format_hints.Hex(mutant.vol.offset), name))
Beispiel #14
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())
Beispiel #15
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
Beispiel #16
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())
Beispiel #17
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()
Beispiel #18
0
    def _generator(self, layer: crash.WindowsCrashDump32Layer):
        header = layer.get_header()
        uptime = datetime.timedelta(microseconds=int(header.SystemUpTime) / 10)

        if header.DumpType == 0x1:
            dump_type = "Full Dump (0x1)"
        elif header.DumpType == 0x5:
            dump_type = "Bitmap Dump (0x5)"
        else:
            # this should never happen since the crash layer only accepts 0x1 and 0x5
            dump_type = "Unknown/Unsupported ({:#x})".format(header.DumpType)

        if header.DumpType == 0x5:
            summary_header = layer.get_summary_header()
            bitmap_header_size = format_hints.Hex(summary_header.HeaderSize)
            bitmap_size = format_hints.Hex(summary_header.BitmapSize)
            bitmap_pages = format_hints.Hex(summary_header.Pages)
        else:
            bitmap_header_size = bitmap_size = bitmap_pages = renderers.NotApplicableValue(
            )

        yield (0, (
            utility.array_to_string(header.Signature),
            header.MajorVersion,
            header.MinorVersion,
            format_hints.Hex(header.DirectoryTableBase),
            format_hints.Hex(header.PfnDataBase),
            format_hints.Hex(header.PsLoadedModuleList),
            format_hints.Hex(header.PsActiveProcessHead),
            header.MachineImageType,
            header.NumberProcessors,
            format_hints.Hex(header.KdDebuggerDataBlock),
            dump_type,
            str(uptime),
            utility.array_to_string(header.Comment),
            conversion.wintime_to_datetime(header.SystemTime),
            bitmap_header_size,
            bitmap_size,
            bitmap_pages,
        ))
Beispiel #19
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))
Beispiel #20
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()

                file_output = "Disabled"
                if self.config['dump']:
                    file_handle = self.dump_pe(
                        self.context,
                        pe_table_name,
                        entry,
                        self.open,
                        proc_layer_name,
                        prefix="pid.{}.".format(proc_id))
                    file_output = "Error outputting file"
                    if file_handle:
                        file_handle.close()
                        file_output = file_handle.preferred_filename

                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, file_output))
Beispiel #21
0
    def _generator(self):
        layer = self.context.layers[self.config['primary']]

        # Yara Rule to scan for MFT Header Signatures
        rules = yarascan.YaraScan.process_yara_options(
            {'yara_rules': '/FILE0|FILE\*|BAAD/'})

        # Read in the Symbol File
        symbol_table = intermed.IntermediateSymbolTable.create(
            context=self.context,
            config_path=self.config_path,
            sub_path="windows",
            filename="mft",
            class_types={
                'FILE_NAME_ENTRY': mft.MFTFileName,
                'MFT_ENTRY': mft.MFTEntry
            })

        # get each of the individual Field Sets
        mft_object = symbol_table + constants.BANG + "MFT_ENTRY"
        attribute_object = symbol_table + constants.BANG + "ATTRIBUTE"
        header_object = symbol_table + constants.BANG + "ATTR_HEADER"
        si_object = symbol_table + constants.BANG + "STANDARD_INFORMATION_ENTRY"
        fn_object = symbol_table + constants.BANG + "FILE_NAME_ENTRY"

        # Scan the layer for Raw MFT records and parse the fields
        for offset, _rule_name, _name, _value in layer.scan(
                context=self.context,
                scanner=yarascan.YaraScanner(rules=rules)):
            try:
                mft_record = self.context.object(mft_object,
                                                 offset=offset,
                                                 layer_name=layer.name)
                # We will update this on each pass in the next loop and use it as the new offset.
                attr_base_offset = mft_record.FirstAttrOffset

                attr_header = self.context.object(header_object,
                                                  offset=offset +
                                                  attr_base_offset,
                                                  layer_name=layer.name)

                # There is no field that has a count of Attributes
                # Keep Attempting to read attributes until we get an invalid attr_header.AttrType

                while attr_header.AttrType.is_valid_choice:
                    vollog.debug(f"Attr Type: {attr_header.AttrType.lookup()}")

                    # Offset past the headers to the attribute data
                    attr_data_offset = offset + attr_base_offset + self.context.symbol_space.get_type(
                        attribute_object).relative_child_offset("Attr_Data")

                    # MFT Flags determine the file type or dir
                    # If we don't have a valid enum, coerce to hex so we can keep the record
                    try:
                        mft_flag = mft_record.Flags.lookup()
                    except ValueError:
                        mft_flag = hex(mft_record.Flags)

                    # Standard Information Attribute
                    if attr_header.AttrType.lookup() == 'STANDARD_INFORMATION':
                        attr_data = self.context.object(
                            si_object,
                            offset=attr_data_offset,
                            layer_name=layer.name)

                        yield 0, (
                            format_hints.Hex(attr_data_offset),
                            mft_record.get_signature(),
                            mft_record.RecordNumber,
                            mft_record.LinkCount,
                            mft_flag,
                            renderers.NotApplicableValue(),
                            attr_header.AttrType.lookup(),
                            conversion.wintime_to_datetime(
                                attr_data.CreationTime),
                            conversion.wintime_to_datetime(
                                attr_data.ModifiedTime),
                            conversion.wintime_to_datetime(
                                attr_data.UpdatedTime),
                            conversion.wintime_to_datetime(
                                attr_data.AccessedTime),
                            renderers.NotApplicableValue(),
                        )

                    # File Name Attribute
                    if attr_header.AttrType.lookup() == 'FILE_NAME':
                        attr_data = self.context.object(
                            fn_object,
                            offset=attr_data_offset,
                            layer_name=layer.name)
                        file_name = attr_data.get_full_name()

                        # If we don't have a valid enum, coerce to hex so we can keep the record
                        try:
                            permissions = attr_data.Flags.lookup()
                        except ValueError:
                            permissions = hex(attr_data.Flags)

                        yield 1, (format_hints.Hex(attr_data_offset),
                                  mft_record.get_signature(),
                                  mft_record.RecordNumber,
                                  mft_record.LinkCount, mft_flag, permissions,
                                  attr_header.AttrType.lookup(),
                                  conversion.wintime_to_datetime(
                                      attr_data.CreationTime),
                                  conversion.wintime_to_datetime(
                                      attr_data.ModifiedTime),
                                  conversion.wintime_to_datetime(
                                      attr_data.UpdatedTime),
                                  conversion.wintime_to_datetime(
                                      attr_data.AccessedTime), file_name)

                    # If there's no advancement the loop will never end, so break it now
                    if attr_header.Length == 0:
                        break

                    # Update the base offset to point to the next attribute
                    attr_base_offset += attr_header.Length
                    # Get the next attribute
                    attr_header = self.context.object(header_object,
                                                      offset=offset +
                                                      attr_base_offset,
                                                      layer_name=layer.name)

            except exceptions.PagedInvalidAddressException:
                pass
Beispiel #22
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(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: Union[interfaces.renderers.BaseAbsentValue,
                                      bytes] = renderers.UnreadableValue()
                else:
                    try:
                        value_data = node.decode_data()

                        if isinstance(value_data, int):
                            value_data = format_hints.MultiTypeData(
                                value_data, encoding='utf-8')
                        elif RegValueTypes(
                                node.Type) == RegValueTypes.REG_BINARY:
                            value_data = format_hints.MultiTypeData(
                                value_data, show_hex=True)
                        elif RegValueTypes(
                                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
Beispiel #23
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)

        # TODO: Fix this so it works with more than just intel layers
        physical_layer_name = self.context.layers[
            self.config['primary']].config.get('memory_layer', None)

        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)
            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
                if (not isinstance(BaseDllName, renderers.UnreadableValue)
                        and physical_layer_name is not None
                        and self.config['extensive']):
                    result = self.find_version_info(self._context,
                                                    physical_layer_name,
                                                    BaseDllName)
                    if result is not None:
                        (major, minor, product, build) = result

            # 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))
Beispiel #24
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
Beispiel #25
0
    def _generator(self) -> Iterator[Tuple]:
        kernel = self.context.modules[self.config["kernel"]]

        # Scan the Layer for drivers
        for driver in driverscan.DriverScan.scan_drivers(
                self.context, kernel.layer_name, kernel.symbol_table_name):
            try:
                try:
                    driver_name = driver.get_driver_name()
                except (ValueError, exceptions.PagedInvalidAddressException):
                    vollog.log(
                        constants.LOGLEVEL_VVVV,
                        f"Failed to get Driver name : {driver.vol.offset:x}")
                    driver_name = renderers.UnparsableValue()

                yield (0, (format_hints.Hex(driver.vol.offset), "DRV",
                           driver_name, renderers.NotApplicableValue(),
                           renderers.NotApplicableValue(),
                           renderers.NotApplicableValue()))

                # Scan to get the device information of driver.
                for device in driver.get_devices():
                    try:
                        device_name = device.get_device_name()
                    except (ValueError,
                            exceptions.PagedInvalidAddressException):
                        vollog.log(
                            constants.LOGLEVEL_VVVV,
                            f"Failed to get Device name : {device.vol.offset:x}"
                        )
                        device_name = renderers.UnparsableValue()

                    device_type = DEVICE_CODES.get(device.DeviceType,
                                                   "UNKNOWN")

                    yield (1, (format_hints.Hex(driver.vol.offset), "DEV",
                               driver_name, device_name,
                               renderers.NotApplicableValue(), device_type))

                    # Scan to get the attached devices information of device.
                    for level, attached_device in enumerate(
                            device.get_attached_devices(), start=2):
                        try:
                            device_name = attached_device.get_device_name()
                        except (ValueError,
                                exceptions.PagedInvalidAddressException):
                            vollog.log(
                                constants.LOGLEVEL_VVVV,
                                f"Failed to get Attached Device Name: {attached_device.vol.offset:x}"
                            )
                            device_name = renderers.UnparsableValue()

                        attached_device_driver_name = attached_device.DriverObject.DriverName.get_string(
                        )
                        attached_device_type = DEVICE_CODES.get(
                            attached_device.DeviceType, "UNKNOWN")

                        yield (level, (format_hints.Hex(driver.vol.offset),
                                       "ATT", driver_name, device_name,
                                       attached_device_driver_name,
                                       attached_device_type))

            except (exceptions.PagedInvalidAddressException):
                vollog.log(
                    constants.LOGLEVEL_VVVV,
                    f"Invalid address identified in drivers and devices: {driver.vol.offset:x}"
                )
                continue
Beispiel #26
0
 def get_file_name(self):
     """Only long(er) vads have mapped files."""
     return renderers.NotApplicableValue()
Beispiel #27
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