Skip to content

Commit

Permalink
Microsoft Office add-in detection (#966)
Browse files Browse the repository at this point in the history
Add msoffice productivity plugin.
  • Loading branch information
twiggler authored Feb 5, 2025
1 parent ffd18db commit a0a8c3e
Show file tree
Hide file tree
Showing 15 changed files with 641 additions and 34 deletions.
26 changes: 19 additions & 7 deletions dissect/target/helpers/regutil.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@
from functools import cached_property
from io import BytesIO
from pathlib import Path
from typing import BinaryIO, Iterator, Optional, TextIO, Union
from typing import BinaryIO, Iterator, NewType, Optional, TextIO, Union

from dissect.regf import c_regf, regf

Expand All @@ -26,7 +26,7 @@
KeyType = Union[regf.IndexLeaf, regf.FastLeaf, regf.HashLeaf, regf.IndexRoot, regf.NamedKey]
"""The possible key types that can be returned from the registry."""

ValueType = Union[int, str, bytes, list[str]]
ValueType = Union[int, str, bytes, list[str], None]
"""The possible value types that can be returned from the registry."""


Expand Down Expand Up @@ -161,15 +161,27 @@ def subkeys(self) -> list[RegistryKey]:
"""Returns a list of subkeys from this key."""
raise NotImplementedError()

def value(self, value: str) -> RegistryValue:
Marker = NewType("Marker", object)
__marker = Marker(object())

def value(self, value: str, default: ValueType | Marker = __marker) -> RegistryValue:
"""Returns a specific value from this key.
Args:
value: The name of the value to retrieve.
default: An optional argument that specifies the default return value in case the value cannot be found.
Raises:
RegistryValueNotFoundError: If this key has no value with the requested name.
RegistryValueNotFoundError: If this key has no value with the requested name and default is not defined.
"""
try:
return self._value(value)
except RegistryValueNotFoundError:
if default is self.__marker:
raise
return VirtualValue(self.hive, value, default)

def _value(self, value: str) -> RegistryValue:
raise NotImplementedError()

def values(self) -> list[RegistryValue]:
Expand Down Expand Up @@ -400,7 +412,7 @@ def subkeys(self) -> list[RegistryKey]: # Dict_values view

return res.values()

def value(self, value: str) -> RegistryValue:
def _value(self, value: str) -> RegistryValue:
try:
return self._values[value.lower()]
except KeyError:
Expand Down Expand Up @@ -588,7 +600,7 @@ def subkeys(self) -> list[KeyCollection]:

return ret.values()

def value(self, value: str) -> ValueCollection:
def _value(self, value: str) -> ValueCollection:
ret = ValueCollection()
for key in self:
try:
Expand Down Expand Up @@ -698,7 +710,7 @@ def subkey(self, subkey: str) -> RegistryKey:
def subkeys(self) -> list[RegistryKey]:
return [RegfKey(self.hive, k) for k in self.key.subkeys()]

def value(self, value: str) -> RegistryValue:
def _value(self, value: str) -> RegistryValue:
try:
return RegfValue(self.hive, self.key.value(value))
except regf.RegistryValueNotFoundError as e:
Expand Down
7 changes: 5 additions & 2 deletions dissect/target/helpers/utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -29,17 +29,20 @@ def findall(buf: bytes, needle: bytes) -> Iterator[int]:
T = TypeVar("T")


def to_list(value: T | list[T]) -> list[T]:
"""Convert a single value or a list of values to a list.
def to_list(value: T | list[T] | None) -> list[T]:
"""Convert a single value or a list of values to a list. A value of ``None`` is converted to an empty list.
Args:
value: The value to convert.
Returns:
A list of values.
"""
if value is None:
return []
if not isinstance(value, list):
return [value]

return value


Expand Down
11 changes: 8 additions & 3 deletions dissect/target/loaders/cb.py
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,12 @@
)
from dissect.target.filesystems.cb import CbFilesystem
from dissect.target.helpers.fsutil import TargetPath
from dissect.target.helpers.regutil import RegistryHive, RegistryKey, RegistryValue
from dissect.target.helpers.regutil import (
RegistryHive,
RegistryKey,
RegistryValue,
ValueType,
)
from dissect.target.loader import Loader
from dissect.target.plugins.os.windows.registry import RegistryPlugin

Expand Down Expand Up @@ -161,7 +166,7 @@ def subkey(self, subkey: str) -> CbRegistryKey:
def subkeys(self) -> list[CbRegistryKey]:
return list(map(self.subkey, self.data["sub_keys"]))

def value(self, value: str) -> str:
def _value(self, value: str) -> CbRegistryValue:
reg_value = value.lower()
for val in self.values():
if val.name.lower() == reg_value:
Expand Down Expand Up @@ -197,7 +202,7 @@ def name(self) -> str:
return self._name

@property
def value(self) -> str:
def value(self) -> ValueType:
return self._value

@property
Expand Down
11 changes: 8 additions & 3 deletions dissect/target/loaders/smb.py
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,12 @@
)
from dissect.target.filesystems.smb import SmbFilesystem
from dissect.target.helpers.fsutil import TargetPath
from dissect.target.helpers.regutil import RegistryHive, RegistryKey, RegistryValue
from dissect.target.helpers.regutil import (
RegistryHive,
RegistryKey,
RegistryValue,
ValueType,
)
from dissect.target.loader import Loader
from dissect.target.plugins.os.windows._os import WindowsPlugin
from dissect.target.plugins.os.windows.registry import RegistryPlugin
Expand Down Expand Up @@ -308,7 +313,7 @@ def subkeys(self) -> list[SmbRegistryKey]:

return subkeys

def value(self, value: str) -> str:
def _value(self, value: str) -> SmbRegistryValue:
reg_value = value.lower()
for val in self.values():
if val.name.lower() == reg_value:
Expand Down Expand Up @@ -351,7 +356,7 @@ def name(self) -> str:
return self._name

@property
def value(self) -> str:
def value(self) -> ValueType:
return self._value

@property
Expand Down
Loading

0 comments on commit a0a8c3e

Please sign in to comment.