With macOS 26, Apple introduced the Apple Sparse Image Format (ASIF) for virtual disks.
As usual, there are no technical details provided about the layout of the ASIF file.
This repository collects reverse-engineered technical details and community-contributed findings about the Apple Sparse Image Format ASIF, for the benefit of forensics engineers, virtualization tool authors, archivists, and researchers.
ASIF is a two‑level indirect block scheme.
Integers are stored in big‑endian order.
| Offset (hex) | Length (bytes) | Description |
|---|---|---|
| 0x00 | 4 | Magic 'shdw' (73 68 64 77) |
| 0x04 | 4 | Version (ex.: 00 00 00 01) |
| 0x08 | 4 | Header size (ex.: 00 00 02 00) |
| 0x0C | 4 | Flags |
| 0x10 | 8 | Offset to Directory (bytes) |
| 0x18 | 8 | Offset to Directory (bytes) |
| 0x20 | 16 | UUID |
| 0x30 | 8 | Sector count |
| 0x38 | 8 | Maximum sector count |
| 0x40 | 4 | Chunk size (bytes) |
| 0x44 | 2 | Sector/block size (bytes) |
| 0x46 | 2 | ?? |
| 0x48 | 8 | Metadata offset? (which unit?) |
Let N be the number of data chunks per chunk‑group.
Let S be the size of a chunk‑group in bytes.
Let C be the number of chunk‑groups that fit into a single table.
Let D be the total amount of data addressed by one table.
Let T be the maximum number of tables required for the image.
N = 4 * sector size
S = 8 * (N + 1)
C = floor(chunk size / S)
D = C * N * chunk size
T = ceil(max sector count * sector size / D)
The header references two directories. The directory with the highest sequence number is considered the active one.
To locate a table for a given logical offset, divide the offset by D (the data range covered by a single table). The integer quotient yields the index into the directory; the corresponding entry provides the chunk number that holds the desired table.
| Offset (hex) | Length (bytes) | Description |
|---|---|---|
| 0x00 | 8 | Sequence number |
| 0x08 | 8 | Chunk number that contains Table 0 |
| 0x16 | 8 | Chunk number that contains Table 1 |
| ... | ||
| 8 * T | 8 | Chunk number that contains Table T-1 |
Each table is composed of C chunk‑groups placed sequentially. To determine the chunk-group, divide the relative offset by N * chunk size (the data range covered by a single chunk-group).
| Offset (hex) | Length (bytes) | Description |
|---|---|---|
| 0x00 | S | Chunk group 0 |
| S | S | Chunk group 1 |
| ... | ||
| S * (C - 1) | S | Chunk group C-1 |
A chunk-group stores N data-chunk references followed by a single bitmap-chunk reference. The most-significant nine bits of each chunk number are reserved for flag bits. The remaining 55 bits represent the physical chunk index.
To determine the data chunk number, divide the relative offset by chunk size.
| Offset (hex) | Length (bytes) | Description |
|---|---|---|
| 0x00 | 8 | Data chunk 0 |
| 0x08 | 8 | Data chunk 1 |
| ... | ||
| 8 * (N - 1) | 8 | Data chunk N-1 |
| 8 * N | 8 | Bitmap chunk |
TODO: describe flags.
TODO
TODO
$ diskutil image create blank --format ASIF --size 123g -fs None test.asif
$ diskutil image info test.asif
diskutil image attach --noMount test.asif
echo -n 1 | dd of=/dev/disk27 bs=1 count=1
hdiutil eject /dev/disk27