ByteScope

OLE2 / CFB file format

Compound File Binary format — the legacy container behind .doc/.xls/.ppt and .msi installers.

MIME type
application/x-ole-storage
Extensions
.doc, .xls, .ppt, .msi
Category
Documents

Magic-number signature

0x00000000D0CF11E0A1B11AE1········CFB / 'docfile' magic

About the OLE2 / CFB format

The Compound File Binary format is a complete filesystem packed into one file: it has sectors, an allocation table, a directory tree of named streams and even a second, smaller allocation scheme for tiny streams. Microsoft built it so an application could store many independent pieces inside a single document without rewriting the whole thing on every save, and everything from Word 97 documents to Windows Installer packages to Outlook .msg files still rides on it. Reading one means walking a chain of sector numbers, not scanning forward through bytes, which is why a hex dump of a .doc looks like noise even though the text is in there uncompressed.

Header layout, byte by byte

OffsetLengthFieldMeaning
08Header signatureAlways D0 CF 11 E0 A1 B1 1A E1. The first four bytes are a deliberate pun — D0CF11E reads as 'docfile' in leetspeak. Nothing about the extension is implied: .doc, .xls, .ppt, .msi and .msg all start with these same eight bytes.
816Header CLSIDReserved class identifier, and the specification requires it to be all zeros. A non-zero value here is a sign of a hand-built or deliberately malformed file rather than a legitimate variant.
242Minor versionLittle-endian, and 0x003E in essentially every file in the wild. It has no functional effect; readers ignore it.
262Major version0x0003 or 0x0004, and this one matters: version 3 uses 512-byte sectors and 32-bit stream sizes, version 4 uses 4096-byte sectors and lets a stream exceed 4 GiB. Almost every Office document is version 3.
282Byte order markFE FF, meaning little-endian. Big-endian was never actually specified, so this is a constant in practice — a useful second sanity check when you suspect the file has been shifted.
302Sector shiftThe base-2 logarithm of the sector size: 0x0009 for 512-byte sectors with major version 3, 0x000C for 4096-byte sectors with version 4. Sector N begins at byte offset (N + 1) times the sector size, because sector numbering starts after the 512-byte header.
322Mini sector shiftLog base 2 of the mini-sector size, mandated as 0x0006 — 64 bytes. The mini stream exists so that a file holding hundreds of tiny property streams does not waste half a kilobyte on each one.
346ReservedSix bytes that must be written as zero and ignored on read. They exist only to align the fields that follow onto a four-byte boundary.
404Number of directory sectorsCount of sectors holding directory entries. Version 3 files must write zero here and follow the directory chain through the allocation table instead; only version 4 uses the value.
444Number of FAT sectorsHow many sectors are given over to the file allocation table. Each FAT sector holds sectorSize divided by four next-sector pointers, so a 512-byte sector maps 128 sectors and the table grows linearly with the document.
484First directory sectorSector number where the directory chain starts. The first directory entry is always the root, whose name is 'Root Entry' in UTF-16, and whose child tree names every stream in the file — this is the single field to follow when you want to know what is actually inside.
524Transaction signatureIncremented by implementations that support transactional saves, zero everywhere else. In practice it is a useful fingerprint for which application wrote the file.
564Mini stream cutoff sizeMandated as 0x00001000, 4096. A stream shorter than this is stored in the mini stream through the mini FAT; a stream at or above it gets whole sectors of its own. Two different allocation paths in one file, decided by this one number.
604First mini FAT sectorStart of the mini allocation table, or the end-of-chain marker FFFFFFFE when the document has no small streams at all.
644Number of mini FAT sectorsLength of that chain in sectors. Zero is normal for a document made entirely of large streams.
684First DIFAT sectorWhere the double-indirect allocation table continues once the 109 slots in the header run out. FFFFFFFE means it never did, which is the case for any file under roughly 7 MB with 512-byte sectors.
724Number of DIFAT sectorsLength of that continuation chain. Position is meaning in the DIFAT: slot i owns a fixed block of FAT indices, so a reader that skips an unreadable slot rather than leaving a placeholder silently misreads every sector number after it.
76436DIFAT array109 four-byte sector numbers naming the first 109 FAT sectors, filling the header out to exactly 512 bytes. Unused slots hold FFFFFFFF. This is why small compound files need no DIFAT sectors of their own — the header already maps everything.

Telling it apart from its neighbours

Easily confused withHow to tell
Word document (docx)The generational split in Office. Both may sit in a folder called 'documents' and both open in Word, but a pre-2007 .doc is D0 CF 11 E0 and a .docx is 50 4B 03 04. The extension is not proof: Office happily saves an old-format file under a .docx name and vice versa, and it sniffs the bytes when opening. Read offset 0.
doc/xls/ppt/msiAll four share the same eight-byte magic and cannot be told apart from the header at all — the container says nothing about what it contains. The answer is the directory tree reached through offset 48: a stream named 'WordDocument' means .doc, 'Workbook' or the older 'Book' means .xls, 'PowerPoint Document' means .ppt, and a set of streams with mangled base-64-ish names means a Windows Installer package.
msgAn Outlook .msg is a compound file too, with the same magic, so a detector will call it OLE2 and stop. What identifies it is a directory full of streams named __substg1.0_ followed by a property tag and type, plus __properties_version1.0 — the MAPI property storage layout rather than a document layout.
SQLite databaseWorth pairing because they are the two 'a whole filesystem in one file' formats you actually meet. SQLite opens with the ASCII string 'SQLite format 3' and a NUL; CFB opens with D0 CF 11 E0. Both use fixed-size pages and a free list, but SQLite's format is public, versioned and exhaustively documented, while CFB's was reverse-engineered for a decade before Microsoft published it.

