mirror of
https://github.com/volatilityfoundation/volatility3.git
synced 2026-09-12 12:47:39 +02:00
Add a new plugin that reports the Driver Signing Enforcement status
This commit is contained in:
@@ -0,0 +1,112 @@
|
||||
# This file is Copyright 2019 Volatility Foundation and licensed under the Volatility Software License 1.0
|
||||
# which is available at https://www.volatilityfoundation.org/license/vsl-v1.0
|
||||
#
|
||||
import logging
|
||||
from typing import List
|
||||
|
||||
from volatility3.framework import exceptions, renderers, interfaces, symbols
|
||||
from volatility3.framework.configuration import requirements
|
||||
from volatility3.framework.objects import utility
|
||||
from volatility3.plugins.windows import info, modules
|
||||
from volatility3.framework.symbols.windows import pdbutil
|
||||
|
||||
vollog = logging.getLogger(__name__)
|
||||
|
||||
class driver_signing_enforcement(interfaces.plugins.PluginInterface):
|
||||
"""Reports the status of Driving Signing Enforcement"""
|
||||
|
||||
_required_framework_version = (2, 0, 0)
|
||||
_version = (1, 0, 0)
|
||||
|
||||
@classmethod
|
||||
def get_requirements(cls) -> List[interfaces.configuration.RequirementInterface]:
|
||||
return [
|
||||
requirements.ModuleRequirement(name = 'kernel', description = 'Windows kernel',
|
||||
architectures = ["Intel32", "Intel64"]),
|
||||
requirements.PluginRequirement(name = 'modules', plugin = modules.Modules, version = (1, 0, 0)),
|
||||
requirements.VersionRequirement(name = 'pdbutil', component = pdbutil.PDBUtility, version = (1, 0, 0)),
|
||||
]
|
||||
|
||||
def _get_ci_dll(self, kernel):
|
||||
"""
|
||||
Finds the CI.DLL kernel module. This module is used for
|
||||
Code Integrity enforcement, and is targetted by malware to disable security checks.
|
||||
|
||||
Args:
|
||||
kernel: interfaces.context.ModuleInterface of the kernel
|
||||
Returns:
|
||||
The `_LDR_DATA_TABLE_ENTRY` of CI.DLL
|
||||
None if module cannot be located
|
||||
"""
|
||||
for mod in modules.Modules.list_modules(self.context,
|
||||
kernel.layer_name,
|
||||
kernel.symbol_table_name):
|
||||
|
||||
try:
|
||||
module_name = mod.BaseDllName.get_string()
|
||||
except exceptions.InvalidAddressException:
|
||||
continue
|
||||
|
||||
if module_name.lower() == "ci.dll":
|
||||
return mod
|
||||
|
||||
return None
|
||||
|
||||
def _check_win10_64bit(self, kernel):
|
||||
"""
|
||||
Checks if the analyzed memory sample is from
|
||||
a Windows 10 64bit system.
|
||||
|
||||
Returns:
|
||||
bool
|
||||
"""
|
||||
kuser = info.Info.get_kuser_structure(self.context,
|
||||
kernel.layer_name,
|
||||
kernel.symbol_table_name)
|
||||
|
||||
nt_major_version = int(kuser.NtMajorVersion)
|
||||
|
||||
is_64bit = symbols.symbol_table_is_64bit(self.context, kernel.symbol_table_name)
|
||||
|
||||
return nt_major_version >= 6 and is_64bit
|
||||
|
||||
def _generator(self):
|
||||
"""
|
||||
Uses the PDB of CI.DLL to locate g_CiOptions and report its value
|
||||
"""
|
||||
kernel = self.context.modules[self.config['kernel']]
|
||||
|
||||
if not self._check_win10_64bit(kernel):
|
||||
vollog.error("This plugin only supports 64-bit Windows 10 or later samples.")
|
||||
return
|
||||
|
||||
ci_mod = self._get_ci_dll(kernel)
|
||||
if ci_mod is None:
|
||||
vollog.error("CI.DLL not found in the kernel module list. Cannot proceed.")
|
||||
return
|
||||
|
||||
# we do not have a fallback mechanism, so if the PDB cannot load then we are done
|
||||
try:
|
||||
ci_symbols = pdbutil.PDBUtility.symbol_table_from_pdb(self.context,
|
||||
interfaces.configuration.path_join(
|
||||
self.config_path, 'ci'),
|
||||
kernel.layer_name,
|
||||
"ci.pdb",
|
||||
ci_mod.DllBase,
|
||||
ci_mod.SizeOfImage)
|
||||
|
||||
except exceptions.VolatilityException as e:
|
||||
vollog.error("Unable to analyze the PDB file for CI.DLL: {}.".format(str(e)))
|
||||
return
|
||||
|
||||
ci_module = self.context.module(ci_symbols, layer_name = kernel.layer_name, offset = ci_mod.DllBase)
|
||||
|
||||
options_address = ci_module.get_absolute_symbol_address("g_CiOptions")
|
||||
|
||||
options = kernel.object(object_type = "unsigned int", offset = options_address, absolute = True)
|
||||
|
||||
yield (0, (options != 0, options))
|
||||
|
||||
def run(self):
|
||||
return renderers.TreeGrid([("Driver Signing Enforcement", bool), ("g_CiOptions Value", int)],
|
||||
self._generator())
|
||||
Reference in New Issue
Block a user