Windows: Adds scheduled tasks plugin

This adds a plugin 'ScheduledTasks' that can decode binary-encoded
scheduled tasks from the Windows registry's SOFTWARE hive using a custom
reader that extends the `io.BytesIO` class. Decoding operations are
intended to be as fault tolerant as possible, swallowing exceptions and
returning `None` to account for smear or missing data.

Because each task can have mulitple triggers and multiple actions, a
single entry is generated for each trigger + action pair. In the event
that the either the actions could not be parsed or the triggers could
not be parsed due to missing or smeared data, an entry will still be
generated using the available information from the other registry value,
since trigger and action data is stored separately.

Much more information is decoded than is rendered, this was done
intentionally to avoid overpopulating the TreeGrid with less pertinent
data and to avoid an explosion of trigger and action-specific fields that
may not apply to most other entries.
This commit is contained in:
David McDonald
2024-10-09 17:27:06 -05:00
parent 4ffaad5a15
commit 57ef3f587e
3 changed files with 1820 additions and 0 deletions
+3
View File
@@ -170,6 +170,9 @@ class RegistryHive(linear.LinearlyMappedLayer):
return_list specifies whether the return result will be a single
node (default) or a list of nodes from root to the current node
(if return_list is true).
Raises RegistryFormatException if an invalid structure is encountered
Raises KeyError if the key is not found
"""
root_node = self.get_node(self.root_cell_offset)
if not root_node.vol.type_name.endswith(constants.BANG + "_CM_KEY_NODE"):
File diff suppressed because it is too large Load Diff
@@ -28,6 +28,27 @@ def wintime_to_datetime(
return renderers.UnparsableValue()
def windows_bytes_to_guid(buf: bytes) -> str:
"""
Converts 16 raw bytes to a windows GUID.
Raises ValueError if the provided buffer is not exactly 16 bytes.
"""
if len(buf) != 16:
raise ValueError("Expected 16 bytes for GUID")
head_components = [format(v, "x") for v in struct.unpack("<IHH", buf[:8])]
tail_component = [
format(v, "x")
for v in struct.unpack(
">HQ",
buf[8:10] + b"\x00\x00" + buf[10:16],
)
]
combined = head_components + tail_component
return "{" + "-".join(combined) + "}"
def unixtime_to_datetime(
unixtime: int,
) -> Union[interfaces.renderers.BaseAbsentValue, datetime.datetime]: