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
47 changes: 37 additions & 10 deletions dissect/target/loaders/kape.py
Original file line number Diff line number Diff line change
@@ -1,8 +1,11 @@
from __future__ import annotations

from pathlib import Path
from typing import TYPE_CHECKING
from typing import TYPE_CHECKING, Iterator

from dissect.target import filesystem, volume
from dissect.target.containers.vhdx import VhdxContainer
from dissect.target.filesystem import Filesystem
from dissect.target.loaders.dir import DirLoader, find_and_map_dirs, find_dirs
from dissect.target.plugin import OperatingSystem

Expand All @@ -15,6 +18,32 @@
USNJRNL_PATHS = ["$Extend/$J", "$Extend/$UsnJrnl$J"]


def open_vhdx(path: Path) -> Iterator[Filesystem]:
container = VhdxContainer(path)
volume_system = volume.open(container)
for vol in volume_system.volumes:
yield filesystem.open(vol)


def is_valid_kape_dir(path: Path) -> bool:
os_type, dirs = find_dirs(path)
if os_type == OperatingSystem.WINDOWS:
for dir_path in dirs:
for path in USNJRNL_PATHS:
if dir_path.joinpath(path).exists():
return True

return False

Check warning on line 36 in dissect/target/loaders/kape.py

View check run for this annotation

Codecov / codecov/patch

dissect/target/loaders/kape.py#L36

Added line #L36 was not covered by tests


def is_valid_kape_vhdx(path: Path) -> bool:
if path.suffix == ".vhdx":
for fs in open_vhdx(path):
return is_valid_kape_dir(fs.path())

return False

Check warning on line 44 in dissect/target/loaders/kape.py

View check run for this annotation

Codecov / codecov/patch

dissect/target/loaders/kape.py#L44

Added line #L44 was not covered by tests


class KapeLoader(DirLoader):
"""Load KAPE forensic image format files.

Expand All @@ -24,19 +53,17 @@

@staticmethod
def detect(path: Path) -> bool:
os_type, dirs = find_dirs(path)
if os_type == OperatingSystem.WINDOWS:
for dir_path in dirs:
for path in USNJRNL_PATHS:
if dir_path.joinpath(path).exists():
return True

return False
if path.is_dir():
return is_valid_kape_dir(path)
if path.suffix.lower() == ".vhdx":
return is_valid_kape_vhdx(path)

def map(self, target: Target) -> None:
path = self.path if self.path.is_dir() else next(open_vhdx(self.path)).path()

find_and_map_dirs(
target,
self.path,
path,
sds_path="$Secure_$SDS",
usnjrnl_path=USNJRNL_PATHS,
)
3 changes: 3 additions & 0 deletions tests/_data/loaders/kape/test.vhdx
Git LFS file not shown
17 changes: 16 additions & 1 deletion tests/loaders/test_kape.py
Original file line number Diff line number Diff line change
@@ -1,11 +1,13 @@
from pathlib import Path
from unittest.mock import patch

from dissect.target import Target
from dissect.target.loaders.kape import KapeLoader
from tests._utils import absolute_path, mkdirs


@patch("dissect.target.filesystems.dir.DirectoryFilesystem.ntfs", None, create=True)
def test_kape_loader(target_bare, tmp_path):
def test_kape_dir_loader(target_bare, tmp_path):
root = tmp_path
mkdirs(root, ["C/windows/system32", "C/$Extend", "D/test", "E/test"])

Expand Down Expand Up @@ -37,3 +39,16 @@ def test_kape_loader(target_bare, tmp_path):
# The 3 found drive letters + sysvol + the fake NTFS filesystem at /$fs$
assert len(target_bare.fs.mounts) == 5
assert len(list(target_bare.fs.mounts["c:"].ntfs.usnjrnl.records())) == 1


def test_kape_vhdx_loader(target_bare: Target) -> None:
p = Path(absolute_path("_data/loaders/kape/test.vhdx"))

assert KapeLoader.detect(p)

loader = KapeLoader(p)
loader.map(target_bare)
target_bare.apply()

assert "sysvol" in target_bare.fs.mounts
assert "c:" in target_bare.fs.mounts
Loading