Keyboard shortcuts

Press or to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

Universal Disk Image Format (UDIF)

The Universal Disk Image Format (UDIF) (.dmg) is one of the disk image formats supported natively by Mac OS. UDIF supersedes the New Disk Image Format (NDIF) format and was introduced in Max OS X 10.0 (Cheetah).

Mac OS referers to the UDIF image format as CUDIFEncoding.

Overview

An UDIF image can consists of one or more segment files, where:

  • the first segment file is named: “image.dmg”
  • successive segment files are named: “image.###.dmgpart”, where “###” represents a numeric value starting with 2 with 0 padding, e.g. “image.002.dmgpart”. Segment files after 999 are assumed to be named without the 0 padding, e.g. “image.1234.dmgpart”.

The data forks of the segment files are used as a contiguous data stream. A compressed block can be stored across multiple segment files.

Only the first segment file contains a resource fork or XML plist.

Known UDIF image types are:

IdentifierDescription
UDBZbzip2 compressed UDIF
UDCOApple Data Compression (ADC) compressed UDIF
UDIFRead-write uncompressed UDIF
UDRORead-only uncompressed UDIF
UDxxUncompressed UDIF
UDZOzlib/DEFLATE compressed UDIF
ULFOLZFSE compressed UDIF
ULMOLZMA compressed UDIF

UDIF images can be encrypted. An encrypted UDIF image consists of one of more UDIF segment files, where each segment file uses a Encrypted Encoding container with its own key protectors.

Terminology

TermDescription
Flattened imageThe disk image is a self-contained, a resource fork is stored within the image
Unflattened imageThe disk image uses the file system to store a resource fork

Image formats

Known types of UDIF segment files are:

  • Uncompressed segment file
  • Compressed segment file
  • Encrypted segment file

Uncompressed segment file format

An uncompressed UDIF segment file consist of:

Note that an uncompressed UDIF image without file footer is equivalent to a RAW storage media image (CRawDiskImage).

Compressed segment file format

A compressed UDIF segment file consist of:

  • Data fork, containing the image data
  • Optional XML plist
  • Optional resource fork
  • File footer at the end of the file

Encrypted Encoding version 1 encrypted UDIF segment file

An Encrypted Encoding version 1 encryped UDIF segment file consists of:

Note that the encrypted UDIF data can contain an uncompressed UDIF image without file footer.

Encrypted Encoding version 2 encrypted UDIF segment file

An Encrypted Encoding version 2 encryped UDIF segment file consists of:

  • Encrypted Encoding container header at the start of the file
  • Key protectors
  • Unknown (empty values), probably reserved for the key protectors
  • Data fork, containing encrypted UDIF data

Note that the encrypted UDIF data can contain an uncompressed UDIF image without file footer.

Characteristics

CharacteristicsDescription
Byte orderbig-endian
Date and time valuesN/A
Character stringsN/A

The number of bytes per sector is 512.

The file footer (also known as resource file or metadata) (UDIFResourceFile) is 512 bytes in size and consists of:

OffsetSizeValueDescription
04"koly"Signature
444Format version
84512File footer size, in number of bytes
124Image flags
168Segment logical offset
248Data fork offset, where the offset is relative from the start of the image file
328Data fork size, in number of bytes
408Resource fork offset, where the offset is relative from the start of the image file
488Resource fork size, in number of bytes
564Segment number, where 1 represents the first segment and contains 0 if not set
604Number of segments, which contains 0 if not set
6416Segment set identifier, which contains an UUID
804Data checksum type
844Data checksum size, in number of bits
88128Data checksum
Introduced in Mac OS 10.2
2168XML plist offset, where the offset is relative from the start of the image file
2248XML plist size
232120Unknown (Reserved)
3524Master checksum type
3564Master checksum size, in number of bits
360128Master checksum
4884Image type (or variant)
4928Media size, in number of sectors, which contains the total number of sectors in the (uncompressed) image
5004Unknown (reserved)
5044Unknown (reserved)
5084Unknown (reserved)

In an encrypted image file the offsets are relative from the start of the unencrypted image file.

Note that both the XML plist and resource fork size can be 0, such as in an UDIF stub (UDxx) image.

Image flags

ValueIdentifierDescription
0x00000001kUDIFFlagsFlattenedFlattened image (set by hdiutil flatten/unflatten)
0x00000002kUDIFFlagsInPlace
0x00000004kUDIFFlagsInternetEnabledInternet enabled (set by hdiutil internet-enable)
0x00000008kUDIFFlagsIsEncrypted

Checksum types

ValueIdentifierDescription
2CRC-32
4MD5

Image types

ValueIdentifierDescription
1kUDIFDeviceImageTypeDevice image
2kUDIFPartitionImageTypeParitition image

Resource fork

In older UDIF images the resource fork contains the image metadata, such as the block table. The resource fork consists of:

  • Resource fork header
  • Resource data
  • Resource map

Resource fork header

The resource fork header is 16 bytes in size and consists of:

OffsetSizeValueDescription
04Resource data offset, which contains the byte offset relative to the start of the resource fork
44Resource map offset, which contains the byte offset relative to the start of the resource fork
84Resource data size, in number of bytes
124Resource map size, in number of bytes

Resource data

OffsetSizeValueDescription
04Size, in number of bytes
4...Data

Resource map

The resource map consists of:

  • Resource map header
  • Entries list
  • Names

Resource map header

The resource map header is 28 bytes in size and consists of:

OffsetSizeValueDescription
016Unknown (reserved)
164Unknown (next resource map)
202Unknown (file reference number)
222Unknown (resource file attribute flags)
242Entries list offset, which contains the byte offset relative to the start of the resource map
262Names list offset, which contains the byte offset relative to the start of the resource map

