Repository: volatilityfoundation/volatility3 (language: python)

Issue:
Update the modules.Modules version requirement.
This is a response to PR [#1173](https://github.com/volatilityfoundation/volatility3/pull/1173)
Handles unable to process sample Volatility 2 reports correctly. UnionType error?
**Describe the bug**
Running windows.handles on a memory sample that Volatility 2 supports fully causes a strange backtrace in Vol3:

```
# python3.8 vol.py -f data.lime windows.handles --pid 3704
Volatility 3 Framework 2.7.0
Progress:  100.00		PDB scanning finished                        
PID	Process	Offset	HandleValue	Type	GrantedAccess	Name
Traceback (most recent call last):
  File "/home/analyst/vol3/volatility3/framework/plugins/windows/handles.py", line 91, in _get_item
    if not self.context.layers[virtual].is_valid(handle_table_entry.Object):
  File "/home/analyst/vol3/volatility3/framework/objects/__init__.py", line 971, in __getattr__
    raise AttributeError(
AttributeError: UnionType has no attribute: symbol_table_name1!_HANDLE_TABLE_ENTRY.Object

During handling of the above exception, another exception occurred:

Traceback (most recent call last):
  File "vol.py", line 10, in <module>
    volatility3.cli.main()
  File "/home/analyst/vol3/volatility3/cli/__init__.py", line 871, in main
    CommandLine().run()
  File "/home/analyst/vol3/volatility3/cli/__init__.py", line 469, in run
    renderer.render(grid)
  File "/home/analyst/vol3/volatility3/cli/text_renderer.py", line 198, in render
    grid.populate(visitor, outfd)
  File "/home/analyst/vol3/volatility3/framework/renderers/__init__.py", line 245, in populate
    for level, item in self._generator:
  File "/home/analyst/vol3/volatility3/framework/plugins/windows/handles.py", line 378, in _generator
    for entry in self.handles(object_table):
  File "/home/analyst/vol3/volatility3/framework/plugins/windows/handles.py", line 348, in handles
    for handle_table_entry in self._make_handle_array(TableCode, table_levels):
  File "/home/analyst/vol3/volatility3/framework/plugins/windows/handles.py", line 311, in _make_handle_array
    for x in self._make_handle_array(entry, level - 1, depth):
  File "/home/analyst/vol3/volatility3/framework/plugins/windows/handles.py", line 323, in _make_handle_array
    item = self._get_item(entry, handle_value)
  File "/home/analyst/vol3/volatility3/framework/plugins/windows/handles.py", line 111, in _get_item
    raise AttributeError(
AttributeError: Unable to find the SAR value for decoding handle table pointers

```

**Context**
Volatility Version:  latest develop
Python Version:  3.8




Can't detect windows on develop branch which works on v1.0.1
**Describe the bug**
A clear and concise description of what the bug is.

**Context**
Volatility Version: 4cb71366c787a079b8a6c31324630e1d1cf25862
Operating System:  Linux
Python Version: Python 3.6.8 
Suspected Operating System: Windows 10  
Command:  python3 vol.py  -vvv -f windows10.memory.dump windows.info

**To Reproduce**
Steps to reproduce the behavior:

```bash
# python3 vol.py  -vvv -f windows10.memory.dump windows.info
Volatility 3 Framework 1.0.1
INFO     volatility3.cli: Volatility plugins path: ['/root/forensics-cnv/volatility3/volatility3/plugins', '/root/forensics-cnv/volatility3/volatility3/framework/plugins']
INFO     volatility3.cli: Volatility symbols path: ['/root/forensics-cnv/volatility3/volatility3/symbols', '/root/forensics-cnv/volatility3/volatility3/framework/symbols']
INFO     volatility3.framework.automagic: Detected a windows category plugin
INFO     volatility3.framework.automagic: Running automagic: ConstructionMagic
Level 9  volatility3.framework.configuration.requirements: IndexError - No configuration provided: plugins.Info.primary
Level 9  volatility3.framework.configuration.requirements: Symbol table requirement not yet fulfilled: plugins.Info.nt_symbols
Level 9  volatility3.framework.configuration.requirements: IndexError - No configuration provided: plugins.Info.primary
Level 9  volatility3.framework.automagic.construct_layers: Failed on requirement: plugins.Info.primary
Level 9  volatility3.framework.configuration.requirements: IndexError - No configuration provided: plugins.Info.primary
Level 9  volatility3.framework.automagic.construct_layers: Failed on requirement: plugins.Info
Level 9  volatility3.framework.configuration.requirements: Symbol table requirement not yet fulfilled: plugins.Info.nt_symbols
Level 9  volatility3.framework.automagic.construct_layers: Failed on requirement: plugins.Info.nt_symbols
Level 9  volatility3.framework.configuration.requirements: Symbol table requirement not yet fulfilled: plugins.Info.nt_symbols
Level 9  volatility3.framework.automagic.construct_layers: Failed on requirement: plugins.Info
INFO     volatility3.framework.automagic: Running automagic: LayerStacker
Level 9  volatility3.framework.configuration.requirements: IndexError - No configuration provided: plugins.Info.primary
Level 9  volatility3.framework.configuration.requirements: Symbol table requirement not yet fulfilled: plugins.Info.nt_symbols
DEBUG    volatility3.framework.automagic.windows: DTB was found at: 0x1aa000
Level 9  volatility3.framework.configuration.requirements: IndexError - No configuration provided: plugins.Info.primary
Level 9  volatility3.framework.configuration.requirements: IndexError - No configuration provided: plugins.Info.primary
Level 9  volatility3.framework.configuration.requirements: Symbol table requirement not yet fulfilled: plugins.Info.nt_symbols
Level 9  volatility3.framework.configuration.requirements: IndexError - No configuration provided: plugins.Info.primary
Level 9  volatility3.framework.configuration.requirements: IndexError - No configuration provided: plugins.Info.primary.memory_layer
Level 9  volatility3.framework.configuration.requirements: IndexError - No configuration provided: plugins.Info.primary.memory_layer.base_layer
Level 9  volatility3.framework.interfaces.configuration: TypeError - kernel_virtual_offset requirements only accept int type: None
Level 9  volatility3.framework.interfaces.configuration: TypeError - kernel_virtual_offset requirements only accept int type: None
Level 9  volatility3.framework.interfaces.configuration: TypeError - kernel_banner requirements only accept str type: None
Level 9  volatility3.framework.interfaces.configuration: TypeError - kernel_banner requirements only accept str type: None
Level 9  volatility3.framework.configuration.requirements: Symbol table requirement not yet fulfilled: plugins.Info.nt_symbols
Level 9  volatility3.framework.automagic.construct_layers: Failed on requirement: plugins.Info.nt_symbols
Level 9  volatility3.framework.configuration.requirements: Symbol table requirement not yet fulfilled: plugins.Info.nt_symbols
Level 9  volatility3.framework.automagic.construct_layers: Failed on requirement: plugins.Info
DEBUG    volatility3.framework.automagic.stacker: Stacked layers: ['IntelLayer', 'Elf64Layer', 'FileLayer']
INFO     volatility3.framework.automagic: Running automagic: WinSwapLayers
INFO     volatility3.framework.automagic: Running automagic: WintelHelper
INFO     volatility3.framework.automagic: Running automagic: KernelPDBScanner
Level 9  volatility3.framework.configuration.requirements: Symbol table requirement not yet fulfilled: plugins.Info.nt_symbols
Level 9  volatility3.framework.configuration.requirements: Symbol table requirement not yet fulfilled: plugins.Info.nt_symbols
Level 9  volatility3.framework.configuration.requirements: Symbol table requirement not yet fulfilled: plugins.Info.nt_symbols
DEBUG    volatility3.framework.automagic.pdbscan: Kernel base determination - searching layer module list structure
DEBUG    volatility3.framework.automagic.pdbscan: Kernel base determination - searching layer module list structure
DEBUG    volatility3.framework.automagic.pdbscan: Kernel base determination - testing fixed base address
DEBUG    volatility3.framework.automagic.pdbscan: Potential kernel_virtual_offset caused a page fault: 0xf80000108000
DEBUG    volatility3.framework.automagic.pdbscan: Kernel base determination - slow scan virtual layer
INFO     volatility3.framework.automagic.pdbscan: No suitable kernels found during pdbscan
Level 9  volatility3.framework.configuration.requirements: Symbol table requirement not yet fulfilled: plugins.Info.nt_symbols

Unsatisfied requirement plugins.Info.nt_symbols: Windows kernel symbols

A symbol table requirement was not fulfilled.  Please verify that:
	You have the correct symbol file for the requirement
	The symbol file is under the correct directory or zip file
	The symbol file is named appropriately or contains the correct banner

Unable to validate the plugin requirements: ['plugins.Info.nt_symbols']
```

**Expected behavior**
This works perfect on `v1.0.1`:

```bash
# python3 vol.py  -vvv -f windows10.memory.dump windows.info
Volatility 3 Framework 1.0.1
INFO     root        : Volatility plugins path: ['/root/forensics-cnv/volatility3/volatility3/plugins', '/root/forensics-cnv/volatility3/volatility3/framework/plugins']
INFO     root        : Volatility symbols path: ['/root/forensics-cnv/volatility3/volatility3/symbols', '/root/forensics-cnv/volatility3/volatility3/framework/symbols']
INFO     volatility3.framework.automagic: Detected a windows category plugin
INFO     volatility3.framework.automagic: Running automagic: ConstructionMagic
Level 9  volatility3.framework.configuration.requirements: IndexError - No configuration provided: plugins.Info.primary
Level 9  volatility3.framework.configuration.requirements: Symbol table requirement not yet fulfilled: plugins.Info.nt_symbols
Level 9  volatility3.framework.configuration.requirements: IndexError - No configuration provided: plugins.Info.primary
Level 9  volatility3.framework.automagic.construct_layers: Failed on requirement: plugins.Info.primary
Level 9  volatility3.framework.configuration.requirements: IndexError - No configuration provided: plugins.Info.primary
Level 9  volatility3.framework.automagic.construct_layers: Failed on requirement: plugins.Info
Level 9  volatility3.framework.configuration.requirements: Symbol table requirement not yet fulfilled: plugins.Info.nt_symbols
Level 9  volatility3.framework.automagic.construct_layers: Failed on requirement: plugins.Info.nt_symbols
Level 9  volatility3.framework.configuration.requirements: Symbol table requirement not yet fulfilled: plugins.Info.nt_symbols
Level 9  volatility3.framework.automagic.construct_layers: Failed on requirement: plugins.Info
INFO     volatility3.framework.automagic: Running automagic: LayerStacker
Level 9  volatility3.framework.configuration.requirements: IndexError - No configuration provided: plugins.Info.primary
Level 9  volatility3.framework.configuration.requirements: Symbol table requirement not yet fulfilled: plugins.Info.nt_symbols
DEBUG    volatility3.framework.automagic.windows: Self-referential pointer not in well-known location, moving to recent windows heuristic
DEBUG    volatility3.framework.automagic.windows: DTB was found at: 0x1aa000
Level 9  volatility3.framework.configuration.requirements: IndexError - No configuration provided: plugins.Info.primary
Level 9  volatility3.framework.configuration.requirements: IndexError - No configuration provided: plugins.Info.primary
Level 9  volatility3.framework.configuration.requirements: Symbol table requirement not yet fulfilled: plugins.Info.nt_symbols
Level 9  volatility3.framework.configuration.requirements: IndexError - No configuration provided: plugins.Info.primary
Level 9  volatility3.framework.configuration.requirements: IndexError - No configuration provided: plugins.Info.primary.memory_layer
Level 9  volatility3.framework.configuration.requirements: IndexError - No configuration provided: plugins.Info.primary.memory_layer.base_layer
Level 9  volatility3.framework.interfaces.configuration: TypeError - kernel_virtual_offset requirements only accept int type: None
Level 9  volatility3.framework.interfaces.configuration: TypeError - kernel_virtual_offset requirements only accept int type: None
Level 9  volatility3.framework.interfaces.configuration: TypeError - kernel_banner requirements only accept str type: None
Level 9  volatility3.framework.interfaces.configuration: TypeError - kernel_banner requirements only accept str type: None
Level 9  volatility3.framework.configuration.requirements: Symbol table requirement not yet fulfilled: plugins.Info.nt_symbols
Level 9  volatility3.framework.automagic.construct_layers: Failed on requirement: plugins.Info.nt_symbols
Level 9  volatility3.framework.configuration.requirements: Symbol table requirement not yet fulfilled: plugins.Info.nt_symbols
Level 9  volatility3.framework.automagic.construct_layers: Failed on requirement: plugins.Info
DEBUG    volatility3.framework.automagic.stacker: Stacked layers: ['IntelLayer', 'Elf64Layer', 'FileLayer']
INFO     volatility3.framework.automagic: Running automagic: WinSwapLayers
INFO     volatility3.framework.automagic: Running automagic: WintelHelper
INFO     volatility3.framework.automagic: Running automagic: KernelPDBScanner
Level 9  volatility3.framework.configuration.requirements: Symbol table requirement not yet fulfilled: plugins.Info.nt_symbols
Level 9  volatility3.framework.configuration.requirements: Symbol table requirement not yet fulfilled: plugins.Info.nt_symbols
Level 9  volatility3.framework.configuration.requirements: Symbol table requirement not yet fulfilled: plugins.Info.nt_symbols
DEBUG    volatility3.framework.automagic.pdbscan: Kernel base determination - searching layer module list structure
DEBUG    volatility3.framework.automagic.pdbscan: Kernel base determination - searching layer module list structure
DEBUG    volatility3.framework.symbols.windows.pdbutil: Using symbol library: ntkrnlmp.pdb/8B11040A5928757B11390AC78F6B6925-1
DEBUG    volatility3.framework.automagic.pdbscan: Setting kernel_virtual_offset to 0xf80538eb4000
Progress:  100.00		PDB scanning finished                     
Variable	Value

Kernel Base	0xf80538eb4000
DTB	0x1aa000
Symbols	file:///root/forensics-cnv/volatility3/volatility3/symbols/windows/ntkrnlmp.pdb/8B11040A5928757B11390AC78F6B6925-1.json.xz
Is64Bit	True
IsPAE	False
primary	0 WindowsIntel32e
memory_layer	1 Elf64Layer
base_layer	2 FileLayer
KdVersionBlock	0xf805392b6dc0
Major/Minor	15.17763
MachineType	34404
KeNumberProcessors	1
SystemTime	2021-05-18 20:38:06
NtSystemRoot	C:\Windows
NtProductType	NtProductWinNt
NtMajorVersion	10
NtMinorVersion	0
PE MajorOperatingSystemVersion	10
PE MinorOperatingSystemVersion	0
PE Machine	34404
PE TimeDateStamp	Thu Oct 28 12:04:50 2060
```

**Screenshots**
If applicable, add screenshots to help explain your problem.

**Additional information**
Add any other information about the problem here.

Missing plugin -> unloadedmodules
Volatility 2 plugin unloadedmodules missing in volatility 3
Missing Plugin -> threads
As of volatility version 2 there were the three plugins: threads, timers and devicetree. I didn't find these plugins in the new version. Do you have plans to bring them back in or are these plugins by community developers?


Missing Plugin -> threads
As of volatility version 2 there were the three plugins: threads, timers and devicetree. I didn't find these plugins in the new version. Do you have plans to bring them back in or are these plugins by community developers?


Missing Plugin -> threads
As of volatility version 2 there were the three plugins: threads, timers and devicetree. I didn't find these plugins in the new version. Do you have plans to bring them back in or are these plugins by community developers?


Page error in layer when dumping Windows 10 hashes
**Describe the bug**
After commit e5a5b895771b655d21c36689c33a534034c31e36, volatility is no longer able to run various modules on a memory dump from a Windows 10 system, such as windows.hashdump.Hashdump and windows.info.Info.

**Context**
Volatility Version:  Commit e5a5b895771b655d21c36689c33a534034c31e36 and later
Operating System:  Linux
Python Version:  3.12.3
Suspected Operating System:  Windows 10
Command:  `python vol.py -f memory.dmp -vvv windows.hashdump.Hashdump`

**To Reproduce**
Steps to reproduce the behavior:

```
git bisect start
git bisect bad develop
git bisect good 55dd39f2
git bisect run python vol.py -f memory.dmp windows.hashdump.Hashdump
```

**Example output**
```
python vol.py -f memory.dmp -vvv windows.hashdump.Hashdump
Volatility 3 Framework 2.7.1
INFO     volatility3.cli: Volatility plugins path: ['/home/ctf/volatility3/volatility3/plugins', '/home/ctf/volatility3/volatility3/framework/plugins']
INFO     volatility3.cli: Volatility symbols path: ['/home/ctf/volatility3/volatility3/symbols', '/home/ctf/volatility3/volatility3/framework/symbols']
INFO     volatility3.framework.automagic: Detected a windows category plugin
INFO     volatility3.framework.automagic: Running automagic: ConstructionMagic
DETAIL 1 volatility3.framework.configuration.requirements: IndexError - No configuration provided: plugins.Hashdump.kernel.layer_name
DETAIL 1 volatility3.framework.configuration.requirements: Symbol table requirement not yet fulfilled: plugins.Hashdump.kernel.symbol_table_name
DETAIL 1 volatility3.framework.configuration.requirements: IndexError - No configuration provided: plugins.Hashdump.kernel.layer_name
DETAIL 1 volatility3.framework.configuration.requirements: Symbol table requirement not yet fulfilled: plugins.Hashdump.kernel.symbol_table_name
DETAIL 1 volatility3.framework.automagic.construct_layers: Failed on requirement: plugins.Hashdump.kernel
DETAIL 1 volatility3.framework.configuration.requirements: IndexError - No configuration provided: plugins.Hashdump.kernel.layer_name
DETAIL 1 volatility3.framework.automagic.construct_layers: Failed on requirement: plugins.Hashdump.kernel.layer_name
DETAIL 1 volatility3.framework.configuration.requirements: IndexError - No configuration provided: plugins.Hashdump.kernel.layer_name
DETAIL 1 volatility3.framework.automagic.construct_layers: Failed on requirement: plugins.Hashdump.kernel
DETAIL 1 volatility3.framework.configuration.requirements: Symbol table requirement not yet fulfilled: plugins.Hashdump.kernel.symbol_table_name
DETAIL 1 volatility3.framework.automagic.construct_layers: Failed on requirement: plugins.Hashdump.kernel.symbol_table_name
DETAIL 1 volatility3.framework.configuration.requirements: Symbol table requirement not yet fulfilled: plugins.Hashdump.kernel.symbol_table_name
DETAIL 1 volatility3.framework.automagic.construct_layers: Failed on requirement: plugins.Hashdump.kernel
DETAIL 1 volatility3.framework.configuration.requirements: IndexError - No configuration provided: plugins.Hashdump.kernel.layer_name
DETAIL 1 volatility3.framework.configuration.requirements: Symbol table requirement not yet fulfilled: plugins.Hashdump.kernel.symbol_table_name
DETAIL 1 volatility3.framework.automagic.construct_layers: Failed on requirement: plugins.Hashdump
INFO     volatility3.framework.automagic: Running automagic: SymbolCacheMagic
INFO     volatility3.framework.automagic: Running automagic: LayerStacker
DETAIL 1 volatility3.framework.configuration.requirements: IndexError - No configuration provided: plugins.Hashdump.kernel.layer_name
DETAIL 1 volatility3.framework.configuration.requirements: Symbol table requirement not yet fulfilled: plugins.Hashdump.kernel.symbol_table_name
DEBUG    volatility3.framework.automagic.windows: Detecting Self-referential pointer for recent windows
DEBUG    volatility3.framework.automagic.windows: DtbSelfRef64bit test succeeded at 0x1ad000
DEBUG    volatility3.framework.automagic.windows: DTB was found at: 0x1ad000
DETAIL 1 volatility3.framework.configuration.requirements: IndexError - No configuration provided: plugins.Hashdump.kernel.layer_name
DETAIL 1 volatility3.framework.configuration.requirements: IndexError - No configuration provided: plugins.Hashdump.kernel.layer_name
DETAIL 1 volatility3.framework.configuration.requirements: Symbol table requirement not yet fulfilled: plugins.Hashdump.kernel.symbol_table_name
DETAIL 1 volatility3.framework.configuration.requirements: IndexError - No configuration provided: plugins.Hashdump.kernel.layer_name
DETAIL 1 volatility3.framework.configuration.requirements: Symbol table requirement not yet fulfilled: plugins.Hashdump.kernel.symbol_table_name
DETAIL 1 volatility3.framework.automagic.construct_layers: Failed on requirement: plugins.Hashdump.kernel
DETAIL 1 volatility3.framework.configuration.requirements: IndexError - No configuration provided: plugins.Hashdump.kernel.layer_name
DETAIL 1 volatility3.framework.configuration.requirements: IndexError - No configuration provided: plugins.Hashdump.kernel.layer_name.memory_layer
DETAIL 1 volatility3.framework.configuration.requirements: IndexError - No configuration provided: plugins.Hashdump.kernel.layer_name.memory_layer.base_layer
DETAIL 1 volatility3.framework.interfaces.configuration: TypeError - kernel_virtual_offset requirements only accept int type: None
DETAIL 1 volatility3.framework.interfaces.configuration: TypeError - kernel_virtual_offset requirements only accept int type: None
DETAIL 1 volatility3.framework.interfaces.configuration: TypeError - kernel_banner requirements only accept str type: None
DETAIL 1 volatility3.framework.interfaces.configuration: TypeError - kernel_banner requirements only accept str type: None
DETAIL 1 volatility3.framework.configuration.requirements: Symbol table requirement not yet fulfilled: plugins.Hashdump.kernel.symbol_table_name
DETAIL 1 volatility3.framework.automagic.construct_layers: Failed on requirement: plugins.Hashdump.kernel.symbol_table_name
DETAIL 1 volatility3.framework.configuration.requirements: Symbol table requirement not yet fulfilled: plugins.Hashdump.kernel.symbol_table_name
DETAIL 1 volatility3.framework.automagic.construct_layers: Failed on requirement: plugins.Hashdump.kernel
DETAIL 1 volatility3.framework.configuration.requirements: Symbol table requirement not yet fulfilled: plugins.Hashdump.kernel.symbol_table_name
DETAIL 1 volatility3.framework.automagic.construct_layers: Failed on requirement: plugins.Hashdump
DEBUG    volatility3.framework.automagic.stacker: physical_layer maximum_address: 1073750015
DEBUG    volatility3.framework.automagic.stacker: Stacked layers: ['IntelLayer', 'WindowsCrashDump64Layer', 'FileLayer']
INFO     volatility3.framework.automagic: Running automagic: WinSwapLayers
INFO     volatility3.framework.automagic: Running automagic: KernelPDBScanner
DETAIL 1 volatility3.framework.configuration.requirements: Symbol table requirement not yet fulfilled: plugins.Hashdump.kernel.symbol_table_name
DETAIL 1 volatility3.framework.configuration.requirements: Symbol table requirement not yet fulfilled: plugins.Hashdump.kernel.symbol_table_name
DETAIL 1 volatility3.framework.configuration.requirements: Symbol table requirement not yet fulfilled: plugins.Hashdump.kernel.symbol_table_name
DEBUG    volatility3.framework.automagic.pdbscan: Kernel base determination - searching layer module list structure
DEBUG    volatility3.framework.automagic.pdbscan: Setting kernel_virtual_offset to 0xf8043b209000
DEBUG    volatility3.framework.symbols.windows.pdbutil: Using symbol library: ntkrnlmp.pdb/68A17FAF3012B7846079AEECDBE0A583-1
INFO     volatility3.framework.automagic: Running automagic: SymbolFinder
INFO     volatility3.framework.automagic: Running automagic: KernelModule
DEBUG    volatility3.framework.symbols: Unresolved reference: symbol_table_name1!_JOB_ACCESS_STATE
DEBUG    volatility3.framework.symbols: Unresolved reference: symbol_table_name1!_JOB_CPU_RATE_CONTROL
DEBUG    volatility3.framework.symbols: Unresolved reference: symbol_table_name1!_JOB_NET_RATE_CONTROL
DEBUG    volatility3.framework.symbols: Unresolved reference: symbol_table_name1!_JOB_NOTIFICATION_INFORMATION
DEBUG    volatility3.framework.symbols: Unresolved reference: symbol_table_name1!_PSP_STORAGE
DEBUG    volatility3.framework.symbols: Unresolved reference: symbol_table_name1!_KTMNOTIFICATION_PACKET
DEBUG    volatility3.framework.symbols: Unresolved reference: symbol_table_name1!_EXP_LICENSE_STATE
DEBUG    volatility3.framework.symbols: Unresolved reference: symbol_table_name1!_DBGKP_ERROR_PORT
DEBUG    volatility3.framework.symbols: Unresolved reference: symbol_table_name1!_CI_NGEN_PATHS
DEBUG    volatility3.framework.symbols: Unresolved reference: symbol_table_name1!_EX_WNF_SUBSCRIPTION
DEBUG    volatility3.framework.symbols: Unresolved reference: symbol_table_name1!_PO_PROCESS_ENERGY_CONTEXT
DEBUG    volatility3.framework.symbols: Unresolved reference: symbol_table_name1!_EPROCESS_QUOTA_BLOCK
DEBUG    volatility3.framework.symbols: Unresolved reference: symbol_table_name1!_PAGEFAULT_HISTORY
DEBUG    volatility3.framework.symbols: Unresolved reference: symbol_table_name1!_DEVICE_NODE_IOMMU_EXTENSION
DEBUG    volatility3.framework.symbols: Unresolved reference: symbol_table_name1!_ETW_EVENT_CALLBACK_CONTEXT
DEBUG    volatility3.framework.symbols: Unresolved reference: symbol_table_name1!_ETW_SOFT_RESTART_CONTEXT
DEBUG    volatility3.framework.symbols: Unresolved reference: symbol_table_name1!_ETW_STACK_CACHE
DEBUG    volatility3.framework.symbols: Unresolved reference: symbol_table_name1!_ACTIVATION_CONTEXT_DATA
DEBUG    volatility3.framework.symbols: Unresolved reference: symbol_table_name1!_ASSEMBLY_STORAGE_MAP
DEBUG    volatility3.framework.symbols: Unresolved reference: symbol_table_name1!_ETW_PERFECT_HASH_FUNCTION
DEBUG    volatility3.framework.symbols: Unresolved reference: symbol_table_name1!_EX_TIMER
DEBUG    volatility3.framework.symbols: Unresolved reference: symbol_table_name1!_HAL_PMC_COUNTERS
DEBUG    volatility3.framework.symbols: Unresolved reference: symbol_table_name1!_SCSI_REQUEST_BLOCK

User    rid     lmhash  nthash


DEBUG    volatility3.cli: Traceback (most recent call last):
  File "/home/ctf/volatility3/volatility3/cli/__init__.py", line 469, in run
    renderer.render(grid)
  File "/home/ctf/volatility3/volatility3/cli/text_renderer.py", line 198, in render
    grid.populate(visitor, outfd)
  File "/home/ctf/volatility3/volatility3/framework/renderers/__init__.py", line 245, in populate
    for level, item in self._generator:
  File "/home/ctf/volatility3/volatility3/framework/plugins/windows/hashdump.py", line 570, in _generator
    bootkey = self.get_bootkey(syshive)
              ^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/home/ctf/volatility3/volatility3/framework/plugins/windows/hashdump.py", line 359, in get_bootkey
    lsa = cls.get_hive_key(syshive, lsa_base)
          ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/home/ctf/volatility3/volatility3/framework/plugins/windows/hashdump.py", line 334, in get_hive_key
    result = hive.get_key(key)
             ^^^^^^^^^^^^^^^^^
  File "/home/ctf/volatility3/volatility3/framework/layers/registry.py", line 174, in get_key
    root_node = self.get_node(self.root_cell_offset)
                ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/home/ctf/volatility3/volatility3/framework/layers/registry.py", line 143, in get_node
    signature = cell.cast("string", max_length=2, encoding="latin-1")
                ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/home/ctf/volatility3/volatility3/framework/interfaces/objects.py", line 189, in cast
    return object_template(context=self._context, object_info=object_info)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/home/ctf/volatility3/volatility3/framework/objects/templates.py", line 96, in __call__
    return self.vol.object_class(
           ^^^^^^^^^^^^^^^^^^^^^^
  File "/home/ctf/volatility3/volatility3/framework/objects/__init__.py", line 352, in __new__
    cls._unmarshall(
  File "/home/ctf/volatility3/volatility3/framework/objects/__init__.py", line 202, in _unmarshall
    data = context.layers.read(
           ^^^^^^^^^^^^^^^^^^^^
  File "/home/ctf/volatility3/volatility3/framework/interfaces/layers.py", line 638, in read
    return self[layer].read(offset, length, pad)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/home/ctf/volatility3/volatility3/framework/layers/linear.py", line 63, in read
    self._context.layers.read(layer, mapped_offset, mapped_length, pad)
  File "/home/ctf/volatility3/volatility3/framework/interfaces/layers.py", line 638, in read
    return self[layer].read(offset, length, pad)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/home/ctf/volatility3/volatility3/framework/layers/linear.py", line 45, in read
    for offset, _, mapped_offset, mapped_length, layer in self.mapping(
  File "/home/ctf/volatility3/volatility3/framework/layers/intel.py", line 295, in mapping
    for offset, size, mapped_offset, mapped_size, map_layer in self._mapping(
  File "/home/ctf/volatility3/volatility3/framework/layers/intel.py", line 351, in _mapping
    chunk_offset, page_size, layer_name = self._translate(offset)
                                          ^^^^^^^^^^^^^^^^^^^^^^^
  File "/home/ctf/volatility3/volatility3/framework/layers/intel.py", line 503, in _translate
    return self._translate_swap(self, offset, self._bits_per_register // 2)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/home/ctf/volatility3/volatility3/framework/layers/intel.py", line 450, in _translate_swap
    return super()._translate(offset)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/home/ctf/volatility3/volatility3/framework/layers/intel.py", line 155, in _translate
    entry, position = self._translate_entry(offset)
                      ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/home/ctf/volatility3/volatility3/framework/layers/intel.py", line 184, in _translate_entry
    raise exceptions.PagedInvalidAddressException(
volatility3.framework.exceptions.PagedInvalidAddressException: Entry outside virtual address range: 0x55fe001

Volatility was unable to read a requested page:
Page error 0xffffc60795389024 in layer layer_name_Process92_1 (Entry outside virtual address range: 0x55fe001)

        * Memory smear during acquisition (try re-acquiring if possible)
        * An intentionally invalid page lookup (operating system protection)
        * A bug in the plugin/volatility3 (re-run with -vvv and file a bug)

No further results will be produced
```

**Additional information**
memory.dmp: https://www.mediafire.com/file/c0v7xmu0f6kq2lr/memory.dmp.gz/file
Missing Plugin -> threads
As of volatility version 2 there were the three plugins: threads, timers and devicetree. I didn't find these plugins in the new version. Do you have plans to bring them back in or are these plugins by community developers?


Missing plugin -> unloadedmodules
Volatility 2 plugin unloadedmodules missing in volatility 3
Missing Plugin -> threads
As of volatility version 2 there were the three plugins: threads, timers and devicetree. I didn't find these plugins in the new version. Do you have plans to bring them back in or are these plugins by community developers?


Missing Plugin -> threads
As of volatility version 2 there were the three plugins: threads, timers and devicetree. I didn't find these plugins in the new version. Do you have plans to bring them back in or are these plugins by community developers?


Windows: add extra debugging messages to handles plugin
Hello 👋 

This is hopefully a simple PR to add more debugging messages to the windows handles plugin. It does **not** fix https://github.com/volatilityfoundation/volatility3/issues/1146 but would help debug the issue or similar issues in the future.

Particularly if the read fails as ObpCaptureHandleInformationEx is paged out - I can see that happening again in the future - which could cause some confusion. 

Thanks! 
🦊  
format_hints throws TypeError when using UnreadableValue
When format_hints parses as UnreadableValue it can throw a TypeError which stops a plugin continues. 

The expected result is that the format_hints does not cause a crash, but instead allow the UnreadableValue etc through so that they are displayed in the results. 

Here is a volshell example:
```python
(primary) >>> from volatility3.framework.renderers import format_hints, UnreadableValue
(primary) >>> offset = UnreadableValue()
(primary) >>> format_hints.Hex(offset) 
Traceback (most recent call last):
  File "<console>", line 1, in <module>
TypeError: int() argument must be a string, a bytes-like object or a real number, not 'UnreadableValue'
(primary) >>> offset = 1
(primary) >>> format_hints.Hex(offset)
1
```

This is also discussed briefly here https://github.com/volatilityfoundation/volatility3/issues/591#issuecomment-2247551726 
Windows: Bug fixes and additions to modules and modscan
This pull request adds several changes to the modules and modscan plugins that fix bugs, unify options and operations, and allow for filtering by name and base address in both plugins. Previously, modscan and modules had a substantial amount of partially duplicated code, which led to bugs, such as:
	Only one allowed filtering by --name
	Only one cycled through the session layers to find the one hosting the kernel module
With the new inheritance and combined implementation, the correct and complete implementation applies to both.

This PR also addresses the feedback in
https://github.com/volatilityfoundation/volatility3/pull/1099. In this PR, --name and –base apply to the processing of modules and determine both which plugins are displayed in output as well as which are processed for extraction. This fixes the issue of using --filters, which only filters the final command line output, but leads to every module being extracted.


Discussion / hints:


Hmmm, interesting.  Are you comfortable carrying out git bisections?  If not, would you be able to share the memory image you're having trouble with (or a similar one that exhibits the issue)?  It looks like the scanner for the module list is no longer finding the list when it used to, but I don't think that code has changed significantly, so it would be good to track down what the exact change that causes the issue is...
Hiya, this might also have been a very recent issue related to scanning for Windows 64 self-referential entries in the DTB.  I found that a PAE image I had was throwing up possible self-refenetial pointers in the region we now scan (which has increased recently as Windows 10 no longer uses a fix pointer, but one that moves within a range which we now scan).  I've try to combat these false positives because in my example every entry in the page was marked as valid (which is highly unlikely for a non-PAE DTB).

As such, it would be extremely helpful if you could test the following two things:
* Does the develop branch now (after having reverted the recent changes) work with your troublesome image?
* If so, does the branch for #511 also work as expected?

If both are yes, then it looks like we've got a solution.  If the first one is no, or the first is yes and the second no, then I'll probably still need the image to figure out what's going wrong... 5:S
> * Does the develop branch now (after having reverted the recent changes) work with your troublesome image?

Current develop branch does not work.

> * If so, does the branch for #511 also work as expected?

Does not work either.

I think I can share the image. Asking now.
Ok, thanks.  I think at this point we'll need the image make much further progress...
Sorry for the delay. I have issues uploading the dump as a zip file.
Hi guys, I may have stomp on the same issue.
The image generating that hang on the PdbSignatureScanner is a Microsoft Developer Environment virtual machine. 
https://developer.microsoft.com/en-us/windows/downloads/virtual-machines/

Hmmm, @k0l0ss thanks for the link, but that seems to be to virtual machines rather than a memory image.  Since they're from a public source, would you be willing to get a memory image that exhibits the problem and share it with us?  It's really tricky to diagnose these problems without a sample that we know exhibits the issue...
@k0l0ss Any progress on this?  Does the issue still happen with the latest version?
I'm going to mark this as closed, given there's been no response in three months.  Feel free to reopen this, or a file a new ticket if it's still an issue with 2.0.0

I believe we just haven't gotten to those yet, I think they were all core plugins of volatility2.  I've given this to the developer that made the previous ones, so we can find out directly the intention for those...  5:)
Thanks for your quick reply!
Hello @mrratherford,
This time, I developed DeviceTree Plugin, one of the requests covered in this issue.
It was finally merged in the `develop` branch, so I would appreciate it if you could give me feedback after using it. 🙌
I believe we just haven't gotten to those yet, I think they were all core plugins of volatility2.  I've given this to the developer that made the previous ones, so we can find out directly the intention for those...  5:)
Thanks for your quick reply!
Hello @mrratherford,
This time, I developed DeviceTree Plugin, one of the requests covered in this issue.
It was finally merged in the `develop` branch, so I would appreciate it if you could give me feedback after using it. 🙌
I believe we just haven't gotten to those yet, I think they were all core plugins of volatility2.  I've given this to the developer that made the previous ones, so we can find out directly the intention for those...  5:)
Thanks for your quick reply!
Hello @mrratherford,
This time, I developed DeviceTree Plugin, one of the requests covered in this issue.
It was finally merged in the `develop` branch, so I would appreciate it if you could give me feedback after using it. 🙌

I believe we just haven't gotten to those yet, I think they were all core plugins of volatility2.  I've given this to the developer that made the previous ones, so we can find out directly the intention for those...  5:)
Thanks for your quick reply!
Hello @mrratherford,
This time, I developed DeviceTree Plugin, one of the requests covered in this issue.
It was finally merged in the `develop` branch, so I would appreciate it if you could give me feedback after using it. 🙌

I believe we just haven't gotten to those yet, I think they were all core plugins of volatility2.  I've given this to the developer that made the previous ones, so we can find out directly the intention for those...  5:)
Thanks for your quick reply!
Hello @mrratherford,
This time, I developed DeviceTree Plugin, one of the requests covered in this issue.
It was finally merged in the `develop` branch, so I would appreciate it if you could give me feedback after using it. 🙌
I believe we just haven't gotten to those yet, I think they were all core plugins of volatility2.  I've given this to the developer that made the previous ones, so we can find out directly the intention for those...  5:)
Thanks for your quick reply!
Hello @mrratherford,
This time, I developed DeviceTree Plugin, one of the requests covered in this issue.
It was finally merged in the `develop` branch, so I would appreciate it if you could give me feedback after using it. 🙌




Fix patch:
diff --git a/.github/workflows/black.yml b/.github/workflows/black.yml
index 5f45230726..e29ab6f290 100644
--- a/.github/workflows/black.yml
+++ b/.github/workflows/black.yml
@@ -6,8 +6,10 @@ jobs:
   lint:
     runs-on: ubuntu-20.04
     steps:
-      - uses: actions/checkout@v3
+      - uses: actions/checkout@v4
       - uses: psf/black@stable
         with:
           options: "--check --diff --verbose"
           src: "./volatility3"
+          # FIXME: Remove when Volatility3 minimum Python version is >3.8
+          version: "24.8.0"
diff --git a/.github/workflows/build-pypi.yml b/.github/workflows/build-pypi.yml
index f21898971a..346d0337e9 100644
--- a/.github/workflows/build-pypi.yml
+++ b/.github/workflows/build-pypi.yml
@@ -20,24 +20,23 @@ jobs:
       matrix:
         python-version: ["3.7"]
     steps:
-    - uses: actions/checkout@v3
+    - uses: actions/checkout@v4
     - name: Set up Python ${{ matrix.python-version }}
-      uses: actions/setup-python@v4
+      uses: actions/setup-python@v5
       with:
         python-version: ${{ matrix.python-version }}
 
     - name: Install dependencies
       run: |
         python -m pip install --upgrade pip
-        pip install setuptools wheel
+        pip install build
 
     - name: Build PyPi packages
       run: |
-        python setup.py sdist --formats=gztar,zip
-        python setup.py bdist_wheel
+        python -m build
 
     - name: Archive dist
-      uses: actions/upload-artifact@v2
+      uses: actions/upload-artifact@v4
       with:
         name: volatility3-pypi
         path: |
diff --git a/.github/workflows/install.yml b/.github/workflows/install.yml
index cc2a7fd3ec..e13161085c 100644
--- a/.github/workflows/install.yml
+++ b/.github/workflows/install.yml
@@ -10,7 +10,7 @@ jobs:
         host: [ ubuntu-latest, windows-latest ]
         python-version: [ "3.7", "3.8", "3.9", "3.10", "3.11" ]
     steps:
-    - uses: actions/checkout@v3
+    - uses: actions/checkout@v4
 
     - name: Set up Python ${{ matrix.python-version }}
       uses: actions/setup-python@v4
diff --git a/.gitignore b/.gitignore
index 328ba5f83b..c132736a9c 100644
--- a/.gitignore
+++ b/.gitignore
@@ -27,6 +27,7 @@ config*.json
 # Pyinstaller files
 build
 dist
+*.egg-info
 
 # Environments
 .env
diff --git a/CITATION.cff b/CITATION.cff
index c36c3b7d5c..ac45dfc18f 100644
--- a/CITATION.cff
+++ b/CITATION.cff
@@ -14,7 +14,7 @@ authors:
 identifiers:
   - type: url
     value: 'https://github.com/volatilityfoundation/volatility3'
-    description: Volatility 3 source code respository
+    description: Volatility 3 source code repository
 repository-code: 'https://github.com/volatilityfoundation/volatility3'
 url: 'https://github.com/volatilityfoundation/volatility3'
 abstract: >-
diff --git a/README.md b/README.md
index f69acb3bb5..886790df8e 100644
--- a/README.md
+++ b/README.md
@@ -20,17 +20,16 @@ more details.
 
 ## Requirements
 
-Volatility 3 requires Python 3.7.0 or later. To install the most minimal set of dependencies (some plugins will not work) use a command such as:
+Volatility 3 requires Python 3.7.3 or later. To install the most minimal set of dependencies (some plugins will not work) use a command such as:
 
 ```shell
 pip3 install -r requirements-minimal.txt
 ```
 
-Alternately, the minimal packages will be installed automatically when Volatility 3 is installed using setup.py. However, as noted in the Quick Start section below, Volatility 3 does not *need* to be installed via setup.py prior to using it.
+Alternately, the minimal packages will be installed automatically when Volatility 3 is installed using pip. However, as noted in the Quick Start section below, Volatility 3 does not *need* to be installed prior to using it.
 
 ```shell
-python3 setup.py build 
-python3 setup.py install
+pip3 install .
 ```
 
 To enable the full range of Volatility 3 functionality, use a command like the one below. For partial functionality, comment out any unnecessary packages in [requirements.txt](requirements.txt) prior to running the command.
diff --git a/pyproject.toml b/pyproject.toml
new file mode 100644
index 0000000000..207f762cc2
--- /dev/null
+++ b/pyproject.toml
@@ -0,0 +1,32 @@
+[project]
+name = "volatility3"
+description = "Memory forensics framework"
+keywords = ["volatility", "memory", "forensics", "framework", "windows", "linux", "volshell"]
+readme = "README.md"
+authors = [
+    { name = "Volatility Foundation", email = "volatility@volatilityfoundation.org" },
+]
+requires-python = ">=3.7.3"
+license = { text = "VSL" }
+dynamic = ["dependencies", "optional-dependencies", "version"]
+
+[project.urls]
+Homepage = "https://github.com/volatilityfoundation/volatility3/"
+"Bug Tracker" = "https://github.com/volatilityfoundation/volatility3/issues"
+Documentation = "https://volatility3.readthedocs.io/"
+"Source Code" = "https://github.com/volatilityfoundation/volatility3"
+
+[project.scripts]
+vol = "volatility3.cli:main"
+volshell = "volatility3.cli.volshell:main"
+
+[tool.setuptools.dynamic]
+version = { attr = "volatility3.framework.constants._version.PACKAGE_VERSION" }
+dependencies = { file = "requirements-minimal.txt" }
+
+[tool.setuptools.packages.find]
+include = ["volatility3*"]
+
+[build-system]
+requires = ["setuptools>=68"]
+build-backend = "setuptools.build_meta"
diff --git a/requirements.txt b/requirements.txt
index c63dc0b364..bd61edf142 100644
--- a/requirements.txt
+++ b/requirements.txt
@@ -15,7 +15,7 @@ capstone>=3.0.5
 pycryptodome
 
 # This is required for memory acquisition via leechcore/pcileech.
-leechcorepyc>=2.4.0
+leechcorepyc>=2.4.0; sys_platform != 'darwin'
 
 # This is required for memory analysis on a Amazon/MinIO S3 and Google Cloud object storage
 gcsfs>=2023.1.0
diff --git a/setup.py b/setup.py
index c2c55067dc..3af0331602 100644
--- a/setup.py
+++ b/setup.py
@@ -4,50 +4,21 @@
 
 import setuptools
 
-from volatility3.framework import constants
 
-with open("README.md", "r", encoding="utf-8") as fh:
-    long_description = fh.read()
-
-
-def get_install_requires():
+def get_requires(filename):
     requirements = []
-    with open("requirements-minimal.txt", "r", encoding="utf-8") as fh:
+    with open(filename, "r", encoding="utf-8") as fh:
         for line in fh.readlines():
             stripped_line = line.strip()
-            if stripped_line == "" or stripped_line.startswith("#"):
+            if stripped_line == "" or stripped_line.startswith(("#", "-r")):
                 continue
             requirements.append(stripped_line)
     return requirements
 
 
 setuptools.setup(
-    name="volatility3",
-    description="Memory forensics framework",
-    version=constants.PACKAGE_VERSION,
-    license="VSL",
-    keywords="volatility memory forensics framework windows linux volshell",
-    author="Volatility Foundation",
-    long_description=long_description,
-    long_description_content_type="text/markdown",
-    author_email="volatility@volatilityfoundation.org",
-    url="https://github.com/volatilityfoundation/volatility3/",
-    project_urls={
-        "Bug Tracker": "https://github.com/volatilityfoundation/volatility3/issues",
-        "Documentation": "https://volatility3.readthedocs.io/",
-        "Source Code": "https://github.com/volatilityfoundation/volatility3",
-    },
-    packages=setuptools.find_namespace_packages(
-        include=["volatility3", "volatility3.*"]
-    ),
-    package_dir={"volatility3": "volatility3"},
-    python_requires=">=3.7.0",
-    include_package_data=True,
-    entry_points={
-        "console_scripts": [
-            "vol = volatility3.cli:main",
-            "volshell = volatility3.cli.volshell:main",
-        ],
+    extras_require={
+        "dev": get_requires("requirements-dev.txt"),
+        "full": get_requires("requirements.txt"),
     },
-    install_requires=get_install_requires(),
 )
diff --git a/vol.py b/vol.py
index ff420cad55..c49d5985d1 100755
--- a/vol.py
+++ b/vol.py
@@ -1,4 +1,5 @@
 #!/usr/bin/env python3
+# PYTHON_ARGCOMPLETE_OK
 
 # 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
diff --git a/volatility3/cli/__init__.py b/volatility3/cli/__init__.py
index 457a493117..1209d7cdc7 100644
--- a/volatility3/cli/__init__.py
+++ b/volatility3/cli/__init__.py
@@ -22,6 +22,13 @@
 from typing import Any, Dict, List, Tuple, Type, Union
 from urllib import parse, request
 
+try:
+    import argcomplete
+
+    HAS_ARGCOMPLETE = True
+except ImportError:
+    HAS_ARGCOMPLETE = False
+
 from volatility3.cli import text_filter
 import volatility3.plugins
 import volatility3.symbols
@@ -351,6 +358,10 @@ def run(self):
         # Hand the plugin requirements over to the CLI (us) and let it construct the config tree
 
         # Run the argparser
+        if HAS_ARGCOMPLETE:
+            # The autocompletion line must be after the partial_arg handling, so that it doesn't trip it
+            # before all the plugins have been added
+            argcomplete.autocomplete(parser)
         args = parser.parse_args()
         if args.plugin is None:
             parser.error("Please select a plugin to run")
@@ -716,19 +727,17 @@ def _get_final_filename(self):
                 """Gets the final filename"""
                 if output_dir is None:
                     raise TypeError("Output directory is not a string")
+
                 os.makedirs(output_dir, exist_ok=True)
 
-                pref_name_array = self.preferred_filename.split(".")
-                filename, extension = (
-                    os.path.join(output_dir, ".".join(pref_name_array[:-1])),
-                    pref_name_array[-1],
-                )
-                output_filename = f"{filename}.{extension}"
+                output_filename = os.path.join(output_dir, self.preferred_filename)
+                filename, extension = os.path.splitext(output_filename)
 
                 counter = 1
                 while os.path.exists(output_filename):
-                    output_filename = f"{filename}-{counter}.{extension}"
+                    output_filename = f"{filename}-{counter}{extension}"
                     counter += 1
+
                 return output_filename
 
         class CLIMemFileHandler(io.BytesIO, CLIFileHandler):
@@ -791,8 +800,16 @@ def close(self):
                 if self._file.closed:
                     return None
 
-                self._file.close()
                 output_filename = self._get_final_filename()
+
+                # Update the filename, which may have changed if a file with
+                # the same name already existed. This needs to be done before
+                # closing the file, otherwise FileHandlerInterface will raise
+                # an exception. Also, the preferred_filename setter only allows
+                #  a specific set of characters, where '/' is not in that list
+                self.preferred_filename = os.path.basename(output_filename)
+
+                self._file.close()
                 os.rename(self._name, output_filename)
 
         if direct:
diff --git a/volatility3/cli/text_renderer.py b/volatility3/cli/text_renderer.py
index b0ba6baa7a..ab9e44141b 100644
--- a/volatility3/cli/text_renderer.py
+++ b/volatility3/cli/text_renderer.py
@@ -25,7 +25,7 @@
     vollog.debug("Disassembly library capstone not found")
 
 
-def hex_bytes_as_text(value: bytes) -> str:
+def hex_bytes_as_text(value: bytes, width: int = 16) -> str:
     """Renders HexBytes as text.
 
     Args:
@@ -36,19 +36,24 @@ def hex_bytes_as_text(value: bytes) -> str:
     """
     if not isinstance(value, bytes):
         raise TypeError(f"hex_bytes_as_text takes bytes not: {type(value)}")
-    ascii = []
-    hex = []
-    count = 0
-    output = ""
-    for byte in value:
-        hex.append(f"{byte:02x}")
-        ascii.append(chr(byte) if 0x20 < byte <= 0x7E else ".")
-        if (count % 8) == 7:
-            output += "\n"
-            output += " ".join(hex[count - 7 : count + 1])
-            output += "\t"
-            output += "".join(ascii[count - 7 : count + 1])
-        count += 1
+
+    printables = ""
+    output = "\n"
+    for count, byte in enumerate(value):
+        output += f"{byte:02x} "
+        char = chr(byte)
+        printables += char if 0x20 <= byte <= 0x7E else "."
+        if count % width == width - 1:
+            output += printables
+            if count < len(value) - 1:
+                output += "\n"
+            printables = ""
+
+    # Handle leftovers when the lenght is not mutiple of width
+    if printables:
+        output += "   " * (width - len(printables))
+        output += printables
+
     return output
 
 
diff --git a/volatility3/cli/volargparse.py b/volatility3/cli/volargparse.py
index 3048a0885e..fd61ddce02 100644
--- a/volatility3/cli/volargparse.py
+++ b/volatility3/cli/volargparse.py
@@ -21,8 +21,6 @@ class HelpfulSubparserAction(argparse._SubParsersAction):
 
     def __init__(self, *args, **kwargs) -> None:
         super().__init__(*args, **kwargs)
-        # We don't want the action self-check to kick in, so we remove the choices list, the check happens in __call__
-        self.choices = None
 
     def __call__(
         self,
@@ -100,3 +98,20 @@ def _match_argument(self, action, arg_strings_pattern) -> int:
 
         # return the number of arguments matched
         return len(match.group(1))
+
+    def _check_value(self, action: argparse.Action, value: Any) -> None:
+        """This is called to ensure a value is correct/valid
+
+        In normal operation, it would check that a value provided is valid and return None
+        If it was not valid, it would throw an ArgumentError
+
+        When people provide a partial plugin name, we want to look for a matching plugin name
+        which happens in the HelpfulSubparserAction's __call_method
+
+        To get there without tripping the check_value failure, we have to prevent the exception
+        being thrown when the value is a HelpfulSubparserAction.  This therefore affects no other
+        checks for normal parameters.
+        """
+        if not isinstance(action, HelpfulSubparserAction):
+            super()._check_value(action, value)
+        return None
diff --git a/volatility3/cli/volshell/__init__.py b/volatility3/cli/volshell/__init__.py
index 035ed9b2e1..2bf1958e2d 100644
--- a/volatility3/cli/volshell/__init__.py
+++ b/volatility3/cli/volshell/__init__.py
@@ -21,6 +21,14 @@
     plugins,
 )
 
+try:
+    import argcomplete
+
+    HAS_ARGCOMPLETE = True
+except ImportError:
+    HAS_ARGCOMPLETE = False
+
+
 # Make sure we log everything
 
 rootlog = logging.getLogger()
@@ -276,6 +284,10 @@ def run(self):
         # Hand the plugin requirements over to the CLI (us) and let it construct the config tree
 
         # Run the argparser
+        if HAS_ARGCOMPLETE:
+            # The autocompletion line must be after the partial_arg handling, so that it doesn't trip it
+            # before all the plugins have been added
+            argcomplete.autocomplete(parser)
         args = parser.parse_args()
 
         vollog.log(
diff --git a/volatility3/framework/__init__.py b/volatility3/framework/__init__.py
index 1565b22670..74db773cf8 100644
--- a/volatility3/framework/__init__.py
+++ b/volatility3/framework/__init__.py
@@ -7,7 +7,7 @@
 import sys
 import zipfile
 
-required_python_version = (3, 7, 0)
+required_python_version = (3, 7, 3)
 if (
     sys.version_info.major != required_python_version[0]
     or sys.version_info.minor < required_python_version[1]
@@ -223,8 +223,14 @@ def list_plugins() -> Dict[str, Type[interfaces.plugins.PluginInterface]]:
     return plugin_list
 
 
-def clear_cache(complete=False):
+def clear_cache(complete=True):
     try:
+        if complete:
+            glob_pattern = "*.cache"
+            for cache_filename in glob.glob(
+                os.path.join(constants.CACHE_PATH, glob_pattern)
+            ):
+                os.unlink(cache_filename)
         os.unlink(os.path.join(constants.CACHE_PATH, constants.IDENTIFIERS_FILENAME))
     except FileNotFoundError:
         vollog.log(constants.LOGLEVEL_VVVV, "Attempting to clear a non-existant cache")
diff --git a/volatility3/framework/automagic/linux.py b/volatility3/framework/automagic/linux.py
index 2eebcc2dcd..52a73f45a8 100644
--- a/volatility3/framework/automagic/linux.py
+++ b/volatility3/framework/automagic/linux.py
@@ -159,7 +159,10 @@ def find_aslr(
 
             # This we get for free
             aslr_shift = (
-                init_task.files.cast("long unsigned int")
+                int.from_bytes(
+                    init_task.files.cast("bytes", length=init_task.files.vol.size),
+                    byteorder=init_task.files.vol.data_format.byteorder,
+                )
                 - module.get_symbol("init_files").address
             )
             kaslr_shift = init_task_address - cls.virtual_to_physical_address(
diff --git a/volatility3/framework/constants/__init__.py b/volatility3/framework/constants/__init__.py
index 3c5e0eb2ff..8743a64b0b 100644
--- a/volatility3/framework/constants/__init__.py
+++ b/volatility3/framework/constants/__init__.py
@@ -14,6 +14,13 @@
 
 import volatility3.framework.constants.linux
 import volatility3.framework.constants.windows
+from volatility3.framework.constants._version import (
+    PACKAGE_VERSION,
+    VERSION_MAJOR,
+    VERSION_MINOR,
+    VERSION_PATCH,
+    VERSION_SUFFIX,
+)
 
 PLUGINS_PATH = [
     os.path.abspath(os.path.join(os.path.dirname(__file__), "..", "..", "plugins")),
@@ -42,20 +49,6 @@
 BANG = "!"
 """Constant used to delimit table names from type names when referring to a symbol"""
 
-# We use the SemVer 2.0.0 versioning scheme
-VERSION_MAJOR = 2  # Number of releases of the library with a breaking change
-VERSION_MINOR = 7  # Number of changes that only add to the interface
-VERSION_PATCH = 0  # Number of changes that do not change the interface
-VERSION_SUFFIX = ""
-
-# TODO: At version 2.0.0, remove the symbol_shift feature
-
-PACKAGE_VERSION = (
-    ".".join([str(x) for x in [VERSION_MAJOR, VERSION_MINOR, VERSION_PATCH]])
-    + VERSION_SUFFIX
-)
-"""The canonical version of the volatility3 package"""
-
 AUTOMAGIC_CONFIG_PATH = "automagic"
 """The root section within the context configuration for automagic values"""
 
diff --git a/volatility3/framework/constants/_version.py b/volatility3/framework/constants/_version.py
new file mode 100644
index 0000000000..f219fb0af2
--- /dev/null
+++ b/volatility3/framework/constants/_version.py
@@ -0,0 +1,11 @@
+# We use the SemVer 2.0.0 versioning scheme
+VERSION_MAJOR = 2  # Number of releases of the library with a breaking change
+VERSION_MINOR = 8  # Number of changes that only add to the interface
+VERSION_PATCH = 0  # Number of changes that do not change the interface
+VERSION_SUFFIX = ""
+
+PACKAGE_VERSION = (
+    ".".join([str(x) for x in [VERSION_MAJOR, VERSION_MINOR, VERSION_PATCH]])
+    + VERSION_SUFFIX
+)
+"""The canonical version of the volatility3 package"""
diff --git a/volatility3/framework/contexts/__init__.py b/volatility3/framework/contexts/__init__.py
index 73868a58f3..4c169728cc 100644
--- a/volatility3/framework/contexts/__init__.py
+++ b/volatility3/framework/contexts/__init__.py
@@ -256,12 +256,13 @@ def object(
         if not absolute:
             offset += self._offset
 
-        # Ensure we don't use a layer_name other than the module's, why would anyone do that?
-        if "layer_name" in kwargs:
-            del kwargs["layer_name"]
+        # We have to allow using an alternative layer name due to pool scanners switching
+        # to the memory layer for scanning samples prior to Windows 10.
+        layer_name = kwargs.pop("layer_name", self._layer_name)
+
         return self._context.object(
             object_type=object_type,
-            layer_name=self._layer_name,
+            layer_name=layer_name,
             offset=offset,
             native_layer_name=native_layer_name or self._native_layer_name,
             **kwargs,
diff --git a/volatility3/framework/interfaces/automagic.py b/volatility3/framework/interfaces/automagic.py
index fe1361b306..0867b1608f 100644
--- a/volatility3/framework/interfaces/automagic.py
+++ b/volatility3/framework/interfaces/automagic.py
@@ -50,7 +50,7 @@ def __init__(
         context: interfaces.context.ContextInterface,
         config_path: str,
         *args,
-        **kwargs
+        **kwargs,
     ) -> None:
         super().__init__(context, config_path)
         for requirement in self.get_requirements():
diff --git a/volatility3/framework/layers/crash.py b/volatility3/framework/layers/crash.py
index 042b18ddcc..3cfc0a25bd 100644
--- a/volatility3/framework/layers/crash.py
+++ b/volatility3/framework/layers/crash.py
@@ -96,12 +96,13 @@ def get_header(self) -> interfaces.objects.ObjectInterface:
     def get_summary_header(self) -> interfaces.objects.ObjectInterface:
         return self.context.object(
             self._crash_common_table_name + constants.BANG + "_SUMMARY_DUMP",
-            offset=0x1000 * self.headerpages,
+            offset=self._page_size * self.headerpages,
             layer_name=self._base_layer,
         )
 
     def _load_segments(self) -> None:
-        """Loads up the segments from the meta_layer."""
+        """Loads up the segments from the meta_layer.
+        A segment is a set of contiguous memory pages."""
 
         segments = []
 
@@ -119,70 +120,87 @@ def _load_segments(self) -> None:
             for run in header.PhysicalMemoryBlockBuffer.Run:
                 segments.append(
                     (
-                        run.BasePage * 0x1000,
-                        offset * 0x1000,
-                        run.PageCount * 0x1000,
-                        run.PageCount * 0x1000,
+                        run.BasePage * self._page_size,
+                        offset * self._page_size,
+                        run.PageCount * self._page_size,
+                        run.PageCount * self._page_size,
                     )
                 )
                 offset += run.PageCount
 
         elif self.dump_type == 0x05:
             summary_header = self.get_summary_header()
-            first_bit = None  # First bit in a run
-            first_offset = 0  # File offset of first bit
-            last_bit_seen = 0  # Most recent bit processed
-            offset = summary_header.HeaderSize  # Size of file headers
-            buffer_char = summary_header.get_buffer_char()
-            buffer_long = summary_header.get_buffer_long()
-
-            for outer_index in range(0, ((summary_header.BitmapSize + 31) // 32)):
-                if buffer_long[outer_index] == 0:
-                    if first_bit is not None:
-                        last_bit = ((outer_index - 1) * 32) + 31
-                        segment_length = (last_bit - first_bit + 1) * 0x1000
+            seg_first_bit = None  # First bit in a run
+            seg_first_offset = 0  # File offset of first bit
+            offset = (
+                summary_header.HeaderSize
+            )  # Offset to the start of actual memory dump
+            ulong_bitmap_array = summary_header.get_buffer_long()
+            # outer_index points to a 32 bits array inside a list of arrays,
+            # each bit indicating a page mapping state
+            for outer_index in range(0, ulong_bitmap_array.vol.count):
+                ulong_bitmap = ulong_bitmap_array[outer_index]
+                # All pages in this 32 bits array are mapped (speedup iteration process)
+                if ulong_bitmap == 0xFFFFFFFF:
+                    # New segment
+                    if seg_first_bit is None:
+                        seg_first_offset = offset
+                        seg_first_bit = outer_index * 32
+                    offset += 32 * self._page_size
+                # No pages in this 32 bits array are mapped (speedup iteration process)
+                elif ulong_bitmap == 0:
+                    # End of segment
+                    if seg_first_bit is not None:
+                        last_bit = (outer_index - 1) * 32 + 31
+                        segment_length = (
+                            last_bit - seg_first_bit + 1
+                        ) * self._page_size
                         segments.append(
                             (
-                                first_bit * 0x1000,
-                                first_offset,
+                                seg_first_bit * self._page_size,
+                                seg_first_offset,
                                 segment_length,
                                 segment_length,
                             )
                         )
-                        first_bit = None
-                elif buffer_long[outer_index] == 0xFFFFFFFF:
-                    if first_bit is None:
-                        first_offset = offset
-                        first_bit = outer_index * 32
-                    offset = offset + (32 * 0x1000)
+                        seg_first_bit = None
+                # Some pages in this 32 bits array are mapped and some aren't
                 else:
-                    for inner_index in range(0, 32):
-                        bit_addr = outer_index * 32 + inner_index
-                        if (buffer_char[bit_addr >> 3] >> (bit_addr & 0x7)) & 1:
-                            if first_bit is None:
-                                first_offset = offset
-                                first_bit = bit_addr
-                            offset = offset + 0x1000
+                    for inner_bit_position in range(0, 32):
+                        current_bit = outer_index * 32 + inner_bit_position
+                        page_mapped = ulong_bitmap & (1 << inner_bit_position)
+                        if page_mapped:
+                            # New segment
+                            if seg_first_bit is None:
+                                seg_first_offset = offset
+                                seg_first_bit = current_bit
+                            offset += self._page_size
                         else:
-                            if first_bit is not None:
+                            # End of segment
+                            if seg_first_bit is not None:
                                 segment_length = (
-                                    (bit_addr - 1) - first_bit + 1
-                                ) * 0x1000
+                                    current_bit - 1 - seg_first_bit + 1
+                                ) * self._page_size
                                 segments.append(
                                     (
-                                        first_bit * 0x1000,
-                                        first_offset,
+                                        seg_first_bit * self._page_size,
+                                        seg_first_offset,
                                         segment_length,
                                         segment_length,
                                     )
                                 )
-                                first_bit = None
-                last_bit_seen = (outer_index * 32) + 31
+                                seg_first_bit = None
+                last_bit_seen = outer_index * 32 + 31
 
-            if first_bit is not None:
-                segment_length = (last_bit_seen - first_bit + 1) * 0x1000
+            if seg_first_bit is not None:
+                segment_length = (last_bit_seen - seg_first_bit + 1) * self._page_size
                 segments.append(
-                    (first_bit * 0x1000, first_offset, segment_length, segment_length)
+                    (
+                        seg_first_bit * self._page_size,
+                        seg_first_offset,
+                        segment_length,
+                        segment_length,
+                    )
                 )
         else:
             vollog.log(
diff --git a/volatility3/framework/layers/intel.py b/volatility3/framework/layers/intel.py
index 75e561b33c..b969b952b3 100644
--- a/volatility3/framework/layers/intel.py
+++ b/volatility3/framework/layers/intel.py
@@ -180,7 +180,9 @@ def _translate_entry(self, offset: int) -> Tuple[int, int]:
         position = self._initial_position
         entry = self._initial_entry
 
-        if self.minimum_address > offset > self.maximum_address:
+        if not (
+            self.minimum_address <= (offset & self.address_mask) <= self.maximum_address
+        ):
             raise exceptions.PagedInvalidAddressException(
                 self.name,
                 offset,
diff --git a/volatility3/framework/layers/resources.py b/volatility3/framework/layers/resources.py
index a64fa7d7a9..2dba7caa8f 100644
--- a/volatility3/framework/layers/resources.py
+++ b/volatility3/framework/layers/resources.py
@@ -151,6 +151,12 @@ def open(self, url: str, mode: str = "rb") -> Any:
                     raise excp
             else:
                 raise excp
+        except ValueError as excp:
+            # Reraise errors such as proxy auth errors as offline exception errors
+            # Example Proxy auth error - ValueError: AbstractDigestAuthHandler does not support the following scheme: 'Negotiate'
+            vollog.info(f"Cannot access {url} due to {excp} - Setting OFFLINE")
+            constants.OFFLINE = True
+            raise exceptions.OfflineException(url)
         except exceptions.OfflineException:
             vollog.info(f"Not accessing {url} in offline mode")
             raise
diff --git a/volatility3/framework/layers/segmented.py b/volatility3/framework/layers/segmented.py
index 0d29d8bff5..e8c0670725 100644
--- a/volatility3/framework/layers/segmented.py
+++ b/volatility3/framework/layers/segmented.py
@@ -152,7 +152,7 @@ def maximum_address(self) -> int:
             raise ValueError("SegmentedLayer must contain some segments")
         if self._maxaddr is None:
             mapped, _, length, _ = self._segments[-1]
-            self._maxaddr = mapped + length
+            self._maxaddr = mapped + length - 1
         return self._maxaddr
 
     @property
diff --git a/volatility3/framework/objects/utility.py b/volatility3/framework/objects/utility.py
index 0292608c12..8aa527cdbe 100644
--- a/volatility3/framework/objects/utility.py
+++ b/volatility3/framework/objects/utility.py
@@ -7,6 +7,27 @@
 from volatility3.framework import interfaces, objects, constants
 
 
+def rol(value: int, count: int, max_bits: int = 64) -> int:
+    """A rotate-left instruction in Python"""
+    max_bits_mask = (1 << max_bits) - 1
+    return (value << count % max_bits) & max_bits_mask | (
+        (value & max_bits_mask) >> (max_bits - (count % max_bits))
+    )
+
+
+def bswap_32(value: int) -> int:
+    value = ((value << 8) & 0xFF00FF00) | ((value >> 8) & 0x00FF00FF)
+
+    return ((value << 16) | (value >> 16)) & 0xFFFFFFFF
+
+
+def bswap_64(value: int) -> int:
+    low = bswap_32((value >> 32))
+    high = bswap_32((value & 0xFFFFFFFF))
+
+    return ((high << 32) | low) & 0xFFFFFFFFFFFFFFFF
+
+
 def array_to_string(
     array: "objects.Array", count: Optional[int] = None, errors: str = "replace"
 ) -> interfaces.objects.ObjectInterface:
diff --git a/volatility3/framework/plugins/layerwriter.py b/volatility3/framework/plugins/layerwriter.py
index 1bee5f20d3..24149a390b 100644
--- a/volatility3/framework/plugins/layerwriter.py
+++ b/volatility3/framework/plugins/layerwriter.py
@@ -18,7 +18,7 @@ class LayerWriter(plugins.PluginInterface):
     default_block_size = 0x500000
 
     _required_framework_version = (2, 0, 0)
-    _version = (2, 0, 0)
+    _version = (2, 0, 1)
 
     @classmethod
     def get_requirements(cls) -> List[interfaces.configuration.RequirementInterface]:
@@ -77,7 +77,7 @@ def write_layer(
 
         file_handle = open_method(preferred_name)
         for i in range(0, layer.maximum_address, chunk_size):
-            current_chunk_size = min(chunk_size, layer.maximum_address - i)
+            current_chunk_size = min(chunk_size, layer.maximum_address + 1 - i)
             data = layer.read(i, current_chunk_size, pad=True)
             file_handle.write(data)
             if progress_callback:
@@ -95,7 +95,7 @@ def _generator(self):
             if not self.config["layers"]:
                 self.config["layers"] = []
                 for name in self.context.layers:
-                    if not self.context.layers[name].metadata.get("mapped", False):
+                    if "mapped" not in self.context.layers[name].metadata:
                         self.config["layers"] = [name]
 
             for name in self.config["layers"]:
@@ -103,7 +103,8 @@ def _generator(self):
                 if name not in self.context.layers:
                     yield 0, (f"Layer Name {name} does not exist",)
                 else:
-                    output_name = self.config.get("output", ".".join([name, "raw"]))
+                    default_output_name = f"{name}.raw"
+                    output_name = self.config.get("output", default_output_name)
                     try:
                         file_handle = self.write_layer(
                             self.context,
@@ -114,10 +115,12 @@ def _generator(self):
                             progress_callback=self._progress_callback,
                         )
                         file_handle.close()
+
+                        # Update the filename, which may have changed if a file
+                        # with the same name already existed.
+                        output_name = file_handle.preferred_filename
                     except IOError as excp:
-                        yield 0, (
-                            f"Layer cannot be written to {self.config['output_name']}: {excp}",
-                        )
+                        yield 0, (f"Layer cannot be written to {output_name}: {excp}",)
 
                     yield 0, (f"Layer has been written to {output_name}",)
 
diff --git a/volatility3/framework/plugins/linux/kmsg.py b/volatility3/framework/plugins/linux/kmsg.py
index c5e0fc302e..e26d695438 100644
--- a/volatility3/framework/plugins/linux/kmsg.py
+++ b/volatility3/framework/plugins/linux/kmsg.py
@@ -66,7 +66,7 @@ def __init__(
         self._config = config
         self.vmlinux = context.modules[self._config["kernel"]]
         self.layer_name = self.vmlinux.layer_name  # type: ignore
-        self.long_unsigned_int_size = self.vmlinux.get_type("long unsigned int").size
+        self.long_unsigned_int_size = self.vmlinux.get_type("pointer").size
 
     @classmethod
     def run_all(
diff --git a/volatility3/framework/plugins/linux/netfilter.py b/volatility3/framework/plugins/linux/netfilter.py
new file mode 100644
index 0000000000..d392a83710
--- /dev/null
+++ b/volatility3/framework/plugins/linux/netfilter.py
@@ -0,0 +1,738 @@
+# This file is Copyright 2024 Volatility Foundation and licensed under the Volatility Software License 1.0
+# which is available at https://www.volatilityfoundation.org/license/vsl-v1.0
+#
+from dataclasses import dataclass, field
+from abc import ABC, abstractmethod
+import logging
+
+from typing import Iterator, List, Tuple
+from volatility3 import framework
+from volatility3.framework import (
+    constants,
+    interfaces,
+    renderers,
+    exceptions,
+)
+from volatility3.framework.renderers import format_hints
+from volatility3.framework.configuration import requirements
+from volatility3.framework.symbols import linux
+from volatility3.plugins.linux import lsmod
+
+vollog = logging.getLogger(__name__)
+
+
+@dataclass
+class Proto:
+    name: str
+    hooks: Tuple[str] = field(default_factory=tuple)
+
+
+PROTO_NOT_IMPLEMENTED = Proto(name="UNSPEC")
+
+NF_INET_HOOKS = ("PRE_ROUTING", "LOCAL_IN", "FORWARD", "LOCAL_OUT", "POST_ROUTING")
+NF_DEC_HOOKS = (
+    "PRE_ROUTING",
+    "LOCAL_IN",
+    "FORWARD",
+    "LOCAL_OUT",
+    "POST_ROUTING",
+    "HELLO",
+    "ROUTE",
+)
+NF_ARP_HOOKS = ("IN", "OUT", "FORWARD")
+NF_NETDEV_HOOKS = ("INGRESS", "EGRESS")
+LARGEST_HOOK_NUMBER = max(
+    len(NF_INET_HOOKS), len(NF_DEC_HOOKS), len(NF_ARP_HOOKS), len(NF_NETDEV_HOOKS)
+)
+
+
+class AbstractNetfilter(ABC):
+    """Netfilter Abstract Base Classes handling details across various
+    Netfilter implementations, including constants, helpers, and common
+    routines.
+    """
+
+    PROTO_HOOKS = (
+        PROTO_NOT_IMPLEMENTED,  # NFPROTO_UNSPEC
+        Proto(name="INET", hooks=NF_INET_HOOKS),  # From kernels 3.14
+        Proto(name="IPV4", hooks=NF_INET_HOOKS),
+        Proto(name="ARP", hooks=NF_ARP_HOOKS),
+        PROTO_NOT_IMPLEMENTED,
+        Proto(name="NETDEV", hooks=NF_NETDEV_HOOKS),
+        PROTO_NOT_IMPLEMENTED,
+        Proto(name="BRIDGE", hooks=NF_INET_HOOKS),
+        PROTO_NOT_IMPLEMENTED,
+        PROTO_NOT_IMPLEMENTED,
+        Proto(name="IPV6", hooks=NF_INET_HOOKS),
+        PROTO_NOT_IMPLEMENTED,
+        Proto(name="DECNET", hooks=NF_DEC_HOOKS),  # Removed in kernel 6.1
+    )
+    NF_MAX_HOOKS = LARGEST_HOOK_NUMBER + 1
+
+    def __init__(
+        self, context: interfaces.context.ContextInterface, kernel_module_name: str
+    ):
+        self._context = context
+        self.vmlinux = context.modules[kernel_module_name]
+        self.layer_name = self.vmlinux.layer_name
+
+        # Set data sizes
+        self.ptr_size = self.vmlinux.get_type("pointer").size
+        self.list_head_size = self.vmlinux.get_type("list_head").size
+
+        lsmod_required_version = Netfilter._required_lsmod_version
+        lsmod_current_version = lsmod.Lsmod._version
+        if not requirements.VersionRequirement.matches_required(
+            lsmod_required_version, lsmod_current_version
+        ):
+            raise exceptions.PluginRequirementException(
+                f"linux.lsmod.Lsmod version not suitable: required {lsmod_required_version} found {lsmod_current_version}"
+            )
+
+        linuxutils_required_version = Netfilter._required_linuxutils_version
+        linuxutils_current_version = linux.LinuxUtilities._version
+        if not requirements.VersionRequirement.matches_required(
+            linuxutils_required_version, linuxutils_current_version
+        ):
+            raise exceptions.PluginRequirementException(
+                f"linux.LinuxUtilities version not suitable: required {linuxutils_required_version} found {linuxutils_current_version}"
+            )
+
+        modules = lsmod.Lsmod.list_modules(context, kernel_module_name)
+        self.handlers = linux.LinuxUtilities.generate_kernel_handler_info(
+            context, kernel_module_name, modules
+        )
+
+    @classmethod
+    def run_all(
+        cls, context: interfaces.context.ContextInterface, kernel_module_name: str
+    ) -> Iterator[Tuple[int, str, str, int, int, str, bool]]:
+        """It calls each subclass symtab_checks() to test the required
+        conditions to that specific kernel implementation.
+
+        Args:
+            context: The volatility3 context on which to operate
+            kernel_module_name: The name of the table containing the kernel symbols
+
+        Yields:
+            The kmsg records. Same as _run()
+        """
+        vmlinux = context.modules[kernel_module_name]
+
+        implementation_inst = None  # type: ignore
+        for subclass in framework.class_subclasses(cls):
+            if not subclass.symtab_checks(vmlinux=vmlinux):
+                vollog.log(
+                    constants.LOGLEVEL_VVVV,
+                    "Netfilter implementation '%s' doesn't match this memory dump",
+                    subclass.__name__,
+                )
+                continue
+
+            vollog.log(
+                constants.LOGLEVEL_VVVV,
+                "Netfilter implementation '%s' matches!",
+                subclass.__name__,
+            )
+            implementation_inst = subclass(
+                context=context, kernel_module_name=kernel_module_name
+            )
+            # More than one class could be executed for an specific kernel version
+            # For instance: Netfilter Ingress hooks
+            yield from implementation_inst._run()
+
+        if implementation_inst is None:
+            vollog.error("Unsupported Netfilter kernel implementation")
+
+    def _run(self) -> Iterator[Tuple[int, str, str, int, int, str, bool]]:
+        """Iterates over namespaces and protocols, executing various callbacks that
+        allow  customization of the code to the specific data structure used in a
+        particular kernel implementation
+
+            get_hooks_container(net, proto_name, hook_name)
+                It returns the data structure used in a specific kernel implementation
+                to store the hooks for a respective namespace and protocol, basically:
+                    For Ingress hooks:
+                        network_namespace[] -> net_device[] -> nf_hooks_ingress[]
+                    For egress hooks:
+                        network_namespace[] -> net_device[] -> nf_hooks_egress[]
+                    For all the other Netfilter hooks:
+                        <= 4.2.8
+                            nf_hooks[]
+                        >= 4.3
+                            network_namespace[] -> nf.hooks[]
+
+            get_hook_ops(hook_container, proto_idx, hook_idx)
+                Give the 'hook_container' got in get_hooks_container(), it
+                returns an iterable of 'nf_hook_ops' elements for a respective protocol
+                and hook type.
+
+        Returns:
+            netns [int]: Network namespace id
+            proto_name [str]: Protocol name
+            hook_name [str]: Hook name
+            priority [int]: Priority
+            hook_ops_hook [int]: Hook address
+            module_name [str]: Linux kernel module name
+            hooked [bool]: hooked?
+        """
+        for netns, net in self.get_net_namespaces():
+            for proto_idx, proto_name, hook_idx, hook_name in self._proto_hook_loop():
+                hooks_container = self.get_hooks_container(net, proto_name, hook_name)
+
+                for hook_container in hooks_container:
+                    for hook_ops in self.get_hook_ops(
+                        hook_container, proto_idx, hook_idx
+                    ):
+                        if not hook_ops:
+                            continue
+
+                        priority = int(hook_ops.priority)
+                        hook_ops_hook = hook_ops.hook
+                        module_name = self.get_module_name_for_address(hook_ops_hook)
+                        hooked = module_name is not None
+
+                        yield netns, proto_name, hook_name, priority, hook_ops_hook, module_name, hooked
+
+    @classmethod
+    @abstractmethod
+    def symtab_checks(cls, vmlinux: interfaces.context.ModuleInterface) -> bool:
+        """This method on each sublasss will be called to evaluate if the kernel
+        being analyzed fulfill the type & symbols requirements for the implementation.
+        The first class returning True will be instantiated and called via the
+        run() method.
+
+        Returns:
+            bool: True if the kernel being analyzed fulfill the class requirements.
+        """
+
+    def _proto_hook_loop(self) -> Iterator[Tuple[int, str, int, str]]:
+        """Flattens the protocol families and hooks"""
+        for proto_idx, proto in enumerate(AbstractNetfilter.PROTO_HOOKS):
+            if proto == PROTO_NOT_IMPLEMENTED:
+                continue
+            if proto.name not in self.subscribed_protocols():
+                # This protocol is not managed in this object
+                continue
+            for hook_idx, hook_name in enumerate(proto.hooks):
+                yield proto_idx, proto.name, hook_idx, hook_name
+
+    def build_nf_hook_ops_array(self, nf_hook_entries):
+        """Function helper to build the nf_hook_ops array when it is not part of the
+        struct 'nf_hook_entries' definition.
+
+        nf_hook_ops was stored adjacent in memory to the nf_hook_entry array, in the
+        new struct 'nf_hook_entries'. However, this 'nf_hooks_ops' array 'orig_ops' is
+        not part of the 'nf_hook_entries' struct. So, we need to calculate the offset.
+
+            struct nf_hook_entries {
+                u16                         num_hook_entries; /* plus padding */
+                struct nf_hook_entry        hooks[];
+                //const struct nf_hook_ops *orig_ops[];
+            }
+        """
+        nf_hook_entry_size = self.vmlinux.get_type("nf_hook_entry").size
+        orig_ops_addr = (
+            nf_hook_entries.hooks.vol.offset
+            + nf_hook_entry_size * nf_hook_entries.num_hook_entries
+        )
+        orig_ops = self._context.object(
+            object_type=self.get_symbol_fullname("array"),
+            offset=orig_ops_addr,
+            subtype=self.vmlinux.get_type("pointer"),
+            layer_name=self.layer_name,
+            count=nf_hook_entries.num_hook_entries,
+        )
+
+        return orig_ops
+
+    def subscribed_protocols(self) -> Tuple[str]:
+        """Allows to select which PROTO_HOOKS protocols will be processed by the
+        Netfiler subclass.
+        """
+
+        # Most implementation handlers respond to these protocols, except for
+        # the ingress hook, which specifically handles the 'NETDEV' protocol.
+        # However, there is no corresponding Netfilter hook implementation for
+        # the INET protocol in the kernel. AFAIU, this is used as
+        # 'NFPROTO_INET = NFPROTO_IPV4 || NFPROTO_IPV6'
+        # in other parts of the kernel source code.
+        return ("IPV4", "ARP", "BRIDGE", "IPV6", "DECNET")
+
+    def get_module_name_for_address(self, addr) -> str:
+        """Helper to obtain the module and symbol name in the format needed for the
+        output of this plugin.
+        """
+        module_name, symbol_name = linux.LinuxUtilities.lookup_module_address(
+            self.vmlinux, self.handlers, addr
+        )
+
+        if module_name == "UNKNOWN":
+            module_name = None
+
+        if symbol_name != "N/A":
+            module_name = f"[{symbol_name}]"
+
+        return module_name
+
+    def get_net_namespaces(self):
+        """Common function to retrieve the different namespaces.
+        From 4.3 on, all the implementations use network namespaces.
+        """
+        nethead = self.vmlinux.object_from_symbol("net_namespace_list")
+        symbol_net_name = self.get_symbol_fullname("net")
+        for net in nethead.to_list(symbol_net_name, "list"):
+            net_ns_id = net.ns.inum
+            yield net_ns_id, net
+
+    def get_hooks_container(self, net, proto_name, hook_name):
+        """Returns the data structure used in a specific kernel implementation to store
+        the hooks for a respective namespace and protocol.
+
+        Except for kernels < 4.3, all the implementations use network namespaces.
+        Also the data structure which contains the hooks, even though it changes its
+        implementation and/or data type, it is always in this location.
+        """
+        yield net.nf.hooks
+
+    def get_hook_ops(self, hook_container, proto_idx, hook_idx):
+        """Given the hook_container obtained from get_hooks_container(), it
+        returns an iterable of 'nf_hook_ops' elements for a corresponding protocol
+        and hook type.
+
+        This is the most variable/unstable part of all Netfilter hook designs, it
+        changes almost in every single implementation.
+        """
+        raise NotImplementedError("You must implement this method")
+
+    def get_symbol_fullname(self, symbol_basename: str) -> str:
+        """Given a short symbol or type name, it returns its full name"""
+        return self.vmlinux.symbol_table_name + constants.BANG + symbol_basename
+
+    @staticmethod
+    def get_member_type(
+        vol_type: interfaces.objects.Template, member_name: str
+    ) -> List[str]:
+        """Returns a list of types/subtypes belonging to the given type member.
+
+        Args:
+            vol_type (interfaces.objects.Template): A vol3 type object
+            member_name (str): The member name
+
+        Returns:
+            list: A list of types/subtypes
+        """
+        _size, vol_obj = vol_type.vol.members[member_name]
+        type_name = vol_obj.type_name
+        type_basename = type_name.split(constants.BANG)[1]
+        member_type = [type_basename]
+        cur_type = vol_obj
+        while hasattr(cur_type, "subtype"):
+            subtype_name = cur_type.subtype.type_name
+            subtype_basename = subtype_name.split(constants.BANG)[1]
+            member_type.append(subtype_basename)
+            cur_type = cur_type.subtype
+
+        return member_type
+
+
+class NetfilterImp_to_4_3(AbstractNetfilter):
+    """At this point, Netfilter hooks were implemented as a linked list of struct
+    'nf_hook_ops' type. One linked list per protocol per hook type.
+    It was like that until 4.2.8.
+
+        struct list_head nf_hooks[NFPROTO_NUMPROTO][NF_MAX_HOOKS];
+    """
+
+    @classmethod
+    def symtab_checks(cls, vmlinux) -> bool:
+        return vmlinux.has_symbol("nf_hooks")
+
+    def get_net_namespaces(self):
+        # In kernels <= 4.2.8 netfilter hooks are not implemented per namespaces
+        netns, net = renderers.NotAvailableValue(), renderers.NotAvailableValue()
+        yield netns, net
+
+    def get_hooks_container(self, net, proto_name, hook_name):
+        nf_hooks = self.vmlinux.object_from_symbol("nf_hooks")
+        if not nf_hooks:
+            return
+
+        yield nf_hooks
+
+    def get_hook_ops(self, hook_container, proto_idx, hook_idx):
+        list_head = hook_container[proto_idx][hook_idx]
+        nf_hooks_ops_name = self.get_symbol_fullname("nf_hook_ops")
+        return list_head.to_list(nf_hooks_ops_name, "list")
+
+
+class NetfilterImp_4_3_to_4_9(AbstractNetfilter):
+    """Netfilter hooks were added to network namepaces in 4.3.
+    It is still implemented as a linked list of 'struct nf_hook_ops' type but inside a
+    network namespace. One linked list per protocol per hook type.
+
+        struct net { ... struct netns_nf nf; ... }
+        struct netns_nf { ...
+            struct list_head hooks[NFPROTO_NUMPROTO][NF_MAX_HOOKS]; ... }
+    """
+
+    @classmethod
+    def symtab_checks(cls, vmlinux) -> bool:
+        return (
+            vmlinux.has_symbol("net_namespace_list")
+            and vmlinux.has_type("netns_nf")
+            and vmlinux.get_type("netns_nf").has_member("hooks")
+            and cls.get_member_type(vmlinux.get_type("netns_nf"), "hooks")
+            == ["array", "array", "list_head"]
+        )
+
+    def get_hook_ops(self, hook_container, proto_idx, hook_idx):
+        list_head = hook_container[proto_idx][hook_idx]
+        nf_hooks_ops_name = self.get_symbol_fullname("nf_hook_ops")
+        return list_head.to_list(nf_hooks_ops_name, "list")
+
+
+class NetfilterImp_4_9_to_4_14(AbstractNetfilter):
+    """In this range of kernel versions, the doubly-linked lists of netfilter hooks were
+    replaced by an array of arrays of 'nf_hook_entry' pointers in a singly-linked lists.
+        struct net { ... struct netns_nf nf; ... }
+        struct netns_nf { ..
+            struct nf_hook_entry __rcu *hooks[NFPROTO_NUMPROTO][NF_MAX_HOOKS]; ... }
+
+    Also in v4.10 the struct nf_hook_entry changed, a hook function pointer was added to
+    it. However, for simplicity of this design, we will still take the hook address from
+    the 'nf_hook_ops'. As per v5.0-rc2, the hook address is duplicated in both sides.
+    - v4.9:
+        struct nf_hook_entry {
+            struct nf_hook_entry      *next;
+            struct nf_hook_ops        ops;
+            const struct nf_hook_ops  *orig_ops; };
+    - v4.10:
+        struct nf_hook_entry {
+            struct nf_hook_entry      *next;
+            nf_hookfn                 *hook;
+            void                      *priv;
+            const struct nf_hook_ops  *orig_ops; };
+    (*) Even though the hook address is in the struct 'nf_hook_entry', we use the
+    original 'nf_hook_ops' hook address value, the one which was filled by the user, to
+    make it uniform to all the implementations.
+    """
+
+    @classmethod
+    def symtab_checks(cls, vmlinux) -> bool:
+        hooks_type = ["array", "array", "pointer", "nf_hook_entry"]
+        return (
+            vmlinux.has_symbol("net_namespace_list")
+            and vmlinux.has_type("netns_nf")
+            and vmlinux.get_type("netns_nf").has_member("hooks")
+            and cls.get_member_type(vmlinux.get_type("netns_nf"), "hooks") == hooks_type
+        )
+
+    def _get_hook_ops(self, hook_container, proto_idx, hook_idx):
+        list_head = hook_container[proto_idx][hook_idx]
+        nf_hooks_ops_name = self.get_symbol_fullname("nf_hook_ops")
+        return list_head.to_list(nf_hooks_ops_name, "list")
+
+    def get_hook_ops(self, hook_container, proto_idx, hook_idx):
+        nf_hook_entry_list = hook_container[proto_idx][hook_idx]
+        while nf_hook_entry_list:
+            yield nf_hook_entry_list.orig_ops
+            nf_hook_entry_list = nf_hook_entry_list.next
+
+
+class NetfilterImp_4_14_to_4_16(AbstractNetfilter):
+    """'nf_hook_ops' was removed from struct 'nf_hook_entry'. Instead, it was stored
+    adjacent in memory to the 'nf_hook_entry' array, in the new struct 'nf_hook_entries'
+    However, 'orig_ops' is not part of the 'nf_hook_entries' struct definition. So, we
+    have to craft it by hand.
+
+        struct net { ... struct netns_nf nf; ... }
+        struct netns_nf {
+            struct nf_hook_entries *hooks[NFPROTO_NUMPROTO][NF_MAX_HOOKS]; ... }
+        struct nf_hook_entries {
+            u16                         num_hook_entries; /* plus padding */
+            struct nf_hook_entry        hooks[];
+            //const struct nf_hook_ops *orig_ops[]; }
+        struct nf_hook_entry {
+            nf_hookfn   *hook;
+            void        *priv; }
+
+    (*) Even though the hook address is in the struct 'nf_hook_entry', we use the
+    original 'nf_hook_ops' hook address value, the one which was filled by the user, to
+    make it uniform to all the implementations.
+    """
+
+    @classmethod
+    def symtab_checks(cls, vmlinux) -> bool:
+        hooks_type = ["array", "array", "pointer", "nf_hook_entries"]
+        return (
+            vmlinux.has_symbol("net_namespace_list")
+            and vmlinux.has_type("netns_nf")
+            and vmlinux.get_type("netns_nf").has_member("hooks")
+            and cls.get_member_type(vmlinux.get_type("netns_nf"), "hooks") == hooks_type
+        )
+
+    def get_nf_hook_entries(self, nf_hooks_addr, proto_idx, hook_idx):
+        """This allows to support different hook array implementations from this version
+        on. For instance, in kernels >= 4.16 this multi-dimensional array is split in
+        one-dimensional array of pointers to 'nf_hooks_entries' per each protocol."""
+        return nf_hooks_addr[proto_idx][hook_idx]
+
+    def get_hook_ops(self, hook_container, proto_idx, hook_idx):
+        nf_hook_entries = self.get_nf_hook_entries(hook_container, proto_idx, hook_idx)
+        if not nf_hook_entries:
+            return
+
+        nf_hook_ops_name = self.get_symbol_fullname("nf_hook_ops")
+        nf_hook_ops_ptr_arr = self.build_nf_hook_ops_array(nf_hook_entries)
+        for nf_hook_ops_ptr in nf_hook_ops_ptr_arr:
+            nf_hook_ops = nf_hook_ops_ptr.dereference().cast(nf_hook_ops_name)
+            yield nf_hook_ops
+
+
+class NetfilterImp_4_16_to_latest(NetfilterImp_4_14_to_4_16):
+    """The multidimensional array of nf_hook_entries was split in a one-dimensional
+    array per each protocol.
+
+        struct net {
+            struct netns_nf nf; ... }
+        struct  netns_nf  {
+            struct nf_hook_entries * hooks_ipv4[NF_INET_NUMHOOKS];
+            struct nf_hook_entries * hooks_ipv6[NF_INET_NUMHOOKS];
+            struct nf_hook_entries * hooks_arp[NF_ARP_NUMHOOKS];
+            struct nf_hook_entries * hooks_bridge[NF_INET_NUMHOOKS];
+            struct nf_hook_entries * hooks_decnet[NF_DN_NUMHOOKS]; ... }
+        struct nf_hook_entries {
+                u16 num_hook_entries; /* plus padding */
+                struct nf_hook_entry hooks[];
+                //const struct nf_hook_ops *orig_ops[]; }
+        struct nf_hook_entry {
+            nf_hookfn   *hook;
+                void *priv; }
+
+    (*) Even though the hook address is in the struct nf_hook_entry, we use the original
+    nf_hook_ops hook address value, the one which was filled by the user, to make it
+    uniform to all the implementations.
+    """
+
+    @classmethod
+    def symtab_checks(cls, vmlinux) -> bool:
+        return (
+            vmlinux.has_symbol("net_namespace_list")
+            and vmlinux.has_type("netns_nf")
+            and vmlinux.get_type("netns_nf").has_member("hooks_ipv4")
+        )
+
+    def get_hooks_container(self, net, proto_name, hook_name):
+        try:
+            if proto_name == "IPV4":
+                net_nf_hooks = net.nf.hooks_ipv4
+            elif proto_name == "ARP":
+                net_nf_hooks = net.nf.hooks_arp
+            elif proto_name == "BRIDGE":
+                net_nf_hooks = net.nf.hooks_bridge
+            elif proto_name == "IPV6":
+                net_nf_hooks = net.nf.hooks_ipv6
+            elif proto_name == "DECNET":
+                net_nf_hooks = net.nf.hooks_decnet
+            else:
+                return
+
+            yield net_nf_hooks
+
+        except AttributeError:
+            # Protocol family disabled at kernel compilation
+            #  CONFIG_NETFILTER_FAMILY_ARP=n ||
+            #  CONFIG_NETFILTER_FAMILY_BRIDGE=n ||
+            #  CONFIG_DECNET=n
+            pass
+
+    def _get_nf_hook_entries_ptr(self, nf_hooks_addr, proto_idx, hook_idx):
+        nf_hook_entries_ptr = nf_hooks_addr[hook_idx]
+        return nf_hook_entries_ptr
+
+    def get_nf_hook_entries(self, nf_hooks_addr, proto_idx, hook_idx):
+        return nf_hooks_addr[hook_idx]
+
+
+class AbstractNetfilterNetDev(AbstractNetfilter):
+    """Base class to handle the Netfilter NetDev hooks.
+    It won't be executed. It has some common functions to all Netfilter NetDev hook
+    implementions.
+
+    Netfilter NetDev hooks are set per network device which belongs to a network
+    namespace.
+    """
+
+    @classmethod
+    def symtab_checks(cls, vmlinux) -> bool:
+        return False
+
+    def subscribed_protocols(self):
+        return ("NETDEV",)
+
+    def get_hooks_container(self, net, proto_name, hook_name):
+        net_device_type = self.vmlinux.get_type("net_device")
+        net_device_name = self.get_symbol_fullname("net_device")
+        for net_device in net.dev_base_head.to_list(net_device_name, "dev_list"):
+            if hook_name == "INGRESS":
+                if net_device_type.has_member("nf_hooks_ingress"):
+                    # CONFIG_NETFILTER_INGRESS=y
+                    yield net_device.nf_hooks_ingress
+
+            elif hook_name == "EGRESS":
+                if net_device_type.has_member("nf_hooks_egress"):
+                    # CONFIG_NETFILTER_EGRESS=y
+                    yield net_device.nf_hooks_egress
+
+
+class NetfilterNetDevImp_4_2_to_4_9(AbstractNetfilterNetDev):
+    """This is the first version of Netfilter Ingress hooks which was implemented using
+    a doubly-linked list of 'nf_hook_ops'.
+        struct list_head nf_hooks_ingress;
+    """
+
+    @classmethod
+    def symtab_checks(cls, vmlinux) -> bool:
+        hooks_type = ["list_head"]
+        return (
+            vmlinux.has_symbol("net_namespace_list")
+            and vmlinux.has_type("net_device")
+            and vmlinux.get_type("net_device").has_member("nf_hooks_ingress")
+            and cls.get_member_type(vmlinux.get_type("net_device"), "nf_hooks_ingress")
+            == hooks_type
+        )
+
+    def get_hook_ops(self, hook_container, proto_idx, hook_idx):
+        nf_hooks_ingress = hook_container
+        nf_hook_ops_name = self.get_symbol_fullname("nf_hook_ops")
+        return nf_hooks_ingress.to_list(nf_hook_ops_name, "list")
+
+
+class NetfilterNetDevImp_4_9_to_4_14(AbstractNetfilterNetDev):
+    """In 4.9 it was changed to a simple singly-linked list.
+    struct nf_hook_entry * nf_hooks_ingress;
+    """
+
+    @classmethod
+    def symtab_checks(cls, vmlinux) -> bool:
+        hooks_type = ["pointer", "nf_hook_entry"]
+        return (
+            vmlinux.has_symbol("net_namespace_list")
+            and vmlinux.has_type("net_device")
+            and vmlinux.get_type("net_device").has_member("nf_hooks_ingress")
+            and cls.get_member_type(vmlinux.get_type("net_device"), "nf_hooks_ingress")
+            == hooks_type
+        )
+
+    def get_hook_ops(self, hook_container, proto_idx, hook_idx):
+        nf_hooks_ingress_ptr = hook_container
+        if not nf_hooks_ingress_ptr:
+            return
+
+        while nf_hooks_ingress_ptr:
+            nf_hook_entry = nf_hooks_ingress_ptr.dereference()
+            orig_ops = nf_hook_entry.orig_ops.dereference()
+            yield orig_ops
+            nf_hooks_ingress_ptr = nf_hooks_ingress_ptr.next
+
+
+class NetfilterNetDevImp_4_14_to_latest(AbstractNetfilterNetDev):
+    """In 4.14 the hook list was converted to an array of pointers inside the struct
+    'nf_hook_entries':
+    struct nf_hook_entries * nf_hooks_ingress;
+    struct nf_hook_entries {
+            u16 num_hook_entries;
+            struct nf_hook_entry        hooks[];
+            //const struct nf_hook_ops *orig_ops[]; }
+    """
+
+    @classmethod
+    def symtab_checks(cls, vmlinux) -> bool:
+        hooks_type = ["pointer", "nf_hook_entries"]
+        return (
+            vmlinux.has_symbol("net_namespace_list")
+            and vmlinux.has_type("net_device")
+            and vmlinux.get_type("net_device").has_member("nf_hooks_ingress")
+            and cls.get_member_type(vmlinux.get_type("net_device"), "nf_hooks_ingress")
+            == hooks_type
+        )
+
+    def get_hook_ops(self, hook_container, proto_idx, hook_idx):
+        nf_hook_entries = hook_container
+        if not nf_hook_entries:
+            return
+
+        nf_hook_ops_name = self.get_symbol_fullname("nf_hook_ops")
+        nf_hook_ops_ptr_arr = self.build_nf_hook_ops_array(nf_hook_entries)
+        for nf_hook_ops_ptr in nf_hook_ops_ptr_arr:
+            nf_hook_ops = nf_hook_ops_ptr.dereference().cast(nf_hook_ops_name)
+            yield nf_hook_ops
+
+
+class Netfilter(interfaces.plugins.PluginInterface):
+    """Lists Netfilter hooks."""
+
+    _required_framework_version = (2, 0, 0)
+
+    _version = (1, 0, 0)
+
+    _required_linuxutils_version = (2, 1, 0)
+    _required_lsmod_version = (2, 0, 0)
+
+    @classmethod
+    def get_requirements(cls) -> List[interfaces.configuration.RequirementInterface]:
+        return [
+            requirements.ModuleRequirement(
+                name="kernel",
+                description="Linux kernel",
+                architectures=["Intel32", "Intel64"],
+            ),
+            requirements.PluginRequirement(
+                name="lsmod", plugin=lsmod.Lsmod, version=cls._required_lsmod_version
+            ),
+            requirements.VersionRequirement(
+                name="linuxutils",
+                component=linux.LinuxUtilities,
+                version=cls._required_linuxutils_version,
+            ),
+        ]
+
+    def _format_fields(self, fields):
+        (
+            netns,
+            proto_name,
+            hook_name,
+            priority,
+            hook_func,
+            module_name,
+            hooked,
+        ) = fields
+        return (
+            netns,
+            proto_name,
+            hook_name,
+            priority,
+            format_hints.Hex(hook_func),
+            module_name,
+            str(hooked),
+        )
+
+    def _generator(self):
+        kernel_module_name = self.config["kernel"]
+        for fields in AbstractNetfilter.run_all(
+            context=self.context, kernel_module_name=kernel_module_name
+        ):
+            yield (0, self._format_fields(fields))
+
+    def run(self):
+        headers = [
+            ("Net NS", int),
+            ("Proto", str),
+            ("Hook", str),
+            ("Priority", int),
+            ("Handler", format_hints.Hex),
+            ("Module", str),
+            ("Is Hooked", str),
+        ]
+        return renderers.TreeGrid(headers, self._generator())
diff --git a/volatility3/framework/plugins/timeliner.py b/volatility3/framework/plugins/timeliner.py
index d1c1c0f703..f657a29183 100644
--- a/volatility3/framework/plugins/timeliner.py
+++ b/volatility3/framework/plugins/timeliner.py
@@ -105,7 +105,9 @@ def _sort_function(self, item):
         data = item[1]
 
         def sortable(timestamp):
-            max_date = datetime.datetime(day=1, month=12, year=datetime.MAXYEAR)
+            max_date = datetime.datetime(
+                day=1, month=12, year=datetime.MAXYEAR, tzinfo=datetime.timezone.utc
+            )
             if isinstance(timestamp, interfaces.renderers.BaseAbsentValue):
                 return max_date
             return timestamp
@@ -183,16 +185,16 @@ def _generator(
                                     plugin_name,
                                     self._sanitize_body_format(item),
                                     self._text_format(
-                                        times.get(TimeLinerType.ACCESSED, "")
+                                        times.get(TimeLinerType.ACCESSED, "0")
                                     ),
                                     self._text_format(
-                                        times.get(TimeLinerType.MODIFIED, "")
+                                        times.get(TimeLinerType.MODIFIED, "0")
                                     ),
                                     self._text_format(
-                                        times.get(TimeLinerType.CHANGED, "")
+                                        times.get(TimeLinerType.CHANGED, "0")
                                     ),
                                     self._text_format(
-                                        times.get(TimeLinerType.CREATED, "")
+                                        times.get(TimeLinerType.CREATED, "0")
                                     ),
                                 )
                             )
diff --git a/volatility3/framework/plugins/vmscan.py b/volatility3/framework/plugins/vmscan.py
new file mode 100644
index 0000000000..64377d7d8c
--- /dev/null
+++ b/volatility3/framework/plugins/vmscan.py
@@ -0,0 +1,217 @@
+# This file is Copyright 2023 Volatility Foundation and licensed under the Volatility Software License 1.0
+# which is available at https://www.volatilityfoundation.org/license/vsl-v1.0
+#
+
+import enum
+import logging
+import os
+import struct
+from typing import Dict, List
+
+from volatility3.framework import constants, exceptions, interfaces, renderers
+from volatility3.framework.configuration import requirements
+from volatility3.framework.interfaces import configuration, plugins
+from volatility3.framework.renderers import format_hints
+from volatility3.framework.symbols import intermed
+
+vollog = logging.getLogger(__name__)
+
+
+class VMCSTest(enum.IntFlag):
+    VMCS_ABORT_INVALID = enum.auto()
+    VMCS_LINK_PTR_IS_NOT_FS = enum.auto()
+    VMCS_HOST_CR4_NO_VTX = enum.auto()
+    VMCS_CR3_IS_ZERO = enum.auto()
+    VMCS_GUEST_CR4_RESERVED = enum.auto()
+
+
+class PageStartScanner(interfaces.layers.ScannerInterface):
+    def __init__(self, signatures: List[bytes], page_size: int = 0x1000):
+        super().__init__()
+        if not len(signatures):
+            raise ValueError("No signatures passed to constructor")
+        self._siglen = len(signatures[0])
+        for item in signatures:
+            if len(item) != self._siglen:
+                raise ValueError(
+                    "Signatures of different lengths passed to PageStartScanner"
+                )
+        self._signatures = signatures
+        self._page_size = page_size
+
+    def __call__(self, data: bytes, data_offset: int):
+        """Scans only the start of every page, to see whether a signature is present or not"""
+        for page_start in range(
+            data_offset % self._page_size, len(data), self._page_size
+        ):
+            if data[page_start : page_start + self._siglen] in self._signatures:
+                yield (
+                    page_start + data_offset,
+                    data[page_start : page_start + self._siglen],
+                )
+
+
+class Vmscan(plugins.PluginInterface):
+    """Scans for Intel VT-d structues and generates VM volatility configs for them"""
+
+    _required_framework_version = (2, 2, 0)
+    _version = (1, 0, 0)
+
+    STRICTLY_REQUIRED_TESTS = {
+        VMCSTest.VMCS_ABORT_INVALID,
+        VMCSTest.VMCS_LINK_PTR_IS_NOT_FS,
+        VMCSTest.VMCS_HOST_CR4_NO_VTX,
+    }
+
+    @classmethod
+    def get_requirements(cls) -> List[interfaces.configuration.RequirementInterface]:
+        return [
+            requirements.TranslationLayerRequirement(
+                name="primary", description="Physical base memory layer"
+            ),
+            requirements.IntRequirement(
+                name="log-threshold",
+                description="Number of criteria failed to log to debug output",
+                default=2,
+                optional=True,
+            ),
+        ]
+
+    # Scan for VMCS structures based on the known VMCS structures
+    # found in symbols/vmcs directory
+
+    def _gather_vmcs_structures(
+        self, context: interfaces.context.ContextInterface, config_path: str
+    ) -> Dict[bytes, str]:
+        """Enumerate all JSON files containing VMCS information and return the structures
+        Signatures can be generated using data extracted using the vmcs_layout tool at
+        https://github.com/google/rekall/tree/master/tools/linux/vmcs_layout
+
+        Args:
+            context: The volatility context to work against
+            config_path: The location to store symbol table configurations under
+
+        Returns:
+            A dictionary of pattern bytes to the string representation of the architecture
+        """
+        filenames = intermed.IntermediateSymbolTable.file_symbol_url(
+            os.path.join("generic", "vmcs")
+        )
+        table_names = []
+        for filename in filenames:
+            base_name = os.path.basename(filename).split(".")[0]
+            table_name = intermed.IntermediateSymbolTable.create(
+                context,
+                configuration.path_join(config_path, "vmcs"),
+                os.path.join("generic", "vmcs"),
+                filename=base_name,
+            )
+            table_names.append(table_name)
+
+        result = {}
+        for table_name in table_names:
+            symbol_table = context.symbol_space[table_name]
+            revision_id = struct.pack(
+                "<I", int(symbol_table.get_symbol("revision_id").constant_data)
+            )
+            result[revision_id] = table_name
+
+        return result
+
+    @classmethod
+    def _verify_vmcs_page(
+        cls,
+        context: interfaces.context.ContextInterface,
+        vmcs: interfaces.objects.ObjectInterface,
+    ) -> List[str]:
+        """Runs tests to verify whether a block of data is a VMCS page
+        Some tests based on the Hypervisor Memory Forensics paper by
+        Mariano Graziano, Andrea Lanzi and Davide Balzarotti
+
+        Args:
+            context: The volatility context to be used for this call
+            vmcs: The instantiated VMCS object to verify
+
+        Returns:
+            The list of failed criteria that the VMCS did not meet
+        """
+
+        # The VMCS should have been constructed on the physical layer (even a nested VMCS)
+        physical_layer_name = vmcs.vol.layer_name
+
+        failed_tests: VMCSTest = VMCSTest(0)
+        # The abort field must be valid (generally 0, although other abort codes may exist)
+        if context.layers[physical_layer_name].read(vmcs.vol.offset + 4, 4) not in [
+            b"\x00\x00\x00\x00"
+        ]:
+            failed_tests |= VMCSTest.VMCS_ABORT_INVALID
+        # The vmcs link pointer is supposed to always be set
+        if vmcs.vmcs_link_ptr != 0xFFFFFFFFFFFFFFFF:
+            failed_tests |= VMCSTest.VMCS_LINK_PTR_IS_NOT_FS
+        # To have a VMCS the host needs the VTx bit set in CR4, this can false positive often when all bits are set
+        if (vmcs.host_cr4 & 1 << 13) == 0:
+            failed_tests |= VMCSTest.VMCS_HOST_CR4_NO_VTX
+        # The guest CR3 is *exceptionally* unlikely to be 0 and the guest cr4 is likely to have some bits unset
+        if (vmcs.guest_cr3 == 0) or (vmcs.host_cr3 == 0):
+            failed_tests |= VMCSTest.VMCS_CR3_IS_ZERO
+        # CR4 registers have certain bits reserved that should not be set
+        if vmcs.guest_cr4 & 0xFFFFFFFFFF889000:
+            failed_tests |= VMCSTest.VMCS_GUEST_CR4_RESERVED
+
+        if failed_tests and failed_tests.name:
+            failed_list = failed_tests.name.split("|")
+            return failed_list
+
+        return []
+
+    def _generator(self):
+        # Gather VMCS structures
+        structures = self._gather_vmcs_structures(self.context, self.config_path)
+        # Scan memory for them
+        layer = self.context.layers[self.config["primary"]]
+
+        # Try to move down to the highest physical layer
+        if layer.config.get("memory_layer"):
+            layer = self.context.layers[layer.config["memory_layer"]]
+
+        # Run the scan
+        for offset, match in layer.scan(
+            self.context,
+            PageStartScanner(list(structures.keys())),
+            self._progress_callback,
+        ):
+            try:
+                vmcs = self.context.object(
+                    structures[match] + constants.BANG + "_VMCS",
+                    layer.name,
+                    offset=offset,
+                )
+                failed_list = self._verify_vmcs_page(self.context, vmcs)
+                if not failed_list:
+                    yield (
+                        0,
+                        (
+                            structures[match],
+                            format_hints.Hex(vmcs.vol.offset),
+                            format_hints.Hex(vmcs.ept),
+                            format_hints.Hex(vmcs.guest_cr3),
+                        ),
+                    )
+                    if len(failed_list) <= self.config["log-threshold"]:
+                        vollog.debug(
+                            f"Potential {structures[match]} VMCS found at {vmcs.vol.offset:x} with failed criteria: {failed_list}"
+                        )
+            except (exceptions.InvalidAddressException, AttributeError):
+                # Not what we're looking for
+                continue
+
+    def run(self):
+        return renderers.TreeGrid(
+            [
+                ("Architecture", str),
+                ("VMCS Physical offset", format_hints.Hex),
+                ("EPT", format_hints.Hex),
+                ("Guest CR3", format_hints.Hex),
+            ],
+            self._generator(),
+        )
diff --git a/volatility3/framework/plugins/windows/callbacks.py b/volatility3/framework/plugins/windows/callbacks.py
index fcc333b9fa..d5eeda1ea3 100644
--- a/volatility3/framework/plugins/windows/callbacks.py
+++ b/volatility3/framework/plugins/windows/callbacks.py
@@ -2,16 +2,24 @@
 # which is available at https://www.volatilityfoundation.org/license/vsl-v1.0
 #
 
-import logging
 import contextlib
-from typing import List, Iterable, Tuple, Optional, Union
-
-from volatility3.framework import constants, exceptions, renderers, interfaces, symbols
+import logging
+from typing import Dict, Iterable, List, Optional, Tuple, Union, cast
+
+from volatility3.framework import (
+    constants,
+    exceptions,
+    interfaces,
+    objects,
+    renderers,
+    symbols,
+)
 from volatility3.framework.configuration import requirements
 from volatility3.framework.renderers import format_hints
 from volatility3.framework.symbols import intermed
 from volatility3.framework.symbols.windows import versions
-from volatility3.plugins.windows import ssdt
+from volatility3.framework.symbols.windows.extensions import callbacks
+from volatility3.plugins.windows import driverirp, handles, poolscanner, ssdt
 
 vollog = logging.getLogger(__name__)
 
@@ -20,7 +28,7 @@ class Callbacks(interfaces.plugins.PluginInterface):
     """Lists kernel callbacks and notification routines."""
 
     _required_framework_version = (2, 0, 0)
-    _version = (1, 0, 0)
+    _version = (2, 0, 0)
 
     @classmethod
     def get_requirements(cls) -> List[interfaces.configuration.RequirementInterface]:
@@ -33,27 +41,154 @@ def get_requirements(cls) -> List[interfaces.configuration.RequirementInterface]
             requirements.PluginRequirement(
                 name="ssdt", plugin=ssdt.SSDT, version=(1, 0, 0)
             ),
+            requirements.PluginRequirement(
+                name="poolscanner", plugin=poolscanner.PoolScanner, version=(1, 0, 0)
+            ),
+            requirements.PluginRequirement(
+                name="driverirp", plugin=driverirp.DriverIrp, version=(1, 0, 0)
+            ),
+            requirements.PluginRequirement(
+                name="handles", plugin=handles.Handles, version=(1, 0, 0)
+            ),
         ]
 
-    @staticmethod
-    def create_callback_table(
+    @classmethod
+    def create_callback_scan_constraints(
+        cls,
         context: interfaces.context.ContextInterface,
         symbol_table: str,
+        is_vista_or_above: bool,
+    ) -> List[poolscanner.PoolConstraint]:
+        """Creates a list of Pool Tag Constraints for callback objects.
+
+        Args:
+            context: The context to retrieve required elements (layers, symbol tables) from
+            symbol_table: The name of an existing symbol table containing the symbols / types
+            is_vista_or_above: A boolean indicating whether the OS version is Vista or newer.
+
+        Returns:
+            The list containing the built constraints.
+        """
+        constraints = cls._create_default_scan_constraints(context, symbol_table)
+        if is_vista_or_above:
+            constraints += cls._create_scan_constraints_vista_and_above(symbol_table)
+        return constraints
+
+    @staticmethod
+    def _create_default_scan_constraints(
+        context: interfaces.context.ContextInterface, symbol_table: str
+    ) -> List[poolscanner.PoolConstraint]:
+
+        shutdown_packet_size = context.symbol_space.get_type(
+            symbol_table + constants.BANG + "_SHUTDOWN_PACKET"
+        ).size
+        generic_callback_size = context.symbol_space.get_type(
+            symbol_table + constants.BANG + "_GENERIC_CALLBACK"
+        ).size
+        notification_packet_size = context.symbol_space.get_type(
+            symbol_table + constants.BANG + "_NOTIFICATION_PACKET"
+        ).size
+
+        return [
+            poolscanner.PoolConstraint(
+                b"IoFs",
+                type_name=symbol_table + constants.BANG + "_NOTIFICATION_PACKET",
+                size=(notification_packet_size, None),
+                page_type=poolscanner.PoolType.NONPAGED
+                | poolscanner.PoolType.PAGED
+                | poolscanner.PoolType.FREE,
+            ),
+            poolscanner.PoolConstraint(
+                b"IoSh",
+                type_name=symbol_table + constants.BANG + "_SHUTDOWN_PACKET",
+                size=(shutdown_packet_size, None),
+                page_type=poolscanner.PoolType.NONPAGED
+                | poolscanner.PoolType.PAGED
+                | poolscanner.PoolType.FREE,
+                index=(0, 0),
+            ),
+            poolscanner.PoolConstraint(
+                b"Cbrb",
+                type_name=symbol_table + constants.BANG + "_GENERIC_CALLBACK",
+                size=(generic_callback_size, None),
+                page_type=poolscanner.PoolType.NONPAGED
+                | poolscanner.PoolType.PAGED
+                | poolscanner.PoolType.FREE,
+            ),
+        ]
+
+    @staticmethod
+    def _create_scan_constraints_vista_and_above(
+        symbol_table: str,
+    ) -> List[poolscanner.PoolConstraint]:
+        """Creates a list of Pool Tag Constraints for callback objects.
+
+        Args:
+            context: The context to retrieve required elements (layers, symbol tables) from
+            symbol_table: The name of an existing symbol table containing the symbols / types
+
+        Returns:
+            The list containing the built constraints.
+        """
+
+        return [
+            poolscanner.PoolConstraint(
+                b"DbCb",
+                type_name=symbol_table + constants.BANG + "_DBGPRINT_CALLBACK",
+                size=(0x20, 0x40),
+                page_type=poolscanner.PoolType.NONPAGED
+                | poolscanner.PoolType.PAGED
+                | poolscanner.PoolType.FREE,
+            ),
+            poolscanner.PoolConstraint(
+                b"Pnp9",
+                type_name=symbol_table + constants.BANG + "_NOTIFY_ENTRY_HEADER",
+                size=(0x30, None),
+                page_type=poolscanner.PoolType.NONPAGED
+                | poolscanner.PoolType.PAGED
+                | poolscanner.PoolType.FREE,
+                index=(1, 1),
+            ),
+            poolscanner.PoolConstraint(
+                b"PnpD",
+                type_name=symbol_table + constants.BANG + "_NOTIFY_ENTRY_HEADER",
+                size=(0x40, None),
+                page_type=poolscanner.PoolType.NONPAGED
+                | poolscanner.PoolType.PAGED
+                | poolscanner.PoolType.FREE,
+                index=(1, 1),
+            ),
+            poolscanner.PoolConstraint(
+                b"PnpC",
+                type_name=symbol_table + constants.BANG + "_NOTIFY_ENTRY_HEADER",
+                size=(0x38, None),
+                page_type=poolscanner.PoolType.NONPAGED
+                | poolscanner.PoolType.PAGED
+                | poolscanner.PoolType.FREE,
+                index=(1, 1),
+            ),
+        ]
+
+    @classmethod
+    def create_callback_symbol_table(
+        cls,
+        context: interfaces.context.ContextInterface,
+        nt_symbol_table: str,
         config_path: str,
     ) -> str:
-        """Creates a symbol table for a set of callbacks.
+        """Creates a symbol table for kernel callback objects.
 
         Args:
             context: The context to retrieve required elements (layers, symbol tables) from
-            symbol_table: The name of an existing symbol table containing the kernel symbols
-            config_path: The configuration path within the context of the symbol table to create
+            nt_symbol_table: The name of the table containing the kernel symbols
+            config_path: The config path where to find symbol files
 
         Returns:
-            The name of the constructed callback table
+            The name of the constructed symbol table
         """
-        native_types = context.symbol_space[symbol_table].natives
-        is_64bit = symbols.symbol_table_is_64bit(context, symbol_table)
-        table_mapping = {"nt_symbols": symbol_table}
+        native_types = context.symbol_space[nt_symbol_table].natives
+        is_64bit = symbols.symbol_table_is_64bit(context, nt_symbol_table)
+        table_mapping = {"nt_symbols": nt_symbol_table}
 
         if is_64bit:
             symbol_filename = "callbacks-x64"
@@ -65,10 +200,143 @@ def create_callback_table(
             config_path,
             "windows",
             symbol_filename,
+            class_types=callbacks.class_types_x86 if not is_64bit else None,
             native_types=native_types,
             table_mapping=table_mapping,
         )
 
+    @classmethod
+    def scan(
+        cls,
+        context: interfaces.context.ContextInterface,
+        layer_name: str,
+        nt_symbol_table: str,
+        callback_symbol_table: str,
+    ) -> Iterable[
+        Tuple[
+            Union[str, interfaces.renderers.BaseAbsentValue],
+            int,
+            Union[str, interfaces.renderers.BaseAbsentValue],
+        ]
+    ]:
+        """Scans for callback objects using the poolscanner module and constraints.
+
+        Args:
+            context: The context to retrieve required elements (layers, symbol tables) from
+            layer_name: The name of the layer on which to operate
+            nt_symbol_table: The name of the table containing the kernel symbols
+            callback_symbol_table: The name of the table containing the callback object symbols (_SHUTDOWN_PACKET etc.)
+
+        Returns:
+            A list of callback objects found by scanning the `layer_name` layer for callback pool signatures
+        """
+        is_vista_or_later = versions.is_vista_or_later(
+            context=context, symbol_table=nt_symbol_table
+        )
+
+        type_map = handles.Handles.get_type_map(context, layer_name, nt_symbol_table)
+
+        constraints = cls.create_callback_scan_constraints(
+            context, callback_symbol_table, is_vista_or_later
+        )
+
+        for (
+            _constraint,
+            mem_object,
+            _header,
+        ) in poolscanner.PoolScanner.generate_pool_scan(
+            context, layer_name, nt_symbol_table, constraints
+        ):
+            try:
+                if hasattr(mem_object, "is_valid") and not mem_object.is_valid():
+                    continue
+
+                yield cls._process_scanned_callback(mem_object, type_map)
+            except exceptions.InvalidAddressException:
+                continue
+
+    @classmethod
+    def _process_scanned_callback(
+        cls, memory_object: objects.StructType, type_map: Dict[int, str]
+    ) -> Tuple[
+        Union[str, interfaces.renderers.BaseAbsentValue],
+        int,
+        Union[str, interfaces.renderers.BaseAbsentValue],
+    ]:
+        symbol_table = memory_object.get_symbol_table_name()
+        type_name = memory_object.vol.type_name
+
+        if isinstance(memory_object, callbacks._SHUTDOWN_PACKET) or (
+            type_name == symbol_table + constants.BANG + "_SHUTDOWN_PACKET"
+        ):
+            callback_type = "IoRegisterShutdownNotification"
+
+            try:
+                driver = memory_object.DeviceObject.DriverObject
+                index = driverirp.MAJOR_FUNCTIONS.index("IRP_MJ_SHUTDOWN")
+                callback_address = driver.MajorFunction[index]
+                details = driver.DriverName.String or renderers.UnparsableValue()
+            except exceptions.InvalidAddressException:
+                callback_address = memory_object.vol.offset
+                details = renderers.NotApplicableValue()
+
+        elif type_name == symbol_table + constants.BANG + "_NOTIFICATION_PACKET":
+            callback_type = "IoRegisterFsRegistrationChange"
+            callback_address = memory_object.NotificationRoutine
+            details = renderers.NotApplicableValue()
+
+        elif type_name == symbol_table + constants.BANG + "_NOTIFY_ENTRY_HEADER":
+            driver = (
+                memory_object.DriverObject.dereference()
+                if memory_object.DriverObject.is_readable()
+                else None
+            )
+
+            if driver:
+                # Instantiate an object header for the driver name
+                header = driver.get_object_header()
+                try:
+                    if header.get_object_type(type_map) == "Driver":
+                        # Grab the object name
+                        details = header.NameInfo.Name.String
+                    else:
+                        details = renderers.NotApplicableValue()
+                except exceptions.InvalidAddressException:
+                    details = renderers.UnreadableValue()
+            else:
+                details = renderers.UnreadableValue()
+
+            callback_type = (
+                memory_object.EventCategory.description
+                if memory_object.EventCategory.is_valid_choice
+                else renderers.UnparsableValue()
+            )
+
+            callback_address = memory_object.CallbackRoutine
+
+        elif type_name == symbol_table + constants.BANG + "_GENERIC_CALLBACK":
+            callback_type = "GenericKernelCallback"
+            callback_address = memory_object.Callback
+            details = renderers.NotApplicableValue()
+
+        elif type_name == symbol_table + constants.BANG + "_DBGPRINT_CALLBACK":
+            callback_type = "DbgSetDebugPrintCallback"
+            callback_address = memory_object.Function
+            details = renderers.NotApplicableValue()
+
+        else:
+            raise ValueError(f"Unexpected object type {type_name}")
+
+        return (
+            callback_type,
+            callback_address,
+            (
+                details
+                if not isinstance(details, interfaces.renderers.BaseAbsentValue)
+                else details
+            ),
+        )
+
     @classmethod
     def list_notify_routines(
         cls,
@@ -115,11 +383,14 @@ def list_notify_routines(
             else:
                 count = 8
 
-            fast_refs = ntkrnlmp.object(
-                object_type="array",
-                offset=symbol_offset,
-                subtype=ntkrnlmp.get_type("_EX_FAST_REF"),
-                count=count,
+            fast_refs = cast(
+                List[objects.Pointer],
+                ntkrnlmp.object(
+                    object_type="array",
+                    offset=symbol_offset,
+                    subtype=ntkrnlmp.get_type("_EX_FAST_REF"),
+                    count=count,
+                ),
             )
 
             for fast_ref in fast_refs:
@@ -159,11 +430,14 @@ def _list_registry_callbacks_legacy(
         if callback_count == 0:
             return None
 
-        fast_refs = ntkrnlmp.object(
-            object_type="array",
-            offset=symbol_offset,
-            subtype=ntkrnlmp.get_type("_EX_FAST_REF"),
-            count=callback_count,
+        fast_refs = cast(
+            List[objects.Pointer],
+            ntkrnlmp.object(
+                object_type="array",
+                offset=symbol_offset,
+                subtype=ntkrnlmp.get_type("_EX_FAST_REF"),
+                count=callback_count,
+            ),
         )
 
         for fast_ref in fast_refs:
@@ -265,7 +539,13 @@ def list_bugcheck_reason_callbacks(
         layer_name: str,
         symbol_table: str,
         callback_table_name: str,
-    ) -> Iterable[Tuple[str, int, str]]:
+    ) -> Iterable[
+        Tuple[
+            str,
+            int,
+            interfaces.renderers.BaseAbsentValue,
+        ]
+    ]:
         """Lists all kernel bugcheck reason callbacks.
 
         Args:
@@ -323,7 +603,13 @@ def list_bugcheck_callbacks(
         layer_name: str,
         symbol_table: str,
         callback_table_name: str,
-    ) -> Iterable[Tuple[str, int, str]]:
+    ) -> Iterable[
+        Tuple[
+            str,
+            int,
+            Union[interfaces.objects.ObjectInterface, renderers.UnreadableValue],
+        ]
+    ]:
         """Lists all kernel bugcheck callbacks.
 
         Args:
@@ -372,7 +658,7 @@ def list_bugcheck_callbacks(
     def _generator(self):
         kernel = self.context.modules[self.config["kernel"]]
 
-        callback_table_name = self.create_callback_table(
+        callback_symbol_table = self.create_callback_symbol_table(
             self.context, kernel.symbol_table_name, self.config_path
         )
 
@@ -385,6 +671,7 @@ def _generator(self):
             self.list_bugcheck_callbacks,
             self.list_bugcheck_reason_callbacks,
             self.list_registry_callbacks,
+            self.scan,
         )
 
         for callback_method in callback_methods:
@@ -392,7 +679,7 @@ def _generator(self):
                 self.context,
                 kernel.layer_name,
                 kernel.symbol_table_name,
-                callback_table_name,
+                callback_symbol_table,
             ):
                 if callback_detail is None:
                     detail = renderers.NotApplicableValue()
diff --git a/volatility3/framework/plugins/windows/dlllist.py b/volatility3/framework/plugins/windows/dlllist.py
index f876dc1a21..5a1b37fcf8 100644
--- a/volatility3/framework/plugins/windows/dlllist.py
+++ b/volatility3/framework/plugins/windows/dlllist.py
@@ -1,10 +1,10 @@
-# This file is Copyright 2019 Volatility Foundation and licensed under the Volatility Software License 1.0
+# This file is Copyright 2024 Volatility Foundation and licensed under the Volatility Software License 1.0
 # which is available at https://www.volatilityfoundation.org/license/vsl-v1.0
 #
 import contextlib
 import datetime
 import logging
-import ntpath
+import re
 from typing import List, Optional, Type
 
 from volatility3.framework import constants, exceptions, interfaces, renderers
@@ -13,7 +13,7 @@
 from volatility3.framework.symbols import intermed
 from volatility3.framework.symbols.windows.extensions import pe
 from volatility3.plugins import timeliner
-from volatility3.plugins.windows import info, pslist, psscan
+from volatility3.plugins.windows import info, pslist, psscan, pedump
 
 vollog = logging.getLogger(__name__)
 
@@ -22,7 +22,7 @@ class DllList(interfaces.plugins.PluginInterface, timeliner.TimeLinerInterface):
     """Lists the loaded modules in a particular windows memory image."""
 
     _required_framework_version = (2, 0, 0)
-    _version = (2, 0, 0)
+    _version = (3, 0, 0)
 
     @classmethod
     def get_requirements(cls) -> List[interfaces.configuration.RequirementInterface]:
@@ -53,73 +53,33 @@ def get_requirements(cls) -> List[interfaces.configuration.RequirementInterface]
                 description="Process offset in the physical address space",
                 optional=True,
             ),
+            requirements.StringRequirement(
+                name="name",
+                description="Specify a regular expression to match dll name(s)",
+                optional=True,
+            ),
+            requirements.IntRequirement(
+                name="base",
+                description="Specify a base virtual address in process memory",
+                optional=True,
+            ),
+            requirements.BooleanRequirement(
+                name="ignore-case",
+                description="Specify case insensitivity for the regular expression name matching",
+                default=False,
+                optional=True,
+            ),
             requirements.BooleanRequirement(
                 name="dump",
                 description="Extract listed DLLs",
                 default=False,
                 optional=True,
             ),
+            requirements.VersionRequirement(
+                name="pedump", component=pedump.PEDump, version=(1, 0, 0)
+            ),
         ]
 
-    @classmethod
-    def dump_pe(
-        cls,
-        context: interfaces.context.ContextInterface,
-        pe_table_name: str,
-        dll_entry: interfaces.objects.ObjectInterface,
-        open_method: Type[interfaces.plugins.FileHandlerInterface],
-        layer_name: str = None,
-        prefix: str = "",
-    ) -> Optional[interfaces.plugins.FileHandlerInterface]:
-        """Extracts the complete data for a process as a FileInterface
-
-        Args:
-            context: the context to operate upon
-            pe_table_name: the name for the symbol table containing the PE format symbols
-            dll_entry: the object representing the module
-            layer_name: the layer that the DLL lives within
-            open_method: class for constructing output files
-
-        Returns:
-            An open FileHandlerInterface object containing the complete data for the DLL or None in the case of failure
-        """
-        try:
-            try:
-                name = dll_entry.FullDllName.get_string()
-            except exceptions.InvalidAddressException:
-                name = "UnreadableDLLName"
-
-            if layer_name is None:
-                layer_name = dll_entry.vol.layer_name
-
-            file_handle = open_method(
-                "{}{}.{:#x}.{:#x}.dmp".format(
-                    prefix,
-                    ntpath.basename(name),
-                    dll_entry.vol.offset,
-                    dll_entry.DllBase,
-                )
-            )
-
-            dos_header = context.object(
-                pe_table_name + constants.BANG + "_IMAGE_DOS_HEADER",
-                offset=dll_entry.DllBase,
-                layer_name=layer_name,
-            )
-
-            for offset, data in dos_header.reconstruct():
-                file_handle.seek(offset)
-                file_handle.write(data)
-        except (
-            IOError,
-            exceptions.VolatilityException,
-            OverflowError,
-            ValueError,
-        ) as excp:
-            vollog.debug(f"Unable to dump dll at offset {dll_entry.DllBase}: {excp}")
-            return None
-        return file_handle
-
     def _generator(self, procs):
         pe_table_name = intermed.IntermediateSymbolTable.create(
             self.context, self.config_path, "windows", "pe", class_types=pe.class_types
@@ -144,9 +104,35 @@ def _generator(self, procs):
                 BaseDllName = FullDllName = renderers.UnreadableValue()
                 with contextlib.suppress(exceptions.InvalidAddressException):
                     BaseDllName = entry.BaseDllName.get_string()
-                    # We assume that if the BaseDllName points to an invalid buffer, so will FullDllName
+                    # We assume that if BaseDllName points to invalid buffer, so will FullDllName
                     FullDllName = entry.FullDllName.get_string()
 
+                # Check if a name regex was passed and apply it to only show matches
+                if self.config["name"]:
+                    try:
+                        flags = re.I if self.config["ignore-case"] else 0
+                        mod_re = re.compile(self.config["name"], flags)
+                    except re.error:
+                        vollog.debug(
+                            "Error parsing regular expression: %s", self.config["name"]
+                        )
+                        return None
+
+                    # If Base or Full Dll Name are invalid, move on
+                    if isinstance(BaseDllName, renderers.UnreadableValue) or isinstance(
+                        FullDllName, renderers.UnreadableValue
+                    ):
+                        continue
+
+                    # If regex does not match, move on
+                    if not mod_re.search(BaseDllName) and not mod_re.search(
+                        FullDllName
+                    ):
+                        continue
+
+                if self.config["base"] and self.config["base"] != entry.DllBase:
+                    continue
+
                 if dll_load_time_field:
                     # Versions prior to 6.1 won't have the LoadTime attribute
                     # and 32bit version shouldn't have the Quadpart according to MSDN
@@ -161,7 +147,7 @@ def _generator(self, procs):
 
                 file_output = "Disabled"
                 if self.config["dump"]:
-                    file_handle = self.dump_pe(
+                    file_output = pedump.PEDump.dump_ldr_entry(
                         self.context,
                         pe_table_name,
                         entry,
@@ -169,10 +155,10 @@ def _generator(self, procs):
                         proc_layer_name,
                         prefix=f"pid.{proc_id}.",
                     )
-                    file_output = "Error outputting file"
-                    if file_handle:
-                        file_handle.close()
-                        file_output = file_handle.preferred_filename
+
+                    if not file_output:
+                        file_output = "Error outputting file"
+
                 try:
                     dllbase = format_hints.Hex(entry.DllBase)
                 except exceptions.InvalidAddressException:
diff --git a/volatility3/framework/plugins/windows/driverirp.py b/volatility3/framework/plugins/windows/driverirp.py
index 433c61ca2e..c3eb7c5c16 100644
--- a/volatility3/framework/plugins/windows/driverirp.py
+++ b/volatility3/framework/plugins/windows/driverirp.py
@@ -44,6 +44,7 @@ class DriverIrp(interfaces.plugins.PluginInterface):
     """List IRPs for drivers in a particular windows memory image."""
 
     _required_framework_version = (2, 0, 0)
+    _version = (1, 0, 0)
 
     @classmethod
     def get_requirements(cls):
diff --git a/volatility3/framework/plugins/windows/dumpfiles.py b/volatility3/framework/plugins/windows/dumpfiles.py
index 48539c7525..33d2d0d41d 100755
--- a/volatility3/framework/plugins/windows/dumpfiles.py
+++ b/volatility3/framework/plugins/windows/dumpfiles.py
@@ -244,6 +244,8 @@ def _generator(self, procs: List, offsets: List):
                 symbol_table=kernel.symbol_table_name,
             )
 
+            dumped_files = set()
+
             for proc in procs:
                 try:
                     object_table = proc.ObjectTable
@@ -267,6 +269,10 @@ def _generator(self, procs: List, offsets: List):
                                 if not file_re.search(name):
                                     continue
 
+                            if file_obj.vol.offset in dumped_files:
+                                continue
+                            dumped_files.add(file_obj.vol.offset)
+
                             for result in self.process_file_object(
                                 self.context, kernel.layer_name, self.open, file_obj
                             ):
@@ -303,6 +309,10 @@ def _generator(self, procs: List, offsets: List):
                             if not file_re.search(name):
                                 continue
 
+                        if file_obj.vol.offset in dumped_files:
+                            continue
+                        dumped_files.add(file_obj.vol.offset)
+
                         for result in self.process_file_object(
                             self.context, kernel.layer_name, self.open, file_obj
                         ):
diff --git a/volatility3/framework/plugins/windows/filescan.py b/volatility3/framework/plugins/windows/filescan.py
index 0f68f39d47..82566361de 100644
--- a/volatility3/framework/plugins/windows/filescan.py
+++ b/volatility3/framework/plugins/windows/filescan.py
@@ -14,6 +14,7 @@ class FileScan(interfaces.plugins.PluginInterface):
     """Scans for file objects present in a particular windows memory image."""
 
     _required_framework_version = (2, 0, 0)
+    _version = (1, 0, 1)
 
     @classmethod
     def get_requirements(cls):
@@ -67,10 +68,10 @@ def _generator(self):
             except exceptions.InvalidAddressException:
                 continue
 
-            yield (0, (format_hints.Hex(fileobj.vol.offset), file_name, fileobj.Size))
+            yield (0, (format_hints.Hex(fileobj.vol.offset), file_name))
 
     def run(self):
         return renderers.TreeGrid(
-            [("Offset", format_hints.Hex), ("Name", str), ("Size", int)],
+            [("Offset", format_hints.Hex), ("Name", str)],
             self._generator(),
         )
diff --git a/volatility3/framework/plugins/windows/handles.py b/volatility3/framework/plugins/windows/handles.py
index d43d26ef19..3e5a2fd826 100644
--- a/volatility3/framework/plugins/windows/handles.py
+++ b/volatility3/framework/plugins/windows/handles.py
@@ -25,7 +25,7 @@ class Handles(interfaces.plugins.PluginInterface):
     """Lists process open handles."""
 
     _required_framework_version = (2, 0, 0)
-    _version = (1, 0, 0)
+    _version = (1, 0, 2)
 
     def __init__(self, *args, **kwargs):
         super().__init__(*args, **kwargs)
@@ -142,9 +142,13 @@ def find_sar_value(self):
         pointers in the _HANDLE_TABLE_ENTRY which allows us to find the
         associated _OBJECT_HEADER.
         """
+        DEFAULT_SAR_VALUE = 0x10  # to be used only when decoding fails
 
         if self._sar_value is None:
             if not has_capstone:
+                vollog.debug(
+                    "capstone module is missing, unable to create disassembly of ObpCaptureHandleInformationEx"
+                )
                 return None
             kernel = self.context.modules[self.config["kernel"]]
 
@@ -159,25 +163,48 @@ def find_sar_value(self):
             try:
                 func_addr = ntkrnlmp.get_symbol("ObpCaptureHandleInformationEx").address
             except exceptions.SymbolError:
+                vollog.debug("Unable to locate ObpCaptureHandleInformationEx symbol")
                 return None
 
-            data = self.context.layers.read(virtual_layer_name, kvo + func_addr, 0x200)
-            if data is None:
-                return None
+            try:
+                func_addr_to_read = kvo + func_addr
+                num_bytes_to_read = 0x200
+                vollog.debug(
+                    f"ObpCaptureHandleInformationEx symbol located at {hex(func_addr_to_read)}"
+                )
+                data = self.context.layers.read(
+                    virtual_layer_name, func_addr_to_read, num_bytes_to_read
+                )
+            except exceptions.InvalidAddressException:
+                vollog.warning(
+                    f"Failed to read {hex(num_bytes_to_read)} bytes at symbol {hex(func_addr_to_read)}. Unable to decode SAR value. Failing back to a common value of {hex(DEFAULT_SAR_VALUE)}"
+                )
+                self._sar_value = DEFAULT_SAR_VALUE
+                return self._sar_value
 
             md = capstone.Cs(capstone.CS_ARCH_X86, capstone.CS_MODE_64)
 
+            instruction_count = 0
             for address, size, mnemonic, op_str in md.disasm_lite(
                 data, kvo + func_addr
             ):
                 # print("{} {} {} {}".format(address, size, mnemonic, op_str))
-
+                instruction_count += 1
                 if mnemonic.startswith("sar"):
                     # if we don't want to parse op strings, we can disasm the
                     # single sar instruction again, but we use disasm_lite for speed
                     self._sar_value = int(op_str.split(",")[1].strip(), 16)
+                    vollog.debug(
+                        f"SAR located at {hex(address)} with value of {hex(self._sar_value)}"
+                    )
                     break
 
+            if self._sar_value is None:
+                vollog.warning(
+                    f"Failed to to locate SAR value having parsed {instruction_count} instructions, failing back to a common value of {hex(DEFAULT_SAR_VALUE)}"
+                )
+                self._sar_value = DEFAULT_SAR_VALUE
+
         return self._sar_value
 
     @classmethod
diff --git a/volatility3/framework/plugins/windows/hollowprocesses.py b/volatility3/framework/plugins/windows/hollowprocesses.py
new file mode 100644
index 0000000000..69fa94f063
--- /dev/null
+++ b/volatility3/framework/plugins/windows/hollowprocesses.py
@@ -0,0 +1,237 @@
+# This file is Copyright 2024 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 NamedTuple, Dict, Generator
+
+from volatility3.framework import interfaces, exceptions, constants
+from volatility3.framework import renderers
+from volatility3.framework.configuration import requirements
+from volatility3.framework.objects import utility
+from volatility3.plugins.windows import pslist, vadinfo
+
+vollog = logging.getLogger(__name__)
+
+VadData = NamedTuple(
+    "VadData",
+    [
+        ("protection", str),
+        ("path", str),
+    ],
+)
+
+DLLData = NamedTuple(
+    "DLLData",
+    [
+        ("path", str),
+    ],
+)
+
+### Useful references on process hollowing
+# https://cysinfo.com/detecting-deceptive-hollowing-techniques/
+# https://github.com/m0n0ph1/Process-Hollowing
+
+
+class HollowProcesses(interfaces.plugins.PluginInterface):
+    """Lists hollowed processes"""
+
+    _required_framework_version = (2, 4, 0)
+
+    @classmethod
+    def get_requirements(cls):
+        # Since we're calling the plugin, make sure we have the plugin's requirements
+        return [
+            requirements.ModuleRequirement(
+                name="kernel",
+                description="Windows kernel",
+                architectures=["Intel32", "Intel64"],
+            ),
+            requirements.ListRequirement(
+                name="pid",
+                element_type=int,
+                description="Process IDs to include (all other processes are excluded)",
+                optional=True,
+            ),
+            requirements.VersionRequirement(
+                name="pslist", component=pslist.PsList, version=(2, 0, 0)
+            ),
+            requirements.VersionRequirement(
+                name="vadinfo", component=vadinfo.VadInfo, version=(2, 0, 0)
+            ),
+        ]
+
+    def _get_vads_data(
+        self, proc: interfaces.objects.ObjectInterface
+    ) -> Dict[int, VadData]:
+        """
+        Returns a dictionary of:
+            base address -> (protection string, file name)
+        For each mapped VAD in the process. This is used
+        for quick lookups of data and matching the DLL
+        at the same base address as the VAD
+        """
+        vads = {}
+
+        kernel = self.context.modules[self.config["kernel"]]
+
+        for vad in proc.get_vad_root().traverse():
+            protection_string = vad.get_protection(
+                vadinfo.VadInfo.protect_values(
+                    self.context, kernel.layer_name, kernel.symbol_table_name
+                ),
+                vadinfo.winnt_protections,
+            )
+
+            fn = vad.get_file_name()
+            if not fn or not isinstance(fn, str):
+                fn = "<Non-File Backed Region>"
+
+            vads[vad.get_start()] = VadData(protection_string, fn)
+
+        return vads
+
+    def _get_dlls_map(
+        self, proc: interfaces.objects.ObjectInterface
+    ) -> Dict[int, DLLData]:
+        """
+        Returns a dictionary of:
+            base address -> path
+        for each DLL loaded in the process
+
+        This is used to cross compare with
+        the corresponding VAD and to have a
+        backup path source in case of smear
+        in the VAD
+        """
+        dlls = {}
+
+        for entry in proc.load_order_modules():
+            try:
+                base = entry.DllBase
+            except exceptions.InvalidAddressException:
+                continue
+
+            try:
+                FullDllName = entry.FullDllName.get_string()
+            except exceptions.InvalidAddressException:
+                FullDllName = renderers.UnreadableValue()
+
+            dlls[base] = DLLData(FullDllName)
+
+        return dlls
+
+    def _get_image_base(self, proc: interfaces.objects.ObjectInterface) -> int:
+        """
+        Uses the PEB to get the image base of the process
+        """
+        kernel = self.context.modules[self.config["kernel"]]
+
+        try:
+            proc_layer_name = proc.add_process_layer()
+            peb = self.context.object(
+                kernel.symbol_table_name + constants.BANG + "_PEB",
+                layer_name=proc_layer_name,
+                offset=proc.Peb,
+            )
+            return peb.ImageBaseAddress
+        except exceptions.InvalidAddressException:
+            return None
+
+    def _check_load_address(self, proc, _, __) -> Generator[str, None, None]:
+        """
+        Detects when the image base in the PEB, which is writable by process malware,
+        does not match the section base address - whose value lives in kernel memory.
+        Many malware samples will manipulate their image base to fool AVs/EDRs and
+        as a necessary part of certain hollowing techniques
+        """
+        image_base = self._get_image_base(proc)
+        if image_base is not None and image_base != proc.SectionBaseAddress:
+            yield "The ImageBaseAddress reported from the PEB ({:#x}) does not match the process SectionBaseAddress ({:#x})".format(
+                image_base, proc.SectionBaseAddress
+            )
+
+    def _check_exe_protection(
+        self, proc, vads: Dict[int, VadData], __
+    ) -> Generator[str, None, None]:
+        """
+        Legitimately mapped application executables and DLLs
+        will have a VAD present and its initial protection will be
+        PAGE_EXECUTE_WRITECOPY.
+        Many process hollowing and code injection techniques will
+        unmap the real executable and/or map in executables with
+        incorrect permissions.
+        This check verifies the VAD for the application exe.
+        `_check_dlls_protection` checks for DLLs mapped in the process.
+        """
+        base = proc.SectionBaseAddress
+
+        if base not in vads:
+            yield "There is no VAD starting at the base address of the process executable ({:#x})".format(
+                base
+            )
+        elif vads[base].protection != "PAGE_EXECUTE_WRITECOPY":
+            yield "Unexpected protection ({}) for VAD hosting the process executable ({:#x}) with path {}".format(
+                vads[base].protection, base, vads[base].path
+            )
+
+    def _check_dlls_protection(
+        self, _, vads: Dict[int, VadData], dlls: Dict[int, DLLData]
+    ) -> Generator[str, None, None]:
+        for dll_base in dlls:
+            # could be malicious but triggers too many FPs from smear
+            if dll_base not in vads:
+                continue
+
+            # PAGE_EXECUTE_WRITECOPY is the only valid permission for mapped DLLs and .exe files
+            if vads[dll_base].protection != "PAGE_EXECUTE_WRITECOPY":
+                yield "Unexpected protection ({}) for DLL in the PEB's load order list ({:#x}) with path {}".format(
+                    vads[dll_base].protection, dll_base, dlls[dll_base].path
+                )
+
+    def _generator(self, procs):
+        checks = [
+            self._check_load_address,
+            self._check_exe_protection,
+            self._check_dlls_protection,
+        ]
+
+        for proc in procs:
+            # smear and/or terminated process
+            dlls = self._get_dlls_map(proc)
+            if len(dlls) < 3:
+                continue
+
+            vads = self._get_vads_data(proc)
+            if len(vads) < 5:
+                continue
+
+            proc_name = utility.array_to_string(proc.ImageFileName)
+            pid = proc.UniqueProcessId
+
+            for check in checks:
+                for note in check(proc, vads, dlls):
+                    yield 0, (
+                        pid,
+                        proc_name,
+                        note,
+                    )
+
+    def run(self):
+        filter_func = pslist.PsList.create_pid_filter(self.config.get("pid", None))
+        kernel = self.context.modules[self.config["kernel"]]
+
+        return renderers.TreeGrid(
+            [
+                ("PID", int),
+                ("Process", str),
+                ("Notes", str),
+            ],
+            self._generator(
+                pslist.PsList.list_processes(
+                    context=self.context,
+                    layer_name=kernel.layer_name,
+                    symbol_table=kernel.symbol_table_name,
+                    filter_func=filter_func,
+                )
+            ),
+        )
diff --git a/volatility3/framework/plugins/windows/info.py b/volatility3/framework/plugins/windows/info.py
index 100a677c2e..137d29c225 100644
--- a/volatility3/framework/plugins/windows/info.py
+++ b/volatility3/framework/plugins/windows/info.py
@@ -10,7 +10,7 @@
 from volatility3.framework.interfaces import plugins
 from volatility3.framework.renderers import TreeGrid
 from volatility3.framework.symbols import intermed
-from volatility3.framework.symbols.windows import extensions
+from volatility3.framework.symbols.windows.extensions import kdbg, pe
 
 
 class Info(plugins.PluginInterface):
@@ -94,16 +94,16 @@ def get_kdbg_structure(
             "windows",
             "kdbg",
             native_types=native_types,
-            class_types=extensions.kdbg.class_types,
+            class_types=kdbg.class_types,
         )
 
-        kdbg = context.object(
+        kdbg_obj = context.object(
             kdbg_table_name + constants.BANG + "_KDDEBUGGER_DATA64",
             offset=ntkrnlmp.offset + kdbg_offset,
             layer_name=layer_name,
         )
 
-        return kdbg
+        return kdbg_obj
 
     @classmethod
     def get_kuser_structure(
@@ -173,7 +173,7 @@ def get_ntheader_structure(
             interfaces.configuration.path_join(config_path, "pe"),
             "windows",
             "pe",
-            class_types=extensions.pe.class_types,
+            class_types=pe.class_types,
         )
 
         dos_header = context.object(
diff --git a/volatility3/framework/plugins/windows/kpcrs.py b/volatility3/framework/plugins/windows/kpcrs.py
new file mode 100644
index 0000000000..558ea844c9
--- /dev/null
+++ b/volatility3/framework/plugins/windows/kpcrs.py
@@ -0,0 +1,106 @@
+# This file is Copyright 2024 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 Iterator, List, Tuple
+
+from volatility3.framework import (
+    renderers,
+    interfaces,
+    constants,
+)
+from volatility3.framework.configuration import requirements
+from volatility3.framework.objects import utility
+from volatility3.framework.renderers import format_hints
+
+vollog = logging.getLogger(__name__)
+
+
+class KPCRs(interfaces.plugins.PluginInterface):
+    """Print KPCR structure for each processor"""
+
+    _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"],
+            ),
+        ]
+
+    @classmethod
+    def list_kpcrs(
+        cls,
+        context: interfaces.context.ContextInterface,
+        kernel_module_name: str,
+        layer_name: str,
+        symbol_table: str,
+    ) -> interfaces.objects.ObjectInterface:
+        """Returns the KPCR structure for each processor
+
+        Args:
+            context: The context to retrieve required elements (layers, symbol tables) from
+            kernel_module_name: The name of the kernel module on which to operate
+            layer_name: The name of the layer on which to operate
+            symbol_table: The name of the table containing the kernel symbols
+
+        Returns:
+            The _KPCR structure for each processor
+        """
+
+        kernel = context.modules[kernel_module_name]
+        cpu_count_offset = kernel.get_symbol("KeNumberProcessors").address
+        cpu_count = kernel.object(
+            object_type="unsigned int", layer_name=layer_name, offset=cpu_count_offset
+        )
+        processor_block = kernel.object(
+            object_type="pointer",
+            layer_name=layer_name,
+            offset=kernel.get_symbol("KiProcessorBlock").address,
+        )
+        processor_pointers = utility.array_of_pointers(
+            context=context,
+            array=processor_block,
+            count=cpu_count,
+            subtype=symbol_table + constants.BANG + "_KPRCB",
+        )
+        for pointer in processor_pointers:
+            kprcb = pointer.dereference()
+            reloff = kernel.get_type("_KPCR").relative_child_offset("Prcb")
+            kpcr = context.object(
+                symbol_table + constants.BANG + "_KPCR",
+                offset=kprcb.vol.offset - reloff,
+                layer_name=layer_name,
+            )
+            yield kpcr
+
+    def _generator(self) -> Iterator[Tuple]:
+        kernel = self.context.modules[self.config["kernel"]]
+        layer_name = kernel.layer_name
+        symbol_table = kernel.symbol_table_name
+
+        for kpcr in self.list_kpcrs(
+            self.context, self.config["kernel"], layer_name, symbol_table
+        ):
+            yield (
+                0,
+                (
+                    format_hints.Hex(kpcr.vol.offset),
+                    format_hints.Hex(kpcr.CurrentPrcb),
+                ),
+            )
+
+    def run(self):
+        return renderers.TreeGrid(
+            [
+                ("Offset", format_hints.Hex),
+                ("PRCB Offset", format_hints.Hex),
+            ],
+            self._generator(),
+        )
diff --git a/volatility3/framework/plugins/windows/ldrmodules.py b/volatility3/framework/plugins/windows/ldrmodules.py
index 4c8456fa96..a888f22e18 100644
--- a/volatility3/framework/plugins/windows/ldrmodules.py
+++ b/volatility3/framework/plugins/windows/ldrmodules.py
@@ -1,3 +1,9 @@
+# This file is Copyright 2024 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 volatility3.framework import constants, exceptions, interfaces, renderers
 from volatility3.framework.configuration import requirements
 from volatility3.framework.renderers import format_hints
@@ -5,12 +11,14 @@
 from volatility3.framework.symbols.windows.extensions import pe
 from volatility3.plugins.windows import pslist, vadinfo
 
+vollog = logging.getLogger(__name__)
+
 
 class LdrModules(interfaces.plugins.PluginInterface):
     """Lists the loaded modules in a particular windows memory image."""
 
     _required_framework_version = (2, 0, 0)
-    _version = (1, 0, 0)
+    _version = (1, 0, 1)
 
     @classmethod
     def get_requirements(cls):
@@ -39,14 +47,6 @@ def _generator(self, procs):
             self.context, self.config_path, "windows", "pe", class_types=pe.class_types
         )
 
-        def filter_function(x: interfaces.objects.ObjectInterface) -> bool:
-            try:
-                return not (x.get_private_memory() == 0 and x.ControlArea)
-            except AttributeError:
-                return False
-
-        filter_func = filter_function
-
         for proc in procs:
             proc_layer_name = proc.add_process_layer()
 
@@ -61,7 +61,7 @@ def filter_function(x: interfaces.objects.ObjectInterface) -> bool:
 
             # Build dictionary of mapped files, where the VAD start address is the key and value is the file name of the mapped file
             mapped_files = {}
-            for vad in vadinfo.VadInfo.list_vads(proc, filter_func=filter_func):
+            for vad in vadinfo.VadInfo.list_vads(proc):
                 dos_header = self.context.object(
                     pe_table_name + constants.BANG + "_IMAGE_DOS_HEADER",
                     offset=vad.get_start(),
@@ -71,7 +71,11 @@ def filter_function(x: interfaces.objects.ObjectInterface) -> bool:
                     # Filter out VADs that do not start with a MZ header
                     if dos_header.e_magic != 0x5A4D:
                         continue
-                except exceptions.PagedInvalidAddressException:
+                except exceptions.InvalidAddressException:
+                    vollog.log(
+                        constants.LOGLEVEL_VVVV,
+                        f"Skipping vad at {hex(dos_header.vol.offset)} due to InvalidAddressException",
+                    )
                     continue
 
                 mapped_files[vad.get_start()] = vad.get_file_name()
diff --git a/volatility3/framework/plugins/windows/malfind.py b/volatility3/framework/plugins/windows/malfind.py
index 8c0cb68ac0..079274d698 100644
--- a/volatility3/framework/plugins/windows/malfind.py
+++ b/volatility3/framework/plugins/windows/malfind.py
@@ -155,12 +155,12 @@ def _generator(self, procs):
 
         for proc in procs:
             # by default, "Notes" column will be set to N/A
-            notes = renderers.NotApplicableValue()
             process_name = utility.array_to_string(proc.ImageFileName)
 
             for vad, data in self.list_injections(
                 self.context, kernel.layer_name, kernel.symbol_table_name, proc
             ):
+                notes = renderers.NotApplicableValue()
                 # Check for unique headers and update "Notes" column if criteria is met
                 if data[0:2] in refined_criteria:
                     notes = refined_criteria[data[0:2]]
diff --git a/volatility3/framework/plugins/windows/mftscan.py b/volatility3/framework/plugins/windows/mftscan.py
index 85c072037a..1b1a1b45e5 100644
--- a/volatility3/framework/plugins/windows/mftscan.py
+++ b/volatility3/framework/plugins/windows/mftscan.py
@@ -264,9 +264,10 @@ def _generator(self):
                                             disasm = interfaces.renderers.Disassembly(
                                                 content, 0, architecture.lower()
                                             )
+                                        content = format_hints.HexBytes(content)
                                     else:
-                                        content = renderers.NotAvailableValue
-                                        disasm = interfaces.renderers.BaseAbsentValue
+                                        content = renderers.NotAvailableValue()
+                                        disasm = interfaces.renderers.BaseAbsentValue()
 
                                     yield 0, (
                                         format_hints.Hex(attr_data.vol.offset),
@@ -275,7 +276,7 @@ def _generator(self):
                                         attr.Attr_Header.AttrType.lookup(),
                                         file_name,
                                         ads_name,
-                                        format_hints.HexBytes(content),
+                                        content,
                                         disasm,
                                     )
                         else:
diff --git a/volatility3/framework/plugins/windows/modscan.py b/volatility3/framework/plugins/windows/modscan.py
index 99fadac07c..fc45e69137 100644
--- a/volatility3/framework/plugins/windows/modscan.py
+++ b/volatility3/framework/plugins/windows/modscan.py
@@ -2,23 +2,24 @@
 # which is available at https://www.volatilityfoundation.org/license/vsl-v1.0
 #
 import logging
-from typing import Iterable, List, Generator
+from typing import Iterable
 
-from volatility3.framework import renderers, interfaces, exceptions, constants
+from volatility3.framework import interfaces
 from volatility3.framework.configuration import requirements
-from volatility3.framework.renderers import format_hints
-from volatility3.framework.symbols import intermed
-from volatility3.framework.symbols.windows.extensions import pe
-from volatility3.plugins.windows import poolscanner, dlllist, pslist
+from volatility3.plugins.windows import poolscanner, modules, pedump
 
 vollog = logging.getLogger(__name__)
 
 
-class ModScan(interfaces.plugins.PluginInterface):
+class ModScan(modules.Modules):
     """Scans for modules present in a particular windows memory image."""
 
     _required_framework_version = (2, 0, 0)
-    _version = (1, 0, 0)
+    _version = (2, 0, 0)
+
+    def __init__(self, *args, **kwargs):
+        super().__init__(*args, **kwargs)
+        self._enumeration_method = self.scan_modules
 
     @classmethod
     def get_requirements(cls):
@@ -32,10 +33,7 @@ def get_requirements(cls):
                 name="poolscanner", component=poolscanner.PoolScanner, version=(1, 0, 0)
             ),
             requirements.VersionRequirement(
-                name="pslist", component=pslist.PsList, version=(2, 0, 0)
-            ),
-            requirements.VersionRequirement(
-                name="dlllist", component=dlllist.DllList, version=(2, 0, 0)
+                name="modules", component=modules.Modules, version=(2, 0, 0)
             ),
             requirements.BooleanRequirement(
                 name="dump",
@@ -43,6 +41,20 @@ def get_requirements(cls):
                 default=False,
                 optional=True,
             ),
+            requirements.IntRequirement(
+                name="base",
+                description="Extract a single module with BASE address",
+                optional=True,
+            ),
+            requirements.StringRequirement(
+                name="name",
+                description="module name/sub string",
+                optional=True,
+                default=None,
+            ),
+            requirements.VersionRequirement(
+                name="pedump", component=pedump.PEDump, version=(1, 0, 0)
+            ),
         ]
 
     @classmethod
@@ -72,157 +84,3 @@ def scan_modules(
         ):
             _constraint, mem_object, _header = result
             yield mem_object
-
-    @classmethod
-    def get_session_layers(
-        cls,
-        context: interfaces.context.ContextInterface,
-        layer_name: str,
-        symbol_table: str,
-        pids: List[int] = None,
-    ) -> Generator[str, None, None]:
-        """Build a cache of possible virtual layers, in priority starting with
-        the primary/kernel layer. Then keep one layer per session by cycling
-        through the process list.
-
-        Args:
-            context: The context to retrieve required elements (layers, symbol tables) from
-            layer_name: The name of the layer on which to operate
-            symbol_table: The name of the table containing the kernel symbols
-            pids: A list of process identifiers to include exclusively or None for no filter
-
-        Returns:
-            A list of session layer names
-        """
-        seen_ids: List[interfaces.objects.ObjectInterface] = []
-        filter_func = pslist.PsList.create_pid_filter(pids or [])
-
-        for proc in pslist.PsList.list_processes(
-            context=context,
-            layer_name=layer_name,
-            symbol_table=symbol_table,
-            filter_func=filter_func,
-        ):
-            proc_id = "Unknown"
-            try:
-                proc_id = proc.UniqueProcessId
-                proc_layer_name = proc.add_process_layer()
-
-                # create the session space object in the process' own layer.
-                # not all processes have a valid session pointer.
-                session_space = context.object(
-                    symbol_table + constants.BANG + "_MM_SESSION_SPACE",
-                    layer_name=layer_name,
-                    offset=proc.Session,
-                )
-
-                if session_space.SessionId in seen_ids:
-                    continue
-
-            except exceptions.InvalidAddressException:
-                vollog.log(
-                    constants.LOGLEVEL_VVV,
-                    "Process {} does not have a valid Session or a layer could not be constructed for it".format(
-                        proc_id
-                    ),
-                )
-                continue
-
-            # save the layer if we haven't seen the session yet
-            seen_ids.append(session_space.SessionId)
-            yield proc_layer_name
-
-    @classmethod
-    def find_session_layer(
-        cls,
-        context: interfaces.context.ContextInterface,
-        session_layers: Iterable[str],
-        base_address: int,
-    ):
-        """Given a base address and a list of layer names, find a layer that
-        can access the specified address.
-
-        Args:
-            context: The context to retrieve required elements (layers, symbol tables) from
-            layer_name: The name of the layer on which to operate
-            symbol_table: The name of the table containing the kernel symbols
-            session_layers: A list of session layer names
-            base_address: The base address to identify the layers that can access it
-
-        Returns:
-            Layer name or None if no layers that contain the base address can be found
-        """
-
-        for layer_name in session_layers:
-            if context.layers[layer_name].is_valid(base_address):
-                return layer_name
-
-        return None
-
-    def _generator(self):
-        kernel = self.context.modules[self.config["kernel"]]
-
-        session_layers = list(
-            self.get_session_layers(
-                self.context, kernel.layer_name, kernel.symbol_table_name
-            )
-        )
-        pe_table_name = intermed.IntermediateSymbolTable.create(
-            self.context, self.config_path, "windows", "pe", class_types=pe.class_types
-        )
-
-        for mod in self.scan_modules(
-            self.context, kernel.layer_name, kernel.symbol_table_name
-        ):
-            try:
-                BaseDllName = mod.BaseDllName.get_string()
-            except exceptions.InvalidAddressException:
-                BaseDllName = ""
-
-            try:
-                FullDllName = mod.FullDllName.get_string()
-            except exceptions.InvalidAddressException:
-                FullDllName = ""
-
-            file_output = "Disabled"
-            if self.config["dump"]:
-                session_layer_name = self.find_session_layer(
-                    self.context, session_layers, mod.DllBase
-                )
-                file_output = f"Cannot find a viable session layer for {mod.DllBase:#x}"
-                if session_layer_name:
-                    file_handle = dlllist.DllList.dump_pe(
-                        self.context,
-                        pe_table_name,
-                        mod,
-                        self.open,
-                        layer_name=session_layer_name,
-                    )
-                    file_output = "Error outputting file"
-                    if file_handle:
-                        file_output = file_handle.preferred_filename
-
-            yield (
-                0,
-                (
-                    format_hints.Hex(mod.vol.offset),
-                    format_hints.Hex(mod.DllBase),
-                    format_hints.Hex(mod.SizeOfImage),
-                    BaseDllName,
-                    FullDllName,
-                    file_output,
-                ),
-            )
-
-    def run(self):
-        return renderers.TreeGrid(
-            [
-                ("Offset", format_hints.Hex),
-                ("Base", format_hints.Hex),
-                ("Size", format_hints.Hex),
-                ("Name", str),
-                ("Path", str),
-                ("File output", str),
-            ],
-            self._generator(),
-        )
diff --git a/volatility3/framework/plugins/windows/modules.py b/volatility3/framework/plugins/windows/modules.py
index 7dabf69545..ba45834d5c 100644
--- a/volatility3/framework/plugins/windows/modules.py
+++ b/volatility3/framework/plugins/windows/modules.py
@@ -4,14 +4,12 @@
 import logging
 from typing import List, Iterable, Generator
 
-from volatility3.framework import constants
-from volatility3.framework import exceptions, interfaces
-from volatility3.framework import renderers
+from volatility3.framework import exceptions, interfaces, constants, renderers
 from volatility3.framework.configuration import requirements
 from volatility3.framework.renderers import format_hints
 from volatility3.framework.symbols import intermed
 from volatility3.framework.symbols.windows.extensions import pe
-from volatility3.plugins.windows import pslist, dlllist
+from volatility3.plugins.windows import pslist, pedump
 
 vollog = logging.getLogger(__name__)
 
@@ -20,7 +18,11 @@ class Modules(interfaces.plugins.PluginInterface):
     """Lists the loaded kernel modules."""
 
     _required_framework_version = (2, 0, 0)
-    _version = (1, 1, 0)
+    _version = (2, 0, 0)
+
+    def __init__(self, *args, **kwargs):
+        super().__init__(*args, **kwargs)
+        self._enumeration_method = self.list_modules
 
     @classmethod
     def get_requirements(cls) -> List[interfaces.configuration.RequirementInterface]:
@@ -33,65 +35,97 @@ def get_requirements(cls) -> List[interfaces.configuration.RequirementInterface]
             requirements.VersionRequirement(
                 name="pslist", component=pslist.PsList, version=(2, 0, 0)
             ),
-            requirements.VersionRequirement(
-                name="dlllist", component=dlllist.DllList, version=(2, 0, 0)
-            ),
             requirements.BooleanRequirement(
                 name="dump",
                 description="Extract listed modules",
                 default=False,
                 optional=True,
             ),
+            requirements.IntRequirement(
+                name="base",
+                description="Extract a single module with BASE address",
+                optional=True,
+            ),
             requirements.StringRequirement(
                 name="name",
                 description="module name/sub string",
                 optional=True,
                 default=None,
             ),
+            requirements.VersionRequirement(
+                name="pedump", component=pedump.PEDump, version=(1, 0, 0)
+            ),
         ]
 
+    def dump_module(self, session_layers, pe_table_name, mod):
+        session_layer_name = self.find_session_layer(
+            self.context, session_layers, mod.DllBase
+        )
+        file_output = f"Cannot find a viable session layer for {mod.DllBase:#x}"
+        if session_layer_name:
+            file_output = pedump.PEDump.dump_ldr_entry(
+                self.context,
+                pe_table_name,
+                mod,
+                self.open,
+                layer_name=session_layer_name,
+            )
+            if not file_output:
+                file_output = "Error outputting file"
+
+        return file_output
+
     def _generator(self):
         kernel = self.context.modules[self.config["kernel"]]
-        pe_table_name = intermed.IntermediateSymbolTable.create(
-            self.context, self.config_path, "windows", "pe", class_types=pe.class_types
-        )
 
-        for mod in self.list_modules(
+        pe_table_name = None
+        session_layers = None
+
+        if self.config["dump"]:
+            pe_table_name = intermed.IntermediateSymbolTable.create(
+                self.context,
+                self.config_path,
+                "windows",
+                "pe",
+                class_types=pe.class_types,
+            )
+
+            session_layers = list(
+                self.get_session_layers(
+                    self.context, kernel.layer_name, kernel.symbol_table_name
+                )
+            )
+
+        for mod in self._enumeration_method(
             self.context, kernel.layer_name, kernel.symbol_table_name
         ):
+            if self.config["base"] and self.config["base"] != mod.DllBase:
+                continue
+
             try:
                 BaseDllName = mod.BaseDllName.get_string()
             except exceptions.InvalidAddressException:
-                BaseDllName = ""
+                BaseDllName = interfaces.renderers.BaseAbsentValue()
+
+            if self.config["name"] and self.config["name"] not in BaseDllName:
+                continue
 
             try:
                 FullDllName = mod.FullDllName.get_string()
             except exceptions.InvalidAddressException:
-                FullDllName = ""
-
-            if self.config["name"] and self.config["name"] not in BaseDllName:
-                continue
+                FullDllName = interfaces.renderers.BaseAbsentValue()
 
             file_output = "Disabled"
             if self.config["dump"]:
-                file_handle = dlllist.DllList.dump_pe(
-                    self.context, pe_table_name, mod, self.open
-                )
-                file_output = "Error outputting file"
-                if file_handle:
-                    file_handle.close()
-                    file_output = file_handle.preferred_filename
-
-            yield (
-                0,
-                (
-                    format_hints.Hex(mod.vol.offset),
-                    format_hints.Hex(mod.DllBase),
-                    format_hints.Hex(mod.SizeOfImage),
-                    BaseDllName,
-                    FullDllName,
-                    file_output,
-                ),
+                file_output = self.dump_module(session_layers, pe_table_name, mod)
+
+            yield 0, (
+                format_hints.Hex(mod.vol.offset),
+                format_hints.Hex(mod.DllBase),
+                format_hints.Hex(mod.SizeOfImage),
+                BaseDllName,
+                FullDllName,
+                file_output,
             )
 
     @classmethod
diff --git a/volatility3/framework/plugins/windows/netscan.py b/volatility3/framework/plugins/windows/netscan.py
index 62ead3ab7d..868bd8bcd1 100644
--- a/volatility3/framework/plugins/windows/netscan.py
+++ b/volatility3/framework/plugins/windows/netscan.py
@@ -218,6 +218,7 @@ def determine_tcpip_version(
                 (10, 0, 18362, 0): "netscan-win10-18362-x64",
                 (10, 0, 18363, 0): "netscan-win10-18363-x64",
                 (10, 0, 19041, 0): "netscan-win10-19041-x64",
+                (10, 0, 20348, 0): "netscan-win10-20348-x64",
             }
 
         # we do not need to check for tcpip's specific FileVersion in every case
diff --git a/volatility3/framework/plugins/windows/netstat.py b/volatility3/framework/plugins/windows/netstat.py
index 24eb02018b..0908767fc7 100644
--- a/volatility3/framework/plugins/windows/netstat.py
+++ b/volatility3/framework/plugins/windows/netstat.py
@@ -35,7 +35,7 @@ def get_requirements(cls):
                 name="netscan", component=netscan.NetScan, version=(1, 0, 0)
             ),
             requirements.VersionRequirement(
-                name="modules", component=modules.Modules, version=(1, 0, 0)
+                name="modules", component=modules.Modules, version=(2, 0, 0)
             ),
             requirements.VersionRequirement(
                 name="pdbutil", component=pdbutil.PDBUtility, version=(1, 0, 0)
diff --git a/volatility3/framework/plugins/windows/pedump.py b/volatility3/framework/plugins/windows/pedump.py
new file mode 100644
index 0000000000..858d0615a5
--- /dev/null
+++ b/volatility3/framework/plugins/windows/pedump.py
@@ -0,0 +1,270 @@
+# This file is Copyright 2024 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
+import ntpath
+from typing import List, Type, Optional
+
+from volatility3.framework import constants, exceptions, interfaces, renderers
+from volatility3.framework.configuration import requirements
+from volatility3.framework.symbols import intermed
+from volatility3.framework.symbols.windows.extensions import pe
+from volatility3.plugins.windows import pslist, modules
+
+vollog = logging.getLogger(__name__)
+
+
+class PEDump(interfaces.plugins.PluginInterface):
+    """Allows extracting PE Files from a specific address in a specific address space"""
+
+    _required_framework_version = (2, 0, 0)
+    _version = (1, 0, 0)
+
+    @classmethod
+    def get_requirements(cls) -> List[interfaces.configuration.RequirementInterface]:
+        # Since we're calling the plugin, make sure we have the plugin's requirements
+        return [
+            requirements.ModuleRequirement(
+                name="kernel",
+                description="Windows kernel",
+                architectures=["Intel32", "Intel64"],
+            ),
+            requirements.VersionRequirement(
+                name="pslist", component=pslist.PsList, version=(2, 0, 0)
+            ),
+            requirements.ListRequirement(
+                name="pid",
+                element_type=int,
+                description="Process IDs to include (all other processes are excluded)",
+                optional=True,
+            ),
+            requirements.IntRequirement(
+                name="base",
+                description="Base address to reconstruct a PE file",
+                optional=False,
+            ),
+            requirements.BooleanRequirement(
+                name="kernel_module",
+                description="Extract from kernel address space.",
+                default=False,
+                optional=True,
+            ),
+        ]
+
+    @classmethod
+    def dump_pe(
+        cls,
+        context: interfaces.context.ContextInterface,
+        pe_table_name: str,
+        layer_name: str,
+        open_method: Type[interfaces.plugins.FileHandlerInterface],
+        file_name: str,
+        base: int,
+    ) -> Optional[str]:
+        """
+        Returns the filename of the dump file or None
+        """
+        try:
+            file_handle = open_method(file_name)
+
+            dos_header = context.object(
+                pe_table_name + constants.BANG + "_IMAGE_DOS_HEADER",
+                offset=base,
+                layer_name=layer_name,
+            )
+
+            for offset, data in dos_header.reconstruct():
+                file_handle.seek(offset)
+                file_handle.write(data)
+        except (
+            IOError,
+            exceptions.VolatilityException,
+            OverflowError,
+            ValueError,
+        ) as excp:
+            vollog.debug(f"Unable to dump PE file at offset {base}: {excp}")
+            return None
+        finally:
+            file_handle.close()
+
+        return file_handle.preferred_filename
+
+    @classmethod
+    def dump_ldr_entry(
+        cls,
+        context: interfaces.context.ContextInterface,
+        pe_table_name: str,
+        ldr_entry: interfaces.objects.ObjectInterface,
+        open_method: Type[interfaces.plugins.FileHandlerInterface],
+        layer_name: str = None,
+        prefix: str = "",
+    ) -> Optional[str]:
+        """Extracts the PE file referenced an LDR_DATA_TABLE_ENTRY (DLL, kernel module) instance
+
+        Args:
+            context: the context to operate upon
+            pe_table_name: the name for the symbol table containing the PE format symbols
+            ldr_entry: the object representing the module
+            open_method: class for constructing output files
+            layer_name: the layer that the DLL lives within
+            prefix: optional string to prepend to filename
+        Returns:
+            The output file name or None in the case of failure
+        """
+        try:
+            name = ldr_entry.FullDllName.get_string()
+        except exceptions.InvalidAddressException:
+            name = "UnreadableDLLName"
+
+        if layer_name is None:
+            layer_name = ldr_entry.vol.layer_name
+
+        file_name = "{}{}.{:#x}.{:#x}.dmp".format(
+            prefix,
+            ntpath.basename(name),
+            ldr_entry.vol.offset,
+            ldr_entry.DllBase,
+        )
+
+        return cls.dump_pe(
+            context,
+            pe_table_name,
+            layer_name,
+            open_method,
+            file_name,
+            ldr_entry.DllBase,
+        )
+
+    @classmethod
+    def dump_pe_at_base(
+        cls,
+        context: interfaces.context.ContextInterface,
+        pe_table_name: str,
+        layer_name: str,
+        open_method: Type[interfaces.plugins.FileHandlerInterface],
+        proc_offset: int,
+        pid: int,
+        base: int,
+    ) -> Optional[str]:
+        file_name = "PE.{:#x}.{:d}.{:#x}.dmp".format(
+            proc_offset,
+            pid,
+            base,
+        )
+
+        return PEDump.dump_pe(
+            context, pe_table_name, layer_name, open_method, file_name, base
+        )
+
+    @classmethod
+    def dump_kernel_pe_at_base(cls, context, kernel, pe_table_name, open_method, base):
+        session_layers = modules.Modules.get_session_layers(
+            context, kernel.layer_name, kernel.symbol_table_name
+        )
+
+        session_layer_name = modules.Modules.find_session_layer(
+            context, session_layers, base
+        )
+
+        if session_layer_name:
+            system_pid = 4
+
+            file_output = PEDump.dump_pe_at_base(
+                context,
+                pe_table_name,
+                session_layer_name,
+                open_method,
+                0,
+                system_pid,
+                base,
+            )
+
+            if file_output:
+                yield system_pid, "Kernel", file_output
+        else:
+            vollog.warning(
+                "Unable to find a session layer with the provided base address mapped in the kernel."
+            )
+
+    @classmethod
+    def dump_processes(
+        cls, context, kernel, pe_table_name, open_method, filter_func, base
+    ):
+        """ """
+
+        for proc in pslist.PsList.list_processes(
+            context=context,
+            layer_name=kernel.layer_name,
+            symbol_table=kernel.symbol_table_name,
+            filter_func=filter_func,
+        ):
+            pid = proc.UniqueProcessId
+            proc_name = proc.ImageFileName.cast(
+                "string",
+                max_length=proc.ImageFileName.vol.count,
+                errors="replace",
+            )
+            proc_layer_name = proc.add_process_layer()
+
+            file_output = PEDump.dump_pe_at_base(
+                context,
+                pe_table_name,
+                proc_layer_name,
+                open_method,
+                proc.vol.offset,
+                pid,
+                base,
+            )
+
+            if file_output:
+                yield pid, proc_name, file_output
+
+    def _generator(self):
+        kernel = self.context.modules[self.config["kernel"]]
+
+        pe_table_name = intermed.IntermediateSymbolTable.create(
+            self.context, self.config_path, "windows", "pe", class_types=pe.class_types
+        )
+
+        if self.config["kernel_module"] and self.config["pid"]:
+            vollog.error("Only --kernel_module or --pid should be set. Not both")
+            return
+
+        if not self.config["kernel_module"] and not self.config["pid"]:
+            vollog.error("--kernel_module or --pid must be set")
+            return
+
+        if self.config["kernel_module"]:
+            pe_files = self.dump_kernel_pe_at_base(
+                self.context, kernel, pe_table_name, self.open, self.config["base"]
+            )
+        else:
+            filter_func = pslist.PsList.create_pid_filter(self.config.get("pid", None))
+            pe_files = self.dump_processes(
+                self.context,
+                kernel,
+                pe_table_name,
+                self.open,
+                filter_func,
+                self.config["base"],
+            )
+
+        for pid, proc_name, file_output in pe_files:
+            yield (
+                0,
+                (
+                    pid,
+                    proc_name,
+                    file_output,
+                ),
+            )
+
+    def run(self):
+        return renderers.TreeGrid(
+            [
+                ("PID", int),
+                ("Process", str),
+                ("File output", str),
+            ],
+            self._generator(),
+        )
diff --git a/volatility3/framework/plugins/windows/processghosting.py b/volatility3/framework/plugins/windows/processghosting.py
new file mode 100644
index 0000000000..50f02c926c
--- /dev/null
+++ b/volatility3/framework/plugins/windows/processghosting.py
@@ -0,0 +1,104 @@
+# This file is Copyright 2024 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
+import contextlib
+
+from volatility3.framework import interfaces, exceptions
+from volatility3.framework import renderers
+from volatility3.framework.configuration import requirements
+from volatility3.framework.objects import utility
+from volatility3.framework.renderers import format_hints
+from volatility3.plugins.windows import pslist
+
+vollog = logging.getLogger(__name__)
+
+
+class ProcessGhosting(interfaces.plugins.PluginInterface):
+    """Lists processes whose DeletePending bit is set or whose FILE_OBJECT is set to 0"""
+
+    _required_framework_version = (2, 4, 0)
+
+    @classmethod
+    def get_requirements(cls):
+        # Since we're calling the plugin, make sure we have the plugin's requirements
+        return [
+            requirements.ModuleRequirement(
+                name="kernel",
+                description="Windows kernel",
+                architectures=["Intel32", "Intel64"],
+            ),
+            requirements.VersionRequirement(
+                name="pslist", component=pslist.PsList, version=(2, 0, 0)
+            ),
+        ]
+
+    def _generator(self, procs):
+        kernel = self.context.modules[self.config["kernel"]]
+
+        if not kernel.get_type("_EPROCESS").has_member("ImageFilePointer"):
+            vollog.warning(
+                "This plugin only supports Windows 10 builds when the ImageFilePointer member of _EPROCESS is present"
+            )
+            return
+
+        for proc in procs:
+            delete_pending = renderers.UnreadableValue()
+            process_name = utility.array_to_string(proc.ImageFileName)
+
+            # if it is 0 then its a side effect of process ghosting
+            if proc.ImageFilePointer.vol.offset != 0:
+                try:
+                    file_object = proc.ImageFilePointer
+                    delete_pending = file_object.DeletePending
+                except exceptions.InvalidAddressException:
+                    file_object = 0
+
+            # ImageFilePointer equal to 0 means process ghosting or similar techniques were used
+            else:
+                file_object = 0
+
+            if isinstance(delete_pending, int) and delete_pending not in [0, 1]:
+                vollog.debug(
+                    f"Invalid delete_pending value {delete_pending} found for {process_name} {proc.UniqueProcessId}"
+                )
+
+            # delete_pending besides 0 or 1 = smear
+            if file_object == 0 or delete_pending == 1:
+                path = renderers.UnreadableValue()
+                if file_object:
+                    with contextlib.suppress(exceptions.InvalidAddressException):
+                        path = file_object.FileName.String
+
+                yield (
+                    0,
+                    (
+                        proc.UniqueProcessId,
+                        process_name,
+                        format_hints.Hex(file_object),
+                        delete_pending,
+                        path,
+                    ),
+                )
+
+    def run(self):
+        filter_func = pslist.PsList.create_active_process_filter()
+        kernel = self.context.modules[self.config["kernel"]]
+
+        return renderers.TreeGrid(
+            [
+                ("PID", int),
+                ("Process", str),
+                ("FILE_OBJECT", format_hints.Hex),
+                ("DeletePending", str),
+                ("Path", str),
+            ],
+            self._generator(
+                pslist.PsList.list_processes(
+                    context=self.context,
+                    layer_name=kernel.layer_name,
+                    symbol_table=kernel.symbol_table_name,
+                    filter_func=filter_func,
+                )
+            ),
+        )
diff --git a/volatility3/framework/plugins/windows/pslist.py b/volatility3/framework/plugins/windows/pslist.py
index e7a0d5dd46..8234b210f2 100644
--- a/volatility3/framework/plugins/windows/pslist.py
+++ b/volatility3/framework/plugins/windows/pslist.py
@@ -136,6 +136,29 @@ def create_pid_filter(
                 filter_func = lambda x: x.UniqueProcessId not in filter_list
         return filter_func
 
+    @classmethod
+    def create_active_process_filter(
+        cls,
+    ) -> Callable[[interfaces.objects.ObjectInterface], bool]:
+        """A factory for producing a filter function that only returns
+           active, userland processes. This prevents plugins from operating on terminated
+           processes that are still in the process list due to smear or handle leaks as well
+           as kernel processes (System, Registry, etc.). Use of this filter for plugins searching
+           for system state anomalies significantly reduces false positive in smeared and terminated
+           processes.
+        Returns:
+            Filter function for passing to the `list_processes` method
+        """
+
+        return lambda x: not (
+            x.is_valid()
+            and x.ActiveThreads > 0
+            and x.UniqueProcessId != 4
+            and x.InheritedFromUniqueProcessId != 4
+            and x.ExitTime.QuadPart == 0
+            and x.get_handle_count() != renderers.UnreadableValue()
+        )
+
     @classmethod
     def create_name_filter(
         cls, name_list: List[str] = None, exclude: bool = False
diff --git a/volatility3/framework/plugins/windows/psscan.py b/volatility3/framework/plugins/windows/psscan.py
index 5634298a85..5ce470cd86 100644
--- a/volatility3/framework/plugins/windows/psscan.py
+++ b/volatility3/framework/plugins/windows/psscan.py
@@ -266,20 +266,28 @@ def _generator(self):
                 if proc.vol.layer_name == kernel.layer_name:
                     vproc = proc
                 else:
-                    vproc = self.virtual_process_from_physical(
-                        self.context, kernel.layer_name, kernel.symbol_table_name, proc
-                    )
+                    try:
+                        vproc = self.virtual_process_from_physical(
+                            self.context,
+                            kernel.layer_name,
+                            kernel.symbol_table_name,
+                            proc,
+                        )
+                    except exceptions.PagedInvalidAddressException:
+                        vproc = None
 
-                file_handle = pslist.PsList.process_dump(
-                    self.context,
-                    kernel.symbol_table_name,
-                    pe_table_name,
-                    vproc,
-                    self.open,
-                )
                 file_output = "Error outputting file"
-                if file_handle:
-                    file_output = file_handle.preferred_filename
+                if vproc:
+                    file_handle = pslist.PsList.process_dump(
+                        self.context,
+                        kernel.symbol_table_name,
+                        pe_table_name,
+                        vproc,
+                        self.open,
+                    )
+
+                    if file_handle:
+                        file_output = file_handle.preferred_filename
 
             if not self.config["physical"]:
                 offset = proc.vol.offset
diff --git a/volatility3/framework/plugins/windows/psxview.py b/volatility3/framework/plugins/windows/psxview.py
new file mode 100644
index 0000000000..71919c4101
--- /dev/null
+++ b/volatility3/framework/plugins/windows/psxview.py
@@ -0,0 +1,251 @@
+import datetime, logging, string
+
+from volatility3.framework import constants, exceptions
+from volatility3.framework.interfaces import plugins
+from volatility3.framework.configuration import requirements
+from volatility3.framework.renderers import format_hints, TreeGrid
+from volatility3.plugins.windows import (
+    handles,
+    info,
+    pslist,
+    psscan,
+    sessions,
+    thrdscan,
+)
+
+vollog = logging.getLogger(__name__)
+
+
+class PsXView(plugins.PluginInterface):
+    """Lists all processes found via four of the methods described in \"The Art of Memory Forensics,\" which may help
+    identify processes that are trying to hide themselves. I recommend using -r pretty if you are looking at this
+    plugin's output in a terminal."""
+
+    # I've omitted the desktop thread scanning method because Volatility3 doesn't appear to have the funcitonality
+    # which the original plugin used to do it.
+
+    # The sessions method is omitted because it begins with the list of processes found by Pslist anyway.
+
+    # Lastly, I've omitted the pspcid method because I could not for the life of me get it to work. I saved the
+    # code I do have from it, and will happily share it if anyone else wants to add it.
+
+    _required_framework_version = (2, 0, 0)
+    _version = (1, 0, 0)
+
+    valid_proc_name_chars = set(
+        string.ascii_lowercase + string.ascii_uppercase + "." + " "
+    )
+
+    @classmethod
+    def get_requirements(cls):
+        return [
+            requirements.ModuleRequirement(
+                name="kernel",
+                description="Windows kernel",
+                architectures=["Intel32", "Intel64"],
+            ),
+            requirements.VersionRequirement(
+                name="info", component=info.Info, version=(1, 0, 0)
+            ),
+            requirements.VersionRequirement(
+                name="pslist", component=pslist.PsList, version=(2, 0, 0)
+            ),
+            requirements.VersionRequirement(
+                name="psscan", component=psscan.PsScan, version=(1, 0, 0)
+            ),
+            requirements.VersionRequirement(
+                name="thrdscan", component=thrdscan.ThrdScan, version=(1, 0, 0)
+            ),
+            requirements.VersionRequirement(
+                name="handles", component=handles.Handles, version=(1, 0, 0)
+            ),
+            requirements.BooleanRequirement(
+                name="physical-offsets",
+                description="List processes with physical offsets instead of virtual offsets.",
+                optional=True,
+            ),
+        ]
+
+    def _proc_name_to_string(self, proc):
+        return proc.ImageFileName.cast(
+            "string", max_length=proc.ImageFileName.vol.count, errors="replace"
+        )
+
+    def _is_valid_proc_name(self, str):
+        for c in str:
+            if not c in self.valid_proc_name_chars:
+                return False
+        return True
+
+    def _filter_garbage_procs(self, proc_list):
+        return [
+            p
+            for p in proc_list
+            if p.is_valid() and self._is_valid_proc_name(self._proc_name_to_string(p))
+        ]
+
+    def _translate_offset(self, offset):
+        if not self.config["physical-offsets"]:
+            return offset
+
+        kernel = self.context.modules[self.config["kernel"]]
+        layer_name = kernel.layer_name
+
+        try:
+            _original_offset, _original_length, offset, _length, _layer_name = list(
+                self.context.layers[layer_name].mapping(offset=offset, length=0)
+            )[0]
+        except exceptions.PagedInvalidAddressException:
+            vollog.debug(f"Page fault: unable to translate {offset:0x}")
+
+        return offset
+
+    def _proc_list_to_dict(self, tasks):
+        tasks = self._filter_garbage_procs(tasks)
+        return {self._translate_offset(proc.vol.offset): proc for proc in tasks}
+
+    def _check_pslist(self, tasks):
+        return self._proc_list_to_dict(tasks)
+
+    def _check_psscan(self, layer_name, symbol_table):
+        res = psscan.PsScan.scan_processes(
+            context=self.context, layer_name=layer_name, symbol_table=symbol_table
+        )
+
+        return self._proc_list_to_dict(res)
+
+    def _check_thrdscan(self):
+        ret = []
+
+        for ethread in thrdscan.ThrdScan.scan_threads(
+            self.context, module_name="kernel"
+        ):
+            process = None
+            try:
+                process = ethread.owning_process()
+                if not process.is_valid():
+                    continue
+
+                ret.append(process)
+            except AttributeError:
+                vollog.log(
+                    constants.LOGLEVEL_VVV,
+                    "Unable to find the owning process of ethread",
+                )
+
+        return self._proc_list_to_dict(ret)
+
+    def _check_csrss_handles(self, tasks, layer_name, symbol_table):
+        ret = []
+
+        for p in tasks:
+            name = self._proc_name_to_string(p)
+            if name == "csrss.exe":
+                try:
+                    if p.has_member("ObjectTable"):
+                        handles_plugin = handles.Handles(
+                            context=self.context, config_path=self.config_path
+                        )
+                        hndls = list(handles_plugin.handles(p.ObjectTable))
+                        for h in hndls:
+                            if (
+                                h.get_object_type(
+                                    handles_plugin.get_type_map(
+                                        self.context, layer_name, symbol_table
+                                    )
+                                )
+                                == "Process"
+                            ):
+                                ret.append(h.Body.cast("_EPROCESS"))
+
+                except exceptions.InvalidAddressException:
+                    vollog.log(
+                        constants.LOGLEVEL_VVV, "Cannot access eprocess object table"
+                    )
+
+        return self._proc_list_to_dict(ret)
+
+    def _generator(self):
+        kernel = self.context.modules[self.config["kernel"]]
+
+        layer_name = kernel.layer_name
+        symbol_table = kernel.symbol_table_name
+
+        kdbg_list_processes = list(
+            pslist.PsList.list_processes(
+                context=self.context, layer_name=layer_name, symbol_table=symbol_table
+            )
+        )
+
+        # get processes from each source
+        processes = {}
+
+        processes["pslist"] = self._check_pslist(kdbg_list_processes)
+        processes["psscan"] = self._check_psscan(layer_name, symbol_table)
+        processes["thrdscan"] = self._check_thrdscan()
+        processes["csrss"] = self._check_csrss_handles(
+            kdbg_list_processes, layer_name, symbol_table
+        )
+
+        # print results
+
+        # list of lists of offsets
+        offsets = [list(processes[source].keys()) for source in processes]
+
+        # flatten to one list
+        offsets = sum(offsets, [])
+
+        # remove duplicates
+        offsets = set(offsets)
+
+        for offset in offsets:
+            proc = None
+
+            in_sources = {src: False for src in processes}
+
+            for source in processes:
+                if offset in processes[source]:
+                    in_sources[source] = True
+                    if not proc:
+                        proc = processes[source][offset]
+
+            pid = proc.UniqueProcessId
+            name = self._proc_name_to_string(proc)
+
+            exit_time = proc.get_exit_time()
+            if type(exit_time) != datetime.datetime:
+                exit_time = ""
+            else:
+                exit_time = str(exit_time)
+
+            yield (
+                0,
+                (
+                    format_hints.Hex(offset),
+                    name,
+                    pid,
+                    in_sources["pslist"],
+                    in_sources["psscan"],
+                    in_sources["thrdscan"],
+                    in_sources["csrss"],
+                    exit_time,
+                ),
+            )
+
+    def run(self):
+        offset_type = "(Physical)" if self.config["physical-offsets"] else "(Virtual)"
+        offset_str = "Offset" + offset_type
+
+        return TreeGrid(
+            [
+                (offset_str, format_hints.Hex),
+                ("Name", str),
+                ("PID", int),
+                ("pslist", bool),
+                ("psscan", bool),
+                ("thrdscan", bool),
+                ("csrss", bool),
+                ("Exit Time", str),
+            ],
+            self._generator(),
+        )
diff --git a/volatility3/framework/plugins/windows/registry/getcellroutine.py b/volatility3/framework/plugins/windows/registry/getcellroutine.py
new file mode 100644
index 0000000000..200a45a823
--- /dev/null
+++ b/volatility3/framework/plugins/windows/registry/getcellroutine.py
@@ -0,0 +1,98 @@
+# This file is Copyright 2024 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 constants, exceptions, interfaces, renderers
+from volatility3.framework.configuration import requirements
+from volatility3.framework.renderers import format_hints
+from volatility3.plugins.windows import ssdt
+from volatility3.plugins.windows.registry import hivelist
+
+vollog = logging.getLogger(__name__)
+
+
+class GetCellRoutine(interfaces.plugins.PluginInterface):
+    """Reports registry hives with a hooked GetCellRoutine handler"""
+
+    _required_framework_version = (2, 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="hivelist", plugin=hivelist.HiveList, version=(1, 0, 0)
+            ),
+            requirements.PluginRequirement(
+                name="ssdt", plugin=ssdt.SSDT, version=(1, 0, 0)
+            ),
+        ]
+
+    def _generator(self):
+        kernel = self.context.modules[self.config["kernel"]]
+
+        collection = ssdt.SSDT.build_module_collection(
+            self.context, kernel.layer_name, kernel.symbol_table_name
+        )
+
+        # walk each hive and validate that the GetCellRoutine handler
+        # is inside of the kernel (ntoskrnl)
+        for hive_object in hivelist.HiveList.list_hives(
+            context=self.context,
+            base_config_path=self.config_path,
+            layer_name=kernel.layer_name,
+            symbol_table=kernel.symbol_table_name,
+        ):
+            hive = hive_object.hive
+
+            try:
+                cellroutine = hive.GetCellRoutine
+            except exceptions.InvalidAddressException:
+                continue
+
+            module_symbols = list(
+                collection.get_module_symbols_by_absolute_location(cellroutine)
+            )
+
+            if module_symbols:
+                for module_name, _ in module_symbols:
+                    # GetCellRoutine handlers should only be in the kernel
+                    if module_name not in constants.windows.KERNEL_MODULE_NAMES:
+                        yield (
+                            0,
+                            (
+                                format_hints.Hex(hive.vol.offset),
+                                hive_object.get_name() or "",
+                                module_name,
+                                format_hints.Hex(cellroutine),
+                            ),
+                        )
+            # Doesn't map to any module...
+            else:
+                yield (
+                    0,
+                    (
+                        format_hints.Hex(hive.vol.offset),
+                        hive_object.get_name() or "",
+                        renderers.NotAvailableValue(),
+                        format_hints.Hex(cellroutine),
+                    ),
+                )
+
+    def run(self):
+        return renderers.TreeGrid(
+            [
+                ("Hive Offset", renderers.format_hints.Hex),
+                ("Hive Name", str),
+                ("GetCellRoutine Module", str),
+                ("GetCellRoutine Handler", renderers.format_hints.Hex),
+            ],
+            self._generator(),
+        )
diff --git a/volatility3/framework/plugins/windows/registry/userassist.py b/volatility3/framework/plugins/windows/registry/userassist.py
index 70c75b50b1..bd832b20c1 100644
--- a/volatility3/framework/plugins/windows/registry/userassist.py
+++ b/volatility3/framework/plugins/windows/registry/userassist.py
@@ -17,11 +17,12 @@
 from volatility3.framework.renderers import conversion, format_hints
 from volatility3.framework.symbols import intermed
 from volatility3.plugins.windows.registry import hivelist
+from volatility3.plugins import timeliner
 
 vollog = logging.getLogger(__name__)
 
 
-class UserAssist(interfaces.plugins.PluginInterface):
+class UserAssist(interfaces.plugins.PluginInterface, timeliner.TimeLinerInterface):
     """Print userassist registry keys and information."""
 
     _required_framework_version = (2, 0, 0)
@@ -285,6 +286,10 @@ def _generator(self):
             hive_offsets = [self.config.get("offset", None)]
         kernel = self.context.modules[self.config["kernel"]]
 
+        self._reg_table_name = intermed.IntermediateSymbolTable.create(
+            self.context, self._config_path, "windows", "registry"
+        )
+
         # get all the user hive offsets or use the one specified
         for hive in hivelist.HiveList.list_hives(
             context=self.context,
@@ -335,11 +340,17 @@ def _generator(self):
             )
             yield result
 
-    def run(self):
-        self._reg_table_name = intermed.IntermediateSymbolTable.create(
-            self.context, self._config_path, "windows", "registry"
-        )
+    def generate_timeline(self):
+        for row in self._generator():
+            _depth, row_data = row
+            # check the name and the timestamp to not be empty
+            if isinstance(row_data[5], str) and not isinstance(
+                row_data[10], renderers.NotApplicableValue
+            ):
+                description = f"UserAssist: {row_data[5]} {row_data[2]} ({row_data[7]})"
+                yield (description, timeliner.TimeLinerType.MODIFIED, row_data[10])
 
+    def run(self):
         return renderers.TreeGrid(
             [
                 ("Hive Offset", renderers.format_hints.Hex),
diff --git a/volatility3/framework/plugins/windows/shimcachemem.py b/volatility3/framework/plugins/windows/shimcachemem.py
new file mode 100644
index 0000000000..6afaf43560
--- /dev/null
+++ b/volatility3/framework/plugins/windows/shimcachemem.py
@@ -0,0 +1,610 @@
+# This file is Copyright 2020 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
+import os
+from datetime import datetime
+from itertools import count
+from typing import Iterator, List, Optional, Tuple
+
+from volatility3.framework import constants, exceptions, interfaces, renderers, symbols
+from volatility3.framework.configuration import requirements
+from volatility3.framework.objects.utility import array_to_string
+from volatility3.framework.renderers import format_hints
+from volatility3.framework.symbols import intermed
+from volatility3.framework.symbols.windows import versions
+from volatility3.framework.symbols.windows.extensions import pe, shimcache
+from volatility3.plugins import timeliner
+from volatility3.plugins.windows import modules, pslist, vadinfo
+
+# from volatility3.plugins.windows import pslist, vadinfo, modules
+
+vollog = logging.getLogger(__name__)
+
+
+class ShimcacheMem(interfaces.plugins.PluginInterface, timeliner.TimeLinerInterface):
+    """Reads Shimcache entries from the ahcache.sys AVL tree"""
+
+    _required_framework_version = (2, 0, 0)
+
+    # These checks must be completed from newest -> oldest OS version.
+    _win_version_file_map: List[Tuple[versions.OsDistinguisher, bool, str]] = [
+        (versions.is_win10, True, "shimcache-win10-x64"),
+        (versions.is_win10, False, "shimcache-win10-x86"),
+        (versions.is_windows_8_or_later, True, "shimcache-win8-x64"),
+        (versions.is_windows_8_or_later, False, "shimcache-win8-x86"),
+        (versions.is_windows_7, True, "shimcache-win7-x64"),
+        (versions.is_windows_7, False, "shimcache-win7-x86"),
+        (versions.is_vista_or_later, True, "shimcache-vista-x64"),
+        (versions.is_vista_or_later, False, "shimcache-vista-x86"),
+        (versions.is_2003, False, "shimcache-2003-x86"),
+        (versions.is_2003, True, "shimcache-2003-x64"),
+        (versions.is_windows_xp_sp3, False, "shimcache-xp-sp3-x86"),
+        (versions.is_windows_xp_sp2, False, "shimcache-xp-sp2-x86"),
+        (versions.is_xp_or_2003, True, "shimcache-xp-2003-x64"),
+        (versions.is_xp_or_2003, False, "shimcache-xp-2003-x86"),
+    ]
+
+    NT_KRNL_MODS = ["ntoskrnl.exe", "ntkrnlpa.exe", "ntkrnlmp.exe", "ntkrpamp.exe"]
+
+    def generate_timeline(
+        self,
+    ) -> Iterator[Tuple[str, timeliner.TimeLinerType, datetime]]:
+        for _, (_, last_modified, last_update, _, _, file_path) in self._generator():
+            if isinstance(last_update, datetime):
+                yield f"Shimcache: File {file_path} executed", timeliner.TimeLinerType.ACCESSED, last_update
+            if isinstance(last_modified, datetime):
+                yield f"Shimcache: File {file_path} modified", timeliner.TimeLinerType.MODIFIED, last_modified
+
+    @classmethod
+    def get_requirements(cls) -> List[interfaces.configuration.RequirementInterface]:
+        # Since we're calling the plugin, make sure we have the plugin's requirements
+        return [
+            requirements.ModuleRequirement(
+                name="kernel",
+                description="Windows kernel",
+                architectures=["Intel32", "Intel64"],
+            ),
+            requirements.PluginRequirement(
+                name="pslist", plugin=pslist.PsList, version=(2, 0, 0)
+            ),
+            requirements.VersionRequirement(
+                name="vadinfo", component=vadinfo.VadInfo, version=(2, 0, 0)
+            ),
+            requirements.VersionRequirement(
+                name="modules", component=modules.Modules, version=(2, 0, 0)
+            ),
+        ]
+
+    @staticmethod
+    def create_shimcache_table(
+        context: interfaces.context.ContextInterface,
+        symbol_table: str,
+        config_path: str,
+    ) -> str:
+        """Creates a shimcache symbol table
+
+        Args:
+            context: The context to retrieve required elements (layers, symbol tables) from
+            symbol_table: The name of an existing symbol table containing the kernel symbols
+            config_path: The configuration path within the context of the symbol table to create
+
+        Returns:
+            The name of the constructed shimcache table
+        """
+        native_types = context.symbol_space[symbol_table].natives
+        is_64bit = symbols.symbol_table_is_64bit(context, symbol_table)
+        table_mapping = {"nt_symbols": symbol_table}
+
+        try:
+            symbol_filename = next(
+                filename
+                for version_check, for_64bit, filename in ShimcacheMem._win_version_file_map
+                if is_64bit == for_64bit
+                and version_check(context=context, symbol_table=symbol_table)
+            )
+        except StopIteration:
+            raise NotImplementedError("This version of Windows is not supported!")
+
+        vollog.debug(f"Using shimcache table {symbol_filename}")
+
+        return intermed.IntermediateSymbolTable.create(
+            context,
+            config_path,
+            os.path.join("windows", "shimcache"),
+            symbol_filename,
+            class_types=shimcache.class_types,
+            native_types=native_types,
+            table_mapping=table_mapping,
+        )
+
+    @classmethod
+    def find_shimcache_win_xp(
+        cls,
+        context: interfaces.context.ContextInterface,
+        layer_name: str,
+        kernel_symbol_table: str,
+        shimcache_symbol_table: str,
+    ) -> Iterator[shimcache.SHIM_CACHE_ENTRY]:
+        """Attempts to find the shimcache in a Windows XP memory image
+
+        :param context: The context to retrieve required elements (layers, symbol tables) from
+        :param layer_name: The name of the memory layer on which to operate.
+        :param kernel_symbol_table: The name of an existing symbol table containing the kernel symbols
+        :param shimcache_symbol_table: The name of a symbol table containing the hand-crafted shimcache symbols
+        """
+
+        SHIM_NUM_ENTRIES_OFFSET = 0x8
+        SHIM_MAX_ENTRIES = 0x60  # 96 max entries in XP shim cache
+        SHIM_LRU_OFFSET = 0x10
+        SHIM_HEADER_SIZE = 0x190
+        SHIM_CACHE_ENTRY_SIZE = 0x228
+
+        seen = set()
+
+        for process in pslist.PsList.list_processes(
+            context, layer_name, kernel_symbol_table
+        ):
+            pid = process.UniqueProcessId
+            vollog.debug("checking process %d" % pid)
+            for vad in vadinfo.VadInfo.list_vads(
+                process, lambda x: x.get_tag() == b"Vad " and x.Protection == 4
+            ):
+                try:
+                    proc_layer_name = process.add_process_layer()
+                    proc_layer = context.layers[proc_layer_name]
+                except exceptions.InvalidAddressException:
+                    continue
+
+                try:
+                    if proc_layer.read(vad.get_start(), 4) != b"\xEF\xBE\xAD\xDE":
+                        if pid == 624:
+                            vollog.debug("VAD magic bytes don't match DEADBEEF")
+                        continue
+                except exceptions.InvalidAddressException:
+                    continue
+
+                num_entries = context.object(
+                    shimcache_symbol_table + constants.BANG + "unsigned int",
+                    proc_layer_name,
+                    vad.get_start() + SHIM_NUM_ENTRIES_OFFSET,
+                )
+
+                if num_entries > SHIM_MAX_ENTRIES:
+                    continue
+
+                cache_idx_ptr = vad.get_start() + SHIM_LRU_OFFSET
+
+                for _ in range(num_entries):
+                    cache_idx_val = proc_layer.context.object(
+                        shimcache_symbol_table + constants.BANG + "unsigned long",
+                        proc_layer_name,
+                        cache_idx_ptr,
+                    )
+
+                    cache_idx_ptr += 4
+
+                    if cache_idx_val > SHIM_MAX_ENTRIES - 1:
+                        continue
+
+                    shim_entry_offset = (
+                        vad.get_start()
+                        + SHIM_HEADER_SIZE
+                        + (SHIM_CACHE_ENTRY_SIZE * cache_idx_val)
+                    )
+
+                    if not proc_layer.is_valid(shim_entry_offset):
+                        continue
+
+                    physical_addr = proc_layer.translate(shim_entry_offset)
+
+                    if physical_addr in seen:
+                        continue
+                    seen.add(physical_addr)
+
+                    shim_entry = proc_layer.context.object(
+                        shimcache_symbol_table + constants.BANG + "SHIM_CACHE_ENTRY",
+                        proc_layer_name,
+                        shim_entry_offset,
+                    )
+                    if not proc_layer.is_valid(shim_entry.vol.offset):
+                        continue
+                    if not shim_entry.is_valid():
+                        continue
+
+                    yield shim_entry
+
+    @classmethod
+    def find_shimcache_win_2k3_to_7(
+        cls,
+        context: interfaces.context.ContextInterface,
+        config_path: str,
+        kernel_layer_name: str,
+        nt_symbol_table: str,
+        shimcache_symbol_table: str,
+    ) -> Iterator[shimcache.SHIM_CACHE_ENTRY]:
+        """Implements the algorithm to search for the shim cache on Windows 2000
+        (x64) through Windows 7 / 2008 R2. The algorithm consists of the following:
+
+        1) Find the NT kernel module's .data and PAGE sections
+        2) Iterate over every 4/8 bytes (depending on OS bitness) in the .data
+           section and test for the following:
+           a) offset represents a valid RTL_AVL_TABLE object
+           b) RTL_AVL_TABLE is preceeded by an ERESOURCE object
+           c) RTL_AVL_TABLE is followed by the beginning of the SHIM LRU list
+
+        :param context: The context to retrieve required elements (layers, symbol tables) from
+        :param layer_name: The name of the memory layer on which to operate.
+        :param kernel_symbol_table: The name of an existing symbol table containing the kernel symbols
+        :param shimcache_symbol_table: The name of a symbol table containing the hand-crafted shimcache symbols
+        """
+
+        data_sec = cls.get_module_section_range(
+            context,
+            config_path,
+            kernel_layer_name,
+            nt_symbol_table,
+            cls.NT_KRNL_MODS,
+            ".data",
+        )
+        mod_page = cls.get_module_section_range(
+            context,
+            config_path,
+            kernel_layer_name,
+            nt_symbol_table,
+            cls.NT_KRNL_MODS,
+            "PAGE",
+        )
+
+        # We require both in order to accurately handle AVL table
+        if not (data_sec and mod_page):
+            return None
+
+        data_sec_offset, data_sec_size = data_sec
+        mod_page_offset, mod_page_size = mod_page
+
+        addr_size = 8 if symbols.symbol_table_is_64bit(context, nt_symbol_table) else 4
+
+        shim_head = None
+        for offset in range(
+            data_sec_offset, data_sec_offset + data_sec_size, addr_size
+        ):
+            shim_head = cls.try_get_shim_head_at_offset(
+                context,
+                shimcache_symbol_table,
+                nt_symbol_table,
+                kernel_layer_name,
+                mod_page_offset,
+                mod_page_offset + mod_page_size,
+                offset,
+            )
+
+            if shim_head:
+                break
+
+        if not shim_head:
+            return
+
+        for shim_entry in shim_head.ListEntry.to_list(
+            shimcache_symbol_table + constants.BANG + "SHIM_CACHE_ENTRY", "ListEntry"
+        ):
+            yield shim_entry
+
+    @classmethod
+    def try_get_shim_head_at_offset(
+        cls,
+        context: interfaces.context.ContextInterface,
+        symbol_table: str,
+        kernel_symbol_table: str,
+        layer_name: str,
+        mod_page_start: int,
+        mod_page_end: int,
+        offset: int,
+    ) -> Optional[shimcache.SHIM_CACHE_ENTRY]:
+        """Attempts to construct a SHIM_CACHE_HEAD within a layer of the given context,
+        using the provided offset within that layer, as well as the start and end offsets
+        of the kernel module's `PAGE` section start and end offsets.
+
+        If a number of validity checks are passed, this method will return the `SHIM_CACHE_HEAD`
+        object. Otherwise, `None` is returned.
+        """
+        # print("checking RTL_AVL_TABLE at offset %s" % hex(offset))
+        rtl_avl_table = context.object(
+            symbol_table + constants.BANG + "_RTL_AVL_TABLE", layer_name, offset
+        )
+        if not rtl_avl_table.is_valid(mod_page_start, mod_page_end):
+            return None
+
+        vollog.debug(f"Candidate RTL_AVL_TABLE found at offset {hex(offset)}")
+
+        ersrc_size = context.symbol_space.get_type(
+            kernel_symbol_table + constants.BANG + "_ERESOURCE"
+        ).size
+        ersrc_alignment = (
+            0x20
+            if symbols.symbol_table_is_64bit(context, kernel_symbol_table)
+            else 0x10
+            # 0x20 if context.symbol_space.get_type("pointer").size == 8 else 0x10
+        )
+        vollog.debug(
+            f"ERESOURCE size: {hex(ersrc_size)}, ERESOURCE alignment: {hex(ersrc_alignment)}"
+        )
+
+        eresource_rel_off = ersrc_size + ((offset - ersrc_size) % ersrc_alignment)
+        eresource_offset = offset - eresource_rel_off
+
+        vollog.debug("Constructing ERESOURCE at %s" % hex(eresource_offset))
+        eresource = context.object(
+            kernel_symbol_table + constants.BANG + "_ERESOURCE",
+            layer_name,
+            eresource_offset,
+        )
+        if not eresource.is_valid():
+            vollog.debug("ERESOURCE Invalid")
+            return None
+
+        shim_head_offset = offset + rtl_avl_table.vol.size
+
+        if not context.layers[layer_name].is_valid(shim_head_offset):
+            return None
+
+        shim_head = context.object(
+            symbol_table + constants.BANG + "SHIM_CACHE_ENTRY",
+            layer_name,
+            shim_head_offset,
+        )
+
+        if not shim_head.is_valid():
+            vollog.debug("shim head invalid")
+            return None
+        else:
+            vollog.debug("returning shim head")
+            return shim_head
+
+    @classmethod
+    def find_shimcache_win_8_or_later(
+        cls,
+        context: interfaces.context.ContextInterface,
+        config_path: str,
+        kernel_layer_name: str,
+        nt_symbol_table: str,
+        shimcache_symbol_table: str,
+    ) -> Iterator[shimcache.SHIM_CACHE_ENTRY]:
+        """Attempts to locate and yield shimcache entries from a Windows 8 or later memory image.
+
+        :param context: The context to retrieve required elements (layers, symbol tables) from
+        :param layer_name: The name of the memory layer on which to operate.
+        :param kernel_symbol_table: The name of an existing symbol table containing the kernel symbols
+        :param shimcache_symbol_table: The name of a symbol table containing the hand-crafted shimcache symbols
+        """
+
+        is_8_1_or_later = versions.is_windows_8_1_or_later(
+            context, nt_symbol_table
+        ) or versions.is_win10(context, nt_symbol_table)
+
+        module_names = ["ahcache.sys"] if is_8_1_or_later else cls.NT_KRNL_MODS
+        vollog.debug(f"Searching for modules {module_names}")
+
+        data_sec = cls.get_module_section_range(
+            context,
+            config_path,
+            kernel_layer_name,
+            nt_symbol_table,
+            module_names,
+            ".data",
+        )
+        mod_page = cls.get_module_section_range(
+            context,
+            config_path,
+            kernel_layer_name,
+            nt_symbol_table,
+            module_names,
+            "PAGE",
+        )
+
+        if not (data_sec and mod_page):
+            return None
+
+        mod_page_offset, mod_page_size = mod_page
+        data_sec_offset, data_sec_size = data_sec
+
+        # iterate over ahcache kernel module's .data section in search of *two* SHIM handles
+        shim_heads = []
+
+        vollog.debug(f"PAGE offset: {hex(mod_page_offset)}")
+        vollog.debug(f".data offset: {hex(data_sec_offset)}")
+
+        handle_type = context.symbol_space.get_type(
+            shimcache_symbol_table + constants.BANG + "SHIM_CACHE_HANDLE"
+        )
+        for offset in range(
+            data_sec_offset,
+            data_sec_offset + data_sec_size,
+            8 if symbols.symbol_table_is_64bit(context, nt_symbol_table) else 4,
+        ):
+            vollog.debug(f"Building shim handle pointer at {hex(offset)}")
+            shim_handle = context.object(
+                object_type=shimcache_symbol_table + constants.BANG + "pointer",
+                layer_name=kernel_layer_name,
+                subtype=handle_type,
+                offset=offset,
+            )
+
+            if shim_handle.is_valid(mod_page_offset, mod_page_offset + mod_page_size):
+                if shim_handle.head is not None:
+                    vollog.debug(
+                        f"Found valid shim handle @ {hex(shim_handle.vol.offset)}"
+                    )
+                    shim_heads.append(shim_handle.head)
+                if len(shim_heads) == 2:
+                    break
+
+        if len(shim_heads) != 2:
+            vollog.debug("Failed to identify two valid SHIM_CACHE_HANDLE structures")
+            return
+
+        # On Windows 8 x64, the frist cache contains the shim cache
+        # On Windows 8 x86, 8.1 x86/x64, and 10, the second cache contains the shim cache.
+        if (
+            not symbols.symbol_table_is_64bit(context, nt_symbol_table)
+            and not is_8_1_or_later
+        ):
+            valid_head = shim_heads[1]
+        elif not is_8_1_or_later:
+            valid_head = shim_heads[0]
+        else:
+            valid_head = shim_heads[1]
+
+        for shim_entry in valid_head.ListEntry.to_list(
+            shimcache_symbol_table + constants.BANG + "SHIM_CACHE_ENTRY", "ListEntry"
+        ):
+            if shim_entry.is_valid():
+                yield shim_entry
+
+    def _generator(self):
+        kernel = self.context.modules[self.config["kernel"]]
+
+        shimcache_table_name = self.create_shimcache_table(
+            self.context, kernel.symbol_table_name, self.config_path
+        )
+
+        c = count()
+
+        if versions.is_windows_8_or_later(self._context, kernel.symbol_table_name):
+            vollog.info("Finding shimcache entries for Windows 8.0+")
+            entries = self.find_shimcache_win_8_or_later(
+                self.context,
+                self.config_path,
+                kernel.layer_name,
+                kernel.symbol_table_name,
+                shimcache_table_name,
+            )
+
+        elif (
+            versions.is_2003(self.context, kernel.symbol_table_name)
+            or versions.is_vista_or_later(self.context, kernel.symbol_table_name)
+            or versions.is_windows_7(self.context, kernel.symbol_table_name)
+        ):
+            vollog.info("Finding shimcache entries for Windows 2k3/Vista/7")
+            entries = self.find_shimcache_win_2k3_to_7(
+                self.context,
+                self.config_path,
+                kernel.layer_name,
+                kernel.symbol_table_name,
+                shimcache_table_name,
+            )
+
+        elif versions.is_windows_xp_sp2(
+            self._context, kernel.symbol_table_name
+        ) or versions.is_windows_xp_sp3(self.context, kernel.symbol_table_name):
+            vollog.info("Finding shimcache entries for WinXP")
+            entries = self.find_shimcache_win_xp(
+                self._context,
+                kernel.layer_name,
+                kernel.symbol_table_name,
+                shimcache_table_name,
+            )
+        else:
+            vollog.warn("Cannot parse shimcache entries for this version of Windows")
+            return
+
+        for entry in entries:
+            try:
+                vollog.debug(f"SHIM_CACHE_ENTRY type: {entry.__class__}")
+                shim_entry = (
+                    entry.last_modified,
+                    entry.last_update,
+                    entry.exec_flag,
+                    (
+                        format_hints.Hex(entry.file_size)
+                        if isinstance(entry.file_size, int)
+                        else entry.file_size
+                    ),
+                    entry.file_path,
+                )
+            except exceptions.InvalidAddressException:
+                continue
+
+            yield (
+                0,
+                (next(c), *shim_entry),
+            )
+
+    def run(self):
+        return renderers.TreeGrid(
+            [
+                ("Order", int),
+                ("Last Modified", datetime),
+                ("Last Update", datetime),
+                ("Exec Flag", bool),
+                ("File Size", format_hints.Hex),
+                ("File Path", str),
+            ],
+            self._generator(),
+        )
+
+    @classmethod
+    def get_module_section_range(
+        cls,
+        context: interfaces.context.ContextInterface,
+        config_path: str,
+        layer_name: str,
+        symbol_table: str,
+        module_list: List[str],
+        section_name: str,
+    ) -> Optional[Tuple[int, int]]:
+        """Locates the size and offset of the first found module section
+        specified by name from the list of modules.
+
+        :param context: The context to operate on
+        :param layer_name: The memory layer to read from
+        :param module_list: A list of module names to search for the given section
+        :param section_name: The name of the section to search for.
+
+        :return: The offset and size of the module, if found; Otherwise, returns `None`
+        """
+
+        try:
+            krnl_mod = next(
+                module
+                for module in modules.Modules.list_modules(
+                    context, layer_name, symbol_table
+                )
+                if module.BaseDllName.String in module_list
+            )
+        except StopIteration:
+            return None
+
+        pe_table_name = intermed.IntermediateSymbolTable.create(
+            context,
+            interfaces.configuration.path_join(config_path, "pe"),
+            "windows",
+            "pe",
+            class_types=pe.class_types,
+        )
+
+        # code taken from Win32KBase._section_chunks (win32_core.py)
+        dos_header = context.object(
+            pe_table_name + constants.BANG + "_IMAGE_DOS_HEADER",
+            layer_name,
+            offset=krnl_mod.DllBase,
+        )
+
+        if not dos_header:
+            return None
+
+        nt_header = dos_header.get_nt_header()
+
+        try:
+            section = next(
+                sec
+                for sec in nt_header.get_sections()
+                if section_name.lower() == array_to_string(sec.Name).lower()
+            )
+        except StopIteration:
+            return None
+
+        section_offset = krnl_mod.DllBase + section.VirtualAddress
+        section_size = section.Misc.VirtualSize
+
+        return section_offset, section_size
diff --git a/volatility3/framework/plugins/windows/suspicious_threads.py b/volatility3/framework/plugins/windows/suspicious_threads.py
new file mode 100644
index 0000000000..2679b191ac
--- /dev/null
+++ b/volatility3/framework/plugins/windows/suspicious_threads.py
@@ -0,0 +1,214 @@
+# This file is Copyright 2024 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, Dict, Tuple, Generator
+from volatility3.framework import renderers, interfaces
+from volatility3.framework.configuration import requirements
+from volatility3.framework.objects import utility
+from volatility3.framework.renderers import format_hints
+from volatility3.plugins.windows import pslist, threads, vadinfo, thrdscan
+
+vollog = logging.getLogger(__name__)
+
+
+class SupsiciousThreads(interfaces.plugins.PluginInterface):
+    """Lists suspicious userland process threads"""
+
+    _required_framework_version = (2, 4, 0)
+    _version = (2, 0, 0)
+
+    @classmethod
+    def get_requirements(cls) -> List[interfaces.configuration.RequirementInterface]:
+        # Since we're calling the plugin, make sure we have the plugin's requirements
+        return [
+            requirements.ModuleRequirement(
+                name="kernel",
+                description="Windows kernel",
+                architectures=["Intel32", "Intel64"],
+            ),
+            requirements.ListRequirement(
+                name="pid",
+                description="Filter on specific process IDs",
+                element_type=int,
+                optional=True,
+            ),
+            requirements.PluginRequirement(
+                name="threads", plugin=threads.Threads, version=(1, 0, 0)
+            ),
+            requirements.VersionRequirement(
+                name="vadinfo", component=vadinfo.VadInfo, version=(2, 0, 0)
+            ),
+        ]
+
+    def _get_ranges(
+        self,
+        kernel: interfaces.context.ModuleInterface,
+        all_ranges: Dict[int, List[Tuple[int, int, str, str]]],
+        proc,
+    ) -> Tuple[int, int, str, str]:
+        """
+        Maintains a hash table so each process' VADs
+        are only enumerated once per plugin run
+        """
+        key = proc.vol.offset
+
+        if key not in all_ranges:
+            all_ranges[key] = []
+
+            for vad in proc.get_vad_root().traverse():
+                fn = vad.get_file_name()
+                if not isinstance(fn, str) or not fn:
+                    fn = None
+
+                protection_string = vad.get_protection(
+                    vadinfo.VadInfo.protect_values(
+                        self.context, kernel.layer_name, kernel.symbol_table_name
+                    ),
+                    vadinfo.winnt_protections,
+                )
+
+                all_ranges[key].append(
+                    (vad.get_start(), vad.get_end(), protection_string, fn)
+                )
+
+        return all_ranges[key]
+
+    def _get_range(
+        self, ranges: Dict[int, List[Tuple[int, int, str, str]]], address: int
+    ) -> Tuple[int, str, str]:
+        """
+        Walks a process' VADs looking for the one
+        containing `address`
+
+        Returns its base address, protection string, and mapped file, if any
+        """
+        for start, end, protection_string, fn in ranges:
+            if start <= address < end:
+                return start, protection_string, fn
+
+        return None, None, None
+
+    def _check_thread_address(
+        self, exe_path: str, ranges, thread_address: int
+    ) -> Generator[Tuple[str, str], None, None]:
+        vad_base, prot, vad_path = self._get_range(ranges, thread_address)
+
+        # threads outside of a VAD means either smear from this thread or this process' VAD tree
+        if vad_base is None:
+            return
+
+        if vad_path is None:
+            # set this so checks after report the non file backed region in the path column
+            vad_path = "<Non-File Backed Region>"
+
+            yield (
+                vad_path,
+                f"This thread started execution in the VAD starting at base address ({vad_base:#x}), which is not backed by a file",
+            )
+
+        # All threads should point to PAGE_EXECUTE_WRITECOPY mapped regions
+        if prot != "PAGE_EXECUTE_WRITECOPY":
+            yield (
+                vad_path,
+                f"VAD at base address ({vad_base:#x}) hosting this thread has an unexpected starting protection {prot}",
+            )
+
+        # check for process hollowing type techniques that mapped in a second, malicious exe file
+        if (
+            exe_path
+            and vad_path.lower().endswith(".exe")
+            and (vad_path.lower() != exe_path.lower())
+        ):
+            yield (
+                vad_path,
+                "VAD at base address ({vad_base:#x}) hosting this thread maps an application executable that is not the process exectuable",
+            )
+
+    def _enumerate_processes(
+        self, kernel: interfaces.context.ModuleInterface, all_ranges
+    ):
+        filter_func = pslist.PsList.create_pid_filter(self.config.get("pid", None))
+
+        for proc in pslist.PsList.list_processes(
+            context=self.context,
+            layer_name=kernel.layer_name,
+            symbol_table=kernel.symbol_table_name,
+            filter_func=filter_func,
+        ):
+            ranges = self._get_ranges(kernel, all_ranges, proc)
+
+            # smeared vads or process is terminating
+            if len(all_ranges[proc.vol.offset]) < 5:
+                continue
+
+            pid = proc.UniqueProcessId
+            proc_name = utility.array_to_string(proc.ImageFileName)
+
+            _, __, exe_path = self._get_range(ranges, proc.SectionBaseAddress)
+            if not isinstance(exe_path, str):
+                exe_path = None
+
+            yield proc, pid, proc_name, exe_path, ranges
+
+    def _generator(self):
+        kernel = self.context.modules[self.config["kernel"]]
+
+        all_ranges = {}
+
+        for proc, pid, proc_name, exe_path, ranges in self._enumerate_processes(
+            kernel, all_ranges
+        ):
+            # processes often create multiple threads at the same address
+            # there is no benefit to checking the same address more than once per process
+            checked = set()
+
+            for thread in threads.Threads.list_threads(kernel, proc):
+                # do not process if a thread is exited or terminated (4 = Terminated)
+                if thread.ExitTime.QuadPart > 0 or thread.Tcb.State == 4:
+                    continue
+
+                # bail if accessing the threads members causes a page fault
+                info = thrdscan.ThrdScan.gather_thread_info(thread)
+                if not info:
+                    continue
+
+                _, _, tid, start_address, _, _ = info
+
+                addresses = [
+                    (start_address, "Start"),
+                    (thread.Win32StartAddress, "Win32Start"),
+                ]
+
+                for address, context in addresses:
+                    if address in checked:
+                        continue
+                    checked.add(address)
+
+                    for vad_path, note in self._check_thread_address(
+                        exe_path, ranges, address
+                    ):
+                        yield 0, (
+                            proc_name,
+                            pid,
+                            tid,
+                            context,
+                            format_hints.Hex(address),
+                            vad_path,
+                            note,
+                        )
+
+    def run(self):
+        return renderers.TreeGrid(
+            [
+                ("Process", str),
+                ("PID", int),
+                ("TID", int),
+                ("Context", str),
+                ("Address", format_hints.Hex),
+                ("VAD Path", str),
+                ("Note", str),
+            ],
+            self._generator(),
+        )
diff --git a/volatility3/framework/plugins/windows/svcdiff.py b/volatility3/framework/plugins/windows/svcdiff.py
new file mode 100644
index 0000000000..84d06a6951
--- /dev/null
+++ b/volatility3/framework/plugins/windows/svcdiff.py
@@ -0,0 +1,103 @@
+# This file is Copyright 2024 Volatility Foundation and licensed under the Volatility Software License 1.0
+# which is available at https://www.volatilityfoundation.org/license/vsl-v1.0
+#
+
+# This module attempts to locate skeleton-key like function hooks.
+# It does this by locating the CSystems array through a variety of methods,
+# and then validating the entry for RC4 HMAC (0x17 / 23)
+#
+# For a thorough walkthrough on how the R&D was performed to develop this plugin,
+# please see our blogpost here:
+#
+# https://volatility-labs.blogspot.com/2021/10/memory-forensics-r-illustrated.html
+
+import logging
+
+from volatility3.framework import symbols, interfaces
+from volatility3.framework.configuration import requirements
+from volatility3.plugins.windows import svclist, svcscan
+from volatility3.framework.symbols.windows import versions
+
+vollog = logging.getLogger(__name__)
+
+
+class SvcDiff(svcscan.SvcScan):
+    """Compares services found through list walking versus scanning to find rootkits"""
+
+    _required_framework_version = (2, 4, 0)
+
+    def __init__(self, *args, **kwargs):
+        super().__init__(*args, **kwargs)
+        self._enumeration_method = self.service_diff
+
+    @classmethod
+    def get_requirements(cls):
+        # Since we're calling the plugin, make sure we have the plugin's requirements
+        return [
+            requirements.ModuleRequirement(
+                name="kernel",
+                description="Windows kernel",
+                architectures=["Intel32", "Intel64"],
+            ),
+            requirements.VersionRequirement(
+                name="svclist", component=svclist.SvcList, version=(1, 0, 0)
+            ),
+            requirements.VersionRequirement(
+                name="svcscan", component=svcscan.SvcScan, version=(3, 0, 0)
+            ),
+        ]
+
+    @classmethod
+    def service_diff(
+        cls,
+        context: interfaces.context.ContextInterface,
+        layer_name: str,
+        symbol_table: str,
+        service_table_name: str,
+        service_binary_dll_map,
+        filter_func,
+    ):
+        """
+        On Windows 10 version 15063+ 64bit Windows memory samples, walk the services list
+        and scan for services then report differences
+        """
+        if not symbols.symbol_table_is_64bit(
+            context, symbol_table
+        ) or not versions.is_win10_15063_or_later(
+            context=context, symbol_table=symbol_table
+        ):
+            vollog.warning(
+                "This plugin only supports Windows 10 version 15063+ 64bit Windows memory samples"
+            )
+            return
+
+        from_scan = set()
+        from_list = set()
+        records = {}
+
+        # collect unique service names from scanning
+        for service in svcscan.SvcScan.service_scan(
+            context,
+            layer_name,
+            symbol_table,
+            service_table_name,
+            service_binary_dll_map,
+            filter_func,
+        ):
+            from_scan.add(service[6])
+            records[service[6]] = service
+
+        # collect services from listing walking
+        for service in svclist.SvcList.service_list(
+            context,
+            layer_name,
+            symbol_table,
+            service_table_name,
+            service_binary_dll_map,
+            filter_func,
+        ):
+            from_list.add(service[6])
+
+        # report services found from scanning but not list walking
+        for hidden_service in from_scan - from_list:
+            yield records[hidden_service]
diff --git a/volatility3/framework/plugins/windows/svclist.py b/volatility3/framework/plugins/windows/svclist.py
new file mode 100644
index 0000000000..a59581063b
--- /dev/null
+++ b/volatility3/framework/plugins/windows/svclist.py
@@ -0,0 +1,115 @@
+# 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, Optional, Tuple
+
+from volatility3.framework import interfaces, exceptions, symbols
+from volatility3.framework.configuration import requirements
+from volatility3.framework.symbols.windows import versions
+from volatility3.plugins.windows import svcscan, pslist
+from volatility3.framework.layers import scanners
+
+vollog = logging.getLogger(__name__)
+
+
+class SvcList(svcscan.SvcScan):
+    """Lists services contained with the services.exe doubly linked list of services"""
+
+    _version = (1, 0, 0)
+
+    def __init__(self, *args, **kwargs):
+        super().__init__(*args, **kwargs)
+        self._enumeration_method = self.service_list
+
+    @classmethod
+    def get_requirements(cls) -> List[interfaces.configuration.RequirementInterface]:
+        # Since we're calling the plugin, make sure we have the plugin's requirements
+        return [
+            requirements.PluginRequirement(
+                name="svcscan", plugin=svcscan.SvcScan, version=(3, 0, 0)
+            ),
+            requirements.ModuleRequirement(
+                name="kernel",
+                description="Windows kernel",
+                architectures=["Intel32", "Intel64"],
+            ),
+        ]
+
+    @classmethod
+    def _get_exe_range(cls, proc) -> Optional[Tuple[int, int]]:
+        """
+        Returns a tuple of starting,ending address for
+        the VAD containing services.exe
+        """
+
+        vad_root = proc.get_vad_root()
+        for vad in vad_root.traverse():
+            filename = vad.get_file_name()
+            if isinstance(filename, str) and filename.lower().endswith(
+                "\\services.exe"
+            ):
+                return [(vad.get_start(), vad.get_size())]
+
+        return None
+
+    @classmethod
+    def service_list(
+        cls,
+        context: interfaces.context.ContextInterface,
+        layer_name: str,
+        symbol_table: str,
+        service_table_name: str,
+        service_binary_dll_map,
+        filter_func,
+    ):
+        if not symbols.symbol_table_is_64bit(
+            context, symbol_table
+        ) or not versions.is_win10_15063_or_later(
+            context=context, symbol_table=symbol_table
+        ):
+            vollog.warning(
+                "This plugin only supports Windows 10 version 15063+ 64bit Windows memory samples"
+            )
+            return
+
+        for proc in pslist.PsList.list_processes(
+            context=context,
+            layer_name=layer_name,
+            symbol_table=symbol_table,
+            filter_func=filter_func,
+        ):
+            try:
+                layer_name = proc.add_process_layer()
+            except exceptions.InvalidAddressException:
+                vollog.warning(
+                    "Unable to access memory of services.exe running with PID: {}".format(
+                        proc.UniqueProcessId
+                    )
+                )
+                continue
+
+            layer = context.layers[layer_name]
+
+            exe_range = cls._get_exe_range(proc)
+            if not exe_range:
+                vollog.warning(
+                    "Could not find the application executable VAD for services.exe. Unable to proceed."
+                )
+                continue
+
+            for offset in layer.scan(
+                context=context,
+                scanner=scanners.BytesScanner(needle=b"Sc27"),
+                sections=exe_range,
+            ):
+                for record in cls.enumerate_vista_or_later_header(
+                    context,
+                    service_table_name,
+                    service_binary_dll_map,
+                    layer_name,
+                    offset,
+                ):
+                    yield record
diff --git a/volatility3/framework/plugins/windows/svcscan.py b/volatility3/framework/plugins/windows/svcscan.py
index 10de46e2a5..52ed5e759e 100644
--- a/volatility3/framework/plugins/windows/svcscan.py
+++ b/volatility3/framework/plugins/windows/svcscan.py
@@ -19,7 +19,7 @@
 from volatility3.framework.renderers import format_hints
 from volatility3.framework.symbols import intermed
 from volatility3.framework.symbols.windows import versions
-from volatility3.framework.symbols.windows.extensions import services
+from volatility3.framework.symbols.windows.extensions import services as services_types
 from volatility3.plugins.windows import poolscanner, pslist, vadyarascan
 from volatility3.plugins.windows.registry import hivelist
 
@@ -39,7 +39,11 @@ class SvcScan(interfaces.plugins.PluginInterface):
     """Scans for windows services."""
 
     _required_framework_version = (2, 0, 0)
-    _version = (2, 0, 0)
+    _version = (3, 0, 0)
+
+    def __init__(self, *args, **kwargs):
+        super().__init__(*args, **kwargs)
+        self._enumeration_method = self.service_scan
 
     @classmethod
     def get_requirements(cls) -> List[interfaces.configuration.RequirementInterface]:
@@ -106,7 +110,7 @@ def get_record_tuple(
     ]
 
     @staticmethod
-    def create_service_table(
+    def _create_service_table(
         context: interfaces.context.ContextInterface,
         symbol_table: str,
         config_path: str,
@@ -140,18 +144,21 @@ def create_service_table(
             config_path,
             os.path.join("windows", "services"),
             symbol_filename,
-            class_types=services.class_types,
+            class_types=services_types.class_types,
             native_types=native_types,
         )
 
-    def _get_service_key(self, kernel) -> Optional[objects.StructType]:
+    @staticmethod
+    def _get_service_key(
+        context, config_path: str, layer_name: str, symbol_table: str
+    ) -> Optional[objects.StructType]:
         for hive in hivelist.HiveList.list_hives(
-            context=self.context,
+            context=context,
             base_config_path=interfaces.configuration.path_join(
-                self.config_path, "hivelist"
+                config_path, "hivelist"
             ),
-            layer_name=kernel.layer_name,
-            symbol_table=kernel.symbol_table_name,
+            layer_name=layer_name,
+            symbol_table=symbol_table,
             filter_string="machine\\system",
         ):
             # Get ControlSet\Services.
@@ -232,30 +239,55 @@ def _get_service_binary_map(
             for service_key in services
         }
 
-    def _generator(self):
-        kernel = self.context.modules[self.config["kernel"]]
+    @classmethod
+    def enumerate_vista_or_later_header(
+        cls,
+        context,
+        service_table_name,
+        service_binary_dll_map,
+        proc_layer_name,
+        offset,
+    ):
+        if offset % 8:
+            return
 
-        service_table_name = self.create_service_table(
-            self.context, kernel.symbol_table_name, self.config_path
+        service_header = context.object(
+            service_table_name + constants.BANG + "_SERVICE_HEADER",
+            offset=offset,
+            layer_name=proc_layer_name,
         )
 
-        # Building the dictionary ahead of time is much better for performance
-        # vs looking up each service's DLL individually.
-        services_key = self._get_service_key(kernel)
-        service_binary_dll_map = (
-            self._get_service_binary_map(services_key)
-            if services_key is not None
-            else {}
-        )
+        if not service_header.is_valid():
+            return
+
+        # since we walk the s-list backwards, if we've seen
+        # an object, then we've also seen all objects that
+        # exist before it, thus we can break at that time.
+        for service_record in service_header.ServiceRecord.traverse():
+            service_info = service_binary_dll_map.get(
+                service_record.get_name(),
+                ServiceBinaryInfo(
+                    renderers.UnreadableValue(), renderers.UnreadableValue()
+                ),
+            )
+            yield cls.get_record_tuple(service_record, service_info)
 
-        relative_tag_offset = self.context.symbol_space.get_type(
+    @classmethod
+    def service_scan(
+        cls,
+        context: interfaces.context.ContextInterface,
+        layer_name: str,
+        symbol_table: str,
+        service_table_name: str,
+        service_binary_dll_map,
+        filter_func,
+    ):
+        relative_tag_offset = context.symbol_space.get_type(
             service_table_name + constants.BANG + "_SERVICE_RECORD"
         ).relative_child_offset("Tag")
 
-        filter_func = pslist.PsList.create_name_filter(["services.exe"])
-
         is_vista_or_later = versions.is_vista_or_later(
-            context=self.context, symbol_table=kernel.symbol_table_name
+            context=context, symbol_table=symbol_table
         )
 
         if is_vista_or_later:
@@ -266,9 +298,9 @@ def _generator(self):
         seen = []
 
         for task in pslist.PsList.list_processes(
-            context=self.context,
-            layer_name=kernel.layer_name,
-            symbol_table=kernel.symbol_table_name,
+            context=context,
+            layer_name=layer_name,
+            symbol_table=symbol_table,
             filter_func=filter_func,
         ):
             proc_id = "Unknown"
@@ -283,15 +315,15 @@ def _generator(self):
                 )
                 continue
 
-            layer = self.context.layers[proc_layer_name]
+            layer = context.layers[proc_layer_name]
 
             for offset in layer.scan(
-                context=self.context,
+                context=context,
                 scanner=scanners.BytesScanner(needle=service_tag),
                 sections=vadyarascan.VadYaraScan.get_vad_maps(task),
             ):
                 if not is_vista_or_later:
-                    service_record = self.context.object(
+                    service_record = context.object(
                         service_table_name + constants.BANG + "_SERVICE_RECORD",
                         offset=offset - relative_tag_offset,
                         layer_name=proc_layer_name,
@@ -306,37 +338,60 @@ def _generator(self):
                             renderers.UnreadableValue(), renderers.UnreadableValue()
                         ),
                     )
-                    yield (
-                        0,
-                        self.get_record_tuple(service_record, service_info),
-                    )
+                    yield cls.get_record_tuple(service_record, service_info)
                 else:
-                    service_header = self.context.object(
-                        service_table_name + constants.BANG + "_SERVICE_HEADER",
-                        offset=offset,
-                        layer_name=proc_layer_name,
-                    )
-
-                    if not service_header.is_valid():
-                        continue
-
-                    # since we walk the s-list backwards, if we've seen
-                    # an object, then we've also seen all objects that
-                    # exist before it, thus we can break at that time.
-                    for service_record in service_header.ServiceRecord.traverse():
+                    for service_record in cls.enumerate_vista_or_later_header(
+                        context,
+                        service_table_name,
+                        service_binary_dll_map,
+                        proc_layer_name,
+                        offset,
+                    ):
                         if service_record in seen:
                             break
                         seen.append(service_record)
-                        service_info = service_binary_dll_map.get(
-                            service_record.get_name(),
-                            ServiceBinaryInfo(
-                                renderers.UnreadableValue(), renderers.UnreadableValue()
-                            ),
-                        )
-                        yield (
-                            0,
-                            self.get_record_tuple(service_record, service_info),
-                        )
+                        yield service_record
+
+    @classmethod
+    def get_prereq_info(cls, context, config_path, layer_name: str, symbol_table: str):
+        """
+        Data structures and information needed to analyze service information
+        """
+
+        service_table_name = cls._create_service_table(
+            context, symbol_table, config_path
+        )
+
+        services_key = cls._get_service_key(
+            context, config_path, layer_name, symbol_table
+        )
+
+        service_binary_dll_map = (
+            cls._get_service_binary_map(services_key)
+            if services_key is not None
+            else {}
+        )
+
+        filter_func = pslist.PsList.create_name_filter(["services.exe"])
+
+        return service_table_name, service_binary_dll_map, filter_func
+
+    def _generator(self):
+        kernel = self.context.modules[self.config["kernel"]]
+
+        service_table_name, service_binary_dll_map, filter_func = self.get_prereq_info(
+            self.context, self.config_path, kernel.layer_name, kernel.symbol_table_name
+        )
+
+        for record in self._enumeration_method(
+            self.context,
+            kernel.layer_name,
+            kernel.symbol_table_name,
+            service_table_name,
+            service_binary_dll_map,
+            filter_func,
+        ):
+            yield (0, record)
 
     def run(self):
         return renderers.TreeGrid(
diff --git a/volatility3/framework/plugins/windows/thrdscan.py b/volatility3/framework/plugins/windows/thrdscan.py
index 80906b3b91..6e664e0526 100644
--- a/volatility3/framework/plugins/windows/thrdscan.py
+++ b/volatility3/framework/plugins/windows/thrdscan.py
@@ -3,7 +3,7 @@
 ##
 import logging
 import datetime
-from typing import Iterable
+from typing import Callable, Iterable
 
 from volatility3.framework import renderers, interfaces, exceptions
 from volatility3.framework.configuration import requirements
@@ -19,7 +19,11 @@ class ThrdScan(interfaces.plugins.PluginInterface, timeliner.TimeLinerInterface)
 
     # version 2.6.0 adds support for scanning for 'Ethread' structures by pool tags
     _required_framework_version = (2, 6, 0)
-    _version = (1, 0, 0)
+    _version = (1, 1, 0)
+
+    def __init__(self, *args, **kwargs):
+        self.implementation = self.scan_threads
+        super().__init__(*args, **kwargs)
 
     @classmethod
     def get_requirements(cls):
@@ -38,8 +42,7 @@ def get_requirements(cls):
     def scan_threads(
         cls,
         context: interfaces.context.ContextInterface,
-        layer_name: str,
-        symbol_table: str,
+        module_name: str,
     ) -> Iterable[interfaces.objects.ObjectInterface]:
         """Scans for threads using the poolscanner module and constraints.
 
@@ -52,6 +55,10 @@ def scan_threads(
               A list of _ETHREAD objects found by scanning memory for the "Thre" / "Thr\\xE5" pool signatures
         """
 
+        module = context.modules[module_name]
+        layer_name = module.layer_name
+        symbol_table = module.symbol_table_name
+
         constraints = poolscanner.PoolScanner.builtin_constraints(
             symbol_table, [b"Thr\xe5", b"Thre"]
         )
@@ -62,45 +69,45 @@ def scan_threads(
             _constraint, mem_object, _header = result
             yield mem_object
 
-    def _generator(self):
-        kernel = self.context.modules[self.config["kernel"]]
+    @classmethod
+    def gather_thread_info(cls, ethread):
+        try:
+            thread_offset = ethread.vol.offset
+            owner_proc_pid = ethread.Cid.UniqueProcess
+            thread_tid = ethread.Cid.UniqueThread
+            thread_start_addr = ethread.StartAddress
+            thread_create_time = (
+                ethread.get_create_time()
+            )  # datetime.datetime object / volatility3.framework.renderers.UnparsableValue object
+            thread_exit_time = (
+                ethread.get_exit_time()
+            )  # datetime.datetime object / volatility3.framework.renderers.UnparsableValue object
+        except exceptions.InvalidAddressException:
+            vollog.debug("Thread invalid address {:#x}".format(ethread.vol.offset))
+            return None
+
+        return (
+            format_hints.Hex(thread_offset),
+            owner_proc_pid,
+            thread_tid,
+            format_hints.Hex(thread_start_addr),
+            thread_create_time,
+            thread_exit_time,
+        )
 
-        for ethread in self.scan_threads(
-            self.context, kernel.layer_name, kernel.symbol_table_name
-        ):
-            try:
-                thread_offset = ethread.vol.offset
-                owner_proc_pid = ethread.Cid.UniqueProcess
-                thread_tid = ethread.Cid.UniqueThread
-                thread_start_addr = ethread.StartAddress
-                thread_create_time = (
-                    ethread.get_create_time()
-                )  # datetime.datetime object / volatility3.framework.renderers.UnparsableValue object
-                thread_exit_time = (
-                    ethread.get_exit_time()
-                )  # datetime.datetime object / volatility3.framework.renderers.UnparsableValue object
-            except (ValueError, exceptions.InvalidAddressException):
-                vollog.debug(
-                    "Thread :{}, invalid address {} in layer {}".format(
-                        thread_tid, thread_start_addr, kernel.layer_name
-                    )
-                )
-                continue
+    def _generator(self, filter_func: Callable):
+        kernel_name = self.config["kernel"]
+
+        for ethread in self.implementation(self.context, kernel_name):
+            info = self.gather_thread_info(ethread)
 
-            yield (
-                0,
-                (
-                    format_hints.Hex(thread_offset),
-                    owner_proc_pid,
-                    thread_tid,
-                    format_hints.Hex(thread_start_addr),
-                    thread_create_time,
-                    thread_exit_time,
-                ),
-            )
+            if info:
+                yield (0, info)
 
     def generate_timeline(self):
-        for row in self._generator():
+        filt_func = self.filter_func(self.config)
+
+        for row in self._generator(filt_func):
             _depth, row_data = row
             row_dict = {}
             (
@@ -127,7 +134,14 @@ def generate_timeline(self):
                     row_dict["ExitTime"],
                 )
 
+    @classmethod
+    def filter_func(cls, config: interfaces.configuration.HierarchicalDict) -> Callable:
+        """Returns a function that can filter this plugin's implementation method based on the config"""
+        return lambda x: False
+
     def run(self):
+        filt_func = self.filter_func(self.config)
+
         return renderers.TreeGrid(
             [
                 ("Offset", format_hints.Hex),
@@ -137,5 +151,5 @@ def run(self):
                 ("CreateTime", datetime.datetime),
                 ("ExitTime", datetime.datetime),
             ],
-            self._generator(),
+            self._generator(filt_func),
         )
diff --git a/volatility3/framework/plugins/windows/threads.py b/volatility3/framework/plugins/windows/threads.py
new file mode 100644
index 0000000000..39f3b7d773
--- /dev/null
+++ b/volatility3/framework/plugins/windows/threads.py
@@ -0,0 +1,90 @@
+# 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 Callable, Iterable, List, Generator
+
+from volatility3.framework import interfaces, constants
+from volatility3.framework.configuration import requirements
+from volatility3.plugins.windows import pslist, thrdscan
+
+vollog = logging.getLogger(__name__)
+
+
+class Threads(thrdscan.ThrdScan):
+    """Lists process threads"""
+
+    _required_framework_version = (2, 4, 0)
+    _version = (1, 0, 0)
+
+    def __init__(self, *args, **kwargs):
+        self.implementation = self.list_process_threads
+        super().__init__(*args, **kwargs)
+
+    @classmethod
+    def get_requirements(cls) -> List[interfaces.configuration.RequirementInterface]:
+        # Since we're calling the plugin, make sure we have the plugin's requirements
+        return [
+            requirements.ModuleRequirement(
+                name="kernel",
+                description="Windows kernel",
+                architectures=["Intel32", "Intel64"],
+            ),
+            requirements.ListRequirement(
+                name="pid",
+                description="Filter on specific process IDs",
+                element_type=int,
+                optional=True,
+            ),
+            requirements.PluginRequirement(
+                name="thrdscan", plugin=thrdscan.ThrdScan, version=(1, 1, 0)
+            ),
+        ]
+
+    @classmethod
+    def list_threads(
+        cls, kernel, proc: interfaces.objects.ObjectInterface
+    ) -> Generator[interfaces.objects.ObjectInterface, None, None]:
+        """Lists the Threads of a specific process.
+
+        Args:
+            proc: _EPROCESS object from which to list the VADs
+            filter_func: Function to take a virtual address descriptor value and return True if it should be filtered out
+
+        Returns:
+            A list of threads based on the process and filtered based on the filter function
+        """
+        seen = set()
+        for thread in proc.ThreadListHead.to_list(
+            f"{kernel.symbol_table_name}{constants.BANG}_ETHREAD", "ThreadListEntry"
+        ):
+            if thread.vol.offset in seen:
+                break
+            seen.add(thread.vol.offset)
+            yield thread
+
+    @classmethod
+    def filter_func(cls, config: interfaces.configuration.HierarchicalDict) -> Callable:
+        return pslist.PsList.create_pid_filter(config.get("pid", None))
+
+    @classmethod
+    def list_process_threads(
+        cls,
+        context: interfaces.context.ContextInterface,
+        module_name: str,
+        filter_func: Callable,
+    ) -> Iterable[interfaces.objects.ObjectInterface]:
+        """Runs through all processes and lists threads for each process"""
+        module = context.modules[module_name]
+        layer_name = module.layer_name
+        symbol_table_name = module.symbol_table_name
+
+        for proc in pslist.PsList.list_processes(
+            context=context,
+            layer_name=layer_name,
+            symbol_table=symbol_table_name,
+            filter_func=filter_func,
+        ):
+            for thread in cls.list_threads(module, proc):
+                yield thread
diff --git a/volatility3/framework/plugins/windows/timers.py b/volatility3/framework/plugins/windows/timers.py
new file mode 100644
index 0000000000..d49c287842
--- /dev/null
+++ b/volatility3/framework/plugins/windows/timers.py
@@ -0,0 +1,212 @@
+# This file is Copyright 2024 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 Iterator, List, Tuple, Iterable
+
+from volatility3.framework import (
+    renderers,
+    interfaces,
+    constants,
+    symbols,
+)
+from volatility3.framework.configuration import requirements
+from volatility3.framework.renderers import format_hints
+from volatility3.framework.symbols.windows import versions
+from volatility3.plugins.windows import ssdt, kpcrs
+
+vollog = logging.getLogger(__name__)
+
+
+class Timers(interfaces.plugins.PluginInterface):
+    """Print kernel timers and associated module DPCs"""
+
+    _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="ssdt", plugin=ssdt.SSDT, version=(1, 0, 0)
+            ),
+            requirements.PluginRequirement(
+                name="kpcrs", plugin=kpcrs.KPCRs, version=(1, 0, 0)
+            ),
+        ]
+
+    @classmethod
+    def list_timers(
+        cls,
+        context: interfaces.context.ContextInterface,
+        kernel_module_name: str,
+        layer_name: str,
+        symbol_table: str,
+    ) -> Iterable[Tuple[str, int, str]]:
+        """Lists all kernel timers.
+
+        Args:
+            context: The context to retrieve required elements (layers, symbol tables) from
+            kernel_module_name: The name of the kernel module on which to operate
+            layer_name: The name of the layer on which to operate
+            symbol_table: The name of the table containing the kernel symbols
+
+        Yields:
+            A _KTIMER entry
+        """
+
+        kernel = context.modules[kernel_module_name]
+        if versions.is_windows_7(
+            context=context, symbol_table=symbol_table
+        ) or versions.is_windows_8_or_later(context=context, symbol_table=symbol_table):
+            # Starting with Windows 7, there is no more KiTimerTableListHead. The list is
+            # at _KPCR.PrcbData.TimerTable.TimerEntries
+            # See http://pastebin.com/FiRsGW3f
+            for kpcr in kpcrs.KPCRs.list_kpcrs(
+                context, kernel_module_name, layer_name, symbol_table
+            ):
+                if hasattr(kpcr.Prcb.TimerTable, "TableState"):
+                    for timer_entries in kpcr.Prcb.TimerTable.TimerEntries:
+                        for timer_entry in timer_entries:
+                            for timer in timer_entry.Entry.to_list(
+                                symbol_table + constants.BANG + "_KTIMER",
+                                "TimerListEntry",
+                            ):
+                                yield timer
+
+                else:
+                    for timer_entries in kpcr.Prcb.TimerTable.TimerEntries:
+                        for timer in timer_entries.Entry.to_list(
+                            symbol_table + constants.BANG + "_KTIMER",
+                            "TimerListEntry",
+                        ):
+                            yield timer
+
+        elif versions.is_xp_or_2003(
+            context=context, symbol_table=symbol_table
+        ) or versions.is_vista_or_later(context=context, symbol_table=symbol_table):
+            is_64bit = symbols.symbol_table_is_64bit(context, symbol_table)
+            if is_64bit or versions.is_vista_or_later(
+                context=context, symbol_table=symbol_table
+            ):
+                # On XP x64, Windows 2003 SP1-SP2, and Vista SP0-SP2, KiTimerTableListHead
+                # is an array of 512 _KTIMER_TABLE_ENTRY structs.
+                array_size = 512
+            else:
+                # On XP SP0-SP3 x86 and Windows 2003 SP0, KiTimerTableListHead
+                # is an array of 256 _LIST_ENTRY for _KTIMERs.
+                array_size = 256
+
+            timer_table_list_head = kernel.object(
+                object_type="array",
+                offset=kernel.get_symbol("KiTimerTableListHead").address,
+                subtype=kernel.get_type("_LIST_ENTRY"),
+                count=array_size,
+            )
+            for table in timer_table_list_head:
+                for timer in table.to_list(
+                    symbol_table + constants.BANG + "_KTIMER",
+                    "TimerListEntry",
+                ):
+                    yield timer
+
+        else:
+            raise NotImplementedError("This version of Windows is not supported!")
+
+    def _generator(self) -> Iterator[Tuple]:
+        kernel = self.context.modules[self.config["kernel"]]
+        layer_name = kernel.layer_name
+        symbol_table = kernel.symbol_table_name
+
+        collection = ssdt.SSDT.build_module_collection(
+            self.context, kernel.layer_name, kernel.symbol_table_name
+        )
+
+        for timer in self.list_timers(
+            self.context, self.config["kernel"], layer_name, symbol_table
+        ):
+            if not timer.valid_type():
+                continue
+            try:
+                dpc = timer.get_dpc()
+                if dpc == 0:
+                    continue
+                if dpc.DeferredRoutine == 0:
+                    continue
+                deferred_routine = dpc.DeferredRoutine
+            except Exception as e:
+                continue
+
+            module_symbols = list(
+                collection.get_module_symbols_by_absolute_location(deferred_routine)
+            )
+
+            if module_symbols:
+                for module_name, symbol_generator in module_symbols:
+                    symbols_found = False
+
+                    # we might have multiple symbols pointing to the same location
+                    for symbol in symbol_generator:
+                        symbols_found = True
+                        yield (
+                            0,
+                            (
+                                format_hints.Hex(timer.vol.offset),
+                                timer.get_due_time(),
+                                timer.Period,
+                                timer.get_signaled(),
+                                format_hints.Hex(deferred_routine),
+                                module_name,
+                                symbol.split(constants.BANG)[1],
+                            ),
+                        )
+
+                    # no symbols, but we at least can report the module name
+                    if not symbols_found:
+                        yield (
+                            0,
+                            (
+                                format_hints.Hex(timer.vol.offset),
+                                timer.get_due_time(),
+                                timer.Period,
+                                timer.get_signaled(),
+                                format_hints.Hex(deferred_routine),
+                                module_name,
+                                renderers.NotAvailableValue(),
+                            ),
+                        )
+            else:
+                # no module was found at the absolute location
+                yield (
+                    0,
+                    (
+                        format_hints.Hex(timer.vol.offset),
+                        timer.get_due_time(),
+                        timer.Period,
+                        timer.get_signaled(),
+                        format_hints.Hex(deferred_routine),
+                        renderers.NotAvailableValue(),
+                        renderers.NotAvailableValue(),
+                    ),
+                )
+
+    def run(self):
+        return renderers.TreeGrid(
+            [
+                ("Offset", format_hints.Hex),
+                ("DueTime", str),
+                ("Period(ms)", int),
+                ("Signaled", str),
+                ("Routine", format_hints.Hex),
+                ("Module", str),
+                ("Symbol", str),
+            ],
+            self._generator(),
+        )
diff --git a/volatility3/framework/plugins/windows/truecrypt.py b/volatility3/framework/plugins/windows/truecrypt.py
index 81250a749e..7fd26cb4e6 100644
--- a/volatility3/framework/plugins/windows/truecrypt.py
+++ b/volatility3/framework/plugins/windows/truecrypt.py
@@ -33,7 +33,7 @@ def get_requirements(cls) -> List[RequirementInterface]:
                 architectures=["Intel32", "Intel64"],
             ),
             requirements.VersionRequirement(
-                name="modules", component=modules.Modules, version=(1, 1, 0)
+                name="modules", component=modules.Modules, version=(2, 0, 0)
             ),
             requirements.IntRequirement(
                 name="min-length",
diff --git a/volatility3/framework/plugins/windows/unloadedmodules.py b/volatility3/framework/plugins/windows/unloadedmodules.py
new file mode 100644
index 0000000000..0d88e96ffb
--- /dev/null
+++ b/volatility3/framework/plugins/windows/unloadedmodules.py
@@ -0,0 +1,160 @@
+# This file is Copyright 2024 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
+import datetime
+from typing import List, Iterable
+
+from volatility3.framework import constants
+from volatility3.framework import interfaces, symbols
+from volatility3.framework import renderers
+from volatility3.framework.configuration import requirements
+from volatility3.framework.interfaces import configuration
+from volatility3.framework.renderers import format_hints, conversion
+from volatility3.framework.symbols import intermed
+from volatility3.plugins import timeliner
+
+vollog = logging.getLogger(__name__)
+
+
+class UnloadedModules(interfaces.plugins.PluginInterface, timeliner.TimeLinerInterface):
+    """Lists the unloaded kernel modules."""
+
+    _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"],
+            ),
+        ]
+
+    @staticmethod
+    def create_unloadedmodules_table(
+        context: interfaces.context.ContextInterface,
+        symbol_table: str,
+        config_path: str,
+    ) -> str:
+        """Creates a symbol table for the unloaded modules.
+
+        Args:
+            context: The context to retrieve required elements (layers, symbol tables) from
+            symbol_table: The name of an existing symbol table containing the kernel symbols
+            config_path: The configuration path within the context of the symbol table to create
+
+        Returns:
+            The name of the constructed unloaded modules table
+        """
+        native_types = context.symbol_space[symbol_table].natives
+        is_64bit = symbols.symbol_table_is_64bit(context, symbol_table)
+        table_mapping = {"nt_symbols": symbol_table}
+
+        if is_64bit:
+            symbol_filename = "unloadedmodules-x64"
+        else:
+            symbol_filename = "unloadedmodules-x86"
+
+        return intermed.IntermediateSymbolTable.create(
+            context,
+            configuration.path_join(config_path, "unloadedmodules"),
+            "windows",
+            symbol_filename,
+            native_types=native_types,
+            table_mapping=table_mapping,
+        )
+
+    @classmethod
+    def list_unloadedmodules(
+        cls,
+        context: interfaces.context.ContextInterface,
+        layer_name: str,
+        symbol_table: str,
+        unloadedmodule_table_name: str,
+    ) -> Iterable[interfaces.objects.ObjectInterface]:
+        """Lists all the unloaded modules in the primary layer.
+
+        Args:
+            context: The context to retrieve required elements (layers, symbol tables) from
+            layer_name: The name of the layer on which to operate
+            symbol_table: The name of the table containing the kernel symbols
+
+        Returns:
+            A list of Unloaded Modules as retrieved from MmUnloadedDrivers
+        """
+
+        kvo = context.layers[layer_name].config["kernel_virtual_offset"]
+        ntkrnlmp = context.module(symbol_table, layer_name=layer_name, offset=kvo)
+        unloadedmodules_offset = ntkrnlmp.get_symbol("MmUnloadedDrivers").address
+        unloadedmodules = ntkrnlmp.object(
+            object_type="pointer",
+            offset=unloadedmodules_offset,
+            subtype="array",
+        )
+        is_64bit = symbols.symbol_table_is_64bit(context, symbol_table)
+
+        if is_64bit:
+            unloaded_count_type = "unsigned long long"
+        else:
+            unloaded_count_type = "unsigned long"
+
+        last_unloadedmodule_offset = ntkrnlmp.get_symbol("MmLastUnloadedDriver").address
+        unloaded_count = ntkrnlmp.object(
+            object_type=unloaded_count_type, offset=last_unloadedmodule_offset
+        )
+
+        unloadedmodules_array = context.object(
+            object_type=unloadedmodule_table_name
+            + constants.BANG
+            + "_UNLOADED_DRIVERS",
+            layer_name=layer_name,
+            offset=unloadedmodules,
+        )
+        unloadedmodules_array.UnloadedDrivers.count = unloaded_count
+
+        for mod in unloadedmodules_array.UnloadedDrivers:
+            yield mod
+
+    def _generator(self):
+        kernel = self.context.modules[self.config["kernel"]]
+
+        unloadedmodule_table_name = self.create_unloadedmodules_table(
+            self.context, kernel.symbol_table_name, self.config_path
+        )
+
+        for mod in self.list_unloadedmodules(
+            self.context,
+            kernel.layer_name,
+            kernel.symbol_table_name,
+            unloadedmodule_table_name,
+        ):
+            yield (
+                0,
+                (
+                    mod.Name.String,
+                    format_hints.Hex(mod.StartAddress),
+                    format_hints.Hex(mod.EndAddress),
+                    conversion.wintime_to_datetime(mod.CurrentTime),
+                ),
+            )
+
+    def generate_timeline(self):
+        for row in self._generator():
+            _depth, row_data = row
+            description = f"Unloaded Module: {row_data[0]}"
+            yield (description, timeliner.TimeLinerType.CHANGED, row_data[3])
+
+    def run(self):
+        return renderers.TreeGrid(
+            [
+                ("Name", str),
+                ("StartAddress", format_hints.Hex),
+                ("EndAddress", format_hints.Hex),
+                ("Time", datetime.datetime),
+            ],
+            self._generator(),
+        )
diff --git a/volatility3/framework/plugins/windows/vadyarascan.py b/volatility3/framework/plugins/windows/vadyarascan.py
index d795818e93..dc318dd934 100644
--- a/volatility3/framework/plugins/windows/vadyarascan.py
+++ b/volatility3/framework/plugins/windows/vadyarascan.py
@@ -18,7 +18,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 +32,8 @@ def get_requirements(cls) -> List[interfaces.configuration.RequirementInterface]
             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 +56,8 @@ def _generator(self):
 
         filter_func = pslist.PsList.create_pid_filter(self.config.get("pid", None))
 
+        sanity_check = 1024 * 1024 * 1024  # 1 GB
+
         for task in pslist.PsList.list_processes(
             context=self.context,
             layer_name=kernel.layer_name,
@@ -67,18 +66,33 @@ def _generator(self):
         ):
             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, size in self.get_vad_maps(task):
+                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, size, 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(
@@ -91,7 +105,7 @@ def get_vad_maps(
             task: The EPROCESS object of which to traverse the vad tree
 
         Returns:
-            An iterable of tuples containing start and end addresses for each descriptor
+            An iterable of tuples containing start and size for each descriptor
         """
         vad_root = task.get_vad_root()
         for vad in vad_root.traverse():
diff --git a/volatility3/framework/plugins/windows/virtmap.py b/volatility3/framework/plugins/windows/virtmap.py
index 5190bec8d2..3f3f270e2e 100644
--- a/volatility3/framework/plugins/windows/virtmap.py
+++ b/volatility3/framework/plugins/windows/virtmap.py
@@ -78,7 +78,7 @@ def determine_map(
                 )
             else:
                 raise exceptions.SymbolError(
-                    None, module.name, "Required structures not found"
+                    "SystemVaRegions", module.name, "Required structures not found"
                 )
         elif module.has_symbol("MiSystemVaType"):
             system_range_start = module.object(
@@ -99,7 +99,7 @@ def determine_map(
             )
         else:
             raise exceptions.SymbolError(
-                None, module.name, "Required structures not found"
+                "MiVisibleState", module.name, "Required structures not found"
             )
 
         return result
diff --git a/volatility3/framework/plugins/yarascan.py b/volatility3/framework/plugins/yarascan.py
index 11c7086073..496ec18446 100644
--- a/volatility3/framework/plugins/yarascan.py
+++ b/volatility3/framework/plugins/yarascan.py
@@ -43,7 +43,7 @@ def __call__(
         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 +61,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 +119,14 @@ def get_yarascan_option_requirements(
             ),
         ]
 
+    @classmethod
+    def yara_returns_instances(cls) -> 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
diff --git a/volatility3/framework/renderers/conversion.py b/volatility3/framework/renderers/conversion.py
index bb18fcc8a6..864794860b 100644
--- a/volatility3/framework/renderers/conversion.py
+++ b/volatility3/framework/renderers/conversion.py
@@ -19,9 +19,11 @@ def wintime_to_datetime(
         return renderers.NotApplicableValue()
     unix_time = unix_time - 11644473600
     try:
-        return datetime.datetime.utcfromtimestamp(unix_time)
-        # Windows sometimes throws OSErrors rather than ValueErrors when it can't convert a value
-    except (ValueError, OSError):
+        return datetime.datetime.fromtimestamp(unix_time, datetime.timezone.utc)
+        # Windows sometimes throws OSErrors rather than ValueError/OverflowError when it can't convert a value
+        # Since Python 3.3, this should raise OverflowError instead of ValueError. However, it was observed
+        # that even in Python 3.7.17, ValueError is still being raised.
+    except (ValueError, OverflowError, OSError):
         return renderers.UnparsableValue()
 
 
@@ -33,8 +35,10 @@ def unixtime_to_datetime(
     )
 
     if unixtime > 0:
-        with contextlib.suppress(ValueError):
-            ret = datetime.datetime.utcfromtimestamp(unixtime)
+        # Since Python 3.3, this should raise OverflowError instead of ValueError. However, it was observed
+        # that even in Python 3.7.17, ValueError is still being raised. OSError is also raised on Linux
+        with contextlib.suppress(ValueError, OverflowError, OSError):
+            ret = datetime.datetime.fromtimestamp(unixtime, datetime.timezone.utc)
 
     return ret
 
diff --git a/volatility3/framework/renderers/format_hints.py b/volatility3/framework/renderers/format_hints.py
index 6120b77c93..194e38099c 100644
--- a/volatility3/framework/renderers/format_hints.py
+++ b/volatility3/framework/renderers/format_hints.py
@@ -10,6 +10,8 @@
 """
 from typing import Type, Union
 
+from volatility3.framework import interfaces
+
 
 class Bin(int):
     """A class to indicate that the integer value should be represented as a
@@ -66,3 +68,17 @@ def __eq__(self, other):
             and self.split_nulls == other.split_nulls
             and self.show_hex == other.show_hex
         )
+
+
+BinOrAbsent = lambda x: (
+    Bin(x) if not isinstance(x, interfaces.renderers.BaseAbsentValue) else x
+)
+HexOrAbsent = lambda x: (
+    Hex(x) if not isinstance(x, interfaces.renderers.BaseAbsentValue) else x
+)
+HexBytesOrAbsent = lambda x: (
+    HexBytes(x) if not isinstance(x, interfaces.renderers.BaseAbsentValue) else x
+)
+MultiTypeDataOrAbsent = lambda x: (
+    MultiTypeData(x) if not isinstance(x, interfaces.renderers.BaseAbsentValue) else x
+)
diff --git a/volatility3/framework/symbols/intermed.py b/volatility3/framework/symbols/intermed.py
index 8c40e466a0..751f88e39c 100644
--- a/volatility3/framework/symbols/intermed.py
+++ b/volatility3/framework/symbols/intermed.py
@@ -282,7 +282,7 @@ def create(
         urls = list(cls.file_symbol_url(sub_path, filename))
         if not urls:
             raise FileNotFoundError(
-                "No symbol files found at provided filename: {}", filename
+                f"No symbol files found at provided filename: {filename}",
             )
         table_name = context.symbol_space.free_table_name(filename)
         table = cls(
diff --git a/volatility3/framework/symbols/linux/__init__.py b/volatility3/framework/symbols/linux/__init__.py
index c4e2587f49..03353135d0 100644
--- a/volatility3/framework/symbols/linux/__init__.py
+++ b/volatility3/framework/symbols/linux/__init__.py
@@ -29,12 +29,18 @@ def __init__(self, *args, **kwargs) -> None:
         self.set_type_class("files_struct", extensions.files_struct)
         self.set_type_class("kobject", extensions.kobject)
         self.set_type_class("cred", extensions.cred)
+        self.set_type_class("inode", extensions.inode)
         # Might not exist in the current symbols
         self.optional_set_type_class("module", extensions.module)
         self.optional_set_type_class("bpf_prog", extensions.bpf_prog)
         self.optional_set_type_class("kernel_cap_struct", extensions.kernel_cap_struct)
         self.optional_set_type_class("kernel_cap_t", extensions.kernel_cap_t)
 
+        # kernels >= 4.18
+        self.optional_set_type_class("timespec64", extensions.timespec64)
+        # kernels < 4.18. Reuses timespec64 obj extension, since both has the same members
+        self.optional_set_type_class("timespec", extensions.timespec64)
+
         # Mount
         self.set_type_class("vfsmount", extensions.vfsmount)
         # Might not exist in older kernels or the current symbols
diff --git a/volatility3/framework/symbols/linux/extensions/__init__.py b/volatility3/framework/symbols/linux/extensions/__init__.py
index e7c6b66d7d..05679523f3 100644
--- a/volatility3/framework/symbols/linux/extensions/__init__.py
+++ b/volatility3/framework/symbols/linux/extensions/__init__.py
@@ -4,10 +4,13 @@
 
 import collections.abc
 import logging
+import stat
+from datetime import datetime
 import socket as socket_module
-from typing import Generator, Iterable, Iterator, Optional, Tuple, List
+from typing import Generator, Iterable, Iterator, Optional, Tuple, List, Union
 
 from volatility3.framework import constants, exceptions, objects, interfaces, symbols
+from volatility3.framework.renderers import conversion
 from volatility3.framework.constants.linux import SOCK_TYPES, SOCK_FAMILY
 from volatility3.framework.constants.linux import IP_PROTOCOLS, IPV6_PROTOCOLS
 from volatility3.framework.constants.linux import TCP_STATES, NETLINK_PROTOCOLS
@@ -1761,3 +1764,136 @@ def get_capabilities(self) -> int:
             )
 
         return cap_value & self.get_kernel_cap_full()
+
+
+class timespec64(objects.StructType):
+    def to_datetime(self) -> datetime:
+        """Returns the respective aware datetime"""
+
+        dt = conversion.unixtime_to_datetime(self.tv_sec + self.tv_nsec / 1e9)
+        return dt
+
+
+class inode(objects.StructType):
+    def is_valid(self) -> bool:
+        # i_count is a 'signed' counter (atomic_t). Smear, or essentially a wrong inode
+        # pointer, will easily cause an integer overflow here.
+        return self.i_ino > 0 and self.i_count.counter >= 0
+
+    @property
+    def is_dir(self) -> bool:
+        """Returns True if the inode is a directory"""
+        return stat.S_ISDIR(self.i_mode) != 0
+
+    @property
+    def is_reg(self) -> bool:
+        """Returns True if the inode is a regular file"""
+        return stat.S_ISREG(self.i_mode) != 0
+
+    @property
+    def is_link(self) -> bool:
+        """Returns True if the inode is a symlink"""
+        return stat.S_ISLNK(self.i_mode) != 0
+
+    @property
+    def is_fifo(self) -> bool:
+        """Returns True if the inode is a FIFO"""
+        return stat.S_ISFIFO(self.i_mode) != 0
+
+    @property
+    def is_sock(self) -> bool:
+        """Returns True if the inode is a socket"""
+        return stat.S_ISSOCK(self.i_mode) != 0
+
+    @property
+    def is_block(self) -> bool:
+        """Returns True if the inode is a block device"""
+        return stat.S_ISBLK(self.i_mode) != 0
+
+    @property
+    def is_char(self) -> bool:
+        """Returns True if the inode is a char device"""
+        return stat.S_ISCHR(self.i_mode) != 0
+
+    @property
+    def is_sticky(self) -> bool:
+        """Returns True if the sticky bit is set"""
+        return (self.i_mode & stat.S_ISVTX) != 0
+
+    def get_inode_type(self) -> Union[str, None]:
+        """Returns inode type name
+
+        Returns:
+            The inode type name
+        """
+        if self.is_dir:
+            return "DIR"
+        elif self.is_reg:
+            return "REG"
+        elif self.is_link:
+            return "LNK"
+        elif self.is_fifo:
+            return "FIFO"
+        elif self.is_sock:
+            return "SOCK"
+        elif self.is_char:
+            return "CHR"
+        elif self.is_block:
+            return "BLK"
+        else:
+            return None
+
+    def _time_member_to_datetime(self, member) -> datetime:
+        if self.has_member(f"{member}_sec") and self.has_member(f"{member}_nsec"):
+            # kernels >= 6.11 it's i_*_sec -> time64_t and i_*_nsec -> u32
+            # Ref Linux commit 3aa63a569c64e708df547a8913c84e64a06e7853
+            return conversion.unixtime_to_datetime(
+                self.member(f"{member}_sec") + self.has_member(f"{member}_nsec") / 1e9
+            )
+        elif self.has_member(f"__{member}"):
+            # 6.6 <= kernels < 6.11 it's a timespec64
+            # Ref Linux commit 13bc24457850583a2e7203ded05b7209ab4bc5ef / 12cd44023651666bd44baa36a5c999698890debb
+            return self.member(f"__{member}").to_datetime()
+        elif self.has_member(member):
+            # In kernels < 6.6 it's a timespec64 or timespec
+            return self.member(member).to_datetime()
+        else:
+            raise exceptions.VolatilityException(
+                "Unsupported kernel inode type implementation"
+            )
+
+    def get_access_time(self) -> datetime:
+        """Returns the inode's last access time
+        This is updated when inode contents are read
+
+        Returns:
+            A datetime with the inode's last access time
+        """
+        return self._time_member_to_datetime("i_atime")
+
+    def get_modification_time(self) -> datetime:
+        """Returns the inode's last modification time
+        This is updated when the inode contents change
+
+        Returns:
+            A datetime with the inode's last data modification time
+        """
+
+        return self._time_member_to_datetime("i_mtime")
+
+    def get_change_time(self) -> datetime:
+        """Returns the inode's last change time
+        This is updated when the inode metadata changes
+
+        Returns:
+            A datetime with the inode's last change time
+        """
+        return self._time_member_to_datetime("i_ctime")
+
+    def get_file_mode(self) -> str:
+        """Returns the inode's file mode as string of the form '-rwxrwxrwx'.
+
+        Returns:
+            The inode's file mode string
+        """
+        return stat.filemode(self.i_mode)
diff --git a/volatility3/framework/symbols/windows/__init__.py b/volatility3/framework/symbols/windows/__init__.py
index abf9f6da32..c1b7894ffa 100755
--- a/volatility3/framework/symbols/windows/__init__.py
+++ b/volatility3/framework/symbols/windows/__init__.py
@@ -17,6 +17,7 @@ def __init__(self, *args, **kwargs) -> None:
         self.set_type_class("_KTHREAD", extensions.KTHREAD)
         self.set_type_class("_LIST_ENTRY", extensions.LIST_ENTRY)
         self.set_type_class("_EPROCESS", extensions.EPROCESS)
+        self.set_type_class("_ERESOURCE", extensions.ERESOURCE)
         self.set_type_class("_UNICODE_STRING", extensions.UNICODE_STRING)
         self.set_type_class("_EX_FAST_REF", extensions.EX_FAST_REF)
         self.set_type_class("_TOKEN", extensions.TOKEN)
@@ -39,6 +40,7 @@ def __init__(self, *args, **kwargs) -> None:
         self.set_type_class("_VACB", extensions.VACB)
         self.set_type_class("_POOL_TRACKER_BIG_PAGES", pool.POOL_TRACKER_BIG_PAGES)
         self.set_type_class("_IMAGE_DOS_HEADER", pe.IMAGE_DOS_HEADER)
+        self.set_type_class("_KTIMER", extensions.KTIMER)
 
         # Might not necessarily defined in every version of windows
         self.optional_set_type_class("_IMAGE_NT_HEADERS", pe.IMAGE_NT_HEADERS)
diff --git a/volatility3/framework/symbols/windows/callbacks-x64.json b/volatility3/framework/symbols/windows/callbacks-x64.json
index 87682cb923..705f2361d5 100644
--- a/volatility3/framework/symbols/windows/callbacks-x64.json
+++ b/volatility3/framework/symbols/windows/callbacks-x64.json
@@ -1,6 +1,18 @@
 {
     "symbols": {},
-    "enums": {},
+    "enums": {
+        "EventCategory": {
+            "base": "long",
+            "constants": {
+                "EventCategoryReserved": 0,
+                "EventCategoryHardwareProfileChange": 1,
+                "EventCategoryDeviceInterfaceChange": 2,
+                "EventCategoryTargetDeviceChange": 3,
+                "EventCategoryKernelSoftRestart": 4
+            },
+            "size": 4
+        }
+    },
     "base_types": {
         "unsigned long": {
             "kind": "int",
@@ -48,19 +60,164 @@
     "user_types": {
         "_GENERIC_CALLBACK": {
             "fields": {
-              "Callback": {
-                "type": {
-                  "kind": "pointer",
-                  "subtype": {
-                    "kind": "base",
-                    "name": "void"
-                  }
+                "Callback": {
+                    "type": {
+                        "kind": "pointer",
+                        "subtype": {
+                            "kind": "base",
+                            "name": "void"
+                        }
+                    },
+                    "offset": 8
                 },
-                "offset": 8
-              }
+                "Associated": {
+                    "type": {
+                        "kind": "pointer",
+                        "subtype": {
+                            "kind": "base",
+                            "name": "void"
+                        }
+                    },
+                    "offset": 16
+                }
+            },
+            "kind": "struct",
+            "size": 24
+        },
+        "_NOTIFICATION_PACKET": {
+            "fields": {
+                "ListEntry": {
+                    "type": {
+                        "kind": "struct",
+                        "name": "nt_symbols!_LIST_ENTRY"
+                    },
+                    "offset": 0
+                },
+                "DriverObject": {
+                    "type": {
+                        "kind": "pointer",
+                        "subtype": {
+                            "kind": "struct",
+                            "name": "nt_symbols!_DRIVER_OBJECT"
+                        }
+                    },
+                    "offset": 16
+                },
+                "NotificationRoutine": {
+                    "type": {
+                        "kind": "pointer",
+                        "subtype": {
+                            "kind": "base",
+                            "name": "void"
+                        }
+                    },
+                    "offset": 24
+                }
+            },
+            "kind": "struct",
+            "size": 48
+        },
+        "_SHUTDOWN_PACKET": {
+            "fields": {
+                "Entry": {
+                    "type": {
+                        "kind": "struct",
+                        "name": "nt_symbols!_LIST_ENTRY"
+                    },
+                    "offset": 0
+                },
+                "DeviceObject": {
+                    "type": {
+                        "kind": "pointer",
+                        "subtype": {
+                            "kind": "struct",
+                            "name": "nt_symbols!_DEVICE_OBJECT"
+                        }
+                    },
+                    "offset": 16
+                }
+            },
+            "kind": "struct",
+            "size": 24
+        },
+        "_DBGPRINT_CALLBACK": {
+            "fields": {
+                "Function": {
+                    "type": {
+                        "kind": "pointer",
+                        "subtype": {
+                            "kind": "base",
+                            "name": "void"
+                        }
+                    },
+                    "offset": 16
+                }
+            },
+            "kind": "struct",
+            "size": 24
+        },
+        "_NOTIFY_ENTRY_HEADER": {
+            "fields": {
+                "ListEntry": {
+                    "type": {
+                        "kind": "struct",
+                        "name": "nt_symbols!_LIST_ENTRY"
+                    },
+                    "offset": 0
+                },
+                "EventCategory": {
+                    "type": {
+                        "kind": "enum",
+                        "name": "EventCategory"
+                    },
+                    "offset": 16
+                },
+                "CallbackRoutine": {
+                    "type": {
+                        "kind": "pointer",
+                        "subtype": {
+                            "kind": "base",
+                            "name": "void"
+                        }
+                    },
+                    "offset": 32
+                },
+                "DriverObject": {
+                    "type": {
+                        "kind": "pointer",
+                        "subtype": {
+                            "kind": "struct",
+                            "name": "nt_symbols!_DRIVER_OBJECT"
+                        }
+                    },
+                    "offset": 48
+                }
+            },
+            "kind": "struct",
+            "size": 64
+        },
+        "_REGISTRY_CALLBACK": {
+            "fields": {
+                "ListEntry": {
+                    "type": {
+                        "kind": "struct",
+                        "name": "nt_symbols!_LIST_ENTRY"
+                    },
+                    "offset": 0
+                },
+                "Function": {
+                    "type": {
+                        "kind": "pointer",
+                        "subtype": {
+                            "kind": "base",
+                            "name": "void"
+                        }
+                    },
+                    "offset": 40
+                }
             },
             "kind": "struct",
-            "size": 16
+            "size": 48
         },
         "_KBUGCHECK_CALLBACK_RECORD": {
             "fields": {
@@ -184,10 +341,10 @@
     },
     "metadata": {
         "producer": {
-            "version": "0.0.1",
-            "name": "mhl by hand",
-            "datetime": "2019-08-27T18:17:16.417006"
+            "version": "0.0.2",
+            "name": "dgmcdona by hand",
+            "datetime": "2024-02-02T19:32:00.000000"
         },
         "format": "4.0.0"
     }
-}
\ No newline at end of file
+}
diff --git a/volatility3/framework/symbols/windows/callbacks-x86.json b/volatility3/framework/symbols/windows/callbacks-x86.json
index 702b68a650..63b8c69b4f 100644
--- a/volatility3/framework/symbols/windows/callbacks-x86.json
+++ b/volatility3/framework/symbols/windows/callbacks-x86.json
@@ -1,6 +1,18 @@
 {
     "symbols": {},
-    "enums": {},
+    "enums": {
+        "EventCategory": {
+            "base": "long",
+            "constants": {
+                "EventCategoryReserved": 0,
+                "EventCategoryHardwareProfileChange": 1,
+                "EventCategoryDeviceInterfaceChange": 2,
+                "EventCategoryTargetDeviceChange": 3,
+                "EventCategoryKernelSoftRestart": 4
+            },
+            "size": 4
+        }
+    },
     "base_types": {
         "unsigned long": {
             "kind": "int",
@@ -46,6 +58,151 @@
         }
     },
     "user_types": {
+        "_NOTIFICATION_PACKET": {
+            "fields": {
+                "ListEntry": {
+                    "type": {
+                        "kind": "struct",
+                        "name": "nt_symbols!_LIST_ENTRY"
+                    },
+                    "offset": 0
+                },
+                "DriverObject": {
+                    "type": {
+                        "kind": "pointer",
+                        "subtype": {
+                            "kind": "struct",
+                            "name": "nt_symbols!_DRIVER_OBJECT"
+                        }
+                    },
+                    "offset": 8
+                },
+                "NotificationRoutine": {
+                    "type": {
+                        "kind": "base",
+                        "name": "unsigned int"
+                    },
+                    "offset": 12
+                }
+            },
+            "kind": "struct",
+            "size": 16
+        },
+        "_SHUTDOWN_PACKET": {
+            "fields": {
+                "Entry": {
+                    "type": {
+                        "kind": "struct",
+                        "name": "nt_symbols!_LIST_ENTRY"
+                    },
+                    "offset": 0
+                },
+                "DeviceObject": {
+                    "type": {
+                        "kind": "pointer",
+                        "subtype": {
+                            "kind": "struct",
+                            "name": "nt_symbols!_DEVICE_OBJECT"
+                        }
+                    },
+                    "offset": 8
+                }
+            },
+            "kind": "struct",
+            "size": 12
+        },
+        "_REGISTRY_CALLBACK": {
+            "fields": {
+                "ListEntry": {
+                    "type": {
+                        "kind": "struct",
+                        "name": "nt_symbols!_LIST_ENTRY"
+                    },
+                    "offset": 0
+                },
+                "Function": {
+                    "type": {
+                        "kind": "pointer",
+                        "subtype": {
+                            "kind": "base",
+                            "name": "void"
+                        }
+                    },
+                    "offset": 28
+                }
+            },
+            "kind": "struct",
+            "size": 32
+        },
+        "_REGISTRY_CALLBACK_LEGACY": {
+            "fields": {
+                "CreateTime": {
+                    "type": {
+                        "kind": "pointer",
+                        "subtype": {
+                            "kind": "base",
+                            "name": "void"
+                        }
+                    },
+                    "offset": 28
+                }
+            },
+            "kind": "struct",
+            "size": 32
+        },
+        "_DBGPRINT_CALLBACK": {
+            "fields": {
+                "Function": {
+                    "type": {
+                        "kind": "pointer",
+                        "subtype": {
+                            "kind": "base",
+                            "name": "void"
+                        }
+                    },
+                    "offset": 8
+                }
+            },
+            "kind": "struct",
+            "size": 20
+        },
+        "_NOTIFY_ENTRY_HEADER": {
+            "fields": {
+                "ListEntry": {
+                    "type": {
+                        "kind": "struct",
+                        "name": "nt_symbols!_LIST_ENTRY"
+                    },
+                    "offset": 0
+                },
+                "EventCategory": {
+                    "type": {
+                        "kind": "enum",
+                        "name": "EventCategory"
+                    },
+                    "offset": 8
+                },
+                "CallbackRoutine": {
+                    "type": {
+                        "kind": "base",
+                        "name": "unsigned int"
+                    },
+                    "offset": 20
+                },
+                "DriverObject": {
+                    "type": {
+                        "kind": "pointer",
+                        "subtype": {
+                            "kind": "struct",
+                            "name": "nt_symbols!_DRIVER_OBJECT"
+                        }
+                    },
+                    "offset": 28
+                }
+            },
+            "kind": "struct",
+            "size": 32
+        },
         "_GENERIC_CALLBACK": {
             "fields": {
                 "Callback": {
@@ -57,10 +214,20 @@
                         }
                     },
                     "offset": 4
+                },
+                "Associated": {
+                    "type": {
+                        "kind": "pointer",
+                        "subtype": {
+                            "kind": "base",
+                            "name": "void"
+                        }
+                    },
+                    "offset": 8
                 }
             },
             "kind": "struct",
-            "size": 8
+            "size": 12
         },
         "_KBUGCHECK_CALLBACK_RECORD": {
             "fields": {
@@ -184,10 +351,10 @@
     },
     "metadata": {
         "producer": {
-            "version": "0.0.1",
-            "name": "mhl by hand",
-            "datetime": "2019-08-27T18:17:16.417006"
+            "version": "0.0.2",
+            "name": "dgmcdona by hand",
+            "datetime": "2024-02-02T19:32:00.000000"
         },
         "format": "4.0.0"
     }
-}
\ No newline at end of file
+}
diff --git a/volatility3/framework/symbols/windows/extensions/__init__.py b/volatility3/framework/symbols/windows/extensions/__init__.py
index a8fa7b2ff4..80d3b48b76 100755
--- a/volatility3/framework/symbols/windows/extensions/__init__.py
+++ b/volatility3/framework/symbols/windows/extensions/__init__.py
@@ -20,9 +20,10 @@
 )
 from volatility3.framework.interfaces.objects import ObjectInterface
 from volatility3.framework.layers import intel
+from volatility3.framework.objects import utility
 from volatility3.framework.renderers import conversion
 from volatility3.framework.symbols import generic
-from volatility3.framework.symbols.windows.extensions import kdbg, pe, pool
+from volatility3.framework.symbols.windows.extensions import pool
 
 vollog = logging.getLogger(__name__)
 
@@ -306,16 +307,19 @@ def get_private_memory(self):
 
         raise AttributeError("Unable to find the private memory member")
 
+    @property
+    def Protection(self):
+        if self.has_member("u"):
+            return self.u.VadFlags.Protection
+        elif self.has_member("Core"):
+            return self.Core.u.VadFlags.Protection
+        else:
+            return None
+
     def get_protection(self, protect_values, winnt_protections):
         """Get the VAD's protection constants as a string."""
 
-        protect = None
-
-        if self.has_member("u"):
-            protect = self.u.VadFlags.Protection
-
-        elif self.has_member("Core"):
-            protect = self.Core.u.VadFlags.Protection
+        protect = self.Protection
 
         try:
             value = protect_values[protect]
@@ -593,6 +597,38 @@ def get_string(self) -> interfaces.objects.ObjectInterface:
     String = property(get_string)
 
 
+class ERESOURCE(objects.StructType):
+    def is_valid(self) -> bool:
+        vollog.debug(f"Checking ERESOURCE Validity: {hex(self.vol.offset)}")
+
+        if not self._context.layers[self.vol.layer_name].is_valid(self.vol.offset):
+            return False
+
+        sym_table = self.get_symbol_table_name()
+
+        waiters_valid = self.SharedWaiters == 0 or self._context.layers[
+            self.vol.layer_name
+        ].is_valid(
+            self.SharedWaiters.vol.offset,
+            self._context.symbol_space.get_type(
+                sym_table + constants.BANG + "_KSEMAPHORE"
+            ).size,
+        )
+
+        try:
+            return (
+                waiters_valid
+                and self.SystemResourcesList.Flink is not None
+                and self.SystemResourcesList.Blink is not None
+                and self.SystemResourcesList.Flink != self.SystemResourcesList.Blink
+                and self.SystemResourcesList.Flink.Blink == self.vol.offset
+                and self.SystemResourcesList.Blink.Flink == self.vol.offset
+                and self.NumberOfSharedWaiters == 0
+            )
+        except exceptions.InvalidAddressException:
+            return False
+
+
 class EPROCESS(generic.GenericIntelProcess, pool.ExecutiveObject):
     """A class for executive kernel processes objects."""
 
@@ -611,11 +647,23 @@ def is_valid(self) -> bool:
 
                 ctime = self.get_create_time()
                 if not isinstance(ctime, datetime.datetime):
+                    # A process must have a creation time
                     return False
 
-                if not (1998 < ctime.year < 2030):
+                current_year = datetime.datetime.now().year
+                if not (1998 < ctime.year < current_year + 10):
                     return False
 
+                etime = self.get_exit_time()
+                if isinstance(etime, datetime.datetime):
+                    if not (1998 < etime.year < current_year + 10):
+                        return False
+
+                    # Exit time, if available, must be after the creation time
+                    # At this point, we are sure both are datetimes, so let's compare them
+                    if ctime > etime:
+                        return False
+
             # NT pids are divisible by 4
             if self.UniqueProcessId % 4 != 0:
                 return False
@@ -633,7 +681,11 @@ def is_valid(self) -> bool:
             if dtb & ~0xFFF == 0:
                 return False
 
-            ## TODO: we can also add the thread Flink and Blink tests if necessary
+            # Quick smear test on thread Flink and Blink
+            kernel = 0x80000000  # Yes, it's a quick test
+            list_head = self.ThreadListHead
+            if list_head.Flink < kernel or list_head.Blink < kernel:
+                return False
 
         except exceptions.InvalidAddressException:
             return False
@@ -994,6 +1046,83 @@ def privileges(self):
                 vollog.log(constants.LOGLEVEL_VVVV, "Broken Token Privileges.")
 
 
+class KTIMER(objects.StructType):
+    """A class for Kernel Timers"""
+
+    VALID_TYPES = {
+        8: "TimerNotificationObject",
+        9: "TimerSynchronizationObject",
+    }
+
+    def get_signaled(self):
+        if self.Header.SignalState:
+            return "Yes"
+        return "-"
+
+    def get_raw_dpc(self):
+        """Returns the encoded DPC since it may not look like a pointer after encoding"""
+        symbol_table_name = self.get_symbol_table_name()
+        pointer_type = self._context.symbol_space.get_type(
+            symbol_table_name + constants.BANG + "pointer"
+        )
+
+        return self._context.object(
+            object_type=pointer_type,
+            layer_name=self.vol.layer_name,
+            offset=self.Dpc.vol.offset,
+        )
+
+    def valid_type(self):
+        return self.Header.Type in self.VALID_TYPES
+
+    def get_due_time(self):
+        return "{0:#010x}:{1:#010x}".format(self.DueTime.HighPart, self.DueTime.LowPart)
+
+    def get_dpc(self):
+        """Return Dpc, and if Windows 7 or later, decode it"""
+        symbol_table_name = self.get_symbol_table_name()
+        kvo = self._context.layers[self.vol.native_layer_name].config[
+            "kernel_virtual_offset"
+        ]
+        ntkrnlmp = self._context.module(
+            symbol_table_name,
+            layer_name=self.vol.native_layer_name,
+            offset=kvo,
+            native_layer_name=self.vol.native_layer_name,
+        )
+
+        if ntkrnlmp.has_symbol("KiWaitNever") and ntkrnlmp.has_symbol("KiWaitAlways"):
+            wait_never = ntkrnlmp.object(
+                object_type="unsigned long long",
+                offset=ntkrnlmp.get_symbol("KiWaitNever").address,
+            )
+            wait_always = ntkrnlmp.object(
+                object_type="unsigned long long",
+                offset=ntkrnlmp.get_symbol("KiWaitAlways").address,
+            )
+
+            low_byte = (wait_never) & 0xFF
+            entry = utility.rol(self.get_raw_dpc() ^ wait_never, low_byte)
+            swap_xor = self._context.layers[self.vol.native_layer_name].canonicalize(
+                self.vol.offset
+            )
+            entry = utility.bswap_64(entry ^ swap_xor)
+            dpc = entry ^ wait_always
+
+            symbol_table_name = self.get_symbol_table_name()
+            kdpc_type = self._context.symbol_space.get_type(
+                symbol_table_name + constants.BANG + "_KDPC"
+            )
+
+            return self._context.object(
+                object_type=kdpc_type,
+                layer_name=self.vol.layer_name,
+                offset=dpc,
+            )
+        else:
+            return self.Dpc
+
+
 class KTHREAD(objects.StructType):
     """A class for thread control block objects."""
 
diff --git a/volatility3/framework/symbols/windows/extensions/callbacks.py b/volatility3/framework/symbols/windows/extensions/callbacks.py
new file mode 100644
index 0000000000..f894644dbb
--- /dev/null
+++ b/volatility3/framework/symbols/windows/extensions/callbacks.py
@@ -0,0 +1,51 @@
+import logging
+
+from volatility3.framework import exceptions, objects
+from volatility3.framework.symbols.windows.extensions import pool
+
+vollog = logging.getLogger(__name__)
+
+
+class _SHUTDOWN_PACKET(objects.StructType, pool.ExecutiveObject):
+    """Class for _SHUTDOWN_PACKET objects found in IoSh pools.
+
+    This class serves as a base class for all pooled shutdown callback packets.
+
+    It exposes a function which sanity-checks structure members.
+    """
+
+    def is_valid(self) -> bool:
+        """
+        Perform some checks.
+        """
+        try:
+            if not (
+                self.Entry.Flink.is_readable()
+                and self.Entry.Blink.is_readable()
+                and self.DeviceObject.is_readable()
+            ):
+                return False
+
+            device = self.DeviceObject
+            if not device or not (device.DriverObject.DriverStart % 0x1000 == 0):
+                vollog.debug(
+                    f"callback obj 0x{self.vol.offset:x} invalid due to invalid device object"
+                )
+                return False
+
+        except exceptions.InvalidAddressException:
+            vollog.debug(
+                f"callback obj 0x{self.vol.offset:x} invalid due to invalid address access"
+            )
+            return False
+
+        try:
+            header = device.get_object_header()
+            valid = header.NameInfo.Name == "Device"
+            return valid
+        except ValueError:
+            vollog.debug(f"Could not get NameInfo for object at 0x{self.vol.offset:x}")
+            return False
+
+
+class_types_x86 = {"_SHUTDOWN_PACKET": _SHUTDOWN_PACKET}
diff --git a/volatility3/framework/symbols/windows/extensions/shimcache.py b/volatility3/framework/symbols/windows/extensions/shimcache.py
new file mode 100644
index 0000000000..b84a7df6fd
--- /dev/null
+++ b/volatility3/framework/symbols/windows/extensions/shimcache.py
@@ -0,0 +1,278 @@
+# 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
+import struct
+from datetime import datetime
+from typing import Dict, Optional, Tuple, Union
+
+from volatility3.framework import constants, exceptions, interfaces, objects, renderers
+from volatility3.framework.symbols.windows.extensions import conversion
+
+vollog = logging.getLogger(__name__)
+
+
+class SHIM_CACHE_ENTRY(objects.StructType):
+    """Class for abstracting variations in the shimcache LRU list entry structure"""
+
+    def __init__(
+        self,
+        context: interfaces.context.ContextInterface,
+        type_name: str,
+        object_info: interfaces.objects.ObjectInformation,
+        size: int,
+        members: Dict[str, Tuple[int, interfaces.objects.Template]],
+    ) -> None:
+        super().__init__(context, type_name, object_info, size, members)
+        self._exec_flag = None
+        self._file_path = None
+        self._file_size = None
+        self._last_modified = None
+        self._last_updated = None
+
+    @property
+    def exec_flag(self) -> Union[bool, interfaces.renderers.BaseAbsentValue]:
+        """Checks if InsertFlags fields has been bitwise OR'd with a value of 2.
+        This behavior was observed when processes are created by CSRSS."""
+        if self._exec_flag is not None:
+            return self._exec_flag
+
+        if hasattr(self, "ListEntryDetail") and hasattr(
+            self.ListEntryDetail, "InsertFlags"
+        ):
+            self._exec_flag = self.ListEntryDetail.InsertFlags & 0x2 == 2
+
+        elif hasattr(self, "InsertFlags"):
+            self._exec_flag = self.InsertFlags & 0x2 == 2
+
+        elif hasattr(self, "ListEntryDetail") and hasattr(
+            self.ListEntryDetail, "BlobBuffer"
+        ):
+            blob_offset = self.ListEntryDetail.BlobBuffer
+            blob_size = self.ListEntryDetail.BlobSize
+
+            if not self._context.layers[self.vol.native_layer_name].is_valid(
+                blob_offset, blob_size
+            ):
+                self._exec_flag = renderers.UnparsableValue()
+
+            raw_flag = self._context.layers[self.vol.native_layer_name].read(
+                blob_offset, blob_size
+            )
+            if not raw_flag:
+                self._exec_flag = renderers.UnparsableValue()
+
+            try:
+                self._exec_flag = bool(struct.unpack("<I", raw_flag)[0])
+            except struct.error:
+                self._exec_flag = renderers.UnparsableValue()
+
+        else:
+            # Always set to true for XP/2K3
+            self._exec_flag = renderers.NotApplicableValue()
+        return self._exec_flag
+
+    @property
+    def file_size(self) -> Union[int, interfaces.renderers.BaseAbsentValue]:
+        if self._file_size is not None:
+            return self._file_size
+        try:
+            self._file_size = self.FileSize
+            if self._file_size < 0:
+                self._file_size = 0
+
+        except AttributeError:
+            self._file_size = renderers.NotApplicableValue()
+        except exceptions.InvalidAddressException:
+            self._file_size = renderers.UnreadableValue()
+
+        return self._file_size
+
+    @property
+    def last_modified(self) -> Union[datetime, interfaces.renderers.BaseAbsentValue]:
+        if self._last_modified is not None:
+            return self._last_modified
+        try:
+            self._last_modified = conversion.wintime_to_datetime(
+                self.ListEntryDetail.LastModified.QuadPart
+            )
+        except AttributeError:
+            self._last_modified = conversion.wintime_to_datetime(
+                self.LastModified.QuadPart
+            )
+        except exceptions.InvalidAddressException:
+            self._last_modified = renderers.UnreadableValue()
+
+        return self._last_modified
+
+    @property
+    def last_update(self) -> Union[datetime, interfaces.renderers.BaseAbsentValue]:
+        if self._last_updated is not None:
+            return self._last_updated
+
+        try:
+            self._last_updated = conversion.wintime_to_datetime(
+                self.LastUpdate.QuadPart
+            )
+        except AttributeError:
+            self._last_updated = renderers.NotApplicableValue()
+
+        return self._last_updated
+
+    @property
+    def file_path(self) -> Union[str, interfaces.renderers.BaseAbsentValue]:
+        if self._file_path is not None:
+            return self._file_path
+
+        if not hasattr(self.Path, "Buffer"):
+            return self.Path.cast(
+                "string", max_length=self.Path.vol.count, encoding="utf-16le"
+            )
+
+        try:
+            file_path_raw = (
+                self._context.layers[self.vol.native_layer_name].read(
+                    self.Path.Buffer, self.Path.Length
+                )
+                or b""
+            )
+            self._file_path = file_path_raw.decode("utf-16", errors="replace")
+        except exceptions.InvalidAddressException:
+            self._file_path = renderers.UnreadableValue()
+
+        return self._file_path
+
+    def is_valid(self) -> bool:
+        """Shim cache validation is limited to ensuring that a subset of the
+        pointers in the LIST_ENTRY field are valid (similar to validation of
+        ERESOURCE)"""
+
+        # shim entries on Windows XP do not have list entry attributes; in this case,
+        # perform a different set of validations
+        try:
+            if not hasattr(self, "ListEntry"):
+                return bool(self.last_modified and self.last_update and self.file_size)
+
+            # on some platforms ListEntry.Blink is null, so this cannot be validated
+            if (
+                self.ListEntry.Flink != 0
+                and (
+                    self.ListEntry.Blink.dereference()
+                    != self.ListEntry.Flink.dereference()
+                )
+                and (
+                    self.ListEntry.Flink.Blink
+                    == self.ListEntry.Flink.Blink.dereference().vol.offset
+                )
+            ):
+
+                return True
+            else:
+                return False
+        except exceptions.InvalidAddressException:
+            return False
+
+
+class SHIM_CACHE_HANDLE(objects.StructType):
+    def __init__(
+        self,
+        context: interfaces.context.ContextInterface,
+        type_name: str,
+        object_info: interfaces.objects.ObjectInformation,
+        size: int,
+        members: Dict[str, Tuple[int, interfaces.objects.Template]],
+    ) -> None:
+        super().__init__(context, type_name, object_info, size, members)
+
+    @property
+    def head(self) -> Optional[SHIM_CACHE_ENTRY]:
+        try:
+            if not self.eresource.is_valid():
+                return None
+        except exceptions.InvalidAddressException:
+            return None
+
+        rtl_avl_table = self._context.object(
+            self.get_symbol_table_name() + constants.BANG + "_RTL_AVL_TABLE",
+            self.vol.layer_name,
+            self.rtl_avl_table,
+            self.vol.native_layer_name,
+        )
+
+        if not self._context.layers[self.vol.layer_name].is_valid(
+            self.rtl_avl_table.vol.offset
+        ):
+            return None
+
+        offset_head = rtl_avl_table.vol.offset + rtl_avl_table.vol.size
+
+        head = self._context.object(
+            self.get_symbol_table_name() + constants.BANG + "SHIM_CACHE_ENTRY",
+            self.vol.layer_name,
+            offset_head,
+        )
+
+        if not head.is_valid():
+            return None
+
+        return head
+
+    def is_valid(self, avl_section_start: int, avl_section_end: int) -> bool:
+        if self.vol.offset == 0:
+            return False
+
+        vollog.debug(f"Checking SHIM_CACHE_HANDLE validity @ {hex(self.vol.offset)}")
+
+        if not (
+            self._context.layers[self.vol.layer_name].is_valid(self.vol.offset)
+            and self.eresource.is_valid()
+            and self.rtl_avl_table.is_valid(avl_section_start, avl_section_end)
+            and self.head
+        ):
+            return False
+
+        return self.head.is_valid()
+
+
+class RTL_AVL_TABLE(objects.StructType):
+    def is_valid(self, page_start: int, page_end: int) -> bool:
+        try:
+            if self.BalancedRoot.Parent != self.BalancedRoot.vol.offset:
+                vollog.debug(
+                    f"RTL_AVL_TABLE @ {self.vol.offset} Invalid: Failed BalancedRoot parent equality check"
+                )
+                return False
+
+            elif self.AllocateRoutine < page_start or self.AllocateRoutine > page_end:
+                vollog.debug(
+                    f"RTL_AVL_TABLE @ {self.vol.offset} Invalid: Failed AllocateRoutine range check"
+                )
+                return False
+
+            elif self.CompareRoutine < page_start or self.CompareRoutine > page_end:
+                vollog.debug(
+                    f"RTL_AVL_TABLE @ {self.vol.offset} Invalid: Failed CompareRoutine range check"
+                )
+                return False
+
+            elif (
+                (self.AllocateRoutine.vol.offset == self.CompareRoutine.vol.offset)
+                or (self.AllocateRoutine.vol.offset == self.FreeRoutine.vol.offset)
+                or (self.CompareRoutine.vol.offset == self.FreeRoutine.vol.offset)
+            ):
+                vollog.debug(
+                    f"RTL_AVL_TABLE @ {self.vol.offset} Invalid: Failed (Compare|Allocate|Free)Routine uniqueness check"
+                )
+                return False
+
+            return True
+        except exceptions.InvalidAddressException:
+            return False
+
+
+class_types = {
+    "SHIM_CACHE_HANDLE": SHIM_CACHE_HANDLE,
+    "SHIM_CACHE_ENTRY": SHIM_CACHE_ENTRY,
+    "_RTL_AVL_TABLE": RTL_AVL_TABLE,
+}
diff --git a/volatility3/framework/symbols/windows/netscan/netscan-win10-20348-x64.json b/volatility3/framework/symbols/windows/netscan/netscan-win10-20348-x64.json
new file mode 100644
index 0000000000..bd574b2b7c
--- /dev/null
+++ b/volatility3/framework/symbols/windows/netscan/netscan-win10-20348-x64.json
@@ -0,0 +1,582 @@
+{
+    "base_types": {
+        "unsigned long": {
+            "kind": "int",
+            "size": 4,
+            "signed": false,
+            "endian": "little"
+        },
+        "unsigned char": {
+            "kind": "char",
+            "size": 1,
+            "signed": false,
+            "endian": "little"
+        },
+        "pointer": {
+            "kind": "int",
+            "size": 8,
+            "signed": false,
+            "endian": "little"
+        },
+        "unsigned int": {
+            "kind": "int",
+            "size": 4,
+            "signed": false,
+            "endian": "little"
+        },
+        "unsigned short": {
+            "kind": "int",
+            "size": 2,
+            "signed": false,
+            "endian": "little"
+        },
+        "unsigned be short": {
+            "kind": "int",
+            "size": 2,
+            "signed": false,
+            "endian": "big"
+        },
+        "long long": {
+          "endian": "little",
+          "kind": "int",
+          "signed": true,
+          "size": 8
+        },
+        "long": {
+            "kind": "int",
+            "size": 4,
+            "signed": false,
+            "endian": "little"
+        }
+    },
+  "symbols": {},
+  "user_types": {
+      "_UDP_ENDPOINT": {
+        "fields": {
+            "Owner": {
+                "offset": 40,
+                "type": {
+                    "kind": "pointer",
+                    "subtype": {
+                        "kind": "struct",
+                        "name": "nt_symbols!_EPROCESS"
+                    }
+
+                }
+            },
+            "CreateTime": {
+                "offset": 88,
+                "type": {
+                    "kind": "union",
+                    "name": "_LARGE_INTEGER"
+                }
+            },
+            "Next": {
+                "offset": 112,
+                "type":{
+                    "kind": "pointer",
+                    "subtype": {
+                        "kind": "struct",
+                        "name": "_UDP_ENDPOINT"
+                    }
+                }
+            },
+            "LocalAddr": {
+                "offset": 168,
+                "type":{
+                    "kind": "pointer",
+                    "subtype": {
+                        "kind": "struct",
+                        "name": "_LOCAL_ADDRESS_WIN10_UDP"
+                    }
+                }
+            },
+            "InetAF": {
+                "offset": 32,
+                "type":{
+                    "kind": "pointer",
+                    "subtype": {
+                        "kind": "struct",
+                        "name": "_INETAF"
+                    }
+
+                }
+            },
+            "Port": {
+                "offset": 160,
+                "type": {
+                    "kind": "base",
+                    "name": "unsigned be short"
+                }
+            }
+        },
+        "kind": "struct",
+        "size": 168
+    },
+    "_TCP_LISTENER": {
+        "fields": {
+            "Owner": {
+                "offset": 48,
+                "type": {
+                    "kind": "pointer",
+                    "subtype": {
+                        "kind": "struct",
+                        "name": "nt_symbols!_EPROCESS"
+                    }
+
+                }
+            },
+            "CreateTime": {
+                "offset": 64,
+                "type": {
+                    "kind": "union",
+                    "name": "_LARGE_INTEGER"
+                }
+            },
+            "LocalAddr": {
+                "offset": 96,
+                "type":{
+                    "kind": "pointer",
+                    "subtype": {
+                        "kind": "struct",
+                        "name": "_LOCAL_ADDRESS"
+                    }
+
+                }
+            },
+            "InetAF": {
+                "offset": 40,
+                "type":{
+                    "kind": "pointer",
+                    "subtype": {
+                        "kind": "struct",
+                        "name": "_INETAF"
+                    }
+
+                }
+            },
+            "Next": {
+                "offset": 120,
+                "type":{
+                    "kind": "pointer",
+                    "subtype": {
+                        "kind": "struct",
+                        "name": "_TCP_LISTENER"
+                    }
+                }
+            },
+            "Port": {
+                "offset": 114,
+                "type": {
+                    "kind": "base",
+                    "name": "unsigned be short"
+                }
+            }
+        },
+        "kind": "struct",
+        "size": 128
+    },
+    "_TCP_ENDPOINT": {
+        "fields": {
+            "Owner": {
+                "offset": 752,
+                "type": {
+                    "kind": "pointer",
+                    "subtype": {
+                        "kind": "struct",
+                        "name": "nt_symbols!_EPROCESS"
+                    }
+                }
+            },
+            "CreateTime": {
+                "offset": 776,
+                "type": {
+                    "kind": "union",
+                    "name": "_LARGE_INTEGER"
+                }
+            },
+            "AddrInfo": {
+                "offset": 24,
+                "type":{
+                    "kind": "pointer",
+                    "subtype": {
+                        "kind": "struct",
+                        "name": "_ADDRINFO"
+                    }
+                }
+            },
+            "ListEntry": {
+                "offset": 40,
+                "type": {
+                    "kind": "union",
+                    "name": "nt_symbols!_LIST_ENTRY"
+                }
+            },
+            "InetAF": {
+                "offset": 16,
+                "type":{
+                    "kind": "pointer",
+                    "subtype": {
+                        "kind": "struct",
+                        "name": "_INETAF"
+                    }
+                }
+            },
+            "LocalPort": {
+                "offset": 112,
+                "type": {
+                    "kind": "base",
+                    "name": "unsigned be short"
+                }
+            },
+            "RemotePort": {
+                "offset": 114,
+                "type": {
+                    "kind": "base",
+                    "name": "unsigned be short"
+                }
+            },
+            "State": {
+                "offset": 108,
+                "type": {
+                    "kind": "enum",
+                    "name": "TCPStateEnum"
+                }
+            }
+        },
+        "kind": "struct",
+        "size": 632
+    },
+    "_LOCAL_ADDRESS": {
+        "fields": {
+            "pData": {
+                "offset": 16,
+                "type": {
+                    "kind": "pointer",
+                    "subtype": {
+                        "kind": "pointer",
+                        "subtype": {
+                            "kind": "struct",
+                            "name": "_IN_ADDR"
+                        }
+                    }
+                }
+            }
+        },
+        "kind": "struct",
+        "size": 20
+    },
+    "_LOCAL_ADDRESS_WIN10_UDP": {
+        "fields": {
+            "pData": {
+                "offset": 0,
+                "type": {
+                    "kind": "pointer",
+                    "subtype": {
+                        "kind": "struct",
+                        "name": "_IN_ADDR"
+                    }
+                }
+            }
+        },
+        "kind": "struct",
+        "size": 4
+    },
+    "_ADDRINFO": {
+        "fields": {
+            "Local": {
+                "offset": 0,
+                "type": {
+                    "kind": "pointer",
+                    "subtype": {
+                        "kind": "struct",
+                        "name": "_LOCAL_ADDRESS"
+                    }
+                }
+            },
+            "Remote": {
+                "offset": 16,
+                "type": {
+                    "kind": "pointer",
+                    "subtype": {
+                        "kind": "struct",
+                        "name": "_IN_ADDR"
+                    }
+                }
+            }
+        },
+        "kind": "struct",
+        "size": 4
+    },
+    "_IN_ADDR": {
+        "fields": {
+            "addr4": {
+                "offset": 0,
+                "type": {
+                    "count": 4,
+                    "subtype": {
+                        "kind": "base",
+                        "name": "unsigned char"
+                    },
+                    "kind": "array"
+                }
+            },
+            "addr6": {
+                "offset": 0,
+                "type": {
+                    "count": 16,
+                    "subtype": {
+                        "kind": "base",
+                        "name": "unsigned char"
+                    },
+                    "kind": "array"
+                }
+            }
+        },
+        "kind": "struct",
+        "size": 6
+    },
+    "_INETAF": {
+        "fields": {
+            "AddressFamily": {
+                "offset": 24,
+                "type": {
+                    "kind": "base",
+                    "name": "unsigned short"
+                }
+            }
+        },
+        "kind": "struct",
+        "size": 26
+    },
+    "_LARGE_INTEGER": {
+      "fields": {
+        "HighPart": {
+          "offset": 4,
+          "type": {
+            "kind": "base",
+            "name": "long"
+          }
+        },
+        "LowPart": {
+          "offset": 0,
+          "type": {
+            "kind": "base",
+            "name": "unsigned long"
+          }
+        },
+        "QuadPart": {
+          "offset": 0,
+          "type": {
+            "kind": "base",
+            "name": "long long"
+          }
+        },
+        "u": {
+          "offset": 0,
+          "type": {
+            "kind": "struct",
+            "name": "__unnamed_2"
+          }
+        }
+      },
+      "kind": "union",
+      "size": 8
+    },
+    "_INET_COMPARTMENT_SET": {
+        "fields": {
+            "InetCompartment": {
+                "offset": 328,
+                "type": {
+                    "kind": "pointer",
+                    "subtype": {
+                        "kind": "struct",
+                        "name": "_INET_COMPARTMENT"
+                    }
+                }
+            }
+        },
+        "kind": "struct",
+        "size": 384
+    },
+    "_INET_COMPARTMENT": {
+        "fields": {
+            "ProtocolCompartment": {
+                "offset": 32,
+                "type": {
+                    "kind": "pointer",
+                    "subtype": {
+                        "kind": "struct",
+                        "name": "_PROTOCOL_COMPARTMENT"
+                    }
+                }
+            }
+        },
+        "kind": "struct",
+        "size": 48
+    },
+    "_PROTOCOL_COMPARTMENT": {
+        "fields": {
+            "PortPool": {
+                "offset": 0,
+                "type": {
+                    "kind": "pointer",
+                    "subtype": {
+                      "kind": "struct",
+                      "name": "_INET_PORT_POOL"
+                    }
+                }
+            }
+        },
+        "kind": "struct",
+        "size": 16
+    },
+    "_PORT_ASSIGNMENT_ENTRY": {
+        "fields": {
+            "Entry": {
+                "offset": 16,
+                "type": {
+                    "kind": "pointer",
+                    "subtype": {
+                      "kind": "base",
+                      "name": "void"
+                    }
+                }
+            }
+        },
+        "kind": "struct",
+        "size": 32
+    },
+    "_PORT_ASSIGNMENT_LIST": {
+        "fields": {
+            "Assignments": {
+                "offset": 0,
+                "type": {
+                    "count": 256,
+                    "kind": "array",
+                    "subtype": {
+                        "kind": "struct",
+                        "name": "_PORT_ASSIGNMENT_ENTRY"
+                    }
+                }
+            }
+        },
+        "kind": "struct",
+        "size": 6144
+    },
+    "_PORT_ASSIGNMENT": {
+        "fields": {
+            "InPaBigPoolBase": {
+                "offset": 24,
+                "type": {
+                    "kind": "pointer",
+                    "subtype": {
+                      "kind": "struct",
+                      "name": "_PORT_ASSIGNMENT_LIST"
+                    }
+                }
+            }
+        },
+        "kind": "struct",
+        "size": 32
+    },
+    "_INET_PORT_POOL": {
+        "fields": {
+            "PortAssignments": {
+                "offset": 224,
+                "type": {
+                    "count": 256,
+                    "kind": "array",
+                    "subtype": {
+                        "kind": "pointer",
+                        "subtype": {
+                          "kind": "struct",
+                          "name": "_PORT_ASSIGNMENT"
+                        }
+                    }
+                }
+            },
+            "PortBitMap": {
+                "offset": 208,
+                "type": {
+                    "kind": "struct",
+                    "name": "nt_symbols!_RTL_BITMAP"
+                }
+            }
+        },
+        "kind": "struct",
+        "size": 11200
+    },
+    "_PARTITION": {
+        "fields": {
+            "Endpoints" : {
+                "offset": 8,
+                "type": {
+                    "kind": "pointer",
+                    "subtype": {
+                      "kind": "struct",
+                      "name": "nt_symbols!_RTL_DYNAMIC_HASH_TABLE"
+                    }
+                }
+            },
+            "UnknownHashTable" : {
+                "offset": 16,
+                "type": {
+                    "kind": "pointer",
+                    "subtype": {
+                      "kind": "struct",
+                      "name": "nt_symbols!_RTL_DYNAMIC_HASH_TABLE"
+                    }
+                }
+            }
+        },
+        "kind": "struct",
+        "size": 192
+    },
+    "_PARTITION_TABLE": {
+        "fields": {
+            "Partitions": {
+                "offset": 0,
+                "type": {
+                    "count": 1,
+                    "kind": "array",
+                    "subtype": {
+                        "kind": "struct",
+                        "name": "_PARTITION"
+                    }
+                }
+            }
+        },
+        "kind": "struct",
+        "size": 128
+    }
+  },
+  "enums": {
+    "TCPStateEnum": {
+        "base": "long",
+        "constants": {
+            "CLOSED": 0,
+            "LISTENING": 1,
+            "SYN_SENT": 2,
+            "SYN_RCVD": 3,
+            "ESTABLISHED": 4,
+            "FIN_WAIT1": 5,
+            "FIN_WAIT2": 6,
+            "CLOSE_WAIT": 7,
+            "CLOSING": 8,
+            "LAST_ACK": 9,
+            "TIME_WAIT": 12,
+            "DELETE_TCB": 13
+        },
+        "size": 4
+    }
+  },
+  "metadata": {
+    "producer": {
+      "version": "0.0.1",
+      "name": "dgmcdona-by-hand",
+      "datetime": "2024-07-30T13:00:00"
+    },
+    "format": "6.0.0"
+  }
+}
diff --git a/volatility3/framework/symbols/windows/shimcache/shimcache-2003-x64.json b/volatility3/framework/symbols/windows/shimcache/shimcache-2003-x64.json
new file mode 100644
index 0000000000..d1540f12f0
--- /dev/null
+++ b/volatility3/framework/symbols/windows/shimcache/shimcache-2003-x64.json
@@ -0,0 +1,327 @@
+{
+    "symbols": {},
+    "enums": {},
+    "base_types": {
+        "unsigned long": {
+            "kind": "int",
+            "size": 4,
+            "signed": false,
+            "endian": "little"
+        },
+        "unsigned long long": {
+            "kind": "int",
+            "size": 8,
+            "signed": false,
+            "endian": "little"
+        },
+        "unsigned char": {
+            "kind": "char",
+            "size": 1,
+            "signed": false,
+            "endian": "little"
+        },
+        "pointer": {
+            "kind": "int",
+            "size": 8,
+            "signed": false,
+            "endian": "little"
+        },
+        "unsigned int": {
+            "kind": "int",
+            "size": 4,
+            "signed": false,
+            "endian": "little"
+        },
+        "unsigned short": {
+            "kind": "int",
+            "size": 2,
+            "signed": false,
+            "endian": "little"
+        },
+        "long": {
+            "kind": "int",
+            "size": 4,
+            "signed": false,
+            "endian": "little"
+        }
+    },
+    "user_types": {
+        "_RTL_BALANCED_LINKS": {
+            "fields": {
+                "Parent": {
+                    "type": {
+                        "kind": "pointer",
+                        "subtype": {
+                            "kind": "struct",
+                            "name": "_RTL_BALANCED_LINKS"
+                        }
+                    },
+                    "offset": 0
+                },
+                "LeftChild": {
+                    "type": {
+                        "kind": "pointer",
+                        "subtype": {
+                            "kind": "struct",
+                            "name": "_RTL_BALANCED_LINKS"
+                        }
+                    },
+                    "offset": 8
+                },
+                "RightChild": {
+                    "type": {
+                        "kind": "pointer",
+                        "subtype": {
+                            "kind": "struct",
+                            "name": "_RTL_BALANCED_LINKS"
+                        }
+                    },
+                    "offset": 16
+                },
+                "Balance": {
+                    "type": {
+                        "kind": "base",
+                        "name": "unsigned char"
+                    },
+                    "offset": 24
+                },
+                "Reserved": {
+                    "type": {
+                        "kind": "array",
+                        "count": 3,
+                        "subtype": {
+                            "kind": "base",
+                            "name": "unsigned char"
+                        }
+                    },
+                    "offset": 25
+                }
+            },
+            "kind": "struct",
+            "size": 32
+        },
+        "_RTL_AVL_TABLE": {
+            "fields": {
+                "BalancedRoot": {
+                    "type": {
+                        "kind": "struct",
+                        "name": "_RTL_BALANCED_LINKS"
+                    },
+                    "offset": 0
+                },
+                "OrderedPointer": {
+                    "type": {
+                        "kind": "pointer",
+                        "subtype": {
+                            "kind": "base",
+                            "name": "void"
+                        }
+                    },
+                    "offset": 32
+                },
+                "WhichOrderedElement": {
+                    "type": {
+                        "kind": "base",
+                        "name": "unsigned long"
+                    },
+                    "offset": 40
+                },
+                "NumberGenericTableElements": {
+                    "type": {
+                        "kind": "base",
+                        "name": "unsigned long"
+                    },
+                    "offset": 44
+                },
+                "DepthOfTree": {
+                    "type": {
+                        "kind": "base",
+                        "name": "unsigned long"
+                    },
+                    "offset": 48
+                },
+                "RestartKey": {
+                    "type": {
+                        "kind": "pointer",
+                        "subtype": {
+                            "kind": "struct",
+                            "name": "_RTL_BALANCED_LINKS"
+                        }
+                    },
+                    "offset": 56
+                },
+                "DeleteCount": {
+                    "type": {
+                        "kind": "base",
+                        "name": "unsigned long"
+                    },
+                    "offset": 64
+                },
+                "CompareRoutine": {
+                    "type": {
+                        "kind": "pointer",
+                        "subtype": {
+                            "kind": "base",
+                            "name": "void"
+                        }
+                    },
+                    "offset": 72
+                },
+                "AllocateRoutine": {
+                    "type": {
+                        "kind": "pointer",
+                        "subtype": {
+                            "kind": "base",
+                            "name": "void"
+                        }
+                    },
+                    "offset": 80
+                },
+                "FreeRoutine": {
+                    "type": {
+                        "kind": "pointer",
+                        "subtype": {
+                            "kind": "base",
+                            "name": "void"
+                        }
+                    },
+                    "offset": 88
+                },
+                "TableContext": {
+                    "type": {
+                        "kind": "pointer",
+                        "subtype": {
+                            "kind": "base",
+                            "name": "void"
+                        }
+                    },
+                    "offset": 96
+                }
+            },
+            "kind": "struct",
+            "size": 104
+        },
+        "SHIM_CACHE_HANDLE": {
+            "fields": {
+                "eresource": {
+                    "type": {
+                        "kind": "pointer",
+                        "subtype": {
+                            "kind": "struct",
+                            "name": "nt_symbols!_ERESOURCE"
+                        }
+                    },
+                    "offset": 0
+                },
+                "rtl_avl_table": {
+                    "type": {
+                        "kind": "pointer",
+                        "subtype": {
+                            "kind": "struct",
+                            "name": "_RTL_AVL_TABLE"
+                        }
+                    },
+                    "offset": 8
+                }
+            },
+            "kind": "struct",
+            "size": 16
+        },
+        "_LARGE_INTEGER": {
+            "fields": {
+                "HighPart": {
+                    "offset": 4,
+                    "type": {
+                        "kind": "base",
+                        "name": "long"
+                    }
+                },
+                "LowPart": {
+                    "offset": 0,
+                    "type": {
+                        "kind": "base",
+                        "name": "unsigned long"
+                    }
+                },
+                "QuadPart": {
+                    "offset": 0,
+                    "type": {
+                        "kind": "base",
+                        "name": "long long"
+                    }
+                },
+                "u": {
+                    "offset": 0,
+                    "type": {
+                        "kind": "struct",
+                        "name": "__unnamed_2"
+                    }
+                }
+            },
+            "kind": "union",
+            "size": 8
+        },
+        "__unnamed_2": {
+          "fields": {
+            "HighPart": {
+              "offset": 4,
+              "type": {
+                "kind": "base",
+                "name": "long"
+              }
+            },
+            "LowPart": {
+              "offset": 0,
+              "type": {
+                "kind": "base",
+                "name": "unsigned long"
+              }
+            }
+          },
+          "kind": "struct",
+          "size": 8
+        },
+        "SHIM_CACHE_ENTRY": {
+            "fields": {
+                "ListEntry": {
+                    "offset": 0,
+                    "type": {
+                        "kind": "struct",
+                        "name": "nt_symbols!_LIST_ENTRY"
+                    }
+                },
+                "Path": {
+                    "offset": 16,
+                    "type": {
+                        "kind": "struct",
+                        "name": "nt_symbols!_UNICODE_STRING"
+                    }
+                },
+                "LastModified": {
+                    "offset": 32,
+                    "type": {
+                        "kind": "union",
+                        "name": "_LARGE_INTEGER"
+                    }
+                },
+                "FileSize": {
+                    "offset": 40,
+                    "type": {
+                        "kind": "base",
+                        "name": "unsigned long"
+                    }
+                }
+            },
+            "kind": "struct",
+            "size": 48
+        }
+    },
+    "metadata": {
+        "producer": {
+            "version": "0.0.1",
+            "name": "dgmcdona by hand",
+            "datetime": "2024-07-05T18:28:00.000000+00:00"
+        },
+        "format": "4.0.0"
+    }
+}
diff --git a/volatility3/framework/symbols/windows/shimcache/shimcache-2003-x86.json b/volatility3/framework/symbols/windows/shimcache/shimcache-2003-x86.json
new file mode 100644
index 0000000000..e4739c4a0a
--- /dev/null
+++ b/volatility3/framework/symbols/windows/shimcache/shimcache-2003-x86.json
@@ -0,0 +1,334 @@
+{
+    "symbols": {},
+    "enums": {},
+    "base_types": {
+        "unsigned long": {
+            "kind": "int",
+            "size": 4,
+            "signed": false,
+            "endian": "little"
+        },
+        "unsigned long long": {
+            "kind": "int",
+            "size": 8,
+            "signed": false,
+            "endian": "little"
+        },
+        "unsigned char": {
+            "kind": "char",
+            "size": 1,
+            "signed": false,
+            "endian": "little"
+        },
+        "pointer": {
+            "kind": "int",
+            "size": 4,
+            "signed": false,
+            "endian": "little"
+        },
+        "unsigned int": {
+            "kind": "int",
+            "size": 4,
+            "signed": false,
+            "endian": "little"
+        },
+        "unsigned short": {
+            "kind": "int",
+            "size": 2,
+            "signed": false,
+            "endian": "little"
+        },
+        "long": {
+            "kind": "int",
+            "size": 4,
+            "signed": false,
+            "endian": "little"
+        }
+    },
+    "user_types": {
+        "_RTL_BALANCED_LINKS": {
+            "fields": {
+                "Parent": {
+                    "type": {
+                        "kind": "pointer",
+                        "subtype": {
+                            "kind": "struct",
+                            "name": "_RTL_BALANCED_LINKS"
+                        }
+                    },
+                    "offset": 0
+                },
+                "LeftChild": {
+                    "type": {
+                        "kind": "pointer",
+                        "subtype": {
+                            "kind": "struct",
+                            "name": "_RTL_BALANCED_LINKS"
+                        }
+                    },
+                    "offset": 4
+                },
+                "RightChild": {
+                    "type": {
+                        "kind": "pointer",
+                        "subtype": {
+                            "kind": "struct",
+                            "name": "_RTL_BALANCED_LINKS"
+                        }
+                    },
+                    "offset": 8
+                },
+                "Balance": {
+                    "type": {
+                        "kind": "base",
+                        "name": "unsigned char"
+                    },
+                    "offset": 12
+                },
+                "Reserved": {
+                    "type": {
+                        "kind": "array",
+                        "count": 3,
+                        "subtype": {
+                            "kind": "base",
+                            "name": "unsigned char"
+                        }
+                    },
+                    "offset": 12
+                }
+            },
+            "kind": "struct",
+            "size": 16
+        },
+        "_RTL_AVL_TABLE": {
+            "fields": {
+                "BalancedRoot": {
+                    "type": {
+                        "kind": "struct",
+                        "name": "_RTL_BALANCED_LINKS"
+                    },
+                    "offset": 0
+                },
+                "OrderedPointer": {
+                    "type": {
+                        "kind": "pointer",
+                        "subtype": {
+                            "kind": "base",
+                            "name": "void"
+                        }
+                    },
+                    "offset": 16
+                },
+                "WhichOrderedElement": {
+                    "type": {
+                        "kind": "base",
+                        "name": "unsigned long"
+                    },
+                    "offset": 20
+                },
+                "NumberGenericTableElements": {
+                    "type": {
+                        "kind": "base",
+                        "name": "unsigned long"
+                    },
+                    "offset": 24
+                },
+                "DepthOfTree": {
+                    "type": {
+                        "kind": "base",
+                        "name": "unsigned long"
+                    },
+                    "offset": 28
+                },
+                "RestartKey": {
+                    "type": {
+                        "kind": "pointer",
+                        "subtype": {
+                            "kind": "struct",
+                            "name": "_RTL_BALANCED_LINKS"
+                        }
+                    },
+                    "offset": 32
+                },
+                "DeleteCount": {
+                    "type": {
+                        "kind": "base",
+                        "name": "unsigned long"
+                    },
+                    "offset": 36
+                },
+                "CompareRoutine": {
+                    "type": {
+                        "kind": "pointer",
+                        "subtype": {
+                            "kind": "base",
+                            "name": "void"
+                        }
+                    },
+                    "offset": 40
+                },
+                "AllocateRoutine": {
+                    "type": {
+                        "kind": "pointer",
+                        "subtype": {
+                            "kind": "base",
+                            "name": "void"
+                        }
+                    },
+                    "offset": 44
+                },
+                "FreeRoutine": {
+                    "type": {
+                        "kind": "pointer",
+                        "subtype": {
+                            "kind": "base",
+                            "name": "void"
+                        }
+                    },
+                    "offset": 48
+                },
+                "TableContext": {
+                    "type": {
+                        "kind": "pointer",
+                        "subtype": {
+                            "kind": "base",
+                            "name": "void"
+                        }
+                    },
+                    "offset": 52
+                }
+            },
+            "kind": "struct",
+            "size": 56
+        },
+        "SHIM_CACHE_HANDLE": {
+            "fields": {
+                "eresource": {
+                    "type": {
+                        "kind": "pointer",
+                        "subtype": {
+                            "kind": "struct",
+                            "name": "nt_symbols!_ERESOURCE"
+                        }
+                    },
+                    "offset": 0
+                },
+                "rtl_avl_table": {
+                    "type": {
+                        "kind": "pointer",
+                        "subtype": {
+                            "kind": "struct",
+                            "name": "_RTL_AVL_TABLE"
+                        }
+                    },
+                    "offset": 8
+                }
+            },
+            "kind": "struct",
+            "size": 8
+        },
+        "_LARGE_INTEGER": {
+            "fields": {
+                "HighPart": {
+                    "offset": 4,
+                    "type": {
+                        "kind": "base",
+                        "name": "long"
+                    }
+                },
+                "LowPart": {
+                    "offset": 0,
+                    "type": {
+                        "kind": "base",
+                        "name": "unsigned long"
+                    }
+                },
+                "QuadPart": {
+                    "offset": 0,
+                    "type": {
+                        "kind": "base",
+                        "name": "long long"
+                    }
+                },
+                "u": {
+                    "offset": 0,
+                    "type": {
+                        "kind": "struct",
+                        "name": "__unnamed_2"
+                    }
+                }
+            },
+            "kind": "union",
+            "size": 8
+        },
+        "__unnamed_2": {
+          "fields": {
+            "HighPart": {
+              "offset": 4,
+              "type": {
+                "kind": "base",
+                "name": "long"
+              }
+            },
+            "LowPart": {
+              "offset": 0,
+              "type": {
+                "kind": "base",
+                "name": "unsigned long"
+              }
+            }
+          },
+          "kind": "struct",
+          "size": 8
+        },
+        "SHIM_CACHE_ENTRY": {
+            "fields": {
+                "ListEntry": {
+                    "offset": 0,
+                    "type": {
+                        "kind": "struct",
+                        "name": "nt_symbols!_LIST_ENTRY"
+                    }
+                },
+                "Path": {
+                    "offset": 8,
+                    "type": {
+                        "kind": "struct",
+                        "name": "nt_symbols!_UNICODE_STRING"
+                    }
+                },
+                "LastModified": {
+                    "offset": 16,
+                    "type": {
+                        "kind": "union",
+                        "name": "_LARGE_INTEGER"
+                    }
+                },
+                "FileSize": {
+                    "offset": 24,
+                    "type": {
+                        "kind": "base",
+                        "name": "unsigned long"
+                    }
+                },
+                "Padding": {
+                    "offset": 32,
+                    "type": {
+                        "kind": "base",
+                        "name": "unsigned long"
+                    }
+                }
+            },
+            "kind": "struct",
+            "size": 36
+        }
+    },
+    "metadata": {
+        "producer": {
+            "version": "0.0.1",
+            "name": "dgmcdona by hand",
+            "datetime": "2024-07-05T18:28:00.000000+00:00"
+        },
+        "format": "4.0.0"
+    }
+}
diff --git a/volatility3/framework/symbols/windows/shimcache/shimcache-vista-x64.json b/volatility3/framework/symbols/windows/shimcache/shimcache-vista-x64.json
new file mode 100644
index 0000000000..0c5183a4a5
--- /dev/null
+++ b/volatility3/framework/symbols/windows/shimcache/shimcache-vista-x64.json
@@ -0,0 +1,334 @@
+{
+    "symbols": {},
+    "enums": {},
+    "base_types": {
+        "unsigned long": {
+            "kind": "int",
+            "size": 4,
+            "signed": false,
+            "endian": "little"
+        },
+        "unsigned long long": {
+            "kind": "int",
+            "size": 8,
+            "signed": false,
+            "endian": "little"
+        },
+        "unsigned char": {
+            "kind": "char",
+            "size": 1,
+            "signed": false,
+            "endian": "little"
+        },
+        "pointer": {
+            "kind": "int",
+            "size": 8,
+            "signed": false,
+            "endian": "little"
+        },
+        "unsigned int": {
+            "kind": "int",
+            "size": 4,
+            "signed": false,
+            "endian": "little"
+        },
+        "unsigned short": {
+            "kind": "int",
+            "size": 2,
+            "signed": false,
+            "endian": "little"
+        },
+        "long": {
+            "kind": "int",
+            "size": 4,
+            "signed": false,
+            "endian": "little"
+        }
+    },
+    "user_types": {
+        "_RTL_BALANCED_LINKS": {
+            "fields": {
+                "Parent": {
+                    "type": {
+                        "kind": "pointer",
+                        "subtype": {
+                            "kind": "struct",
+                            "name": "_RTL_BALANCED_LINKS"
+                        }
+                    },
+                    "offset": 0
+                },
+                "LeftChild": {
+                    "type": {
+                        "kind": "pointer",
+                        "subtype": {
+                            "kind": "struct",
+                            "name": "_RTL_BALANCED_LINKS"
+                        }
+                    },
+                    "offset": 8
+                },
+                "RightChild": {
+                    "type": {
+                        "kind": "pointer",
+                        "subtype": {
+                            "kind": "struct",
+                            "name": "_RTL_BALANCED_LINKS"
+                        }
+                    },
+                    "offset": 16
+                },
+                "Balance": {
+                    "type": {
+                        "kind": "base",
+                        "name": "unsigned char"
+                    },
+                    "offset": 24
+                },
+                "Reserved": {
+                    "type": {
+                        "kind": "array",
+                        "count": 3,
+                        "subtype": {
+                            "kind": "base",
+                            "name": "unsigned char"
+                        }
+                    },
+                    "offset": 25
+                }
+            },
+            "kind": "struct",
+            "size": 32
+        },
+        "_RTL_AVL_TABLE": {
+            "fields": {
+                "BalancedRoot": {
+                    "type": {
+                        "kind": "struct",
+                        "name": "_RTL_BALANCED_LINKS"
+                    },
+                    "offset": 0
+                },
+                "OrderedPointer": {
+                    "type": {
+                        "kind": "pointer",
+                        "subtype": {
+                            "kind": "base",
+                            "name": "void"
+                        }
+                    },
+                    "offset": 32
+                },
+                "WhichOrderedElement": {
+                    "type": {
+                        "kind": "base",
+                        "name": "unsigned long"
+                    },
+                    "offset": 40
+                },
+                "NumberGenericTableElements": {
+                    "type": {
+                        "kind": "base",
+                        "name": "unsigned long"
+                    },
+                    "offset": 44
+                },
+                "DepthOfTree": {
+                    "type": {
+                        "kind": "base",
+                        "name": "unsigned long"
+                    },
+                    "offset": 48
+                },
+                "RestartKey": {
+                    "type": {
+                        "kind": "pointer",
+                        "subtype": {
+                            "kind": "struct",
+                            "name": "_RTL_BALANCED_LINKS"
+                        }
+                    },
+                    "offset": 56
+                },
+                "DeleteCount": {
+                    "type": {
+                        "kind": "base",
+                        "name": "unsigned long"
+                    },
+                    "offset": 64
+                },
+                "CompareRoutine": {
+                    "type": {
+                        "kind": "pointer",
+                        "subtype": {
+                            "kind": "base",
+                            "name": "void"
+                        }
+                    },
+                    "offset": 72
+                },
+                "AllocateRoutine": {
+                    "type": {
+                        "kind": "pointer",
+                        "subtype": {
+                            "kind": "base",
+                            "name": "void"
+                        }
+                    },
+                    "offset": 80
+                },
+                "FreeRoutine": {
+                    "type": {
+                        "kind": "pointer",
+                        "subtype": {
+                            "kind": "base",
+                            "name": "void"
+                        }
+                    },
+                    "offset": 88
+                },
+                "TableContext": {
+                    "type": {
+                        "kind": "pointer",
+                        "subtype": {
+                            "kind": "base",
+                            "name": "void"
+                        }
+                    },
+                    "offset": 96
+                }
+            },
+            "kind": "struct",
+            "size": 104
+        },
+        "SHIM_CACHE_HANDLE": {
+            "fields": {
+                "eresource": {
+                    "type": {
+                        "kind": "pointer",
+                        "subtype": {
+                            "kind": "struct",
+                            "name": "nt_symbols!_ERESOURCE"
+                        }
+                    },
+                    "offset": 0
+                },
+                "rtl_avl_table": {
+                    "type": {
+                        "kind": "pointer",
+                        "subtype": {
+                            "kind": "struct",
+                            "name": "_RTL_AVL_TABLE"
+                        }
+                    },
+                    "offset": 8
+                }
+            },
+            "kind": "struct",
+            "size": 16
+        },
+        "_LARGE_INTEGER": {
+            "fields": {
+                "HighPart": {
+                    "offset": 4,
+                    "type": {
+                        "kind": "base",
+                        "name": "long"
+                    }
+                },
+                "LowPart": {
+                    "offset": 0,
+                    "type": {
+                        "kind": "base",
+                        "name": "unsigned long"
+                    }
+                },
+                "QuadPart": {
+                    "offset": 0,
+                    "type": {
+                        "kind": "base",
+                        "name": "long long"
+                    }
+                },
+                "u": {
+                    "offset": 0,
+                    "type": {
+                        "kind": "struct",
+                        "name": "__unnamed_2"
+                    }
+                }
+            },
+            "kind": "union",
+            "size": 8
+        },
+        "__unnamed_2": {
+          "fields": {
+            "HighPart": {
+              "offset": 4,
+              "type": {
+                "kind": "base",
+                "name": "long"
+              }
+            },
+            "LowPart": {
+              "offset": 0,
+              "type": {
+                "kind": "base",
+                "name": "unsigned long"
+              }
+            }
+          },
+          "kind": "struct",
+          "size": 8
+        },
+        "SHIM_CACHE_ENTRY": {
+            "fields": {
+                "ListEntry": {
+                    "offset": 0,
+                    "type": {
+                        "kind": "struct",
+                        "name": "nt_symbols!_LIST_ENTRY"
+                    }
+                },
+                "Path": {
+                    "offset": 16,
+                    "type": {
+                        "kind": "struct",
+                        "name": "nt_symbols!_UNICODE_STRING"
+                    }
+                },
+                "LastModified": {
+                    "offset": 32,
+                    "type": {
+                        "kind": "union",
+                        "name": "_LARGE_INTEGER"
+                    }
+                },
+                "InsertFlags": {
+                    "offset": 40,
+                    "type": {
+                        "kind": "base",
+                        "name": "unsigned int"
+                    }
+                },
+                "ShimFlags": {
+                    "offset": 44,
+                    "type": {
+                        "kind": "base",
+                        "name": "unsigned int"
+                    }
+                }
+            },
+            "kind": "struct",
+            "size": 48
+        }
+    },
+    "metadata": {
+        "producer": {
+            "version": "0.0.1",
+            "name": "dgmcdona by hand",
+            "datetime": "2024-07-05T18:28:00.000000+00:00"
+        },
+        "format": "4.0.0"
+    }
+}
diff --git a/volatility3/framework/symbols/windows/shimcache/shimcache-vista-x86.json b/volatility3/framework/symbols/windows/shimcache/shimcache-vista-x86.json
new file mode 100644
index 0000000000..91290b1ba1
--- /dev/null
+++ b/volatility3/framework/symbols/windows/shimcache/shimcache-vista-x86.json
@@ -0,0 +1,334 @@
+{
+    "symbols": {},
+    "enums": {},
+    "base_types": {
+        "unsigned long": {
+            "kind": "int",
+            "size": 4,
+            "signed": false,
+            "endian": "little"
+        },
+        "unsigned long long": {
+            "kind": "int",
+            "size": 8,
+            "signed": false,
+            "endian": "little"
+        },
+        "unsigned char": {
+            "kind": "char",
+            "size": 1,
+            "signed": false,
+            "endian": "little"
+        },
+        "pointer": {
+            "kind": "int",
+            "size": 4,
+            "signed": false,
+            "endian": "little"
+        },
+        "unsigned int": {
+            "kind": "int",
+            "size": 4,
+            "signed": false,
+            "endian": "little"
+        },
+        "unsigned short": {
+            "kind": "int",
+            "size": 2,
+            "signed": false,
+            "endian": "little"
+        },
+        "long": {
+            "kind": "int",
+            "size": 4,
+            "signed": false,
+            "endian": "little"
+        }
+    },
+    "user_types": {
+        "_RTL_BALANCED_LINKS": {
+            "fields": {
+                "Parent": {
+                    "type": {
+                        "kind": "pointer",
+                        "subtype": {
+                            "kind": "struct",
+                            "name": "_RTL_BALANCED_LINKS"
+                        }
+                    },
+                    "offset": 0
+                },
+                "LeftChild": {
+                    "type": {
+                        "kind": "pointer",
+                        "subtype": {
+                            "kind": "struct",
+                            "name": "_RTL_BALANCED_LINKS"
+                        }
+                    },
+                    "offset": 4
+                },
+                "RightChild": {
+                    "type": {
+                        "kind": "pointer",
+                        "subtype": {
+                            "kind": "struct",
+                            "name": "_RTL_BALANCED_LINKS"
+                        }
+                    },
+                    "offset": 8
+                },
+                "Balance": {
+                    "type": {
+                        "kind": "base",
+                        "name": "unsigned char"
+                    },
+                    "offset": 12
+                },
+                "Reserved": {
+                    "type": {
+                        "kind": "array",
+                        "count": 3,
+                        "subtype": {
+                            "kind": "base",
+                            "name": "unsigned char"
+                        }
+                    },
+                    "offset": 12
+                }
+            },
+            "kind": "struct",
+            "size": 16
+        },
+        "_RTL_AVL_TABLE": {
+            "fields": {
+                "BalancedRoot": {
+                    "type": {
+                        "kind": "struct",
+                        "name": "_RTL_BALANCED_LINKS"
+                    },
+                    "offset": 0
+                },
+                "OrderedPointer": {
+                    "type": {
+                        "kind": "pointer",
+                        "subtype": {
+                            "kind": "base",
+                            "name": "void"
+                        }
+                    },
+                    "offset": 16
+                },
+                "WhichOrderedElement": {
+                    "type": {
+                        "kind": "base",
+                        "name": "unsigned long"
+                    },
+                    "offset": 20
+                },
+                "NumberGenericTableElements": {
+                    "type": {
+                        "kind": "base",
+                        "name": "unsigned long"
+                    },
+                    "offset": 24
+                },
+                "DepthOfTree": {
+                    "type": {
+                        "kind": "base",
+                        "name": "unsigned long"
+                    },
+                    "offset": 28
+                },
+                "RestartKey": {
+                    "type": {
+                        "kind": "pointer",
+                        "subtype": {
+                            "kind": "struct",
+                            "name": "_RTL_BALANCED_LINKS"
+                        }
+                    },
+                    "offset": 32
+                },
+                "DeleteCount": {
+                    "type": {
+                        "kind": "base",
+                        "name": "unsigned long"
+                    },
+                    "offset": 36
+                },
+                "CompareRoutine": {
+                    "type": {
+                        "kind": "pointer",
+                        "subtype": {
+                            "kind": "base",
+                            "name": "void"
+                        }
+                    },
+                    "offset": 40
+                },
+                "AllocateRoutine": {
+                    "type": {
+                        "kind": "pointer",
+                        "subtype": {
+                            "kind": "base",
+                            "name": "void"
+                        }
+                    },
+                    "offset": 44
+                },
+                "FreeRoutine": {
+                    "type": {
+                        "kind": "pointer",
+                        "subtype": {
+                            "kind": "base",
+                            "name": "void"
+                        }
+                    },
+                    "offset": 48
+                },
+                "TableContext": {
+                    "type": {
+                        "kind": "pointer",
+                        "subtype": {
+                            "kind": "base",
+                            "name": "void"
+                        }
+                    },
+                    "offset": 52
+                }
+            },
+            "kind": "struct",
+            "size": 56
+        },
+        "SHIM_CACHE_HANDLE": {
+            "fields": {
+                "eresource": {
+                    "type": {
+                        "kind": "pointer",
+                        "subtype": {
+                            "kind": "struct",
+                            "name": "nt_symbols!_ERESOURCE"
+                        }
+                    },
+                    "offset": 0
+                },
+                "rtl_avl_table": {
+                    "type": {
+                        "kind": "pointer",
+                        "subtype": {
+                            "kind": "struct",
+                            "name": "_RTL_AVL_TABLE"
+                        }
+                    },
+                    "offset": 8
+                }
+            },
+            "kind": "struct",
+            "size": 8
+        },
+        "_LARGE_INTEGER": {
+            "fields": {
+                "HighPart": {
+                    "offset": 4,
+                    "type": {
+                        "kind": "base",
+                        "name": "long"
+                    }
+                },
+                "LowPart": {
+                    "offset": 0,
+                    "type": {
+                        "kind": "base",
+                        "name": "unsigned long"
+                    }
+                },
+                "QuadPart": {
+                    "offset": 0,
+                    "type": {
+                        "kind": "base",
+                        "name": "long long"
+                    }
+                },
+                "u": {
+                    "offset": 0,
+                    "type": {
+                        "kind": "struct",
+                        "name": "__unnamed_2"
+                    }
+                }
+            },
+            "kind": "union",
+            "size": 8
+        },
+        "__unnamed_2": {
+          "fields": {
+            "HighPart": {
+              "offset": 4,
+              "type": {
+                "kind": "base",
+                "name": "long"
+              }
+            },
+            "LowPart": {
+              "offset": 0,
+              "type": {
+                "kind": "base",
+                "name": "unsigned long"
+              }
+            }
+          },
+          "kind": "struct",
+          "size": 8
+        },
+        "SHIM_CACHE_ENTRY": {
+            "fields": {
+                "ListEntry": {
+                    "offset": 0,
+                    "type": {
+                        "kind": "struct",
+                        "name": "nt_symbols!_LIST_ENTRY"
+                    }
+                },
+                "Path": {
+                    "offset": 8,
+                    "type": {
+                        "kind": "struct",
+                        "name": "nt_symbols!_UNICODE_STRING"
+                    }
+                },
+                "LastModified": {
+                    "offset": 16,
+                    "type": {
+                        "kind": "union",
+                        "name": "_LARGE_INTEGER"
+                    }
+                },
+                "InsertFlags": {
+                    "offset": 24,
+                    "type": {
+                        "kind": "base",
+                        "name": "unsigned int"
+                    }
+                },
+                "ShimFlags": {
+                    "offset": 28,
+                    "type": {
+                        "kind": "base",
+                        "name": "unsigned int"
+                    }
+                }
+            },
+            "kind": "struct",
+            "size": 36
+        }
+    },
+    "metadata": {
+        "producer": {
+            "version": "0.0.1",
+            "name": "dgmcdona by hand",
+            "datetime": "2024-07-05T18:28:00.000000+00:00"
+        },
+        "format": "4.0.0"
+    }
+}
diff --git a/volatility3/framework/symbols/windows/shimcache/shimcache-win10-x64.json b/volatility3/framework/symbols/windows/shimcache/shimcache-win10-x64.json
new file mode 100644
index 0000000000..fe9593af37
--- /dev/null
+++ b/volatility3/framework/symbols/windows/shimcache/shimcache-win10-x64.json
@@ -0,0 +1,371 @@
+{
+    "symbols": {},
+    "enums": {},
+    "base_types": {
+        "unsigned long": {
+            "kind": "int",
+            "size": 4,
+            "signed": false,
+            "endian": "little"
+        },
+        "unsigned long long": {
+            "kind": "int",
+            "size": 8,
+            "signed": false,
+            "endian": "little"
+        },
+        "unsigned char": {
+            "kind": "char",
+            "size": 1,
+            "signed": false,
+            "endian": "little"
+        },
+        "pointer": {
+            "kind": "int",
+            "size": 8,
+            "signed": false,
+            "endian": "little"
+        },
+        "unsigned int": {
+            "kind": "int",
+            "size": 4,
+            "signed": false,
+            "endian": "little"
+        },
+        "unsigned short": {
+            "kind": "int",
+            "size": 2,
+            "signed": false,
+            "endian": "little"
+        },
+        "long": {
+            "kind": "int",
+            "size": 4,
+            "signed": false,
+            "endian": "little"
+        }
+    },
+    "user_types": {
+        "_RTL_BALANCED_LINKS": {
+            "fields": {
+                "Parent": {
+                    "type": {
+                        "kind": "pointer",
+                        "subtype": {
+                            "kind": "struct",
+                            "name": "_RTL_BALANCED_LINKS"
+                        }
+                    },
+                    "offset": 0
+                },
+                "LeftChild": {
+                    "type": {
+                        "kind": "pointer",
+                        "subtype": {
+                            "kind": "struct",
+                            "name": "_RTL_BALANCED_LINKS"
+                        }
+                    },
+                    "offset": 8
+                },
+                "RightChild": {
+                    "type": {
+                        "kind": "pointer",
+                        "subtype": {
+                            "kind": "struct",
+                            "name": "_RTL_BALANCED_LINKS"
+                        }
+                    },
+                    "offset": 16
+                },
+                "Balance": {
+                    "type": {
+                        "kind": "base",
+                        "name": "unsigned char"
+                    },
+                    "offset": 24
+                },
+                "Reserved": {
+                    "type": {
+                        "kind": "array",
+                        "count": 3,
+                        "subtype": {
+                            "kind": "base",
+                            "name": "unsigned char"
+                        }
+                    },
+                    "offset": 25
+                }
+            },
+            "kind": "struct",
+            "size": 32
+        },
+        "_RTL_AVL_TABLE": {
+            "fields": {
+                "BalancedRoot": {
+                    "type": {
+                        "kind": "struct",
+                        "name": "_RTL_BALANCED_LINKS"
+                    },
+                    "offset": 0
+                },
+                "OrderedPointer": {
+                    "type": {
+                        "kind": "pointer",
+                        "subtype": {
+                            "kind": "base",
+                            "name": "void"
+                        }
+                    },
+                    "offset": 32
+                },
+                "WhichOrderedElement": {
+                    "type": {
+                        "kind": "base",
+                        "name": "unsigned long"
+                    },
+                    "offset": 40
+                },
+                "NumberGenericTableElements": {
+                    "type": {
+                        "kind": "base",
+                        "name": "unsigned long"
+                    },
+                    "offset": 44
+                },
+                "DepthOfTree": {
+                    "type": {
+                        "kind": "base",
+                        "name": "unsigned long"
+                    },
+                    "offset": 48
+                },
+                "RestartKey": {
+                    "type": {
+                        "kind": "pointer",
+                        "subtype": {
+                            "kind": "struct",
+                            "name": "_RTL_BALANCED_LINKS"
+                        }
+                    },
+                    "offset": 56
+                },
+                "DeleteCount": {
+                    "type": {
+                        "kind": "base",
+                        "name": "unsigned long"
+                    },
+                    "offset": 64
+                },
+                "CompareRoutine": {
+                    "type": {
+                        "kind": "pointer",
+                        "subtype": {
+                            "kind": "base",
+                            "name": "void"
+                        }
+                    },
+                    "offset": 72
+                },
+                "AllocateRoutine": {
+                    "type": {
+                        "kind": "pointer",
+                        "subtype": {
+                            "kind": "base",
+                            "name": "void"
+                        }
+                    },
+                    "offset": 80
+                },
+                "FreeRoutine": {
+                    "type": {
+                        "kind": "pointer",
+                        "subtype": {
+                            "kind": "base",
+                            "name": "void"
+                        }
+                    },
+                    "offset": 88
+                },
+                "TableContext": {
+                    "type": {
+                        "kind": "pointer",
+                        "subtype": {
+                            "kind": "base",
+                            "name": "void"
+                        }
+                    },
+                    "offset": 96
+                }
+            },
+            "kind": "struct",
+            "size": 104
+        },
+        "SHIM_CACHE_HANDLE": {
+            "fields": {
+                "eresource": {
+                    "type": {
+                        "kind": "pointer",
+                        "subtype": {
+                            "kind": "struct",
+                            "name": "nt_symbols!_ERESOURCE"
+                        }
+                    },
+                    "offset": 0
+                },
+                "rtl_avl_table": {
+                    "type": {
+                        "kind": "pointer",
+                        "subtype": {
+                            "kind": "struct",
+                            "name": "_RTL_AVL_TABLE"
+                        }
+                    },
+                    "offset": 8
+                }
+            },
+            "kind": "struct",
+            "size": 16
+        },
+        "_LARGE_INTEGER": {
+            "fields": {
+                "HighPart": {
+                    "offset": 4,
+                    "type": {
+                        "kind": "base",
+                        "name": "long"
+                    }
+                },
+                "LowPart": {
+                    "offset": 0,
+                    "type": {
+                        "kind": "base",
+                        "name": "unsigned long"
+                    }
+                },
+                "QuadPart": {
+                    "offset": 0,
+                    "type": {
+                        "kind": "base",
+                        "name": "long long"
+                    }
+                },
+                "u": {
+                    "offset": 0,
+                    "type": {
+                        "kind": "struct",
+                        "name": "__unnamed_2"
+                    }
+                }
+            },
+            "kind": "union",
+            "size": 8
+        },
+        "__unnamed_2": {
+          "fields": {
+            "HighPart": {
+              "offset": 4,
+              "type": {
+                "kind": "base",
+                "name": "long"
+              }
+            },
+            "LowPart": {
+              "offset": 0,
+              "type": {
+                "kind": "base",
+                "name": "unsigned long"
+              }
+            }
+          },
+          "kind": "struct",
+          "size": 8
+        },
+        "SHIM_CACHE_ENTRY": {
+            "fields": {
+                "ListEntry": {
+                    "offset": 0,
+                    "type": {
+                        "kind": "struct",
+                        "name": "nt_symbols!_LIST_ENTRY"
+                    }
+                },
+                "u1": {
+                    "offset": 16,
+                    "type": {
+                        "kind": "base",
+                        "name": "unsigned long long"
+                    }
+                },
+                "Path": {
+                    "offset": 24,
+                    "type": {
+                        "kind": "struct",
+                        "name": "nt_symbols!_UNICODE_STRING"
+                    }
+                },
+                "ListEntryDetail": {
+                    "offset": 40,
+                    "type": {
+                        "kind": "pointer",
+                        "subtype": {
+                            "kind": "struct",
+                            "name": "SHIM_CACHE_ENTRY_DETAIL"
+                        }
+                    }
+                }
+            },
+            "kind": "struct",
+            "size": 48
+        },
+        "SHIM_CACHE_ENTRY_DETAIL": {
+            "fields": {
+                "u1": {
+                    "offset": 0,
+                    "type": {
+                        "kind": "base",
+                        "name": "unsigned long long"
+                    }
+                },
+                "LastModified": {
+                    "offset": 8,
+                    "type": {
+                        "kind": "union",
+                        "name": "_LARGE_INTEGER"
+                    }
+                },
+                "BlobSize": {
+                    "offset": 16,
+                    "type": {
+                        "kind": "base",
+                        "name": "unsigned long"
+                    }
+                },
+                "u2": {
+                    "offset": 20,
+                    "type": {
+                        "kind": "base",
+                        "name": "unsigned long"
+                    }
+                },
+                "BlobBuffer": {
+                    "offset": 24,
+                    "type": {
+                        "kind": "base",
+                        "name": "unsigned long long"
+                    }
+                }
+            },
+            "kind": "struct",
+            "size": 32
+        }
+    },
+    "metadata": {
+        "producer": {
+            "version": "0.0.1",
+            "name": "dgmcdona by hand",
+            "datetime": "2024-07-05T18:28:00.000000+00:00"
+        },
+        "format": "4.0.0"
+    }
+}
diff --git a/volatility3/framework/symbols/windows/shimcache/shimcache-win10-x86.json b/volatility3/framework/symbols/windows/shimcache/shimcache-win10-x86.json
new file mode 100644
index 0000000000..26d493c37a
--- /dev/null
+++ b/volatility3/framework/symbols/windows/shimcache/shimcache-win10-x86.json
@@ -0,0 +1,371 @@
+{
+    "symbols": {},
+    "enums": {},
+    "base_types": {
+        "unsigned long": {
+            "kind": "int",
+            "size": 4,
+            "signed": false,
+            "endian": "little"
+        },
+        "unsigned long long": {
+            "kind": "int",
+            "size": 8,
+            "signed": false,
+            "endian": "little"
+        },
+        "unsigned char": {
+            "kind": "char",
+            "size": 1,
+            "signed": false,
+            "endian": "little"
+        },
+        "pointer": {
+            "kind": "int",
+            "size": 4,
+            "signed": false,
+            "endian": "little"
+        },
+        "unsigned int": {
+            "kind": "int",
+            "size": 4,
+            "signed": false,
+            "endian": "little"
+        },
+        "unsigned short": {
+            "kind": "int",
+            "size": 2,
+            "signed": false,
+            "endian": "little"
+        },
+        "long": {
+            "kind": "int",
+            "size": 4,
+            "signed": false,
+            "endian": "little"
+        }
+    },
+    "user_types": {
+        "SHIM_CACHE_HANDLE": {
+            "fields": {
+                "eresource": {
+                    "type": {
+                        "kind": "pointer",
+                        "subtype": {
+                            "kind": "struct",
+                            "name": "nt_symbols!_ERESOURCE"
+                        }
+                    },
+                    "offset": 0
+                },
+                "rtl_avl_table": {
+                    "type": {
+                        "kind": "pointer",
+                        "subtype": {
+                            "kind": "struct",
+                            "name": "_RTL_AVL_TABLE"
+                        }
+                    },
+                    "offset": 4
+                }
+            },
+            "kind": "struct",
+            "size": 8
+        },
+        "_RTL_BALANCED_LINKS": {
+            "fields": {
+                "Parent": {
+                    "type": {
+                        "kind": "pointer",
+                        "subtype": {
+                            "kind": "struct",
+                            "name": "_RTL_BALANCED_LINKS"
+                        }
+                    },
+                    "offset": 0
+                },
+                "LeftChild": {
+                    "type": {
+                        "kind": "pointer",
+                        "subtype": {
+                            "kind": "struct",
+                            "name": "_RTL_BALANCED_LINKS"
+                        }
+                    },
+                    "offset": 4
+                },
+                "RightChild": {
+                    "type": {
+                        "kind": "pointer",
+                        "subtype": {
+                            "kind": "struct",
+                            "name": "_RTL_BALANCED_LINKS"
+                        }
+                    },
+                    "offset": 8
+                },
+                "Balance": {
+                    "type": {
+                        "kind": "base",
+                        "name": "unsigned char"
+                    },
+                    "offset": 12
+                },
+                "Reserved": {
+                    "type": {
+                        "kind": "array",
+                        "count": 3,
+                        "subtype": {
+                            "kind": "base",
+                            "name": "unsigned char"
+                        }
+                    },
+                    "offset": 12
+                }
+            },
+            "kind": "struct",
+            "size": 16
+        },
+        "_RTL_AVL_TABLE": {
+            "fields": {
+                "BalancedRoot": {
+                    "type": {
+                        "kind": "struct",
+                        "name": "_RTL_BALANCED_LINKS"
+                    },
+                    "offset": 0
+                },
+                "OrderedPointer": {
+                    "type": {
+                        "kind": "pointer",
+                        "subtype": {
+                            "kind": "base",
+                            "name": "void"
+                        }
+                    },
+                    "offset": 16
+                },
+                "WhichOrderedElement": {
+                    "type": {
+                        "kind": "base",
+                        "name": "unsigned long"
+                    },
+                    "offset": 20
+                },
+                "NumberGenericTableElements": {
+                    "type": {
+                        "kind": "base",
+                        "name": "unsigned long"
+                    },
+                    "offset": 24
+                },
+                "DepthOfTree": {
+                    "type": {
+                        "kind": "base",
+                        "name": "unsigned long"
+                    },
+                    "offset": 28
+                },
+                "RestartKey": {
+                    "type": {
+                        "kind": "pointer",
+                        "subtype": {
+                            "kind": "struct",
+                            "name": "_RTL_BALANCED_LINKS"
+                        }
+                    },
+                    "offset": 32
+                },
+                "DeleteCount": {
+                    "type": {
+                        "kind": "base",
+                        "name": "unsigned long"
+                    },
+                    "offset": 36
+                },
+                "CompareRoutine": {
+                    "type": {
+                        "kind": "pointer",
+                        "subtype": {
+                            "kind": "base",
+                            "name": "void"
+                        }
+                    },
+                    "offset": 40
+                },
+                "AllocateRoutine": {
+                    "type": {
+                        "kind": "pointer",
+                        "subtype": {
+                            "kind": "base",
+                            "name": "void"
+                        }
+                    },
+                    "offset": 44
+                },
+                "FreeRoutine": {
+                    "type": {
+                        "kind": "pointer",
+                        "subtype": {
+                            "kind": "base",
+                            "name": "void"
+                        }
+                    },
+                    "offset": 48
+                },
+                "TableContext": {
+                    "type": {
+                        "kind": "pointer",
+                        "subtype": {
+                            "kind": "base",
+                            "name": "void"
+                        }
+                    },
+                    "offset": 52
+                }
+            },
+            "kind": "struct",
+            "size": 56
+        },
+        "_LARGE_INTEGER": {
+            "fields": {
+                "HighPart": {
+                    "offset": 4,
+                    "type": {
+                        "kind": "base",
+                        "name": "long"
+                    }
+                },
+                "LowPart": {
+                    "offset": 0,
+                    "type": {
+                        "kind": "base",
+                        "name": "unsigned long"
+                    }
+                },
+                "QuadPart": {
+                    "offset": 0,
+                    "type": {
+                        "kind": "base",
+                        "name": "long long"
+                    }
+                },
+                "u": {
+                    "offset": 0,
+                    "type": {
+                        "kind": "struct",
+                        "name": "__unnamed_2"
+                    }
+                }
+            },
+            "kind": "union",
+            "size": 8
+        },
+        "__unnamed_2": {
+          "fields": {
+            "HighPart": {
+              "offset": 4,
+              "type": {
+                "kind": "base",
+                "name": "long"
+              }
+            },
+            "LowPart": {
+              "offset": 0,
+              "type": {
+                "kind": "base",
+                "name": "unsigned long"
+              }
+            }
+          },
+          "kind": "struct",
+          "size": 8
+        },
+        "SHIM_CACHE_ENTRY": {
+            "fields": {
+                "ListEntry": {
+                    "offset": 0,
+                    "type": {
+                        "kind": "struct",
+                        "name": "nt_symbols!_LIST_ENTRY"
+                    }
+                },
+                "u1": {
+                    "offset": 8,
+                    "type": {
+                        "kind": "base",
+                        "name": "unsigned long"
+                    }
+                },
+                "Path": {
+                    "offset": 12,
+                    "type": {
+                        "kind": "struct",
+                        "name": "nt_symbols!_UNICODE_STRING"
+                    }
+                },
+                "ListEntryDetail": {
+                    "offset": 20,
+                    "type": {
+                        "kind": "pointer",
+                        "subtype": {
+                            "kind": "struct",
+                            "name": "SHIM_CACHE_ENTRY_DETAIL"
+                        }
+                    }
+                }
+            },
+            "kind": "struct",
+            "size": 24
+        },
+        "SHIM_CACHE_ENTRY_DETAIL": {
+            "fields": {
+                "u1": {
+                    "offset": 0,
+                    "type": {
+                        "kind": "base",
+                        "name": "unsigned long"
+                    }
+                },
+                "InsertFlags": {
+                    "offset": 4,
+                    "type": {
+                        "kind": "base",
+                        "name": "unsigned long"
+                    }
+                },
+                "LastModified": {
+                    "offset": 8,
+                    "type": {
+                        "kind": "union",
+                        "name": "_LARGE_INTEGER"
+                    }
+                },
+                "BlobSize": {
+                    "offset": 16,
+                    "type": {
+                        "kind": "base",
+                        "name": "unsigned long"
+                    }
+                },
+                "BlobBuffer": {
+                    "offset": 20,
+                    "type": {
+                        "kind": "base",
+                        "name": "unsigned long"
+                    }
+                }
+            },
+            "kind": "struct",
+            "size": 24
+        }
+    },
+    "metadata": {
+        "producer": {
+            "version": "0.0.1",
+            "name": "dgmcdona by hand",
+            "datetime": "2024-07-05T18:28:00.000000+00:00"
+        },
+        "format": "4.0.0"
+    }
+}
diff --git a/volatility3/framework/symbols/windows/shimcache/shimcache-win7-x64.json b/volatility3/framework/symbols/windows/shimcache/shimcache-win7-x64.json
new file mode 100644
index 0000000000..eac5407ba3
--- /dev/null
+++ b/volatility3/framework/symbols/windows/shimcache/shimcache-win7-x64.json
@@ -0,0 +1,348 @@
+{
+    "symbols": {},
+    "enums": {},
+    "base_types": {
+        "unsigned long": {
+            "kind": "int",
+            "size": 4,
+            "signed": false,
+            "endian": "little"
+        },
+        "unsigned long long": {
+            "kind": "int",
+            "size": 8,
+            "signed": false,
+            "endian": "little"
+        },
+        "unsigned char": {
+            "kind": "char",
+            "size": 1,
+            "signed": false,
+            "endian": "little"
+        },
+        "pointer": {
+            "kind": "int",
+            "size": 8,
+            "signed": false,
+            "endian": "little"
+        },
+        "unsigned int": {
+            "kind": "int",
+            "size": 4,
+            "signed": false,
+            "endian": "little"
+        },
+        "unsigned short": {
+            "kind": "int",
+            "size": 2,
+            "signed": false,
+            "endian": "little"
+        },
+        "long": {
+            "kind": "int",
+            "size": 4,
+            "signed": false,
+            "endian": "little"
+        }
+    },
+    "user_types": {
+        "_RTL_BALANCED_LINKS": {
+            "fields": {
+                "Parent": {
+                    "type": {
+                        "kind": "pointer",
+                        "subtype": {
+                            "kind": "struct",
+                            "name": "_RTL_BALANCED_LINKS"
+                        }
+                    },
+                    "offset": 0
+                },
+                "LeftChild": {
+                    "type": {
+                        "kind": "pointer",
+                        "subtype": {
+                            "kind": "struct",
+                            "name": "_RTL_BALANCED_LINKS"
+                        }
+                    },
+                    "offset": 8
+                },
+                "RightChild": {
+                    "type": {
+                        "kind": "pointer",
+                        "subtype": {
+                            "kind": "struct",
+                            "name": "_RTL_BALANCED_LINKS"
+                        }
+                    },
+                    "offset": 16
+                },
+                "Balance": {
+                    "type": {
+                        "kind": "base",
+                        "name": "unsigned char"
+                    },
+                    "offset": 24
+                },
+                "Reserved": {
+                    "type": {
+                        "kind": "array",
+                        "count": 3,
+                        "subtype": {
+                            "kind": "base",
+                            "name": "unsigned char"
+                        }
+                    },
+                    "offset": 25
+                }
+            },
+            "kind": "struct",
+            "size": 32
+        },
+        "_RTL_AVL_TABLE": {
+            "fields": {
+                "BalancedRoot": {
+                    "type": {
+                        "kind": "struct",
+                        "name": "_RTL_BALANCED_LINKS"
+                    },
+                    "offset": 0
+                },
+                "OrderedPointer": {
+                    "type": {
+                        "kind": "pointer",
+                        "subtype": {
+                            "kind": "base",
+                            "name": "void"
+                        }
+                    },
+                    "offset": 32
+                },
+                "WhichOrderedElement": {
+                    "type": {
+                        "kind": "base",
+                        "name": "unsigned long"
+                    },
+                    "offset": 40
+                },
+                "NumberGenericTableElements": {
+                    "type": {
+                        "kind": "base",
+                        "name": "unsigned long"
+                    },
+                    "offset": 44
+                },
+                "DepthOfTree": {
+                    "type": {
+                        "kind": "base",
+                        "name": "unsigned long"
+                    },
+                    "offset": 48
+                },
+                "RestartKey": {
+                    "type": {
+                        "kind": "pointer",
+                        "subtype": {
+                            "kind": "struct",
+                            "name": "_RTL_BALANCED_LINKS"
+                        }
+                    },
+                    "offset": 56
+                },
+                "DeleteCount": {
+                    "type": {
+                        "kind": "base",
+                        "name": "unsigned long"
+                    },
+                    "offset": 64
+                },
+                "CompareRoutine": {
+                    "type": {
+                        "kind": "pointer",
+                        "subtype": {
+                            "kind": "base",
+                            "name": "void"
+                        }
+                    },
+                    "offset": 72
+                },
+                "AllocateRoutine": {
+                    "type": {
+                        "kind": "pointer",
+                        "subtype": {
+                            "kind": "base",
+                            "name": "void"
+                        }
+                    },
+                    "offset": 80
+                },
+                "FreeRoutine": {
+                    "type": {
+                        "kind": "pointer",
+                        "subtype": {
+                            "kind": "base",
+                            "name": "void"
+                        }
+                    },
+                    "offset": 88
+                },
+                "TableContext": {
+                    "type": {
+                        "kind": "pointer",
+                        "subtype": {
+                            "kind": "base",
+                            "name": "void"
+                        }
+                    },
+                    "offset": 96
+                }
+            },
+            "kind": "struct",
+            "size": 104
+        },
+        "SHIM_CACHE_HANDLE": {
+            "fields": {
+                "eresource": {
+                    "type": {
+                        "kind": "pointer",
+                        "subtype": {
+                            "kind": "struct",
+                            "name": "nt_symbols!_ERESOURCE"
+                        }
+                    },
+                    "offset": 0
+                },
+                "rtl_avl_table": {
+                    "type": {
+                        "kind": "pointer",
+                        "subtype": {
+                            "kind": "struct",
+                            "name": "_RTL_AVL_TABLE"
+                        }
+                    },
+                    "offset": 8
+                }
+            },
+            "kind": "struct",
+            "size": 8
+        },
+        "_LARGE_INTEGER": {
+            "fields": {
+                "HighPart": {
+                    "offset": 4,
+                    "type": {
+                        "kind": "base",
+                        "name": "long"
+                    }
+                },
+                "LowPart": {
+                    "offset": 0,
+                    "type": {
+                        "kind": "base",
+                        "name": "unsigned long"
+                    }
+                },
+                "QuadPart": {
+                    "offset": 0,
+                    "type": {
+                        "kind": "base",
+                        "name": "long long"
+                    }
+                },
+                "u": {
+                    "offset": 0,
+                    "type": {
+                        "kind": "struct",
+                        "name": "__unnamed_2"
+                    }
+                }
+            },
+            "kind": "union",
+            "size": 8
+        },
+        "__unnamed_2": {
+          "fields": {
+            "HighPart": {
+              "offset": 4,
+              "type": {
+                "kind": "base",
+                "name": "long"
+              }
+            },
+            "LowPart": {
+              "offset": 0,
+              "type": {
+                "kind": "base",
+                "name": "unsigned long"
+              }
+            }
+          },
+          "kind": "struct",
+          "size": 8
+        },
+        "SHIM_CACHE_ENTRY": {
+            "fields": {
+                "ListEntry": {
+                    "offset": 0,
+                    "type": {
+                        "kind": "struct",
+                        "name": "nt_symbols!_LIST_ENTRY"
+                    }
+                },
+                "Path": {
+                    "offset": 16,
+                    "type": {
+                        "kind": "struct",
+                        "name": "nt_symbols!_UNICODE_STRING"
+                    }
+                },
+                "LastModified": {
+                    "offset": 32,
+                    "type": {
+                        "kind": "union",
+                        "name": "_LARGE_INTEGER"
+                    }
+                },
+                "InsertFlags": {
+                    "offset": 40,
+                    "type": {
+                        "kind": "base",
+                        "name": "unsigned int"
+                    }
+                },
+                "ShimFlags": {
+                    "offset": 44,
+                    "type": {
+                        "kind": "base",
+                        "name": "unsigned int"
+                    }
+                },
+                "BlobSize": {
+                    "offset": 48,
+                    "type": {
+                        "kind": "base",
+                        "name": "unsigned long long"
+                    }
+                },
+                "BlobBuffer": {
+                    "offset": 56,
+                    "type": {
+                        "kind": "base",
+                        "name": "unsigned long long"
+                    }
+                }
+            },
+            "kind": "struct",
+            "size": 64
+        }
+    },
+    "metadata": {
+        "producer": {
+            "version": "0.0.1",
+            "name": "dgmcdona by hand",
+            "datetime": "2024-07-05T18:28:00.000000+00:00"
+        },
+        "format": "4.0.0"
+    }
+}
diff --git a/volatility3/framework/symbols/windows/shimcache/shimcache-win7-x86.json b/volatility3/framework/symbols/windows/shimcache/shimcache-win7-x86.json
new file mode 100644
index 0000000000..423f7e2551
--- /dev/null
+++ b/volatility3/framework/symbols/windows/shimcache/shimcache-win7-x86.json
@@ -0,0 +1,348 @@
+{
+    "symbols": {},
+    "enums": {},
+    "base_types": {
+        "unsigned long": {
+            "kind": "int",
+            "size": 4,
+            "signed": false,
+            "endian": "little"
+        },
+        "unsigned long long": {
+            "kind": "int",
+            "size": 8,
+            "signed": false,
+            "endian": "little"
+        },
+        "unsigned char": {
+            "kind": "char",
+            "size": 1,
+            "signed": false,
+            "endian": "little"
+        },
+        "pointer": {
+            "kind": "int",
+            "size": 4,
+            "signed": false,
+            "endian": "little"
+        },
+        "unsigned int": {
+            "kind": "int",
+            "size": 4,
+            "signed": false,
+            "endian": "little"
+        },
+        "unsigned short": {
+            "kind": "int",
+            "size": 2,
+            "signed": false,
+            "endian": "little"
+        },
+        "long": {
+            "kind": "int",
+            "size": 4,
+            "signed": false,
+            "endian": "little"
+        }
+    },
+    "user_types": {
+        "_RTL_BALANCED_LINKS": {
+            "fields": {
+                "Parent": {
+                    "type": {
+                        "kind": "pointer",
+                        "subtype": {
+                            "kind": "struct",
+                            "name": "_RTL_BALANCED_LINKS"
+                        }
+                    },
+                    "offset": 0
+                },
+                "LeftChild": {
+                    "type": {
+                        "kind": "pointer",
+                        "subtype": {
+                            "kind": "struct",
+                            "name": "_RTL_BALANCED_LINKS"
+                        }
+                    },
+                    "offset": 4
+                },
+                "RightChild": {
+                    "type": {
+                        "kind": "pointer",
+                        "subtype": {
+                            "kind": "struct",
+                            "name": "_RTL_BALANCED_LINKS"
+                        }
+                    },
+                    "offset": 8
+                },
+                "Balance": {
+                    "type": {
+                        "kind": "base",
+                        "name": "unsigned char"
+                    },
+                    "offset": 12
+                },
+                "Reserved": {
+                    "type": {
+                        "kind": "array",
+                        "count": 3,
+                        "subtype": {
+                            "kind": "base",
+                            "name": "unsigned char"
+                        }
+                    },
+                    "offset": 12
+                }
+            },
+            "kind": "struct",
+            "size": 16
+        },
+        "_RTL_AVL_TABLE": {
+            "fields": {
+                "BalancedRoot": {
+                    "type": {
+                        "kind": "struct",
+                        "name": "_RTL_BALANCED_LINKS"
+                    },
+                    "offset": 0
+                },
+                "OrderedPointer": {
+                    "type": {
+                        "kind": "pointer",
+                        "subtype": {
+                            "kind": "base",
+                            "name": "void"
+                        }
+                    },
+                    "offset": 16
+                },
+                "WhichOrderedElement": {
+                    "type": {
+                        "kind": "base",
+                        "name": "unsigned long"
+                    },
+                    "offset": 20
+                },
+                "NumberGenericTableElements": {
+                    "type": {
+                        "kind": "base",
+                        "name": "unsigned long"
+                    },
+                    "offset": 24
+                },
+                "DepthOfTree": {
+                    "type": {
+                        "kind": "base",
+                        "name": "unsigned long"
+                    },
+                    "offset": 28
+                },
+                "RestartKey": {
+                    "type": {
+                        "kind": "pointer",
+                        "subtype": {
+                            "kind": "struct",
+                            "name": "_RTL_BALANCED_LINKS"
+                        }
+                    },
+                    "offset": 32
+                },
+                "DeleteCount": {
+                    "type": {
+                        "kind": "base",
+                        "name": "unsigned long"
+                    },
+                    "offset": 36
+                },
+                "CompareRoutine": {
+                    "type": {
+                        "kind": "pointer",
+                        "subtype": {
+                            "kind": "base",
+                            "name": "void"
+                        }
+                    },
+                    "offset": 40
+                },
+                "AllocateRoutine": {
+                    "type": {
+                        "kind": "pointer",
+                        "subtype": {
+                            "kind": "base",
+                            "name": "void"
+                        }
+                    },
+                    "offset": 44
+                },
+                "FreeRoutine": {
+                    "type": {
+                        "kind": "pointer",
+                        "subtype": {
+                            "kind": "base",
+                            "name": "void"
+                        }
+                    },
+                    "offset": 48
+                },
+                "TableContext": {
+                    "type": {
+                        "kind": "pointer",
+                        "subtype": {
+                            "kind": "base",
+                            "name": "void"
+                        }
+                    },
+                    "offset": 52
+                }
+            },
+            "kind": "struct",
+            "size": 56
+        },
+        "SHIM_CACHE_HANDLE": {
+            "fields": {
+                "eresource": {
+                    "type": {
+                        "kind": "pointer",
+                        "subtype": {
+                            "kind": "struct",
+                            "name": "nt_symbols!_ERESOURCE"
+                        }
+                    },
+                    "offset": 0
+                },
+                "rtl_avl_table": {
+                    "type": {
+                        "kind": "pointer",
+                        "subtype": {
+                            "kind": "struct",
+                            "name": "_RTL_AVL_TABLE"
+                        }
+                    },
+                    "offset": 4
+                }
+            },
+            "kind": "struct",
+            "size": 8
+        },
+        "_LARGE_INTEGER": {
+            "fields": {
+                "HighPart": {
+                    "offset": 4,
+                    "type": {
+                        "kind": "base",
+                        "name": "long"
+                    }
+                },
+                "LowPart": {
+                    "offset": 0,
+                    "type": {
+                        "kind": "base",
+                        "name": "unsigned long"
+                    }
+                },
+                "QuadPart": {
+                    "offset": 0,
+                    "type": {
+                        "kind": "base",
+                        "name": "long long"
+                    }
+                },
+                "u": {
+                    "offset": 0,
+                    "type": {
+                        "kind": "struct",
+                        "name": "__unnamed_2"
+                    }
+                }
+            },
+            "kind": "union",
+            "size": 8
+        },
+        "__unnamed_2": {
+          "fields": {
+            "HighPart": {
+              "offset": 4,
+              "type": {
+                "kind": "base",
+                "name": "long"
+              }
+            },
+            "LowPart": {
+              "offset": 0,
+              "type": {
+                "kind": "base",
+                "name": "unsigned long"
+              }
+            }
+          },
+          "kind": "struct",
+          "size": 8
+        },
+        "SHIM_CACHE_ENTRY": {
+            "fields": {
+                "ListEntry": {
+                    "offset": 0,
+                    "type": {
+                        "kind": "struct",
+                        "name": "nt_symbols!_LIST_ENTRY"
+                    }
+                },
+                "Path": {
+                    "offset": 8,
+                    "type": {
+                        "kind": "struct",
+                        "name": "nt_symbols!_UNICODE_STRING"
+                    }
+                },
+                "LastModified": {
+                    "offset": 16,
+                    "type": {
+                        "kind": "union",
+                        "name": "_LARGE_INTEGER"
+                    }
+                },
+                "InsertFlags": {
+                    "offset": 24,
+                    "type": {
+                        "kind": "base",
+                        "name": "unsigned int"
+                    }
+                },
+                "ShimFlags": {
+                    "offset": 28,
+                    "type": {
+                        "kind": "base",
+                        "name": "unsigned int"
+                    }
+                },
+                "BlobSize": {
+                    "offset": 32,
+                    "type": {
+                        "kind": "base",
+                        "name": "unsigned int"
+                    }
+                },
+                "BlobBuffer": {
+                    "offset": 36,
+                    "type": {
+                        "kind": "base",
+                        "name": "unsigned long"
+                    }
+                }
+            },
+            "kind": "struct",
+            "size": 40
+        }
+    },
+    "metadata": {
+        "producer": {
+            "version": "0.0.1",
+            "name": "dgmcdona by hand",
+            "datetime": "2024-07-05T18:28:00.000000+00:00"
+        },
+        "format": "4.0.0"
+    }
+}
diff --git a/volatility3/framework/symbols/windows/shimcache/shimcache-win8-x64.json b/volatility3/framework/symbols/windows/shimcache/shimcache-win8-x64.json
new file mode 100644
index 0000000000..a40c8d6804
--- /dev/null
+++ b/volatility3/framework/symbols/windows/shimcache/shimcache-win8-x64.json
@@ -0,0 +1,392 @@
+{
+    "symbols": {},
+    "enums": {},
+    "base_types": {
+        "unsigned long": {
+            "kind": "int",
+            "size": 4,
+            "signed": false,
+            "endian": "little"
+        },
+        "unsigned long long": {
+            "kind": "int",
+            "size": 8,
+            "signed": false,
+            "endian": "little"
+        },
+        "unsigned char": {
+            "kind": "char",
+            "size": 1,
+            "signed": false,
+            "endian": "little"
+        },
+        "pointer": {
+            "kind": "int",
+            "size": 8,
+            "signed": false,
+            "endian": "little"
+        },
+        "unsigned int": {
+            "kind": "int",
+            "size": 4,
+            "signed": false,
+            "endian": "little"
+        },
+        "unsigned short": {
+            "kind": "int",
+            "size": 2,
+            "signed": false,
+            "endian": "little"
+        },
+        "long": {
+            "kind": "int",
+            "size": 4,
+            "signed": false,
+            "endian": "little"
+        }
+    },
+    "user_types": {
+        "_RTL_BALANCED_LINKS": {
+            "fields": {
+                "Parent": {
+                    "type": {
+                        "kind": "pointer",
+                        "subtype": {
+                            "kind": "struct",
+                            "name": "_RTL_BALANCED_LINKS"
+                        }
+                    },
+                    "offset": 0
+                },
+                "LeftChild": {
+                    "type": {
+                        "kind": "pointer",
+                        "subtype": {
+                            "kind": "struct",
+                            "name": "_RTL_BALANCED_LINKS"
+                        }
+                    },
+                    "offset": 8
+                },
+                "RightChild": {
+                    "type": {
+                        "kind": "pointer",
+                        "subtype": {
+                            "kind": "struct",
+                            "name": "_RTL_BALANCED_LINKS"
+                        }
+                    },
+                    "offset": 16
+                },
+                "Balance": {
+                    "type": {
+                        "kind": "base",
+                        "name": "unsigned char"
+                    },
+                    "offset": 24
+                },
+                "Reserved": {
+                    "type": {
+                        "kind": "array",
+                        "count": 3,
+                        "subtype": {
+                            "kind": "base",
+                            "name": "unsigned char"
+                        }
+                    },
+                    "offset": 25
+                }
+            },
+            "kind": "struct",
+            "size": 32
+        },
+        "_RTL_AVL_TABLE": {
+            "fields": {
+                "BalancedRoot": {
+                    "type": {
+                        "kind": "struct",
+                        "name": "_RTL_BALANCED_LINKS"
+                    },
+                    "offset": 0
+                },
+                "OrderedPointer": {
+                    "type": {
+                        "kind": "pointer",
+                        "subtype": {
+                            "kind": "base",
+                            "name": "void"
+                        }
+                    },
+                    "offset": 32
+                },
+                "WhichOrderedElement": {
+                    "type": {
+                        "kind": "base",
+                        "name": "unsigned long"
+                    },
+                    "offset": 40
+                },
+                "NumberGenericTableElements": {
+                    "type": {
+                        "kind": "base",
+                        "name": "unsigned long"
+                    },
+                    "offset": 44
+                },
+                "DepthOfTree": {
+                    "type": {
+                        "kind": "base",
+                        "name": "unsigned long"
+                    },
+                    "offset": 48
+                },
+                "RestartKey": {
+                    "type": {
+                        "kind": "pointer",
+                        "subtype": {
+                            "kind": "struct",
+                            "name": "_RTL_BALANCED_LINKS"
+                        }
+                    },
+                    "offset": 56
+                },
+                "DeleteCount": {
+                    "type": {
+                        "kind": "base",
+                        "name": "unsigned long"
+                    },
+                    "offset": 64
+                },
+                "CompareRoutine": {
+                    "type": {
+                        "kind": "pointer",
+                        "subtype": {
+                            "kind": "base",
+                            "name": "void"
+                        }
+                    },
+                    "offset": 72
+                },
+                "AllocateRoutine": {
+                    "type": {
+                        "kind": "pointer",
+                        "subtype": {
+                            "kind": "base",
+                            "name": "void"
+                        }
+                    },
+                    "offset": 80
+                },
+                "FreeRoutine": {
+                    "type": {
+                        "kind": "pointer",
+                        "subtype": {
+                            "kind": "base",
+                            "name": "void"
+                        }
+                    },
+                    "offset": 88
+                },
+                "TableContext": {
+                    "type": {
+                        "kind": "pointer",
+                        "subtype": {
+                            "kind": "base",
+                            "name": "void"
+                        }
+                    },
+                    "offset": 96
+                }
+            },
+            "kind": "struct",
+            "size": 104
+        },
+        "SHIM_CACHE_HANDLE": {
+            "fields": {
+                "eresource": {
+                    "type": {
+                        "kind": "pointer",
+                        "subtype": {
+                            "kind": "struct",
+                            "name": "nt_symbols!_ERESOURCE"
+                        }
+                    },
+                    "offset": 0
+                },
+                "rtl_avl_table": {
+                    "type": {
+                        "kind": "pointer",
+                        "subtype": {
+                            "kind": "struct",
+                            "name": "_RTL_AVL_TABLE"
+                        }
+                    },
+                    "offset": 8
+                }
+            },
+            "kind": "struct",
+            "size": 8
+        },
+        "_LARGE_INTEGER": {
+            "fields": {
+                "HighPart": {
+                    "offset": 4,
+                    "type": {
+                        "kind": "base",
+                        "name": "long"
+                    }
+                },
+                "LowPart": {
+                    "offset": 0,
+                    "type": {
+                        "kind": "base",
+                        "name": "unsigned long"
+                    }
+                },
+                "QuadPart": {
+                    "offset": 0,
+                    "type": {
+                        "kind": "base",
+                        "name": "long long"
+                    }
+                },
+                "u": {
+                    "offset": 0,
+                    "type": {
+                        "kind": "struct",
+                        "name": "__unnamed_2"
+                    }
+                }
+            },
+            "kind": "union",
+            "size": 8
+        },
+        "__unnamed_2": {
+          "fields": {
+            "HighPart": {
+              "offset": 4,
+              "type": {
+                "kind": "base",
+                "name": "long"
+              }
+            },
+            "LowPart": {
+              "offset": 0,
+              "type": {
+                "kind": "base",
+                "name": "unsigned long"
+              }
+            }
+          },
+          "kind": "struct",
+          "size": 8
+        },
+        "SHIM_CACHE_ENTRY": {
+            "fields": {
+                "ListEntry": {
+                    "offset": 0,
+                    "type": {
+                        "kind": "struct",
+                        "name": "nt_symbols!_LIST_ENTRY"
+                    }
+                },
+                "u1": {
+                    "offset": 16,
+                    "type": {
+                        "kind": "base",
+                        "name": "unsigned long long"
+                    }
+                },
+                "Path": {
+                    "offset": 24,
+                    "type": {
+                        "kind": "struct",
+                        "name": "nt_symbols!_UNICODE_STRING"
+                    }
+                },
+                "u2": {
+                    "offset": 40,
+                    "type": {
+                        "kind": "base",
+                        "name": "unsigned long long"
+                    }
+                },
+                "u3": {
+                    "offset": 48,
+                    "type": {
+                        "kind": "base",
+                        "name": "unsigned long long"
+                    }
+                },
+                "ListEntryDetail": {
+                    "offset": 56,
+                    "type": {
+                        "kind": "pointer",
+                        "subtype": {
+                            "kind": "struct",
+                            "name": "SHIM_CACHE_ENTRY_DETAIL"
+                        }
+                    }
+                }
+            },
+            "kind": "struct",
+            "size": 64
+        },
+        "SHIM_CACHE_ENTRY_DETAIL": {
+            "fields": {
+                "LastModified": {
+                    "offset": 0,
+                    "type": {
+                        "kind": "struct",
+                        "name": "_LARGE_INTEGER"
+                    }
+                },
+                "InsertFlags": {
+                    "offset": 8,
+                    "type": {
+                        "kind": "base",
+                        "name": "unsigned int"
+                    }
+                },
+                "ShimFlags": {
+                    "offset": 12,
+                    "type": {
+                        "kind": "base",
+                        "name": "unsigned int"
+                    }
+                },
+                "BlobSize": {
+                    "offset": 16,
+                    "type": {
+                        "kind": "base",
+                        "name": "unsigned long long"
+                    }
+                },
+                "Padding": {
+                    "offset": 24,
+                    "type": {
+                        "kind": "base",
+                        "name": "unsigned long long"
+                    }
+                },
+                "BlobBuffer": {
+                    "offset": 32,
+                    "type": {
+                        "kind": "base",
+                        "name": "unsigned long long"
+                    }
+                }
+            },
+            "kind": "struct",
+            "size": 40
+        }
+    },
+    "metadata": {
+        "producer": {
+            "version": "0.0.1",
+            "name": "dgmcdona by hand",
+            "datetime": "2024-07-05T18:28:00.000000+00:00"
+        },
+        "format": "4.0.0"
+    }
+}
diff --git a/volatility3/framework/symbols/windows/shimcache/shimcache-win8-x86.json b/volatility3/framework/symbols/windows/shimcache/shimcache-win8-x86.json
new file mode 100644
index 0000000000..c3cee5febe
--- /dev/null
+++ b/volatility3/framework/symbols/windows/shimcache/shimcache-win8-x86.json
@@ -0,0 +1,386 @@
+{
+    "symbols": {},
+    "enums": {},
+    "base_types": {
+        "unsigned long": {
+            "kind": "int",
+            "size": 4,
+            "signed": false,
+            "endian": "little"
+        },
+        "unsigned long long": {
+            "kind": "int",
+            "size": 8,
+            "signed": false,
+            "endian": "little"
+        },
+        "unsigned char": {
+            "kind": "char",
+            "size": 1,
+            "signed": false,
+            "endian": "little"
+        },
+        "pointer": {
+            "kind": "int",
+            "size": 4,
+            "signed": false,
+            "endian": "little"
+        },
+        "unsigned int": {
+            "kind": "int",
+            "size": 4,
+            "signed": false,
+            "endian": "little"
+        },
+        "unsigned short": {
+            "kind": "int",
+            "size": 2,
+            "signed": false,
+            "endian": "little"
+        },
+        "long": {
+            "kind": "int",
+            "size": 4,
+            "signed": false,
+            "endian": "little"
+        }
+    },
+    "user_types": {
+        "_RTL_BALANCED_LINKS": {
+            "fields": {
+                "Parent": {
+                    "type": {
+                        "kind": "pointer",
+                        "subtype": {
+                            "kind": "struct",
+                            "name": "_RTL_BALANCED_LINKS"
+                        }
+                    },
+                    "offset": 0
+                },
+                "LeftChild": {
+                    "type": {
+                        "kind": "pointer",
+                        "subtype": {
+                            "kind": "struct",
+                            "name": "_RTL_BALANCED_LINKS"
+                        }
+                    },
+                    "offset": 4
+                },
+                "RightChild": {
+                    "type": {
+                        "kind": "pointer",
+                        "subtype": {
+                            "kind": "struct",
+                            "name": "_RTL_BALANCED_LINKS"
+                        }
+                    },
+                    "offset": 8
+                },
+                "Balance": {
+                    "type": {
+                        "kind": "base",
+                        "name": "unsigned char"
+                    },
+                    "offset": 12
+                },
+                "Reserved": {
+                    "type": {
+                        "kind": "array",
+                        "count": 3,
+                        "subtype": {
+                            "kind": "base",
+                            "name": "unsigned char"
+                        }
+                    },
+                    "offset": 12
+                }
+            },
+            "kind": "struct",
+            "size": 16
+        },
+        "_RTL_AVL_TABLE": {
+            "fields": {
+                "BalancedRoot": {
+                    "type": {
+                        "kind": "struct",
+                        "name": "_RTL_BALANCED_LINKS"
+                    },
+                    "offset": 0
+                },
+                "OrderedPointer": {
+                    "type": {
+                        "kind": "pointer",
+                        "subtype": {
+                            "kind": "base",
+                            "name": "void"
+                        }
+                    },
+                    "offset": 16
+                },
+                "WhichOrderedElement": {
+                    "type": {
+                        "kind": "base",
+                        "name": "unsigned long"
+                    },
+                    "offset": 20
+                },
+                "NumberGenericTableElements": {
+                    "type": {
+                        "kind": "base",
+                        "name": "unsigned long"
+                    },
+                    "offset": 24
+                },
+                "DepthOfTree": {
+                    "type": {
+                        "kind": "base",
+                        "name": "unsigned long"
+                    },
+                    "offset": 28
+                },
+                "RestartKey": {
+                    "type": {
+                        "kind": "pointer",
+                        "subtype": {
+                            "kind": "struct",
+                            "name": "_RTL_BALANCED_LINKS"
+                        }
+                    },
+                    "offset": 32
+                },
+                "DeleteCount": {
+                    "type": {
+                        "kind": "base",
+                        "name": "unsigned long"
+                    },
+                    "offset": 36
+                },
+                "CompareRoutine": {
+                    "type": {
+                        "kind": "pointer",
+                        "subtype": {
+                            "kind": "base",
+                            "name": "void"
+                        }
+                    },
+                    "offset": 40
+                },
+                "AllocateRoutine": {
+                    "type": {
+                        "kind": "pointer",
+                        "subtype": {
+                            "kind": "base",
+                            "name": "void"
+                        }
+                    },
+                    "offset": 44
+                },
+                "FreeRoutine": {
+                    "type": {
+                        "kind": "pointer",
+                        "subtype": {
+                            "kind": "base",
+                            "name": "void"
+                        }
+                    },
+                    "offset": 48
+                },
+                "TableContext": {
+                    "type": {
+                        "kind": "pointer",
+                        "subtype": {
+                            "kind": "base",
+                            "name": "void"
+                        }
+                    },
+                    "offset": 52
+                }
+            },
+            "kind": "struct",
+            "size": 56
+        },
+        "SHIM_CACHE_HANDLE": {
+            "fields": {
+                "eresource": {
+                    "type": {
+                        "kind": "pointer",
+                        "subtype": {
+                            "kind": "struct",
+                            "name": "nt_symbols!_ERESOURCE"
+                        }
+                    },
+                    "offset": 0
+                },
+                "rtl_avl_table": {
+                    "type": {
+                        "kind": "pointer",
+                        "subtype": {
+                            "kind": "struct",
+                            "name": "_RTL_AVL_TABLE"
+                        }
+                    },
+                    "offset": 4
+                }
+            },
+            "kind": "struct",
+            "size": 8
+        },
+        "_LARGE_INTEGER": {
+            "fields": {
+                "HighPart": {
+                    "offset": 4,
+                    "type": {
+                        "kind": "base",
+                        "name": "long"
+                    }
+                },
+                "LowPart": {
+                    "offset": 0,
+                    "type": {
+                        "kind": "base",
+                        "name": "unsigned long"
+                    }
+                },
+                "QuadPart": {
+                    "offset": 0,
+                    "type": {
+                        "kind": "base",
+                        "name": "long long"
+                    }
+                },
+                "u": {
+                    "offset": 0,
+                    "type": {
+                        "kind": "struct",
+                        "name": "__unnamed_2"
+                    }
+                }
+            },
+            "kind": "union",
+            "size": 8
+        },
+        "__unnamed_2": {
+          "fields": {
+            "HighPart": {
+              "offset": 4,
+              "type": {
+                "kind": "base",
+                "name": "long"
+              }
+            },
+            "LowPart": {
+              "offset": 0,
+              "type": {
+                "kind": "base",
+                "name": "unsigned long"
+              }
+            }
+          },
+          "kind": "struct",
+          "size": 8
+        },
+        "SHIM_CACHE_ENTRY": {
+            "fields": {
+                "ListEntry": {
+                    "offset": 0,
+                    "type": {
+                        "kind": "struct",
+                        "name": "nt_symbols!_LIST_ENTRY"
+                    }
+                },
+                "u1": {
+                    "offset": 8,
+                    "type": {
+                        "kind": "base",
+                        "name": "unsigned long"
+                    }
+                },
+                "u2": {
+                    "offset": 12,
+                    "type": {
+                        "kind": "base",
+                        "name": "unsigned long"
+                    }
+                },
+                "Path": {
+                    "offset": 16,
+                    "type": {
+                        "kind": "struct",
+                        "name": "nt_symbols!_UNICODE_STRING"
+                    }
+                },
+                "u3": {
+                    "offset": 24,
+                    "type": {
+                        "kind": "base",
+                        "name": "unsigned long long"
+                    }
+                },
+                "ListEntryDetail": {
+                    "offset": 32,
+                    "type": {
+                        "kind": "pointer",
+                        "subtype": {
+                            "kind": "struct",
+                            "name": "SHIM_CACHE_ENTRY_DETAIL"
+                        }
+                    }
+                }
+            },
+            "kind": "struct",
+            "size": 36
+        },
+        "SHIM_CACHE_ENTRY_DETAIL": {
+            "fields": {
+                "LastModified": {
+                    "offset": 0,
+                    "type": {
+                        "kind": "struct",
+                        "name": "_LARGE_INTEGER"
+                    }
+                },
+                "InsertFlags": {
+                    "offset": 8,
+                    "type": {
+                        "kind": "base",
+                        "name": "unsigned int"
+                    }
+                },
+                "ShimFlags": {
+                    "offset": 12,
+                    "type": {
+                        "kind": "base",
+                        "name": "unsigned long"
+                    }
+                },
+                "BlobSize": {
+                    "offset": 16,
+                    "type": {
+                        "kind": "base",
+                        "name": "unsigned long"
+                    }
+                },
+                "BlobBuffer": {
+                    "offset": 20,
+                    "type": {
+                        "kind": "base",
+                        "name": "unsigned long"
+                    }
+                }
+            },
+            "kind": "struct",
+            "size": 24
+        }
+    },
+    "metadata": {
+        "producer": {
+            "version": "0.0.1",
+            "name": "dgmcdona by hand",
+            "datetime": "2024-07-05T18:28:00.000000+00:00"
+        },
+        "format": "4.0.0"
+    }
+}
+
diff --git a/volatility3/framework/symbols/windows/shimcache/shimcache-xp-sp2-x86.json b/volatility3/framework/symbols/windows/shimcache/shimcache-xp-sp2-x86.json
new file mode 100644
index 0000000000..6114e6c856
--- /dev/null
+++ b/volatility3/framework/symbols/windows/shimcache/shimcache-xp-sp2-x86.json
@@ -0,0 +1,485 @@
+{
+    "symbols": {},
+    "enums": {},
+    "base_types": {
+        "unsigned long": {
+            "kind": "int",
+            "size": 4,
+            "signed": false,
+            "endian": "little"
+        },
+        "unsigned long long": {
+            "kind": "int",
+            "size": 8,
+            "signed": false,
+            "endian": "little"
+        },
+        "unsigned char": {
+            "kind": "char",
+            "size": 1,
+            "signed": false,
+            "endian": "little"
+        },
+        "pointer": {
+            "kind": "int",
+            "size": 4,
+            "signed": false,
+            "endian": "little"
+        },
+        "unsigned int": {
+            "kind": "int",
+            "size": 4,
+            "signed": false,
+            "endian": "little"
+        },
+        "unsigned short": {
+            "kind": "int",
+            "size": 2,
+            "signed": false,
+            "endian": "little"
+        },
+        "long": {
+            "kind": "int",
+            "size": 4,
+            "signed": false,
+            "endian": "little"
+        }
+    },
+    "user_types": {
+        "_LARGE_INTEGER": {
+            "fields": {
+                "HighPart": {
+                    "offset": 4,
+                    "type": {
+                        "kind": "base",
+                        "name": "long"
+                    }
+                },
+                "LowPart": {
+                    "offset": 0,
+                    "type": {
+                        "kind": "base",
+                        "name": "unsigned long"
+                    }
+                },
+                "QuadPart": {
+                    "offset": 0,
+                    "type": {
+                        "kind": "base",
+                        "name": "long long"
+                    }
+                },
+                "u": {
+                    "offset": 0,
+                    "type": {
+                        "kind": "struct",
+                        "name": "__unnamed_2"
+                    }
+                }
+            },
+            "kind": "union",
+            "size": 8
+        },
+        "__unnamed_2": {
+          "fields": {
+            "HighPart": {
+              "offset": 4,
+              "type": {
+                "kind": "base",
+                "name": "long"
+              }
+            },
+            "LowPart": {
+              "offset": 0,
+              "type": {
+                "kind": "base",
+                "name": "unsigned long"
+              }
+            }
+          },
+          "kind": "struct",
+          "size": 8
+        },
+        "_RTL_BALANCED_LINKS": {
+            "fields": {
+                "Parent": {
+                    "type": {
+                        "kind": "pointer",
+                        "subtype": {
+                            "kind": "struct",
+                            "name": "_RTL_BALANCED_LINKS"
+                        }
+                    },
+                    "offset": 0
+                },
+                "LeftChild": {
+                    "type": {
+                        "kind": "pointer",
+                        "subtype": {
+                            "kind": "struct",
+                            "name": "_RTL_BALANCED_LINKS"
+                        }
+                    },
+                    "offset": 4
+                },
+                "RightChild": {
+                    "type": {
+                        "kind": "pointer",
+                        "subtype": {
+                            "kind": "struct",
+                            "name": "_RTL_BALANCED_LINKS"
+                        }
+                    },
+                    "offset": 8
+                },
+                "Balance": {
+                    "type": {
+                        "kind": "base",
+                        "name": "unsigned char"
+                    },
+                    "offset": 12
+                },
+                "Reserved": {
+                    "type": {
+                        "kind": "array",
+                        "count": 3,
+                        "subtype": {
+                            "kind": "base",
+                            "name": "unsigned char"
+                        }
+                    },
+                    "offset": 12
+                }
+            },
+            "kind": "struct",
+            "size": 16
+        },
+        "_RTL_AVL_TABLE": {
+            "fields": {
+                "BalancedRoot": {
+                    "type": {
+                        "kind": "struct",
+                        "name": "_RTL_BALANCED_LINKS"
+                    },
+                    "offset": 0
+                },
+                "OrderedPointer": {
+                    "type": {
+                        "kind": "pointer",
+                        "subtype": {
+                            "kind": "base",
+                            "name": "void"
+                        }
+                    },
+                    "offset": 16
+                },
+                "WhichOrderedElement": {
+                    "type": {
+                        "kind": "base",
+                        "name": "unsigned long"
+                    },
+                    "offset": 20
+                },
+                "NumberGenericTableElements": {
+                    "type": {
+                        "kind": "base",
+                        "name": "unsigned long"
+                    },
+                    "offset": 24
+                },
+                "DepthOfTree": {
+                    "type": {
+                        "kind": "base",
+                        "name": "unsigned long"
+                    },
+                    "offset": 28
+                },
+                "RestartKey": {
+                    "type": {
+                        "kind": "pointer",
+                        "subtype": {
+                            "kind": "struct",
+                            "name": "_RTL_BALANCED_LINKS"
+                        }
+                    },
+                    "offset": 32
+                },
+                "DeleteCount": {
+                    "type": {
+                        "kind": "base",
+                        "name": "unsigned long"
+                    },
+                    "offset": 36
+                },
+                "CompareRoutine": {
+                    "type": {
+                        "kind": "pointer",
+                        "subtype": {
+                            "kind": "base",
+                            "name": "void"
+                        }
+                    },
+                    "offset": 40
+                },
+                "AllocateRoutine": {
+                    "type": {
+                        "kind": "pointer",
+                        "subtype": {
+                            "kind": "base",
+                            "name": "void"
+                        }
+                    },
+                    "offset": 44
+                },
+                "FreeRoutine": {
+                    "type": {
+                        "kind": "pointer",
+                        "subtype": {
+                            "kind": "base",
+                            "name": "void"
+                        }
+                    },
+                    "offset": 48
+                },
+                "TableContext": {
+                    "type": {
+                        "kind": "pointer",
+                        "subtype": {
+                            "kind": "base",
+                            "name": "void"
+                        }
+                    },
+                    "offset": 52
+                }
+            },
+            "kind": "struct",
+            "size": 56
+        },
+        "SHIM_CACHE_HANDLE": {
+            "fields": {
+                "eresource": {
+                    "type": {
+                        "kind": "pointer",
+                        "subtype": {
+                            "kind": "struct",
+                            "name": "nt_symbols!_ERESOURCE"
+                        }
+                    },
+                    "offset": 0
+                },
+                "rtl_avl_table": {
+                    "type": {
+                        "kind": "pointer",
+                        "subtype": {
+                            "kind": "struct",
+                            "name": "_RTL_AVL_TABLE"
+                        }
+                    },
+                    "offset": 4
+                }
+            },
+            "kind": "struct",
+            "size": 8
+        },
+        "SHIM_CACHE_HEADER": {
+            "fields": {
+                "Magic": {
+                    "type": {
+                        "kind": "base",
+                        "name": "unsigned int"
+                    },
+                    "offset": 0
+                },
+                "u1": {
+                    "type": {
+                        "kind": "base",
+                        "name": "unsigned int"
+                    },
+                    "offset": 4
+                },
+                "NumEntries": {
+                    "type": {
+                        "kind": "base",
+                        "name": "unsigned int"
+                    },
+                    "offset": 8
+                },
+                "u2": {
+                    "type": {
+                        "kind": "base",
+                        "name": "unsigned int"
+                    },
+                    "offset": 12
+                }
+            },
+            "kind": "struct",
+            "size": 400
+        },
+        "SHIM_CACHE_ENTRY": {
+            "fields": {
+                "Path": {
+                    "type": {
+                        "count": 520,
+                        "kind": "array",
+                        "subtype": {
+                            "kind": "base",
+                            "name": "unsigned char"
+                        }
+                    },
+                    "offset": 0
+                },
+                "LastModified": {
+                    "type": {
+                        "kind": "union",
+                        "name": "LARGE_INTEGER"
+                    },
+                    "offset": 4
+                },
+                "FileSize": {
+                    "type": {
+                        "kind": "base",
+                        "name": "long long"
+                    },
+                    "offset": 8
+                },
+                "LastUpdate": {
+                    "type": {
+                        "kind": "union",
+                        "name": "LARGE_INTEGER"
+                    },
+                    "offset": 12
+                }
+            },
+            "kind": "struct",
+            "size": 552
+        },
+        "_SEGMENT": {
+            "fields": {
+                "ControlArea": {
+                    "offset": 0,
+                    "type": {
+                        "kind": "pointer",
+                        "subtype": {
+                            "kind": "struct",
+                            "name": "nt_symbols!_CONTROL_AREA"
+                        }
+                    }
+                },
+                "TotalNumberOfPtes": {
+                    "offset": 4,
+                    "type": {
+                        "kind": "base",
+                        "name": "unsigned long"
+                    }
+                },
+                "NonExtendedPtes": {
+                    "offset": 8,
+                    "type": {
+                        "kind": "base",
+                        "name": "unsigned long"
+                    }
+                },
+                "WritableUserReferences": {
+                    "offset": 12,
+                    "type": {
+                        "kind": "base",
+                        "name": "unsigned long"
+                    }
+                },
+                "SizeOfSegment": {
+                    "offset": 16,
+                    "type": {
+                        "kind": "base",
+                        "name": "unsigned long"
+                    }
+                },
+                "SegmentPteTemplate": {
+                    "offset": 24,
+                    "type": {
+                        "kind": "struct",
+                        "name": "nt_symbols!_MMPTE"
+                    }
+                },
+                "NumberOfCommittedPages": {
+                    "offset": 28,
+                    "type": {
+                        "kind": "base",
+                        "name": "unsigned long"
+                    }
+                },
+                "ExtendInfo": {
+                    "offset": 32,
+                    "type": {
+                        "kind": "pointer",
+                        "subtype": {
+                            "kind": "struct",
+                            "name": "nt_symbols!_MMEXTEND_INFO"
+                        }
+                    }
+                },
+                "SystemImageBase": {
+                    "offset": 36,
+                    "type": {
+                        "kind": "pointer",
+                        "subtype": {
+                            "kind": "base",
+                            "name": "void"
+                        }
+                    }
+                },
+                "BasedAddress": {
+                    "offset": 40,
+                    "type": {
+                        "kind": "base",
+                        "name": "long"
+                    }
+                },
+                "u1": {
+                    "offset": 44,
+                    "type": {
+                        "kind": "base",
+                        "name": "long"
+                    }
+                },
+                "u2": {
+                    "offset": 48,
+                    "type": {
+                        "kind": "base",
+                        "name": "long"
+                    }
+                },
+                "PrototypePte": {
+                    "offset": 52,
+                    "type": {
+                        "kind": "pointer",
+                        "subtype": {
+                            "kind": "struct",
+                            "name": "nt_symbols!_MMPTE"
+                        }
+                    }
+                },
+                "ThePtes": {
+                    "offset": 60,
+                    "type": {
+                        "kind": "array",
+                        "count": 1,
+                        "subtype": {
+                            "kind": "base",
+                            "name": "nt_symbols!_MMPTE"
+                        }
+                    }
+                }
+            },
+            "kind": "struct",
+            "size": 64
+        }
+    },
+    "metadata": {
+        "producer": {
+            "version": "0.0.1",
+            "name": "dgmcdona by hand",
+            "datetime": "2024-07-05T18:28:00.000000+00:00"
+        },
+        "format": "4.0.0"
+    }
+}
diff --git a/volatility3/framework/symbols/windows/shimcache/shimcache-xp-sp3-x86.json b/volatility3/framework/symbols/windows/shimcache/shimcache-xp-sp3-x86.json
new file mode 100644
index 0000000000..a9b86d93cd
--- /dev/null
+++ b/volatility3/framework/symbols/windows/shimcache/shimcache-xp-sp3-x86.json
@@ -0,0 +1,485 @@
+{
+    "symbols": {},
+    "enums": {},
+    "base_types": {
+        "unsigned long": {
+            "kind": "int",
+            "size": 4,
+            "signed": false,
+            "endian": "little"
+        },
+        "unsigned long long": {
+            "kind": "int",
+            "size": 8,
+            "signed": false,
+            "endian": "little"
+        },
+        "unsigned char": {
+            "kind": "char",
+            "size": 1,
+            "signed": false,
+            "endian": "little"
+        },
+        "pointer": {
+            "kind": "int",
+            "size": 4,
+            "signed": false,
+            "endian": "little"
+        },
+        "unsigned int": {
+            "kind": "int",
+            "size": 4,
+            "signed": false,
+            "endian": "little"
+        },
+        "unsigned short": {
+            "kind": "int",
+            "size": 2,
+            "signed": false,
+            "endian": "little"
+        },
+        "long": {
+            "kind": "int",
+            "size": 4,
+            "signed": false,
+            "endian": "little"
+        }
+    },
+    "user_types": {
+        "_LARGE_INTEGER": {
+            "fields": {
+                "HighPart": {
+                    "offset": 4,
+                    "type": {
+                        "kind": "base",
+                        "name": "long"
+                    }
+                },
+                "LowPart": {
+                    "offset": 0,
+                    "type": {
+                        "kind": "base",
+                        "name": "unsigned long"
+                    }
+                },
+                "QuadPart": {
+                    "offset": 0,
+                    "type": {
+                        "kind": "base",
+                        "name": "long long"
+                    }
+                },
+                "u": {
+                    "offset": 0,
+                    "type": {
+                        "kind": "struct",
+                        "name": "__unnamed_2"
+                    }
+                }
+            },
+            "kind": "union",
+            "size": 8
+        },
+        "__unnamed_2": {
+          "fields": {
+            "HighPart": {
+              "offset": 4,
+              "type": {
+                "kind": "base",
+                "name": "long"
+              }
+            },
+            "LowPart": {
+              "offset": 0,
+              "type": {
+                "kind": "base",
+                "name": "unsigned long"
+              }
+            }
+          },
+          "kind": "struct",
+          "size": 8
+        },
+        "_RTL_BALANCED_LINKS": {
+            "fields": {
+                "Parent": {
+                    "type": {
+                        "kind": "pointer",
+                        "subtype": {
+                            "kind": "struct",
+                            "name": "_RTL_BALANCED_LINKS"
+                        }
+                    },
+                    "offset": 0
+                },
+                "LeftChild": {
+                    "type": {
+                        "kind": "pointer",
+                        "subtype": {
+                            "kind": "struct",
+                            "name": "_RTL_BALANCED_LINKS"
+                        }
+                    },
+                    "offset": 4
+                },
+                "RightChild": {
+                    "type": {
+                        "kind": "pointer",
+                        "subtype": {
+                            "kind": "struct",
+                            "name": "_RTL_BALANCED_LINKS"
+                        }
+                    },
+                    "offset": 8
+                },
+                "Balance": {
+                    "type": {
+                        "kind": "base",
+                        "name": "unsigned char"
+                    },
+                    "offset": 12
+                },
+                "Reserved": {
+                    "type": {
+                        "kind": "array",
+                        "count": 3,
+                        "subtype": {
+                            "kind": "base",
+                            "name": "unsigned char"
+                        }
+                    },
+                    "offset": 12
+                }
+            },
+            "kind": "struct",
+            "size": 16
+        },
+        "_RTL_AVL_TABLE": {
+            "fields": {
+                "BalancedRoot": {
+                    "type": {
+                        "kind": "struct",
+                        "name": "_RTL_BALANCED_LINKS"
+                    },
+                    "offset": 0
+                },
+                "OrderedPointer": {
+                    "type": {
+                        "kind": "pointer",
+                        "subtype": {
+                            "kind": "base",
+                            "name": "void"
+                        }
+                    },
+                    "offset": 16
+                },
+                "WhichOrderedElement": {
+                    "type": {
+                        "kind": "base",
+                        "name": "unsigned long"
+                    },
+                    "offset": 20
+                },
+                "NumberGenericTableElements": {
+                    "type": {
+                        "kind": "base",
+                        "name": "unsigned long"
+                    },
+                    "offset": 24
+                },
+                "DepthOfTree": {
+                    "type": {
+                        "kind": "base",
+                        "name": "unsigned long"
+                    },
+                    "offset": 28
+                },
+                "RestartKey": {
+                    "type": {
+                        "kind": "pointer",
+                        "subtype": {
+                            "kind": "struct",
+                            "name": "_RTL_BALANCED_LINKS"
+                        }
+                    },
+                    "offset": 32
+                },
+                "DeleteCount": {
+                    "type": {
+                        "kind": "base",
+                        "name": "unsigned long"
+                    },
+                    "offset": 36
+                },
+                "CompareRoutine": {
+                    "type": {
+                        "kind": "pointer",
+                        "subtype": {
+                            "kind": "base",
+                            "name": "void"
+                        }
+                    },
+                    "offset": 40
+                },
+                "AllocateRoutine": {
+                    "type": {
+                        "kind": "pointer",
+                        "subtype": {
+                            "kind": "base",
+                            "name": "void"
+                        }
+                    },
+                    "offset": 44
+                },
+                "FreeRoutine": {
+                    "type": {
+                        "kind": "pointer",
+                        "subtype": {
+                            "kind": "base",
+                            "name": "void"
+                        }
+                    },
+                    "offset": 48
+                },
+                "TableContext": {
+                    "type": {
+                        "kind": "pointer",
+                        "subtype": {
+                            "kind": "base",
+                            "name": "void"
+                        }
+                    },
+                    "offset": 52
+                }
+            },
+            "kind": "struct",
+            "size": 56
+        },
+        "SHIM_CACHE_HEADER": {
+            "fields": {
+                "Magic": {
+                    "type": {
+                        "kind": "base",
+                        "name": "unsigned int"
+                    },
+                    "offset": 0
+                },
+                "u1": {
+                    "type": {
+                        "kind": "base",
+                        "name": "unsigned int"
+                    },
+                    "offset": 4
+                },
+                "NumEntries": {
+                    "type": {
+                        "kind": "base",
+                        "name": "unsigned int"
+                    },
+                    "offset": 8
+                },
+                "u2": {
+                    "type": {
+                        "kind": "base",
+                        "name": "unsigned int"
+                    },
+                    "offset": 12
+                }
+            },
+            "kind": "struct",
+            "size": 400
+        },
+        "SHIM_CACHE_ENTRY": {
+            "fields": {
+                "Path": {
+                    "type": {
+                        "count": 520,
+                        "kind": "array",
+                        "subtype": {
+                            "kind": "base",
+                            "name": "unsigned char"
+                        }
+                    },
+                    "offset": 0
+                },
+                "LastModified": {
+                    "type": {
+                        "kind": "union",
+                        "name": "_LARGE_INTEGER"
+                    },
+                    "offset": 528
+                },
+                "FileSize": {
+                    "type": {
+                        "kind": "base",
+                        "name": "long long"
+                    },
+                    "offset": 536
+                },
+                "LastUpdate": {
+                    "type": {
+                        "kind": "union",
+                        "name": "_LARGE_INTEGER"
+                    },
+                    "offset": 544
+                }
+            },
+            "kind": "struct",
+            "size": 552
+        },
+        "SHIM_CACHE_HANDLE": {
+            "fields": {
+                "eresource": {
+                    "type": {
+                        "kind": "pointer",
+                        "subtype": {
+                            "kind": "struct",
+                            "name": "nt_symbols!ERESOURCE"
+                        }
+                    },
+                    "offset": 0
+                },
+                "rtl_avl_table": {
+                    "type": {
+                        "kind": "pointer",
+                        "subtype": {
+                            "kind": "struct",
+                            "name": "_RTL_AVL_TABLE"
+                        }
+                    },
+                    "offset": 4
+                }
+            },
+            "kind": "struct",
+            "size": 8
+        },
+        "_SEGMENT": {
+            "fields": {
+                "ControlArea": {
+                    "offset": 0,
+                    "type": {
+                        "kind": "pointer",
+                        "subtype": {
+                            "kind": "struct",
+                            "name": "nt_symbols!_CONTROL_AREA"
+                        }
+                    }
+                },
+                "TotalNumberOfPtes": {
+                    "offset": 4,
+                    "type": {
+                        "kind": "base",
+                        "name": "unsigned long"
+                    }
+                },
+                "NonExtendedPtes": {
+                    "offset": 8,
+                    "type": {
+                        "kind": "base",
+                        "name": "unsigned long"
+                    }
+                },
+                "WritableUserReferences": {
+                    "offset": 12,
+                    "type": {
+                        "kind": "base",
+                        "name": "unsigned long"
+                    }
+                },
+                "SizeOfSegment": {
+                    "offset": 16,
+                    "type": {
+                        "kind": "base",
+                        "name": "unsigned long"
+                    }
+                },
+                "SegmentPteTemplate": {
+                    "offset": 24,
+                    "type": {
+                        "kind": "struct",
+                        "name": "nt_symbols!_MMPTE"
+                    }
+                },
+                "NumberOfCommittedPages": {
+                    "offset": 32,
+                    "type": {
+                        "kind": "base",
+                        "name": "unsigned long"
+                    }
+                },
+                "ExtendInfo": {
+                    "offset": 36,
+                    "type": {
+                        "kind": "pointer",
+                        "subtype": {
+                            "kind": "struct",
+                            "name": "nt_symbols!_MMEXTEND_INFO"
+                        }
+                    }
+                },
+                "SystemImageBase": {
+                    "offset": 40,
+                    "type": {
+                        "kind": "pointer",
+                        "subtype": {
+                            "kind": "base",
+                            "name": "void"
+                        }
+                    }
+                },
+                "BasedAddress": {
+                    "offset": 44,
+                    "type": {
+                        "kind": "base",
+                        "name": "long"
+                    }
+                },
+                "u1": {
+                    "offset": 48,
+                    "type": {
+                        "kind": "base",
+                        "name": "long"
+                    }
+                },
+                "u2": {
+                    "offset": 52,
+                    "type": {
+                        "kind": "base",
+                        "name": "long"
+                    }
+                },
+                "PrototypePte": {
+                    "offset": 56,
+                    "type": {
+                        "kind": "pointer",
+                        "subtype": {
+                            "kind": "struct",
+                            "name": "nt_symbols!_MMPTE"
+                        }
+                    }
+                },
+                "ThePtes": {
+                    "offset": 64,
+                    "type": {
+                        "kind": "array",
+                        "count": 1,
+                        "subtype": {
+                            "kind": "base",
+                            "name": "nt_symbols!_MMPTE"
+                        }
+                    }
+                }
+            },
+            "kind": "struct",
+            "size": 72
+        }
+    },
+    "metadata": {
+        "producer": {
+            "version": "0.0.1",
+            "name": "dgmcdona by hand",
+            "datetime": "2024-07-05T18:28:00.000000+00:00"
+        },
+        "format": "4.0.0"
+    }
+}
diff --git a/volatility3/framework/symbols/windows/unloadedmodules-x64.json b/volatility3/framework/symbols/windows/unloadedmodules-x64.json
new file mode 100644
index 0000000000..75ab7c690c
--- /dev/null
+++ b/volatility3/framework/symbols/windows/unloadedmodules-x64.json
@@ -0,0 +1,109 @@
+{
+    "symbols": {},
+    "enums": {},
+    "base_types": {
+        "unsigned long": {
+            "kind": "int",
+            "size": 4,
+            "signed": false,
+            "endian": "little"
+        },
+        "unsigned long long": {
+            "kind": "int",
+            "size": 8,
+            "signed": false,
+            "endian": "little"
+        },
+        "unsigned char": {
+            "kind": "char",
+            "size": 1,
+            "signed": false,
+            "endian": "little"
+        },
+        "pointer": {
+            "kind": "int",
+            "size": 8,
+            "signed": false,
+            "endian": "little"
+        },
+        "unsigned int": {
+            "kind": "int",
+            "size": 4,
+            "signed": false,
+            "endian": "little"
+        },
+        "unsigned short": {
+            "kind": "int",
+            "size": 2,
+            "signed": false,
+            "endian": "little"
+        },
+        "long": {
+            "kind": "int",
+            "size": 4,
+            "signed": false,
+            "endian": "little"
+        }
+    },
+    "user_types": {
+        "_UNLOADED_DRIVER": {
+            "fields": {
+                "Name": {
+                    "type": {
+                        "kind": "struct",
+                        "name": "nt_symbols!_UNICODE_STRING"
+                    },
+                    "offset": 0
+                },
+                "StartAddress": {
+                    "type": {
+                        "kind": "base",
+                        "name": "unsigned long long"
+                    },
+                    "offset": 16
+                },
+                "EndAddress": {
+                    "type": {
+                        "kind": "base",
+                        "name": "unsigned long long"
+                    },
+                    "offset": 24
+                },
+                "CurrentTime": {
+                    "type": {
+                        "kind": "base",
+                        "name": "unsigned long long"
+                    },
+                    "offset": 32
+                }
+            },
+            "kind": "struct",
+            "size": 40
+        },
+        "_UNLOADED_DRIVERS": {
+            "fields": {
+                "UnloadedDrivers": {
+                    "offset": 0,
+                    "type": {
+                        "count": 1,
+                        "kind": "array",
+                        "subtype": {
+                            "kind": "struct",
+                            "name": "_UNLOADED_DRIVER"
+                        }
+                    }
+                }
+            },
+            "kind": "struct",
+            "size": 8
+        }
+    },
+    "metadata": {
+        "producer": {
+            "version": "0.0.1",
+            "name": "Dave Lassalle by hand",
+            "datetime": "2024-06-19T17:57:16.394003"
+        },
+        "format": "4.0.0"
+    }
+}
\ No newline at end of file
diff --git a/volatility3/framework/symbols/windows/unloadedmodules-x86.json b/volatility3/framework/symbols/windows/unloadedmodules-x86.json
new file mode 100644
index 0000000000..ff9e78965b
--- /dev/null
+++ b/volatility3/framework/symbols/windows/unloadedmodules-x86.json
@@ -0,0 +1,109 @@
+{
+    "symbols": {},
+    "enums": {},
+    "base_types": {
+        "unsigned long": {
+            "kind": "int",
+            "size": 4,
+            "signed": false,
+            "endian": "little"
+        },
+        "unsigned long long": {
+            "kind": "int",
+            "size": 8,
+            "signed": false,
+            "endian": "little"
+        },
+        "unsigned char": {
+            "kind": "char",
+            "size": 1,
+            "signed": false,
+            "endian": "little"
+        },
+        "pointer": {
+            "kind": "int",
+            "size": 8,
+            "signed": false,
+            "endian": "little"
+        },
+        "unsigned int": {
+            "kind": "int",
+            "size": 4,
+            "signed": false,
+            "endian": "little"
+        },
+        "unsigned short": {
+            "kind": "int",
+            "size": 2,
+            "signed": false,
+            "endian": "little"
+        },
+        "long": {
+            "kind": "int",
+            "size": 4,
+            "signed": false,
+            "endian": "little"
+        }
+    },
+    "user_types": {
+        "_UNLOADED_DRIVER": {
+            "fields": {
+                "Name": {
+                    "type": {
+                        "kind": "struct",
+                        "name": "nt_symbols!_UNICODE_STRING"
+                    },
+                    "offset": 0
+                },
+                "StartAddress": {
+                    "type": {
+                        "kind": "base",
+                        "name": "unsigned long"
+                    },
+                    "offset": 8
+                },
+                "EndAddress": {
+                    "type": {
+                        "kind": "base",
+                        "name": "unsigned long"
+                    },
+                    "offset": 12
+                },
+                "CurrentTime": {
+                    "type": {
+                        "kind": "base",
+                        "name": "unsigned long long"
+                    },
+                    "offset": 16
+                }
+            },
+            "kind": "struct",
+            "size": 24
+        },
+        "_UNLOADED_DRIVERS": {
+            "fields": {
+                "UnloadedDrivers": {
+                    "offset": 0,
+                    "type": {
+                        "count": 1,
+                        "kind": "array",
+                        "subtype": {
+                            "kind": "struct",
+                            "name": "_UNLOADED_DRIVER"
+                        }
+                    }
+                }
+            },
+            "kind": "struct",
+            "size": 4
+        }
+    },
+    "metadata": {
+        "producer": {
+            "version": "0.0.1",
+            "name": "Dave Lassalle by hand",
+            "datetime": "2024-06-19T17:57:16.394003"
+        },
+        "format": "4.0.0"
+    }
+}
\ No newline at end of file
diff --git a/volatility3/framework/symbols/windows/versions.py b/volatility3/framework/symbols/windows/versions.py
index e1e74afc05..495655681b 100644
--- a/volatility3/framework/symbols/windows/versions.py
+++ b/volatility3/framework/symbols/windows/versions.py
@@ -114,6 +114,24 @@ def __call__(
     ],
 )
 
+is_windows_xp_sp2 = OsDistinguisher(
+    version_check=lambda x: (5, 1) <= x < (5, 2),
+    fallback_checks=[
+        ("KdCopyDataBlock", None, False),
+        ("_MMFREE_POOL_ENTRY", None, False),
+        ("_HANDLE_TABLE", "HandleCount", True),
+    ],
+)
+
+is_windows_xp_sp3 = OsDistinguisher(
+    version_check=lambda x: (5, 1) <= x < (5, 2),
+    fallback_checks=[
+        ("KdCopyDataBlock", None, False),
+        ("_MMFREE_POOL_ENTRY", None, True),
+        ("_HANDLE_TABLE", "HandleCount", True),
+    ],
+)
+
 is_xp_or_2003 = OsDistinguisher(
     version_check=lambda x: (5, 1) <= x < (6, 0),
     fallback_checks=[
@@ -122,6 +140,15 @@ def __call__(
     ],
 )
 
+is_2003 = OsDistinguisher(
+    version_check=lambda x: (5, 2) <= x < (5, 3),
+    fallback_checks=[
+        ("KdCopyDataBlock", None, False),
+        ("_HANDLE_TABLE", "HandleCount", True),
+        ("_MM_AVL_TABLE", None, True),
+    ],
+)
+
 is_win10_up_to_15063 = OsDistinguisher(
     version_check=lambda x: (10, 0) <= x < (10, 0, 15063),
     fallback_checks=[
@@ -141,6 +168,15 @@ def __call__(
     ],
 )
 
+is_win10_15063_or_later = OsDistinguisher(
+    version_check=lambda x: x >= (10, 0, 15063),
+    fallback_checks=[
+        ("ObHeaderCookie", None, True),
+        ("_HANDLE_TABLE", "HandleCount", False),
+        ("_EPROCESS", "KeepAliveCounter", False),
+    ],
+)
+
 is_win10_16299_or_later = OsDistinguisher(
     version_check=lambda x: x >= (10, 0, 16299),
     fallback_checks=[
diff --git a/volatility3/symbols/generic/vmcs/haswell-architecture.json b/volatility3/symbols/generic/vmcs/haswell-architecture.json
new file mode 100644
index 0000000000..33b2e55d88
--- /dev/null
+++ b/volatility3/symbols/generic/vmcs/haswell-architecture.json
@@ -0,0 +1,131 @@
+{
+  "base_types": {
+    "pointer": {
+      "endian": "little",
+      "kind": "int",
+      "signed": false,
+      "size": 8
+    },
+    "unsigned char": {
+      "endian": "little",
+      "kind": "int",
+      "signed": false,
+      "size": 1
+    },
+    "unsigned long": {
+      "endian": "little",
+      "kind": "int",
+      "signed": false,
+      "size": 4
+    },
+    "unsigned long long": {
+      "endian": "little",
+      "kind": "int",
+      "signed": false,
+      "size": 8
+    },
+    "unsigned short": {
+      "endian": "little",
+      "kind": "int",
+      "signed": false,
+      "size": 2
+    }
+  },
+  "enums": {},
+  "metadata": {
+    "format": "6.1.0",
+    "producer": {
+      "datetime": "2021-07-31T17:37:28.313255",
+      "name": "vmextract-by-hand",
+      "version": "0.0.1"
+    }
+  },
+  "symbols": {
+    "revision_id": {
+      "address": 0,
+      "constant_data": "MTg="
+    }
+  },
+  "user_types": {
+    "_VMCS": {
+      "fields": {
+        "ept": {
+          "offset": 320,
+          "type": {
+            "kind": "struct",
+            "name": "unsigned long long"
+          }
+        },
+        "executive_vmcs_ptr": {
+          "offset": 208,
+          "type": {
+            "kind": "struct",
+            "name": "unsigned long long"
+          }
+        },
+        "guest_cr3": {
+          "offset": 528,
+          "type": {
+            "kind": "struct",
+            "name": "unsigned long long"
+          }
+        },
+        "guest_cr4": {
+          "offset": 536,
+          "type": {
+            "kind": "struct",
+            "name": "unsigned long long"
+          }
+        },
+        "guest_pdpte": {
+          "offset": 544,
+          "type": {
+            "count": 4,
+            "kind": "array",
+            "subtype": {
+              "kind": "struct",
+              "name": "unsigned long long"
+            }
+          }
+        },
+        "guest_physical_addr": {
+          "offset": 328,
+          "type": {
+            "kind": "struct",
+            "name": "unsigned long long"
+          }
+        },
+        "host_cr3": {
+          "offset": 816,
+          "type": {
+            "kind": "struct",
+            "name": "unsigned long long"
+          }
+        },
+        "host_cr4": {
+          "offset": 824,
+          "type": {
+            "kind": "struct",
+            "name": "unsigned long long"
+          }
+        },
+        "vmcs_link_ptr": {
+          "offset": 248,
+          "type": {
+            "kind": "struct",
+            "name": "unsigned long long"
+          }
+        },
+        "vpid": {
+          "offset": 206,
+          "type": {
+            "kind": "struct",
+            "name": "unsigned short"
+          }
+        }
+      },
+      "kind": "struct",
+      "size": 4096
+    }
+  }
+}
\ No newline at end of file
diff --git a/volatility3/symbols/generic/vmcs/skylake-architecture.json b/volatility3/symbols/generic/vmcs/skylake-architecture.json
new file mode 100644
index 0000000000..78b110d94e
--- /dev/null
+++ b/volatility3/symbols/generic/vmcs/skylake-architecture.json
@@ -0,0 +1,131 @@
+{
+    "base_types": {
+        "pointer": {
+            "endian": "little",
+            "kind": "int",
+            "signed": false,
+            "size": 8
+        },
+        "unsigned char": {
+            "endian": "little",
+            "kind": "int",
+            "signed": false,
+            "size": 1
+        },
+        "unsigned long": {
+            "endian": "little",
+            "kind": "int",
+            "signed": false,
+            "size": 4
+        },
+        "unsigned long long": {
+            "endian": "little",
+            "kind": "int",
+            "signed": false,
+            "size": 8
+        },
+        "unsigned short": {
+            "endian": "little",
+            "kind": "int",
+            "signed": false,
+            "size": 2
+        }
+    },
+    "enums": {},
+    "metadata": {
+        "format": "6.1.0",
+        "producer": {
+            "datetime": "2021-07-16T16:21:01.062423",
+            "name": "vmextract-by-hand",
+            "version": "0.0.1"
+        }
+    },
+    "symbols": {
+        "revision_id": {
+            "address": 0,
+            "constant_data": "NA=="
+        }
+    },
+    "user_types": {
+        "_VMCS": {
+            "fields": {
+                "ept": {
+                    "offset": 320,
+                    "type": {
+                        "kind": "struct",
+                        "name": "unsigned long long"
+                    }
+                },
+                "executive_vmcs_ptr": {
+                    "offset": 208,
+                    "type": {
+                        "kind": "struct",
+                        "name": "unsigned long long"
+                    }
+                },
+                "guest_cr3": {
+                    "offset": 528,
+                    "type": {
+                        "kind": "struct",
+                        "name": "unsigned long long"
+                    }
+                },
+                "guest_cr4": {
+                    "offset": 536,
+                    "type": {
+                        "kind": "struct",
+                        "name": "unsigned long long"
+                    }
+                },
+                "guest_pdpte": {
+                    "offset": 544,
+                    "type": {
+                        "count": 4,
+                        "kind": "array",
+                        "subtype": {
+                            "kind": "struct",
+                            "name": "unsigned long long"
+                        }
+                    }
+                },
+                "guest_physical_addr": {
+                    "offset": 328,
+                    "type": {
+                        "kind": "struct",
+                        "name": "unsigned long long"
+                    }
+                },
+                "host_cr3": {
+                    "offset": 816,
+                    "type": {
+                        "kind": "struct",
+                        "name": "unsigned long long"
+                    }
+                },
+                "host_cr4": {
+                    "offset": 824,
+                    "type": {
+                        "kind": "struct",
+                        "name": "unsigned long long"
+                    }
+                },
+                "vmcs_link_ptr": {
+                    "offset": 248,
+                    "type": {
+                        "kind": "struct",
+                        "name": "unsigned long long"
+                    }
+                },
+                "vpid": {
+                    "offset": 206,
+                    "type": {
+                        "kind": "struct",
+                        "name": "unsigned short"
+                    }
+                }
+            },
+            "kind": "struct",
+            "size": 4096
+        }
+    }
+}
diff --git a/volshell.py b/volshell.py
index 71d35a47c9..65b11885e1 100755
--- a/volshell.py
+++ b/volshell.py
@@ -1,4 +1,5 @@
 #!/usr/bin/env python3
+# PYTHON_ARGCOMPLETE_OK
 
 # 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


Test patch:
diff --git a/.github/workflows/test.yaml b/.github/workflows/test.yaml
index b1a9dd31bd..55b2e4b602 100644
--- a/.github/workflows/test.yaml
+++ b/.github/workflows/test.yaml
@@ -8,9 +8,9 @@ jobs:
       matrix:
         python-version: ["3.7"]
     steps:
-    - uses: actions/checkout@v3
+    - uses: actions/checkout@v4
     - name: Set up Python ${{ matrix.python-version }}
-      uses: actions/setup-python@v4
+      uses: actions/setup-python@v5
       with:
         python-version: ${{ matrix.python-version }}
 
@@ -18,13 +18,12 @@ jobs:
       run: |
         python -m pip install --upgrade pip
         pip install Cmake
-        pip install setuptools wheel
+        pip install build
         pip install -r ./test/requirements-testing.txt
 
     - name: Build PyPi packages
       run: |
-        python setup.py sdist --formats=gztar,zip
-        python setup.py bdist_wheel
+        python -m build
 
     - name: Download images
       run: |