:py:mod:`dissect.hypervisor.disk.asif` ====================================== .. py:module:: dissect.hypervisor.disk.asif Module Contents --------------- Classes ~~~~~~~ .. autoapisummary:: dissect.hypervisor.disk.asif.ASIF dissect.hypervisor.disk.asif.Directory dissect.hypervisor.disk.asif.Table dissect.hypervisor.disk.asif.DataStream .. py:class:: ASIF(fh: BinaryIO) Apple Sparse Image Format (ASIF) disk image. ASIF disk images are a virtual disk format introduced in macOS Tahoe. They can be used in Apple's Virtualization framework, as well as through Disk Utility. An ASIF file is pretty straight forward. There's a small header which, among some other details, contains two directory offsets. Each directory contains a list of tables, which in turn contain a list of data entries. Each data entry points to a chunk of data in the ASIF file. The chunk size is defined in the header and is typically 1 MiB. The chunk size is always a multiple of the block size, which is also defined in the header (typically 512 bytes). Each directory has a version number, and the directory with the highest version number is the active directory. This allows for atomic updates of the directory/table data. The maximum virtual disk size seems to be just under 4 PiB, with a small portion at the end reserved for metadata. The actual size of the virtual disk is defined in the header, as well as the maximum size the disk can grow to. The offset to the metadata block is typically ``(4 PiB - 1 chunk)``, meaning it's within the reserved area. The metadata block contains a small header and a plist. The plist should contain an ``internal metadata`` and ``user metadata`` dictionary. Besides a "stable uuid", it's unclear what the metadata is used for or how to set it. :param fh: File-like object containing the ASIF image. Resources: - Reversing ``diskimagescontroller`` - https://developer.apple.com/documentation/virtualization/vzdiskimagestoragedeviceattachment/ .. py:attribute:: fh .. py:attribute:: header .. py:attribute:: guid .. py:attribute:: block_size .. py:attribute:: chunk_size .. py:attribute:: size .. py:attribute:: max_size .. py:attribute:: directories .. py:attribute:: active_directory .. py:attribute:: metadata_header :value: None .. py:attribute:: metadata :type: dict[str, Any] .. py:property:: internal_metadata :type: dict[str, Any] Get internal metadata from the ASIF image. :returns: A dictionary containing the internal metadata. .. py:property:: user_metadata :type: dict[str, Any] Get user metadata from the ASIF image. :returns: A dictionary containing the user metadata. .. py:method:: open(reserved: bool = False) -> DataStream Open a stream to read the ASIF image data. :param reserved: Whether to allow reading into the reserved area of the ASIF image. :returns: A stream-like object that can be used to read the image data. .. py:class:: Directory(asif: ASIF, offset: int) ASIF Directory. A directory has a version (``uint64``) followed by a list of table entries (``uint64[]``). The version number is used to determine the active directory, with the highest version being the active one. Each table entry is a chunk number and points to a table in the ASIF image. :param asif: The ASIF image this directory belongs to. :param offset: Offset of the directory in the ASIF image. .. py:attribute:: asif .. py:attribute:: offset .. py:attribute:: version .. py:attribute:: table .. py:method:: __repr__() -> str .. py:property:: entries :type: list[int] List of table entries in the directory. .. py:class:: Table(directory: Directory, index: int) ASIF Table. A table contains a list of data entries (``uint64[]``). Each data entry is a chunk number and points to a chunk of data in the ASIF image. Each table covers a fixed amount of data in the virtual disk. Data entries have 55 bits usable for the chunk number and 9 bits reserved for flags. .. rubric :: Encoding .. code-block:: c 0b00000000 01111111 11111111 11111111 11111111 11111111 11111111 11111111 (chunk number) 0b00111111 10000000 00000000 00000000 00000000 00000000 00000000 00000000 (reserved) 0b01000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 (entry dirty) 0b10000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 (content dirty) :param directory: The directory this table belongs to. :param index: Index of the table in the directory. .. py:attribute:: asif .. py:attribute:: directory .. py:attribute:: index .. py:attribute:: offset .. py:attribute:: virtual_offset .. py:method:: __repr__() -> str .. py:property:: entries :type: list[int] List of data entries in the table. .. py:class:: DataStream(asif: ASIF, reserved: bool = False) Bases: :py:obj:`dissect.util.stream.AlignedStream` Stream to read data from an ASIF image. :param asif: The ASIF image to read from. :param reserved: Whether to allow reading into the reserved area of the ASIF image. .. py:attribute:: asif .. py:attribute:: reserved :value: False .. py:attribute:: directory