Resource map entries list

The entries (or type) list is of variable size and consists of:

OffsetSizeValueDescription
02Number of entries, stored as value - 1
2...Array of entries

Resource map entry

The resource map entry is 8 bytes in size and consists of:

OffsetSizeValueDescription
04Type indicator (or signature)
42Number of resource descriptors, stored as value - 1
62Resource descriptors offset, which contains the byte offset relative to the start of the entries list

A resource map entry is comparable to an item in the XML plist resource-fork dictionary such as the “blkx” item.

Resource descriptor

The resource descriptor (or reference list) is 12 bytes in size and consists of:

OffsetSizeValueDescription
02Resource identifier. Corresponds to the "ID" value in the XML plist.
22Resource name offset, which contains the byte offset relative to the start of the names list where 0xffff indicates the resource has no name. Corresponds to the "Name" value in the XML plist.
41Resource flags (0x20: Purgeable, 0x40: Protected). Corresponds to the "Attributes" value in the XML plist.
53Resource data offset, which contains the byte offset relative to the start of the resource data
84Unknown (reserved)

Resource name

The resource name is of variable size and consists of:

OffsetSizeValueDescription
01Name size
2...Name string, without an end-of-string character

XML plist

The XML plist contains image metadata such as the block table.

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
    <key>resource-fork</key>
    <dict>
        <key>blkx</key>
        <array>
            <dict>
                <key>Attributes</key>
                <string>0x0050</string>
                <key>CFName</key>
                <string>Protective Master Boot Record (MBR : 0)</string>
                <key>Data</key>
                <data>
                bWlzaAAAAAEAAAAAAAAAAAAAAAAAAAABAAAAAAAAAAAA
                AAgIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
                AAIAAAAgQfL6MwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
                AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
                AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
                AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
                AAAAAAACgAAABQAAAAMAAAAAAAAAAAAAAAAAAAABAAAA
                AAAAIA0AAAAAAAAAH/////8AAAAAAAAAAAAAAAEAAAAA
                AAAAAAAAAAAAAAAAAAAAAAAAAAA=
                </data>
                <key>ID</key>
                <string>-1</string>
                <key>Name</key>
                <string>Protective Master Boot Record (MBR : 0)</string>
            </dict>
            ...
        </array>
        <key>plst</key>
        <array>
            <dict>
                <key>Attributes</key>
                <string>0x0050</string>
                <key>Data</key>
                <data>
                AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
                AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
                AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
                AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
                AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
                AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
                AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
                AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
                AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
                AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
                AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
                AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
                AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
                AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
                AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
                AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEAAQAAAAAAAAAA
                AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
                AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
                AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
                AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
                AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
                AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
                AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
                AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
                AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
                AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
                AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
                AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
                AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
                AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
                AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
                AAAAAAAAAAAA
                </data>
                <key>ID</key>
                <string>0</string>
                <key>Name</key>
                <string></string>
            </dict>
        </array>
    </dict>
</dict>
</plist>

The XML plist contains the following key-value pairs:

IdentifierDescription
resource-forkdictionary

XML plist resource-fork dictionary

The resource-fork dictionary contains the following key-value pairs:

IdentifierDescription
blkxarray of dictionaries, which contains Block table (or block extents) values
LPicoptional array of dictionaries, which contains values related to license information
plstarray of dictionaries, which contains values related to image properties
STR#optional array of dictionaries, which contains values related to license information
TEXToptional array of dictionaries, which contains values related to license information

XML plist array entry

An array entry contains the following key-value pairs:

IdentifierDescription
Attributesstring that contains a hexadecimal formatted integer value
CFNamestring
Datastring that contains base-64 encoded data
IDstring that contains a decimal formatted integer value
Namestring

Note the the blkx array appears the only one that uses CFName.

Block table

The block table (BLKXTable) is of variable size and consists of:

  • block table header
  • block table entries

The block table header

The block table header is 204 bytes in size and consists of:

OffsetSizeValueDescription
04"mish"Signature
441Format version
88Start sector, which contains the sector number relative to the start of the media data
168Number of sectors
248Base data offset, which contains the byte offset relative to the start of the segment data stream
324Unknown (BuffersNeeded)
364Unknown (BlockDescriptors)
406 x 4 = 240Unknown (reserved)
644Checksum type
684Checksum size
72128Checksum
2004Number of entries

Block table entry

The block table entry (BLKXChunkEntry) is 40 bytes in size and consists of:

OffsetSizeValueDescription
04Entry type
44Unknown (comment related?)
88Start sector, which contains the sector number relative to the start of the start sector of the block table
168Number of sectors
248Data offset, which contains the byte offset relative to the base data offset in the block table header
328Data size, which contain the number of bytes of data stored, which is 0 for sparse data

UDIF block table entry types

ValueIdentifierDescription
0x00000000Unknown (sparse)
0x00000001Uncompressed (raw) data
0x00000002Sparse (used for Apple_Free)
0x7ffffffeComment
0x80000004ADC compressed data
0x80000005zlib compressed data
0x80000006bzip2 compressed data
0x80000007LZFSE compressed data
0x80000008LZMA compressed data
0xffffffffBlock table entries terminator

UDIF comment

TODO: complete section

Notes

Is the maximum compressed chunk size 2048 sectors?

Comment seems to reference compressed data but has no size or number of sectors value.

Format edge cases and corruption scenarios

Non-sequential segment files

It is currently unknown if non-sequential segment files are supported.

XML plist and resource fork both in use

The XML plist and resource fork could be used simultaneously, allowing for a single UDIF to contain multiple images.

It is currently assumed that the XML plist is leading.

XML plist and/or resource fork in non-first segment files

The XML plist and/or resource fork could be used in non-first segment files.