Custom properties are like comments, except the value (of each key/value pair) can be any type of data, not just ASCII text. Each key must still be ASCII text, but the values can be any binary data.
The Custom Properties block (henceforth referred to as the Properties block) begins with a 4-byte start-of-properties marker, followed with a Size integer, followed with a Count integer, followed with key/value pairs (if there are any custom properties), and ending with a 4-byte end-of-properties marker.
The first four bytes of the Properties block store the value 0x534F5000 (ASCII string SOP\0) which marks the start-of-properties.
Start of Properties Marker: SOP\0
The Size integer follows. It is a 32-bit integer that specifies the total size (number of bytes) of the entire Properties block including the Size integer and the start-of-properties marker.
The Count integer follows. It is a 32-bit integer that specifies how many properties (key/value pairs) there are. That is followed with that many key/value pairs, which is followed by an end-of-properties marker.
For each key/value pair, the key specifies the title of custom data, and the value is the custom data.
After the last key/value pair, a 4 byte end-of-properties marker stores 0x454F5000 (ASCII string EOP\0) marking the end of the Properties block.
End of Properties Marker: EOP\0
Each key, of a key/value pair, is a 32-bit integer specifying how many characters the title has (including a termination null byte), followed with that many ASCII characters that are the title of the custom property (including the terminating null byte).
Each value, of a key/value pair, is a 32-bit integer that specifies the number of bytes of custom data, followed with that many bytes of custom data.
The shortest possible Properties block, for no properties, would be 16 bytes. In that case, the first four bytes of the Properties block would be the start-of-properties marker, followed with a 4-byte integer equal to 16 (the total size of the Properties block), followed with a 4-byte integer equal to zero indicating there was zero properties in the Properties block, and the last four bytes storing the end-of-properties marker.