mirror of
https://github.com/volatilityfoundation/volatility3.git
synced 2026-09-27 03:54:49 +02:00
Merge branch 'develop' into issue_713_fix_vad_end_off_by_one_pr
This commit is contained in:
+1
-1
@@ -107,7 +107,7 @@ each_dict_entry_on_separate_line=True
|
||||
i18n_comment=
|
||||
|
||||
# The i18n function call names. The presence of this function stops
|
||||
# reformattting on that line, because the string it has cannot be moved
|
||||
# reformatting on that line, because the string it has cannot be moved
|
||||
# away from the i18n comment.
|
||||
i18n_function_call=
|
||||
|
||||
|
||||
@@ -8,6 +8,10 @@ When an API feature or function is removed or changed, the major version is bump
|
||||
=====
|
||||
Add a `get_size()` method to Windows VAD structures and fix several off-by-one issues when calculating VAD sizes.
|
||||
|
||||
2.3.1
|
||||
=====
|
||||
Update in the windows `_EPROCESS.owning_process` method to support Windows Vista and later versions.
|
||||
|
||||
2.3.0
|
||||
=====
|
||||
Add in `child_template` to template class
|
||||
|
||||
+1
-1
@@ -31,7 +31,7 @@ If you make any Additions available to others, such as by providing copies of th
|
||||
- You are responsible to ensure you have rights in Additions necessary to comply with this section.
|
||||
|
||||
Contributing
|
||||
If you contribute (or offer to contribute) any materials to Volatility Foundation for the software, such as by submitting a pull request to the repository for the software or related content run by Volatility Foundation, you agree to contribute them under the under the BSD 2-Clause Plus Patent License (in the case of software) or the Creative Commons Zero Public Domain Dedication (in the case of content), unless you clearly mark them "Not a Contribution."
|
||||
If you contribute (or offer to contribute) any materials to Volatility Foundation for the software, such as by submitting a pull request to the repository for the software or related content run by Volatility Foundation, you agree to contribute them under the BSD 2-Clause Plus Patent License (in the case of software) or the Creative Commons Zero Public Domain Dedication (in the case of content), unless you clearly mark them "Not a Contribution."
|
||||
|
||||
Trademarks
|
||||
This license grants you no rights to any trademarks or service marks.
|
||||
|
||||
@@ -9,7 +9,7 @@ of a normal plugin, and reuses other plugins appropriately.
|
||||
.. note::
|
||||
|
||||
This document will not include the complete code necessary for a
|
||||
working plugin (such as imports, etc) since it's designed to focus on the necessary componets for writing a plugin.
|
||||
working plugin (such as imports, etc) since it's designed to focus on the necessary components for writing a plugin.
|
||||
For complete and functioning plugins, the ``framework/plugins`` directory should be consulted.
|
||||
|
||||
Inherit from PluginInterface
|
||||
|
||||
@@ -224,7 +224,7 @@ class CSVRenderer(CLIRenderer):
|
||||
# Ignore the type because namedtuples don't realize they have accessible attributes
|
||||
header_list.append(f"{column.name}")
|
||||
|
||||
writer = csv.DictWriter(outfd, header_list)
|
||||
writer = csv.DictWriter(outfd, header_list, lineterminator='\n')
|
||||
writer.writeheader()
|
||||
|
||||
def visitor(node: interfaces.renderers.TreeNode, accumulator):
|
||||
|
||||
@@ -46,7 +46,7 @@ class Cachedump(interfaces.plugins.PluginInterface):
|
||||
rc4 = ARC4.new(rc4key)
|
||||
data = rc4.encrypt(edata) # lgtm [py/weak-cryptographic-algorithm]
|
||||
else:
|
||||
# based on Based on code from http://lab.mediaservice.net/code/cachedump.rb
|
||||
# Based on code from http://lab.mediaservice.net/code/cachedump.rb
|
||||
aes = AES.new(nlkm[16:32], AES.MODE_CBC, ch)
|
||||
data = b""
|
||||
for i in range(0, len(edata), 16):
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
from volatility3.framework import interfaces, constants
|
||||
from volatility3.framework import renderers, interfaces, exceptions
|
||||
from volatility3.framework import constants, exceptions, interfaces, renderers
|
||||
from volatility3.framework.configuration import requirements
|
||||
from volatility3.framework.renderers import format_hints
|
||||
from volatility3.framework.symbols import intermed
|
||||
|
||||
@@ -433,7 +433,7 @@ class NetStat(interfaces.plugins.PluginInterface, timeliner.TimeLinerInterface):
|
||||
self.context, interfaces.configuration.path_join(self.config_path, 'tcpip'),
|
||||
kernel.layer_name, "tcpip.pdb", tcpip_module.DllBase, tcpip_module.SizeOfImage)
|
||||
except exceptions.VolatilityException:
|
||||
vollog.warning("Unable to locate symbols for the memory image's tcpip module")
|
||||
vollog.error("Unable to locate symbols for the memory image's tcpip module")
|
||||
|
||||
for netw_obj in self.list_sockets(self.context, kernel.layer_name, kernel.symbol_table_name,
|
||||
netscan_symbol_table, tcpip_module.DllBase, tcpip_symbol_table):
|
||||
|
||||
@@ -13,7 +13,7 @@ from typing import Any, Dict, Generator, List, Optional, Tuple, Union
|
||||
from urllib import parse, request
|
||||
|
||||
from volatility3 import symbols
|
||||
from volatility3.framework import constants, exceptions, interfaces
|
||||
from volatility3.framework import constants, contexts, exceptions, interfaces
|
||||
from volatility3.framework.automagic import symbol_cache
|
||||
from volatility3.framework.configuration import requirements
|
||||
from volatility3.framework.configuration.requirements import SymbolTableRequirement
|
||||
@@ -344,12 +344,46 @@ class PDBUtility(interfaces.configuration.VersionableInterface):
|
||||
|
||||
vollog.debug(f"Found {guid['pdb_name']}: {guid['GUID']}-{guid['age']}")
|
||||
|
||||
return cls.load_windows_symbol_table(context,
|
||||
guid["GUID"],
|
||||
guid["age"],
|
||||
guid["pdb_name"],
|
||||
"volatility3.framework.symbols.intermed.IntermediateSymbolTable",
|
||||
config_path = config_path)
|
||||
module_name = guid["pdb_name"].strip('.pdb')
|
||||
|
||||
symbol_table_name = cls.load_windows_symbol_table(context,
|
||||
guid["GUID"],
|
||||
guid["age"],
|
||||
guid["pdb_name"],
|
||||
"volatility3.framework.symbols.intermed.IntermediateSymbolTable",
|
||||
config_path = config_path)
|
||||
|
||||
new_module_name = None
|
||||
if create_module:
|
||||
new_module = contexts.Module.create(context, module_name, layer_name, offset = guid['mz_offset'],
|
||||
symbol_table_name = symbol_table_name)
|
||||
new_module_name = new_module.name
|
||||
|
||||
return new_module_name, symbol_table_name
|
||||
|
||||
@classmethod
|
||||
def module_from_pdb(cls, context: interfaces.context.ContextInterface, config_path: str, layer_name: str,
|
||||
pdb_name: str, module_offset: int = None, module_size: int = None) -> str:
|
||||
"""Creates a module in the specified layer_name based on a pdb name.
|
||||
|
||||
Searches the memory section of the loaded module for its PDB GUID
|
||||
and loads the associated symbol table into the symbol space.
|
||||
|
||||
Args:
|
||||
context: The context to retrieve required elements (layers, symbol tables) from
|
||||
config_path: The config path where to find symbol files
|
||||
layer_name: The name of the layer on which to operate
|
||||
module_offset: This memory dump's module image offset
|
||||
module_size: The size of the module for this dump
|
||||
|
||||
Returns:
|
||||
The name of the constructed and loaded symbol table
|
||||
"""
|
||||
|
||||
module_name, _ = cls._modtable_from_pdb(context, config_path, layer_name, pdb_name, module_offset,
|
||||
module_size, create_module = True)
|
||||
|
||||
return module_name
|
||||
|
||||
|
||||
class PdbSignatureScanner(interfaces.layers.ScannerInterface):
|
||||
|
||||
@@ -1,11 +1,14 @@
|
||||
import contextlib
|
||||
import logging
|
||||
import struct
|
||||
from typing import List, Iterator, Tuple
|
||||
from typing import List, Iterator, Optional, Tuple, Type
|
||||
|
||||
from volatility3.framework import interfaces, renderers
|
||||
from volatility3.framework import constants, exceptions, interfaces, renderers
|
||||
from volatility3.framework.configuration import requirements
|
||||
from volatility3.framework.symbols.windows.extensions.registry import RegValueTypes
|
||||
from volatility3.plugins.windows.registry import hivelist, printkey
|
||||
|
||||
vollog = logging.getLogger(__name__)
|
||||
|
||||
class Certificates(interfaces.plugins.PluginInterface):
|
||||
"""Lists the certificates in the registry's Certificate Store."""
|
||||
@@ -15,12 +18,14 @@ class Certificates(interfaces.plugins.PluginInterface):
|
||||
@classmethod
|
||||
def get_requirements(cls) -> List[interfaces.configuration.RequirementInterface]:
|
||||
return [
|
||||
requirements.TranslationLayerRequirement(name = 'primary',
|
||||
description = 'Memory layer for the kernel',
|
||||
requirements.ModuleRequirement(name = 'kernel', description = 'Windows kernel',
|
||||
architectures = ["Intel32", "Intel64"]),
|
||||
requirements.SymbolTableRequirement(name = "nt_symbols", description = "Windows kernel symbols"),
|
||||
requirements.PluginRequirement(name = 'hivelist', plugin = hivelist.HiveList, version = (1, 0, 0)),
|
||||
requirements.PluginRequirement(name = 'printkey', plugin = printkey.PrintKey, version = (1, 0, 0))
|
||||
requirements.PluginRequirement(name = 'printkey', plugin = printkey.PrintKey, version = (1, 0, 0)),
|
||||
requirements.BooleanRequirement(name = 'dump',
|
||||
description = "Extract listed certificates",
|
||||
default = False,
|
||||
optional = True)
|
||||
]
|
||||
|
||||
def parse_data(self, data: bytes) -> Tuple[str, bytes]:
|
||||
@@ -34,36 +39,51 @@ class Certificates(interfaces.plugins.PluginInterface):
|
||||
elif ctype == 0x100000020:
|
||||
certificate_data = cvalue
|
||||
return (name, certificate_data)
|
||||
|
||||
@classmethod
|
||||
def dump_certificate(cls, certificate_data: bytes, hive_offset: int,
|
||||
reg_section: str, key_hash: str,
|
||||
open_method: Type[interfaces.plugins.FileHandlerInterface]) -> \
|
||||
Optional[interfaces.plugins.FileHandlerInterface]:
|
||||
try:
|
||||
if not isinstance(certificate_data, interfaces.renderers.BaseAbsentValue):
|
||||
dump_name = "{}-{}-{}.crt".format(hive_offset, reg_section, key_hash)
|
||||
file_handle = open_method(dump_name)
|
||||
file_handle.write(certificate_data)
|
||||
return file_handle
|
||||
except exceptions.InvalidAddressException:
|
||||
vollog.debug(f"Unable to certificate file at {hive_offset:#x}")
|
||||
return None
|
||||
|
||||
|
||||
def _generator(self) -> Iterator[Tuple[int, Tuple[str, str, str, str]]]:
|
||||
kernel = self.context.modules[self.config['kernel']]
|
||||
|
||||
for hive in hivelist.HiveList.list_hives(self.context,
|
||||
base_config_path = self.config_path,
|
||||
layer_name = self.config['primary'],
|
||||
symbol_table = self.config['nt_symbols']):
|
||||
layer_name = kernel.layer_name,
|
||||
symbol_table = kernel.symbol_table_name):
|
||||
|
||||
for top_key in [
|
||||
"Microsoft\\SystemCertificates",
|
||||
"Software\\Microsoft\\SystemCertificates",
|
||||
]:
|
||||
try:
|
||||
with contextlib.suppress(KeyError, exceptions.InvalidAddressException):
|
||||
# Walk it
|
||||
node_path = hive.get_key(top_key, return_list = True)
|
||||
for (depth, is_key, last_write_time, key_path, volatility,
|
||||
node) in printkey.PrintKey.key_iterator(hive, node_path, recurse = True):
|
||||
for (_depth, is_key, _last_write_time, key_path, _volatility, node) in printkey.PrintKey.key_iterator(hive, node_path, recurse = True):
|
||||
if not is_key and RegValueTypes(node.Type).name == "REG_BINARY":
|
||||
name, certificate_data = self.parse_data(node.decode_data())
|
||||
unique_key_offset = key_path.casefold().index(top_key.casefold()) + len(top_key) + 1
|
||||
reg_section = key_path[unique_key_offset:key_path.index("\\", unique_key_offset)]
|
||||
key_hash = key_path[key_path.rindex("\\") + 1:]
|
||||
|
||||
if not isinstance(certificate_data, interfaces.renderers.BaseAbsentValue):
|
||||
with self.open("{} - {} - {}.crt".format(hex(hive.hive_offset), reg_section,
|
||||
key_hash)) as file_data:
|
||||
file_data.write(certificate_data)
|
||||
if self.config['dump']:
|
||||
file_handle = self.dump_certificate(certificate_data, hive.hive_offset, reg_section, key_hash, self.open)
|
||||
if file_handle:
|
||||
file_handle.close()
|
||||
|
||||
yield (0, (top_key, reg_section, key_hash, name))
|
||||
except KeyError:
|
||||
# Key wasn't found in this hive, carry on
|
||||
pass
|
||||
|
||||
def run(self) -> renderers.TreeGrid:
|
||||
return renderers.TreeGrid([("Certificate path", str), ("Certificate section", str), ("Certificate ID", str),
|
||||
|
||||
Reference in New Issue
Block a user