How these files break

  • A broken FAT chain. Because a stream is a linked list of sector numbers rather than a contiguous run, one damaged entry in the allocation table does not truncate a stream — it redirects it into somebody else's sectors. The document opens, and a paragraph in the middle comes out as another paragraph, or as binary garbage, with no checksum anywhere to notice.
  • Truncation. The 512-byte header survives, so every tool identifies the file correctly and reports its version and sector size, and then extraction fails because the directory sector named at offset 48 lies past the end of the file. A CFB has no trailer, so there is no cheap end-of-file check the way there is for PNG or ZIP.
  • A DIFAT loop. Sector numbers in the double-indirect table are unvalidated, so a corrupt file can point the chain back at itself. A naive parser follows it forever; this is the classic denial-of-service shape for compound-file readers, and the defence is to bound the walk by the number of sectors the file could possibly hold rather than trusting the declared counts at offsets 44 and 72.
  • Text-mode transfer. Every CFB field is binary, so ASCII-mode line-ending translation shifts sector boundaries and corrupts the header from offset 24 onward — the magic at offset 0 contains no 0D 0A and survives untouched, which is precisely the trap. The file is still identified as OLE2 and is completely unreadable.
  • A version 4 file read as version 3. Major version at offset 26 decides whether sectors are 512 or 4096 bytes. Ignore it and every sector offset is wrong by a factor of eight, which produces a stream of plausible-looking but entirely misaligned data rather than a clean failure.

Where the format stands today

OLE2 is a legacy container that refuses to die, because too much still rides on it. Office moved to the ZIP-and-XML formats in 2007 and pre-2007 documents are now genuinely old, but three things keep compound files in daily circulation: Windows Installer packages, which are still CFB and still how Windows software ships; Outlook .msg files, which are what every 'save this email' button produces; and the enormous archived estate of .doc and .xls in legal, government and enterprise document stores that nobody will ever convert. It is also a persistent security surface — macros in an old .doc, and the format's own complexity, made compound files a favourite malware vector for two decades, which is why mail gateways treat D0 CF 11 E0 with suspicion regardless of extension. For anything new the format has no advantages left: OOXML is a ZIP, is inspectable with ordinary tools, compresses far better and is a published standard, while CFB's spec was only released as [MS-CFB] long after everyone had already reverse-engineered it.

Open OLE2 / CFB files on this site

Every one of these runs in your browser — the file never leaves your machine.

Related formats

Formats that are easy to confuse with OLE2 / CFB — compare their leading bytes.

FormatFirst bytesExtension
Word document (docx)50 4B 03 04.docx
Excel workbook (xlsx)50 4B 03 04.xlsx
PowerPoint presentation (pptx)50 4B 03 04.pptx
PDF25 50 44 46 2D.pdf

Frequently asked questions

What is a magic number in a file?

The first few bytes of a file, which identify its format regardless of what the name says. A PNG always starts with 89 50 4E 47; a ZIP with 50 4B 03 04. Operating systems, browsers and the file command all read these bytes rather than trusting the extension, which is why renaming a file does not change what it actually is.

How do I check a file's magic number myself?

On macOS or Linux, xxd -l 16 yourfile prints the first 16 bytes; on Windows, Format-Hex -Path yourfile -Count 16 in PowerShell. Or drop the file into the File Type Identifier on this site, which reads the bytes locally and names the format for you — nothing is uploaded.

Why do two formats share the same magic number?

Because one is built on the other. Every docx, xlsx, pptx, apk, jar and epub begins with the ZIP signature, since all of them are ZIP archives underneath; telling them apart means looking at the entries inside. Java class files and macOS universal binaries both start with CA FE BA BE and are distinguished by the field that follows.

Can a file have no magic number at all?

Yes. Text-based formats — XML, HTML, JSON, SVG, CSV — have no fixed byte signature, so they are recognized structurally instead: a leading <?xml declaration, a <svg element, or a { followed by a quoted key. That detection is a good guess rather than a certainty, which is why this reference marks those formats as probe-detected.

Does a matching magic number mean the file is safe?

No. It tells you what the format is, not whether the contents are harmless — a genuine PDF or docx can still carry a malicious payload. Identifying the true type is a useful first check, especially when the extension disagrees with the bytes, but it is not a malware scan.

Have a file that might be in the OLE2 / CFB format? Identify it with the File Type Identifier — it reads the magic number locally, nothing is uploaded. Or browse all formats.