mirror of
https://github.com/volatilityfoundation/volatility3.git
synced 2026-09-07 10:17:38 +02:00
Registry: handle ints, multi strings, and binary data with StrLike
This commit is contained in:
@@ -58,7 +58,11 @@ def strlike_as_text(value: format_hints.StrLike) -> str:
|
||||
|
||||
This attempts to convert the string based on its encoding and if no data's been lost due to the split on the null character, then it displays it as is
|
||||
"""
|
||||
if value.show_hex:
|
||||
return hex_bytes_as_text(value)
|
||||
string_representation = str(value, encoding = value.encoding, errors = 'replace')
|
||||
if value.split_nulls and ((len(value) / 2 - 1) <= len(string_representation) <= (len(value) / 2)):
|
||||
return "\n".join(string_representation.split("\x00"))
|
||||
if len(string_representation) - 1 <= len(string_representation.split("\x00")[0]) <= len(string_representation):
|
||||
return string_representation.split("\x00")[0]
|
||||
return hex_bytes_as_text(value)
|
||||
@@ -85,6 +89,8 @@ def quoted_optional(func):
|
||||
result = optional(func)(x)
|
||||
if result == "-" or result == "N/A":
|
||||
return ""
|
||||
if isinstance(x, format_hints.StrLike) and x.converted_int:
|
||||
return "{}".format(result)
|
||||
if isinstance(x, int) and not isinstance(x, (format_hints.Hex, format_hints.Bin)):
|
||||
return "{}".format(result)
|
||||
return "\"{}\"".format(result)
|
||||
|
||||
@@ -66,7 +66,8 @@ class PrintKey(interfaces.plugins.PluginInterface):
|
||||
vollog.warning("Hive walker was not passed a valid node_path (or None)")
|
||||
return
|
||||
node = node_path[-1]
|
||||
key_path = '\\'.join([k.get_name() for k in node_path])
|
||||
key_path_items = [hive] + node_path[1:]
|
||||
key_path = '\\'.join([k.get_name() for k in key_path_items])
|
||||
if node.vol.type_name.endswith(constants.BANG + '_CELL_DATA'):
|
||||
raise RegistryFormatException(hive.name, "Encountered _CELL_DATA instead of _CM_KEY_NODE")
|
||||
last_write_time = conversion.wintime_to_datetime(node.LastWriteTime.QuadPart)
|
||||
@@ -113,7 +114,7 @@ class PrintKey(interfaces.plugins.PluginInterface):
|
||||
key_node_name = renderers.UnreadableValue()
|
||||
|
||||
yield (depth, (last_write_time, renderers.format_hints.Hex(hive.hive_offset), "Key", key_path,
|
||||
key_node_name, "", volatile))
|
||||
key_node_name, renderers.NotApplicableValue(), volatile))
|
||||
else:
|
||||
try:
|
||||
value_node_name = node.get_name() or "(Default)"
|
||||
@@ -121,20 +122,33 @@ class PrintKey(interfaces.plugins.PluginInterface):
|
||||
vollog.debug(excp)
|
||||
value_node_name = renderers.UnreadableValue()
|
||||
|
||||
try:
|
||||
value_data = node.decode_data() # type: Union[interfaces.renderers.BaseAbsentValue, bytes]
|
||||
except (ValueError, exceptions.InvalidAddressException, RegistryFormatException) as excp:
|
||||
vollog.debug(excp)
|
||||
value_data = 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.StrLike(value_data, encoding='utf-8')
|
||||
elif RegValueTypes.get(node.Type) == RegValueTypes.REG_BINARY:
|
||||
value_data = format_hints.StrLike(value_data, show_hex=True)
|
||||
elif RegValueTypes.get(node.Type) == RegValueTypes.REG_MULTI_SZ:
|
||||
value_data = format_hints.StrLike(value_data, encoding='utf-16-le', split_nulls=True)
|
||||
else:
|
||||
value_data = format_hints.StrLike(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, format_hints.StrLike(value_data, encoding = 'utf-16-le'), volatile))
|
||||
value_node_name, value_data, volatile))
|
||||
yield result
|
||||
|
||||
def _registry_walker(self,
|
||||
|
||||
@@ -28,9 +28,17 @@ class HexBytes(bytes):
|
||||
class StrLike(bytes):
|
||||
"""The contents are supposed to be a string, but may contain binary data."""
|
||||
|
||||
def __new__(cls, original, encoding: str = 'utf-16-le'):
|
||||
def __new__(cls, original, encoding: str = 'utf-16-le', split_nulls: bool = False, show_hex: bool = False):
|
||||
if isinstance(original, int):
|
||||
original = str(original).encode(encoding)
|
||||
return super().__new__(cls, original)
|
||||
|
||||
def __init__(self, original: bytes, encoding: str = 'utf-16-le'):
|
||||
def __init__(self, original: bytes, encoding: str = 'utf-16-le', split_nulls: bool = False, show_hex: bool = False):
|
||||
if isinstance(original, int):
|
||||
self.converted_int = True
|
||||
else:
|
||||
self.converted_int = False
|
||||
self.encoding = encoding
|
||||
self.split_nulls = split_nulls
|
||||
self.show_hex = show_hex
|
||||
bytes.__init__(original)
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
import enum
|
||||
import logging
|
||||
import struct
|
||||
from typing import Optional, Iterable
|
||||
from typing import Optional, Iterable, Union
|
||||
|
||||
from volatility.framework import constants, exceptions, objects, interfaces
|
||||
from volatility.framework.layers.registry import RegistryHive, RegistryInvalidIndex, RegistryFormatException
|
||||
@@ -239,7 +239,7 @@ class CM_KEY_VALUE(objects.StructType):
|
||||
self.Name.count = namelength
|
||||
return self.Name.cast("string", max_length = namelength, encoding = "latin-1")
|
||||
|
||||
def decode_data(self) -> bytes:
|
||||
def decode_data(self) -> Union[int, bytes]:
|
||||
"""Properly decodes the data associated with the value node"""
|
||||
# Determine if the data is stored inline
|
||||
datalen = self.DataLength
|
||||
@@ -298,4 +298,4 @@ class CM_KEY_VALUE(objects.StructType):
|
||||
|
||||
# Fall back if it's something weird
|
||||
vollog.debug("Unknown registry value type encountered: {}".format(self.Type))
|
||||
return data.hex()
|
||||
return data
|
||||
|
||||
Reference in New Issue
Block a user