-
Notifications
You must be signed in to change notification settings - Fork 47
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
5 changed files
with
97 additions
and
3 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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, | ||
) |
Git LFS file not shown
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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", | ||
] |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters