Skip to content

Commit

Permalink
add parallels child detection
Browse files Browse the repository at this point in the history
  • Loading branch information
JSCU-CNI committed Sep 18, 2024
1 parent c5bf1ed commit 95bbfd3
Show file tree
Hide file tree
Showing 5 changed files with 97 additions and 3 deletions.
67 changes: 67 additions & 0 deletions dissect/target/plugins/child/parallels.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
from typing import Iterator

from dissect.target.exceptions import UnsupportedPluginError
from dissect.target.helpers.fsutil import TargetPath
from dissect.target.helpers.record import ChildTargetRecord
from dissect.target.plugin import ChildTargetPlugin
from dissect.target.target import Target

PARALLELS_USER_PATHS = [
"Parallels",
"Documents/Parallels",
"Library/Group Containers/*.com.parallels.desktop.appstore/Shared/Parallels",
]

PARALLELS_SYSTEM_PATHS = [
"/Users/Shared/Parallels",
]


def find_pvms(target: Target) -> Iterator[TargetPath]:
"""Finds virtual machines located in default folders on a MacOS target.
Resources:
- https://kb.parallels.com/117333
"""
for user_details in target.user_details.all_with_home():
for parallels_path in PARALLELS_SYSTEM_PATHS:
if (path := target.fs.path(parallels_path)).exists():
yield from iter_vms(path)

for parallels_path in PARALLELS_USER_PATHS:
if "*" in parallels_path:
start_path, pattern = parallels_path.split("*", 1)
for path in user_details.home_path.joinpath(start_path).rglob("*" + pattern):
yield from iter_vms(path)
else:
if (path := user_details.home_path.joinpath(parallels_path)).exists():
yield from iter_vms(path)


def iter_vms(path: TargetPath) -> Iterator[TargetPath]:
"""Glob for .pvm folders in the provided folder."""
for file in path.rglob("*.pvm"):
if file.is_dir():
yield file


class ParallelsChildTargetPlugin(ChildTargetPlugin):
"""Child target plugin that yields Parallels Desktop VM files."""

__type__ = "parallels"

def __init__(self, target: Target):
super().__init__(target)
self.pvms = list(find_pvms(target))

def check_compatible(self) -> None:
if not self.pvms:
raise UnsupportedPluginError("No Parallels pvm file(s) found")

def list_children(self):
for pvm in self.pvms:
yield ChildTargetRecord(
type=self.__type__,
path=pvm,
_target=self.target,
)
4 changes: 2 additions & 2 deletions tests/_data/plugins/os/unix/bsd/osx/_os/dissect.plist
Git LFS file not shown
2 changes: 2 additions & 0 deletions tests/conftest.py
Original file line number Diff line number Diff line change
Expand Up @@ -455,6 +455,8 @@ def target_osx_users(target_osx: Target, fs_osx: VirtualFilesystem) -> Iterator[
test = absolute_path("_data/plugins/os/unix/bsd/osx/_os/test.plist")
fs_osx.map_file("/var/db/dslocal/nodes/Default/users/_test.plist", test)

fs_osx.makedirs("/Users/dissect")

yield target_osx


Expand Down
25 changes: 25 additions & 0 deletions tests/plugins/child/test_parallels.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
from dissect.target.filesystem import VirtualFilesystem
from dissect.target.plugins.child.parallels import ParallelsChildTargetPlugin
from dissect.target.target import Target


def test_parallels_child_detection(target_osx_users: Target, fs_osx: VirtualFilesystem) -> None:
"""test if we correctly find Parallels child VMs on MacOS targets."""

fs_osx.makedirs("/Users/dissect/Parallels/Windows 11.pvm")
fs_osx.makedirs("/Users/dissect/Documents/Parallels/Windows 10.pvm")
fs_osx.makedirs(
"/Users/dissect/Library/Group Containers/someversionnumber.com.parallels.desktop.appstore/Shared/Parallels/Windows 8.pvm"
)
fs_osx.makedirs("/Users/Shared/Parallels/Windows 7.pvm")

target_osx_users.add_plugin(ParallelsChildTargetPlugin)
children = list(target_osx_users.list_children())

assert len(children) == 4
assert [c.path for c in children] == [
"/Users/Shared/Parallels/Windows 7.pvm",
"/Users/dissect/Parallels/Windows 11.pvm",
"/Users/dissect/Documents/Parallels/Windows 10.pvm",
"/Users/dissect/Library/Group Containers/someversionnumber.com.parallels.desktop.appstore/Shared/Parallels/Windows 8.pvm",
]
2 changes: 1 addition & 1 deletion tests/plugins/os/unix/bsd/osx/test__os.py
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ def test_unix_bsd_osx_os(target_osx_users, fs_osx):

assert dissect_user.name == "_dissect"
assert dissect_user.passwd == "*"
assert dissect_user.home == "/var/empty"
assert dissect_user.home == "/Users/dissect"
assert dissect_user.shell == "/usr/bin/false"
assert dissect_user.source == "/var/db/dslocal/nodes/Default/users/_dissect.plist"

Expand Down

0 comments on commit 95bbfd3

Please sign in to comment.