Registry: handle ints, multi strings, and binary data with StrLike

This commit is contained in:
Dave Lassalle
2020-07-16 19:44:18 +01:00
committed by ikelos
parent 3111591e06
commit 42a97dd10c
4 changed files with 42 additions and 14 deletions
+6
View File
@@ -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,
+10 -2
View File
@@ -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