Windows.truecrypt.Passphrase plugin failed
Describe the bug A clear and concise description of what the bug is.
I tried using the windows.truecrypt.Passphrase plugin to find encrypted disk password using volatility3 2.27.1 a this error appeared in command output.
Context
Volatility Version: 2.27.1
Operating System: Parrots Security OS - HackTheBox
Python Version: 3.11.2
Suspected Operating System:
Command: #vol -f Snapshot14_1061.vmem windows.truecrypt.Passphrase
To Reproduce Steps to reproduce the behavior:
- Use command '...'
- See error
Expected behavior A clear and concise description of what you expected to happen.
- Show the passphrase
Example output
Please copy and paste the text demonstrating the issue, ideally with verbose output turned on (vol.py -vvv ...).
WARNING volatility3.framework.layers.vmware: No metadata file found alongside VMEM file. A VMSS or VMSN file may be required to correctly process a VMEM file. These should be placed in the same directory with the same file name, e.g. Snapshot14_1609164553061.vmem and Snapshot14_161.vmss.
Progress: 100.00 PDB scanning finished
Offset Length Password
Traceback (most recent call last):
File "/usr/local/bin/vol", line 8, in <module>
sys.exit(main())
^^^^^^
File "/home/hackerone/volatility3/volatility3/cli/__init__.py", line 934, in main
CommandLine().run()
File "/home/hackerone/volatility3/volatility3/cli/__init__.py", line 522, in run
renderer.render(grid)
File "/home/hackerone/volatility3/volatility3/cli/text_renderer.py", line 329, in render
grid.populate(visitor, outfd)
File "/home/hackerone/volatility3/volatility3/framework/renderers/__init__.py", line 318, in populate
for level, item in self._generator:
File "/home/hackerone/volatility3/volatility3/framework/plugins/windows/truecrypt.py", line 137, in _generator
for offset, password in self.scan_module(
File "/home/hackerone/volatility3/volatility3/framework/plugins/windows/truecrypt.py", line 82, in scan_module
raise ValueError("PE data section not DWORD-aligned!")
ValueError: PE data section not DWORD-aligned!
Text is preferred to screenshots for searching and to talk about specific parts of the output.
Additional information Add any other information about the problem here.
Are you attempting to solve a particular HTB room/challenge, or are you just using the the HTB flavour of Parrot? Do you have an accompanying vmss/vmsn file alongside your snapshot? Is it named exactly the same except for the extension? Can you show the contents of the truecrypt plugin (cat truecrypt.py) - there are some potential compatibility/config modifications you may need to make. Are you able to share the sample?
Full Output:
┌─[root@parrot]─[/home/hackerone/volatility3/volatility3/framework/plugins/windows]
└──╼ #cat truecrypt.py
# 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 Generator, Iterable, List, Tuple
from volatility3.framework import constants, interfaces, objects, renderers
from volatility3.framework.configuration import requirements
from volatility3.framework.interfaces import configuration
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.extensions import pe
from volatility3.plugins.windows import modules
vollog = logging.getLogger(__name__)
class Passphrase(interfaces.plugins.PluginInterface):
"""TrueCrypt Cached Passphrase Finder"""
_version = (0, 1, 0)
_required_framework_version = (2, 5, 2)
@classmethod
def get_requirements(cls) -> List[configuration.RequirementInterface]:
return [
requirements.ModuleRequirement(
"kernel",
description="Windows kernel",
architectures=["Intel32", "Intel64"],
),
requirements.VersionRequirement(
name="modules", component=modules.Modules, version=(3, 0, 0)
),
requirements.IntRequirement(
name="min-length",
description="Minimum length of passphrases to identify",
default=5,
optional=True,
),
]
def scan_module(
self, module_base: int, layer_name: str
) -> Generator[Tuple[int, str], None, None]:
"""Scans the TrueCrypt kernel module for cached passphrases.
Args:
module_base: the module's DLL base
layer_name: the name of the layer in which the module resides
Generates:
A tuple of the offset at which a password is found, and the password
"""
pe_table_name = intermed.IntermediateSymbolTable.create(
self.context, self.config_path, "windows", "pe", class_types=pe.class_types
)
dos_header: pe.IMAGE_DOS_HEADER = self.context.object(
pe_table_name + constants.BANG + "_IMAGE_DOS_HEADER",
layer_name,
module_base,
)
data_section: objects.StructType = next(
sec
for sec in dos_header.get_nt_header().get_sections()
if array_to_string(sec.Name) == ".data"
)
base: int = data_section.VirtualAddress + module_base
size: int = data_section.Misc.VirtualSize
# Looking at `Length` in TrueCrypt/Common/Password.h::Password struct
DWORD_SIZE_BYTES: int = 4
format = objects.DataFormatInfo(
length=DWORD_SIZE_BYTES, byteorder="little", signed=True
)
int32 = objects.templates.ObjectTemplate(
objects.Integer, pe_table_name + constants.BANG + "int", data_format=format
)
count, not_aligned = divmod(size, DWORD_SIZE_BYTES)
if not_aligned:
raise ValueError("PE data section not DWORD-aligned!")
lengths = self.context.object(
pe_table_name + constants.BANG + "array",
layer_name,
base,
count=count,
subtype=int32,
)
min_length = self.config.get("min-length")
for length in lengths:
# TrueCrypt maximum password length is 64
# (see TrueCrypt/Common/Password.h)
if not min_length <= length <= 64:
continue
offset = length.vol["offset"] + DWORD_SIZE_BYTES
passphrase: objects.Bytes = self.context.object(
pe_table_name + constants.BANG + "bytes",
layer_name,
offset,
length=length,
)
# TrueCrypt/Common/Password.c permits chars in the range
# [0x20, 0x7F).
if not all(0x20 <= c < 0x7F for c in passphrase):
continue
# TrueCrypt/Common/Password.h::Password struct is padded with
# 3 zero bytes to keep 64-byte alignment.
buf: objects.Bytes = self.context.object(
pe_table_name + constants.BANG + "bytes",
layer_name,
offset + length + 1, # +1 for '\0'-terminated password string
length=3,
)
if any(buf):
continue
# Password found.
yield offset, passphrase.decode(encoding="ascii")
def _generator(self):
kernel = self.context.modules[self.config["kernel"]]
mods: Iterable[interfaces.objects.ObjectInterface] = (
modules.Modules.list_modules(self.context, self.config["kernel"])
)
try:
truecrypt_module_base = next(
mod.DllBase
for mod in mods
if mod.BaseDllName.get_string().lower() == "truecrypt.sys"
)
except StopIteration:
vollog.warning(
"Truecrypt module not found in the modules list. Unable to proceed."
)
return
for offset, password in self.scan_module(
truecrypt_module_base, kernel.layer_name
):
yield (0, (format_hints.Hex(offset), len(password), password))
def run(self) -> renderers.TreeGrid:
return renderers.TreeGrid(
[
("Offset", format_hints.Hex),
("Length", int),
("Password", str),
],
self._generator(),
)
Hey @NaftalidaCosta I faced the same error when doing a room on TryHackMe, I used Gemini Pro to fix the code, which fixed it and it's working for me now: Here's the fixed version: https://gist.github.com/vivxk/1c01ee25018dcee7ee7e22c236f376bb
Replace it with truecrypt.py under : volatility3/volatility3/framework/plugins/windows/truecrypt.py
@vivxk Thanks for that I really appreciate your help. Can I share your respository?
vol -f /home/hackerone/volatility3memory/Snapshot14_1061.vmem windows.truecrypt.Passphrase
Volatility 3 Framework 2.27.1
WARNING volatility3.framework.layers.vmware: No metadata file found alongside VMEM file. A VMSS or VMSN file may be required to correctly process a VMEM file. These should be placed in the same directory with the same file name, e.g. Snapshot14_1061.vmem and Snapshot14_1061.vmss.
Progress: 100.00 PDB scanning finished
Offset Length Password
5xf9500512dee2 8 superman
Sure @NaftalidaCosta