Initial draft of complete-vad vadyarascan

This commit is contained in:
Mike Auty
2024-07-07 15:13:06 +01:00
parent 1d4a27ea41
commit bb4cfb6e00
2 changed files with 46 additions and 21 deletions
@@ -2,10 +2,11 @@
# which is available at https://www.volatilityfoundation.org/license/vsl-v1.0
#
import io
import logging
from typing import Iterable, List, Tuple
from volatility3.framework import interfaces, renderers
from volatility3.framework import exceptions, interfaces, renderers
from volatility3.framework.configuration import requirements
from volatility3.framework.renderers import format_hints
from volatility3.plugins import yarascan
@@ -18,7 +19,7 @@ class VadYaraScan(interfaces.plugins.PluginInterface):
"""Scans all the Virtual Address Descriptor memory maps using yara."""
_required_framework_version = (2, 4, 0)
_version = (1, 0, 1)
_version = (1, 1, 0)
@classmethod
def get_requirements(cls) -> List[interfaces.configuration.RequirementInterface]:
@@ -32,11 +33,8 @@ class VadYaraScan(interfaces.plugins.PluginInterface):
requirements.PluginRequirement(
name="pslist", plugin=pslist.PsList, version=(2, 0, 0)
),
requirements.VersionRequirement(
name="yarascanner", component=yarascan.YaraScanner, version=(2, 0, 0)
),
requirements.PluginRequirement(
name="yarascan", plugin=yarascan.YaraScan, version=(1, 2, 0)
name="yarascan", plugin=yarascan.YaraScan, version=(1, 3, 0)
),
requirements.ListRequirement(
name="pid",
@@ -59,6 +57,8 @@ class VadYaraScan(interfaces.plugins.PluginInterface):
filter_func = pslist.PsList.create_pid_filter(self.config.get("pid", None))
sanity_check = 0x1000 * 0x1000 * 0x1000
for task in pslist.PsList.list_processes(
context=self.context,
layer_name=kernel.layer_name,
@@ -67,18 +67,34 @@ class VadYaraScan(interfaces.plugins.PluginInterface):
):
layer_name = task.add_process_layer()
layer = self.context.layers[layer_name]
for offset, rule_name, name, value in layer.scan(
context=self.context,
scanner=yarascan.YaraScanner(rules=rules),
sections=self.get_vad_maps(task),
):
yield 0, (
format_hints.Hex(offset),
task.UniqueProcessId,
rule_name,
name,
value,
)
for start, end in self.get_vad_maps(task):
size = end - start
if size > sanity_check:
vollog.warn(
f"VAD at 0x{start:x} over sanity-check size, not scanning"
)
continue
for match in rules.match(data=layer.read(start, end - start, True)):
if yarascan.YaraScan.yara_returns_instances():
for match_string in match.strings:
for instance in match_string.instances:
yield 0, (
format_hints.Hex(instance.offset + start),
task.UniqueProcessId,
match.rule,
match_string.identifier,
instance.matched_data,
)
else:
for offset, name, value in match.strings:
yield 0, (
format_hints.Hex(offset + start),
task.UniqueProcessId,
match.rule,
name,
value,
)
@staticmethod
def get_vad_maps(
+12 -3
View File
@@ -2,10 +2,11 @@
# which is available at https://www.volatilityfoundation.org/license/vsl-v1.0
#
import io
import logging
from typing import Any, Dict, Iterable, List, Tuple
from volatility3.framework import interfaces, renderers
from volatility3.framework import exceptions, interfaces, renderers
from volatility3.framework.configuration import requirements
from volatility3.framework.interfaces import plugins
from volatility3.framework.layers import resources
@@ -43,7 +44,7 @@ class YaraScanner(interfaces.layers.ScannerInterface):
self, data: bytes, data_offset: int
) -> Iterable[Tuple[int, str, str, bytes]]:
for match in self._rules.match(data=data):
if self.st_object:
if YaraScan.yara_returns_instances():
for match_string in match.strings:
for instance in match_string.instances:
yield (
@@ -61,7 +62,7 @@ class YaraScan(plugins.PluginInterface):
"""Scans kernel memory using yara rules (string or file)."""
_required_framework_version = (2, 0, 0)
_version = (1, 2, 0)
_version = (1, 3, 0)
# TODO: When the major version is bumped, take the opportunity to rename the yara_rules config to yara_string
# or something that makes more sense
@@ -119,6 +120,14 @@ class YaraScan(plugins.PluginInterface):
),
]
@classmethod
def yara_returns_instances(self) -> bool:
st_object = not tuple([int(x) for x in yara.__version__.split(".")]) < (
4,
3,
)
return st_object
@classmethod
def process_yara_options(cls, config: Dict[str, Any]):
rules = None