Containers#
Containers in dissect.target
are the abstraction layer for anything that looks (or should look) like a raw disk.
For example, VMware VMDK or Microsoft Hyper-V VHD(X) files may be custom file formats, but in the end these are merely containers of the raw disk(s) inside.
The container abstraction layer in dissect.target
makes working with these different disk containers easy. Once
opened, all containers behave as a binary file-like object. This means that there’s no special API for working with
containers, if you know how to read from a file in Python, you’ll know how to read from a container.
See also
To see how to open a container in Python, continue reading here.
View all available container implementations at dissect.target.containers
.
Writing your own#
There are a few methods of using your own container implementation in dissect.target
:
Specify the path to your implementation(s) using the
DISSECT_PLUGINS
environment variable.Specify the path to your implementation(s) using the
--plugin-path
argument with the various Dissect Tools.Add a new implementation in the
dissect.target
source tree atdissect/target/containers
.
The last method requires you to have a source checkout and working development setup of dissect.target
.
This is the recommended method if you intend to contribute your container back to the project.
See also
Read more about using your own modules in dissect.target
at Loading your own modules.
Interested in developing for Dissect? Read more at Developing for Dissect.
Regardless of which method you use, you can use the boilerplate below. Do keep in mind that the final line is only
required if you’re using either of the DISSECT_PLUGINS
or --plugin-path
options!
import io
from pathlib import Path
from typing import BinaryIO, Union
from dissect.target.container import Container, register
class MyContainer(Container):
def __init__(self, fh: Union[BinaryIO, Path], *args, **kwargs):
# Do your initialization here, for example, initialize a parser:
# self.vmdk = VMDK(fh)
# Call ``super().__init__`` with the original file-like object(s) and the container size
super().__init__(fh, size, *args, **kwargs)
@staticmethod
def detect_fh(fh: BinaryIO, original: Union[list, BinaryIO]) -> bool:
# Perform detection for your container from a binary file-like object here
# For example, check a specific magic header value
raise NotImplementedError()
@staticmethod
def detect_path(path: Path, original: Union[list, BinaryIO]) -> bool:
# Perform detection for your container from a Path object here
# For example, check a specific file extension
raise NotImplementedError()
def read(self, length: int) -> bytes:
# Perform a file read for ``length`` amount of bytes
raise NotImplementedError()
def seek(self, offset: int, whence: int = io.SEEK_SET) -> int:
# Perform a file seek here
raise NotImplementedError()
def tell(self) -> int:
# Perform a file tell here
raise NotImplementedError()
def close(self) -> None:
# Perform any close actions here
pass
# This line is necessary if your container is outside the ``dissect.target`` source tree!
register(__name__, MyContainer.__name__, internal=False)
See also
You can refer to the API documentation of the Container
class for more
documentation on the methods referenced here.
If you are placing your implementation in the dissect.target
source tree, you’ll need to register your implementation.
Do this by opening dissect/target/container.py
and add your implementation to the bottom by using
register()
:
register("mycontainer", "MyContainer")