mirror of
https://github.com/volatilityfoundation/volatility3.git
synced 2026-09-08 18:57:38 +02:00
Initial draft of complete-vad vadyarascan
This commit is contained in:
@@ -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(
|
||||
|
||||
@@ -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
|
||||
|
||||
Reference in New Issue
Block a user