dissect.vmfs.descriptor¶
Module Contents¶
Classes¶
Directory entry representation. |
|
VMFS file descriptor implementation. |
|
VMFS5 file descriptor implementation. |
|
VMFS6 file descriptor implementation. |
|
Implements a file-like object for VMFS files. |
|
Implements a file-like object for VMFS files in the case we don't have a volume available. |
- class dissect.vmfs.descriptor.DirEntry(vmfs: dissect.vmfs.vmfs.VMFS, address: int, name: str, type: dissect.vmfs.c_vmfs.FS3_DescriptorType, raw: dissect.vmfs.c_vmfs.c_vmfs.FS3_DirEntry | dissect.vmfs.c_vmfs.c_vmfs.FS6_DirEntry | None = None)¶
Directory entry representation.
- Parameters:
vmfs – The VMFS instance this directory entry belongs to.
address – The address of the file descriptor of this directory entry.
name – The name of the directory entry.
type – The type of the directory entry.
raw – The raw directory entry struct, if available.
- vmfs¶
- address¶
- name¶
- type¶
- raw = None¶
- __repr__() str¶
- property file_descriptor: FileDescriptor¶
Resolve this directory entry to its file descriptor.
- fd¶
- class dissect.vmfs.descriptor.FileDescriptor(vmfs: dissect.vmfs.vmfs.VMFS, address: int)¶
VMFS file descriptor implementation.
See
FileDescriptor5andFileDescriptor6for the VMFS5 and VMFS6 specific implementations.File descriptors are basically the inodes of VMFS and are all stored in the
.fdc.sfresource. They are the combination of a lock block, a metadata block, and a bit of space for data. They start with lock information, which allows multiple ESXi hosts to stay in sync and place locks. This is followed by theFS3_FileMetadatastructure is and contains fields that you would expect of an “inode”.The file descriptor on disk roughly looks like the following:
struct FS3_FileDescriptor { FS3_DiskLock lockBlock; FS3_FileMetadata metaBlock; char data[N]; };
On VMFS5, each block is 512 bytes large, and there’s 1024 bytes of data. On VMFS6, the block size is determined by the metadata alignment. The entire file descriptor is two metadata blocks large, with the lock occupying the first metadata block, and the metadata and data occupying the second metadata block.
Data is stored in a way that is also similar to many Unix filesystems. There is is some space at the end of the metadata for either a block pointer array, or some resident data. On VMFS5, the block pointer array and the data portion are stored in the same place, whereas on VMFS6, the block pointer array is aligned to the end of the file descriptor, and the data portion is aligned to the end of the metadata structure.
The “zeroLevelAddrType” (or ZLA) determines how to interpret the block pointer array. They can generally be seperated into two kinds: direct and indirect. Like other filesystems, direct blocks refer directly to filesystem blocks, or offsets on disk, that contain data. With indirect blocks, you first need to go through one or more layers of indirection go get to the final filesystem block. View the documentation of
BlockStreamfor more information.Directory entries are also stored very differently between VMFS5 and VMFS6. Refer to : func:FileDescriptor5._iterdir and
FileDescriptor6._iterdir()for more information on how these work.- vmfs¶
- address¶
- __repr__() str¶
- debug() str¶
Return a debug string for this file descriptor.
Mimicks
vmkfstool -Doutput.
- static from_bytes(vmfs: dissect.vmfs.vmfs.VMFS, address: int, buf: bytes) FileDescriptor | FileDescriptor5 | FileDescriptor6¶
Create a
FileDescriptor5orFileDescriptor6from a bytes buffer.
- property raw: memoryview¶
The raw buffer of this file descriptor.
- property lock_info: dissect.vmfs.c_vmfs.c_vmfs.FS3_DiskLock¶
The lock info of this file descriptor.
- property metadata: dissect.vmfs.c_vmfs.c_vmfs.FS3_FileMetadata¶
The file metadata of this file descriptor.
- property data: memoryview¶
The data portion of this file descriptor.
- property blocks: list[int]¶
The block array of this file.
Also referred to as the pointer array, or data addresses.
On VMFS5, this is stored in the data portion of the file descriptor as an array of 32-bit integers. On VMFS6, it’s aligned to the end of the file descriptor, and is an array of 64-bit integers.
- property rdm_mapping: dissect.vmfs.c_vmfs.c_vmfs.FS3_RawDiskMap¶
The RDM mapping of this file, if this file is an RDM file.
The RDM mapping is stored in the data portion of the file descriptor.
- property parent: FileDescriptor | None¶
The parent file descriptor of this file, if it has one.
- property size: int¶
The size of this file.
- property type: int¶
The type of this descriptor. Not to be confused with the file type.
- property zla: dissect.vmfs.c_vmfs.FS3_ZeroLevelAddrType¶
The “Zero Level Address” type of this file.
- property mode: int¶
The file mode of this file.
The mode in the metadata only contains a type bit for directories, we add the appropriate type bits for regular files, symlinks and RDM files.
Access the mode through the
metadataattribute to get the raw mode value.
- property block_size: int¶
The file specific block size of this file.
- property atime: datetime.datetime¶
The last access time of this file.
- property mtime: datetime.datetime¶
The last modified time of this file.
- property ctime: datetime.datetime¶
The creation time of this file.
- property link: str¶
The destination of this symlink, if this file descriptor is a symlink.
- is_dir() bool¶
Return whether this file descriptor is a directory.
- is_file() bool¶
Return whether this file descriptor is a regular file.
- is_symlink() bool¶
Return whether this file descriptor is a symlink.
- is_system() bool¶
Return whether this file descriptor is a system file.
- is_rdm() bool¶
Return whether this file descriptor is an RDM file.
- listdir() dict[str, DirEntry]¶
A dictionary of the content of this directory, if this file descriptor is a directory.
- iterdir() collections.abc.Iterator[DirEntry]¶
Iterate file descriptors of the directory entries, if this file descriptor is a directory.
- get(name: str) DirEntry¶
Get a child directory entry by name.
- Parameters:
name – The name of the directory entry to get.
- open() BlockStream¶
Open a read-only stream for this file descriptor.
- class dissect.vmfs.descriptor.FileDescriptor5(vmfs: dissect.vmfs.vmfs.VMFS, address: int)¶
Bases:
FileDescriptorVMFS5 file descriptor implementation.
- class dissect.vmfs.descriptor.FileDescriptor6(vmfs: dissect.vmfs.vmfs.VMFS, address: int)¶
Bases:
FileDescriptorVMFS6 file descriptor implementation.
- class dissect.vmfs.descriptor.BlockStream(descriptor: FileDescriptor)¶
Bases:
dissect.util.stream.AlignedStreamImplements a file-like object for VMFS files.
VMFS file content can be resident or divided over one or more file blocks. These blocks can be directly or indirectly referenced. If they’re directly referenced, we can read immediately from the block, otherwise we need to go through one or more layers of indirection.
Indirection is implemented using PB or PB2 blocks. The actual indirection algorithm differs slightly between VMFS versions.
Eventual file blocks can also differ between FB (filesystem block), SB (sub/small block) and LFB (large filesystem block).
See
FileDescriptor5._resolve_offset()andFileDescriptor6._resolve_offset()for more information on how to resolve offsets.- descriptor¶
- class dissect.vmfs.descriptor.BestEffortBlockStream(descriptor: FileDescriptor)¶
Bases:
dissect.util.stream.AlignedStreamImplements a file-like object for VMFS files in the case we don’t have a volume available.
If we don’t have a volume handle, we can’t read any file blocks on disk, but we can still read resident and sub-block data.
This duplicates some code, but it gives us a cleaner implementation of the happy path while still allowing us to read some data in the case we only have a bunch of system files.
- descriptor¶