Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 9 additions & 0 deletions dissect/target/volumes/bde.py
Original file line number Diff line number Diff line change
Expand Up @@ -86,6 +86,13 @@
if not is_wildcard:
log.exception("Failed to unlock BDE volume with BEK file %s", bek_file)

def unlock_with_fvek(self, raw_key: bytes, is_wildcard: bool = False) -> None:
try:
self.bde.unlock_with_fvek(raw_key)
except ValueError as e:
if not is_wildcard:
log.exception("Failed to unlock BDE volume with raw FVEK key (%r): %s", raw_key, e)

Check warning on line 94 in dissect/target/volumes/bde.py

View check run for this annotation

Codecov / codecov/patch

dissect/target/volumes/bde.py#L92-L94

Added lines #L92 - L94 were not covered by tests

def unlock_volume(self) -> AlignedStream:
if self.bde.has_clear_key():
self.bde.unlock_with_clear_key()
Expand All @@ -101,6 +108,8 @@
elif key.key_type == KeyType.FILE:
bek_file = pathlib.Path(key.value)
self.unlock_with_bek_file(bek_file, key.is_wildcard)
elif key.key_type == KeyType.RAW:
self.unlock_with_fvek(key.value, key.is_wildcard)

if self.bde.unlocked:
log.info("Volume %s with identifiers %s unlocked with %s", self.fh, identifiers, key)
Expand Down
6 changes: 3 additions & 3 deletions pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -56,8 +56,8 @@ full = [
"dissect.extfs>=3,<4",
"dissect.fat>=3,<4",
"dissect.ffs>=3,<4",
"dissect.fve>=4,<5; platform_system != 'Windows' or platform_python_implementation != 'PyPy'",
"dissect.jffs>=1.5.dev,<2", # TODO: update on release
"dissect.fve>=4.2.dev,<5; platform_system != 'Windows' or platform_python_implementation != 'PyPy'", # TODO: update on release
"dissect.jffs>=1.5.dev,<2", # TODO: update on release
"dissect.ole>=3,<4",
"dissect.shellitem>=3,<4",
"dissect.squashfs>=1,<2",
Expand Down Expand Up @@ -93,7 +93,7 @@ dev = [
"dissect.extfs[dev]>=3.0.dev,<4.0.dev",
"dissect.fat[dev]>=3.0.dev,<4.0.dev",
"dissect.ffs[dev]>=3.0.dev,<4.0.dev",
"dissect.fve[dev]>=4.0.dev,<5.0.dev; platform_system != 'Windows' or platform_python_implementation != 'PyPy'",
"dissect.fve[dev]>=4.2.dev,<5.0.dev; platform_system != 'Windows' or platform_python_implementation != 'PyPy'",
"dissect.hypervisor[dev]>=3.0.dev,<4.0.dev",
"dissect.jffs[dev]>=1.5.dev,<2.0.dev",
"dissect.ntfs[dev]>=3.4.dev,<4.0.dev",
Expand Down
51 changes: 43 additions & 8 deletions tests/volumes/test_bde.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,11 @@
from typing import BinaryIO

import pytest

from dissect.target import volume
from dissect.target.helpers import keychain
from dissect.target.target import Target
from tests._utils import absolute_path

try:
from dissect.target.volumes.bde import BitlockerVolumeSystem
Expand All @@ -11,18 +15,17 @@
HAS_DISSECT_FVE = False


from tests._utils import absolute_path


@pytest.fixture
def encrypted_volume():
def encrypted_volume() -> BinaryIO:
data_file = "_data/volumes/bde/enc-volume.bin"
with open(absolute_path(data_file), "rb") as f:
yield f


@pytest.mark.skipif(not HAS_DISSECT_FVE, reason="requires dissect.fve")
def test_bde_volume_failure(target_win, encrypted_volume):
def test_bde_volume_failure(target_win: Target, encrypted_volume: BinaryIO) -> None:
"""Test if not providing a key to decrypt a BDE volume results in no mounted volume."""

enc_vol = volume.Volume(encrypted_volume, 1, 0, None, None, None, disk=encrypted_volume)
target_win.volumes.add(enc_vol)
target_win.volumes.apply()
Expand All @@ -32,9 +35,12 @@ def test_bde_volume_failure(target_win, encrypted_volume):


@pytest.mark.skipif(not HAS_DISSECT_FVE, reason="requires dissect.fve")
def test_bde_volume_with_recovery_key(target_win, encrypted_volume):
def test_bde_volume_with_recovery_key(target_win: Target, encrypted_volume: BinaryIO) -> None:
"""Test if we can decrypt a BDE volume using a recovery key."""

recovery_key = "272316-265804-640728-713570-509047-503305-045837-324731"

keychain.KEYCHAIN.clear()
keychain.register_key(
keychain.KeyType.RECOVERY_KEY,
recovery_key,
Expand All @@ -59,10 +65,13 @@ def test_bde_volume_with_recovery_key(target_win, encrypted_volume):


@pytest.mark.skipif(not HAS_DISSECT_FVE, reason="requires dissect.fve")
def test_bde_volume_with_passphrase(target_win, encrypted_volume):
def test_bde_volume_with_passphrase(target_win: Target, encrypted_volume: BinaryIO) -> None:
"""Test if we can decrypt a BDE volume using a passphrase."""

identifier = "B6AD258A-2725-4A42-93C6-844478BF7A90"
passphrase = "Password1234"

keychain.KEYCHAIN.clear()
keychain.register_key(
keychain.KeyType.PASSPHRASE,
passphrase,
Expand All @@ -87,7 +96,10 @@ def test_bde_volume_with_passphrase(target_win, encrypted_volume):


@pytest.mark.skipif(not HAS_DISSECT_FVE, reason="requires dissect.fve")
def test_bde_volume_with_wildcard_key(target_win, encrypted_volume):
def test_bde_volume_with_wildcard_key(target_win: Target, encrypted_volume: BinaryIO) -> None:
"""Test if we can decrypt a BDE volume using a wildcard keychain key."""

keychain.KEYCHAIN.clear()
keychain.register_wildcard_value("Password1234")

enc_vol = volume.Volume(encrypted_volume, 1, 0, None, None, None, disk=encrypted_volume)
Expand All @@ -104,3 +116,26 @@ def test_bde_volume_with_wildcard_key(target_win, encrypted_volume):
target_win.fs.mount("e:/", dec_vol.fs)

assert target_win.fs.path("e:/test-folder/test-file-2.txt").exists()


@pytest.mark.skipif(not HAS_DISSECT_FVE, reason="requires dissect.fve")
def test_bde_volume_with_raw_key(target_win: Target, encrypted_volume: BinaryIO) -> None:
"""Test if we can decrypt a BDE volume using a raw FVEK key."""

keychain.KEYCHAIN.clear()
keychain.register_wildcard_value("ab60a58f1a0b60be91ffa2b40ec338a072a011302a8ff58fc45eee742711dc7f")

enc_vol = volume.Volume(encrypted_volume, 1, 0, None, None, None, disk=encrypted_volume)
target_win.volumes.add(enc_vol)
target_win.volumes.apply()

assert len(target_win.volumes) == 2
assert enc_vol in target_win.volumes

dec_vol = next(v for v in target_win.volumes if v != enc_vol)

# virtual fs + ntfs fs
assert len(target_win.filesystems) == 2
target_win.fs.mount("e:/", dec_vol.fs)

assert target_win.fs.path("e:/test-folder/test-file-2.txt").exists()
Loading