SketchUp File Format Reverse Engineering Attempt by Thomas Thomassen [thomas@thomthom.net] //////////////////////////////////////////////////////////////////////////////// /// BLOCKS ///////////////////////////////////////////////////////////////////// There are reoccuring patterns. Looks like block signatures. Blocks Signature: FF FE FF ?? The next byte gives the size of the block (or block name) If the UBYTE after the signature is not NULL then it appears to be a UTF-16LE string. UTF-16LE string signature? Many places there is no string, the ?? byte is just NULL. Some places (FF FF) indicates a new section or area. Bytes before that mark might be important. For the Material and Layer section there is four bytes with the total number of Materials and Layers. (FF FF) appear to be preseeded by four bytes. ID number/signature? Apart from the byte indicating the Unicode string there doesn't seem to be any bytes that indicates the size of the blocks. Looks like it's required to know the structure to read the file. Even just part of it. Due to plugins there could be extra information and blocks inserted. Components also complicates things as they appear as files within the file. Due to this you can not blindly scan for strings or byte sequences. What is the pattern to the file structure? How do you scan/skip to the interesting data reliably? /// THEORY ///////////////////////////////////////////////////////////////////// Blocks (Sections): 2 bytes - Signature (FF FF) 2 bytes - (Short) Block ID or VersionMap referance 2 bytes - (Short) Size of Block Name ? bytes (Size of Block Name) - Name of Block (ASCII) FF FE FF Signature indicates Sub-Blocks. (Blocks inside the sections) ================================================================================ TIME_T - 32-bit value representing date and time in C using the format 'MM/dd/yyyy hh:mm:ss'. time_t is a 32-bit integer representing the number of seconds since 01/01/1970 12:00 AM. ================================================================================ /// HEADER BLOCKS ////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////////// /// SkechUp File ID //////////////////////////////////////////////////////////// +------------------------------------------------------------------------------+ | 3 bytes - Block Signature (FF FE FF) | 1 byte - Block Name Size (in characters) | 28 bytes (14 Unicode Characters) - 'SketchUp Model' +------------------------------------------------------------------------------+ //////////////////////////////////////////////////////////////////////////////// /// Version Number ///////////////////////////////////////////////////////////// +------------------------------------------------------------------------------+ | 3 bytes - Block Signature (FF FE FF) | 1 byte - Block Name Size | Variable Bytes (Block Name Size) - Version Number wrapped in curly brackets +------------------------------------------------------------------------------+ | 16 Bytes - ? (Random every time, even when doing a Save As) | | When doing a Save As the files should be identical, but this section of data | differs anyway. (Tested with a file doing Save As two times. Result was | three files with the same size but had differences in two areas of this data | chunk. +------------------------------------------------------------------------------+ //////////////////////////////////////////////////////////////////////////////// /// Time Stamp ///////////////////////////////////////////////////////////////// +------------------------------------------------------------------------------+ | 3 bytes - Block Signature (FF FE FF) | 1 byte - Block Name Size (00) | 4 bytes - Timestamp of when file was saved. Appears to be UTC regardless of | locale. (TIME_T) +------------------------------------------------------------------------------+ /// VERSION MAP //////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////////// +------------------------------------------------------------------------------+ | 6 bytes - Section Sig (FF FF 00 00 0B 00) | 11 bytes - 'CVersionMap' +------------------------------------------------------------------------------+ ~~~ Repeat ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +------------------------------------------------------------------------------+ | 3 bytes - Block Signature (FF FE FF) | 1 byte - Block Name Size | Variable Bytes (Block Name Size) - Name of Capability +------------------------------------------------------------------------------+ | 2 bytes - ? (Capability ID?) Relates to Short Int after Blocks. | 2 bytes - ? +------------------------------------------------------------------------------+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +------------------------------------------------------------------------------+ | 3 bytes - Block Signature (FF FE FF) | 1 byte - Block Name Size | 36 Bytes (18 Unicode Characters) - 'End-Of-Version-Map' +------------------------------------------------------------------------------+ //////////////////////////////////////////////////////////////////////////////// /// Unknown Data /////////////////////////////////////////////////////////////// +------------------------------------------------------------------------------+ | 16 Bytes - ? | 00 00 00 00 01 00 00 00 B0 04 00 00 | ! 01 or 03 | 00 00 00 | | Theory: 4 Ints | 4 bytes - ? (00 00 00 00) Unsigned Int: 0 | 4 bytes - ? (01 00 00 00) Unsigned Int: 1 | 4 bytes - ? (B0 04 00 00) Unsigned Int: 1200 | 4 bytes - ? (03 00 00 00) Unsigned Int: 3 OR (01 00 00 00) | +------------------------------------------------------------------------------+ //////////////////////////////////////////////////////////////////////////////// /// CDib Block ///////////////////////////////////////////////////////////////// +------------------------------------------------------------------------------+ | 6 bytes - Section Sig (FF FF 03 00 04 00) | 4 bytes - 'CDib' +------------------------------------------------------------------------------+ | 4 bytes - ? (04 00 00 00) | 4 bytes - Unsigned Int - Size of Image Data (PNG file) | {PNG DATA} | 10 bytes - ? (01 00 00 00 00 00 00 00 00 00) +------------------------------------------------------------------------------+ //////////////////////////////////////////////////////////////////////////////// /// Camera ///////////////////////////////////////////////////////////////////// +------------------------------------------------------------------------------+ | 3 bytes - Block Signature (FF FE FF) | 1 byte - Block Name Size (00) +------------------------------------------------------------------------------+ | 6 bytes - Section Sig (FF FF 05 00 07 00) | 4 bytes - 'CCamera' +------------------------------------------------------------------------------+ | 139 bytes - ? +------------------------------------------------------------------------------+ +------------------------------------------------------------------------------+ | 3 bytes - Block Signature (FF FE FF) | 1 byte - Block Name Size +------------------------------------------------------------------------------+ | 236 bytes - ? (!) Does not match for .skp files with V-Ray material +------------------------------------------------------------------------------+ //////////////////////////////////////////////////////////////////////////////// /// Materials ////////////////////////////////////////////////////////////////// +------------------------------------------------------------------------------+ | 4 bytes - Material Count +------------------------------------------------------------------------------+ | 6 bytes - Section Sig (FF FF 0C 00 09 00) | 9 bytes - 'CMaterial' +------------------------------------------------------------------------------+ | 2 bytes - ? (00 00) +------------------------------------------------------------------------------+ ~~~ Repeat by number of Material Count ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ /// Material Block ///////////////////////////////////////////////////////////// +------------------------------------------------------------------------------+ | 3 bytes - Block Signature (FF FE FF) | 1 byte - Block Name Size | Variable Bytes (Block Name Size) - Material Name +------------------------------------------------------------------------------+ | 1 byte - ? | 1 byte - ? | 1 byte - Red | 1 byte - Green | 1 byte - Blue | 1 byte - Alpha +------------------------------------------------------------------------------+ /// Unknown //////////////////////////////////////////////////////////////////// +------------------------------------------------------------------------------+ | EMPTY +------------------------------------------------------------------------------+ | 21 bytes - Unknown +------------------------------------------------------------------------------+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ //////////////////////////////////////////////////////////////////////////////// /// Layers ///////////////////////////////////////////////////////////////////// +------------------------------------------------------------------------------+ | 4 bytes - Layer Count +------------------------------------------------------------------------------+ | 6 bytes - Section Sig (FF FF 02 00 06 00) | 6 bytes - 'CLayer' +------------------------------------------------------------------------------+ | 2 bytes - ? (00 00) +------------------------------------------------------------------------------+ ~~~ Repeat by number of Layer Count ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ /// Layer Block //////////////////////////////////////////////////////////////// +------------------------------------------------------------------------------+ | 3 bytes - Block Signature (FF FE FF) | 1 byte - Block Name Size | Variable Bytes (Block Name Size) - Layer Name +------------------------------------------------------------------------------+ | 1 byte - Visibility (00 or 01) | 1 byte - ? | 1 byte - ? +------------------------------------------------------------------------------+ /// Material Block ///////////////////////////////////////////////////////////// +------------------------------------------------------------------------------+ | REF: Material Block | Material block name: Layer_{Layer Name} | 4 bytes - ? Extra bytes trailing the Layer Material Blocks. +------------------------------------------------------------------------------+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ /// Unknown //////////////////////////////////////////////////////////////////// +------------------------------------------------------------------------------+ | EMPTY +------------------------------------------------------------------------------+ | 6 bytes - ? (0C 00 00 00 00) | 4 bytes - CEdge Count? (Unlikely. Return 18 on model with 12 edges) | 2 bytes - ? (FF FF) | 4 bytes - ? (02 00 05 00) | 5 bytes - 'CEdge' +------------------------------------------------------------------------------+