mirror of
https://github.com/SabreTools/BinaryObjectScanner.git
synced 2026-07-15 13:25:05 +00:00
Add CFB models
This commit is contained in:
92
BurnOutSharp.Models/CFB/Binary.cs
Normal file
92
BurnOutSharp.Models/CFB/Binary.cs
Normal file
@@ -0,0 +1,92 @@
|
||||
namespace BurnOutSharp.Models.CFB
|
||||
{
|
||||
/// <summary>
|
||||
/// Microsoft Compound File Binary (CFB) file format, also known as the
|
||||
/// Object Linking and Embedding (OLE) or Component Object Model (COM)
|
||||
/// structured storage compound file implementation binary file format.
|
||||
/// This structure name can be shortened to compound file.
|
||||
/// </summary>
|
||||
/// <see href="https://winprotocoldoc.blob.core.windows.net/productionwindowsarchives/MS-CFB/%5bMS-CFB%5d.pdf"/>
|
||||
public sealed class Binary
|
||||
{
|
||||
/// <summary>
|
||||
/// Compound file header
|
||||
/// </summary>
|
||||
public FileHeader Header { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// The FAT is the main allocator for space within a compound file.
|
||||
/// Every sector in the file is represented within the FAT in some
|
||||
/// fashion, including those sectors that are unallocated (free).
|
||||
/// The FAT is a sector chain that is made up of one or more FAT sectors.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// If Header Major Version is 3, there MUST be 128 fields specified to fill a 512-byte sector.
|
||||
///
|
||||
/// If Header Major Version is 4, there MUST be 1,024 fields specified to fill a 4,096-byte sector
|
||||
/// </remarks>
|
||||
public SectorNumber[] FATSectors { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// The mini FAT is used to allocate space in the mini stream.
|
||||
/// The mini stream is divided intosmaller, equal-length sectors,
|
||||
/// and the sector size that is used for the mini stream is specified
|
||||
/// from the Compound File Header (64 bytes).
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// If Header Major Version is 3, there MUST be 128 fields specified to fill a 512-byte sector.
|
||||
///
|
||||
/// If Header Major Version is 4, there MUST be 1,024 fields specified to fill a 4,096-byte sector
|
||||
/// </remarks>
|
||||
public SectorNumber[] MiniFATSectors { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// The DIFAT array is used to represent storage of the FAT sectors.
|
||||
/// The DIFAT is represented by an array of 32-bit sector numbers.
|
||||
/// The DIFAT array is stored both in the header and in DIFAT sectors.
|
||||
/// In the header, the DIFAT array occupies 109 entries, and in each
|
||||
/// DIFAT sector, the DIFAT array occupies the entire sector minus
|
||||
/// 4 bytes. (The last field is for chaining the DIFAT sector chain.)
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// If Header Major Version is 3, there MUST be 127 fields specified to
|
||||
/// fill a 512-byte sector minus the "Next DIFAT Sector Location" field.
|
||||
///
|
||||
/// If Header Major Version is 4, there MUST be 1,023 fields specified
|
||||
/// to fill a 4,096-byte sector minus the "Next DIFAT Sector Location" field.
|
||||
/// </remarks>
|
||||
public SectorNumber[] DIFATSectors { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// The directory entry array is an array of directory entries that
|
||||
/// are grouped into a directory sector. Each storage object or stream
|
||||
/// object within a compound file is represented by a single directory
|
||||
/// entry. The space for the directory sectors that are holding the
|
||||
/// array is allocated from the FAT.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// The first entry in the first sector of the directory chain (also
|
||||
/// referred to as the first element of the directory array, or stream
|
||||
/// ID #0) is known as the root directory entry, and it is reserved for
|
||||
/// two purposes. First, it provides a root parent for all objects that
|
||||
/// are stationed at the root of the compound file. Second, its function
|
||||
/// is overloaded to store the size and starting sector for the mini stream.
|
||||
///
|
||||
/// The root directory entry behaves as both a stream and a storage object.
|
||||
/// The root directory entry's Name field MUST contain the null-terminated
|
||||
/// string "Root Entry" in Unicode UTF-16.
|
||||
///
|
||||
/// The object class GUID (CLSID) that is stored in the root directory
|
||||
/// entry can be used for COM activation of the document's application.
|
||||
///
|
||||
/// The time stamps for the root storage are not maintained in the root
|
||||
/// directory entry. Rather, the root storage's creation and modification
|
||||
/// time stamps are normally stored on the file itself in the file system.
|
||||
///
|
||||
/// The Creation Time field in the root storage directory entry MUST be
|
||||
/// all zeroes. The Modified Time field in the root storage directory
|
||||
/// entry MAY be all zeroes.
|
||||
/// <remarks>
|
||||
public DirectoryEntry[] Directories { get; set; }
|
||||
}
|
||||
}
|
||||
7
BurnOutSharp.Models/CFB/Constants.cs
Normal file
7
BurnOutSharp.Models/CFB/Constants.cs
Normal file
@@ -0,0 +1,7 @@
|
||||
namespace BurnOutSharp.Models.CFB
|
||||
{
|
||||
public static class Constants
|
||||
{
|
||||
public static readonly byte[] Signature = new byte[] { 0xD0, 0xCF, 0x11, 0xE0, 0xA1, 0xB1, 0x1A, 0xE1 };
|
||||
}
|
||||
}
|
||||
133
BurnOutSharp.Models/CFB/DirectoryEntry.cs
Normal file
133
BurnOutSharp.Models/CFB/DirectoryEntry.cs
Normal file
@@ -0,0 +1,133 @@
|
||||
using System;
|
||||
|
||||
namespace BurnOutSharp.Models.CFB
|
||||
{
|
||||
/// <see href="https://winprotocoldoc.blob.core.windows.net/productionwindowsarchives/MS-CFB/%5bMS-CFB%5d.pdf"/>
|
||||
public sealed class DirectoryEntry
|
||||
{
|
||||
/// <summary>
|
||||
/// This field MUST contain a Unicode string for the storage or stream
|
||||
/// name encoded in UTF-16. The name MUST be terminated with a UTF-16
|
||||
/// terminating null character. Thus, storage and stream names are limited
|
||||
/// to 32 UTF-16 code points, including the terminating null character.
|
||||
/// When locating an object in the compound file except for the root
|
||||
/// storage, the directory entry name is compared by using a special
|
||||
/// case-insensitive uppercase mapping, described in Red-Black Tree.
|
||||
/// The following characters are illegal and MUST NOT be part of the
|
||||
/// name: '/', '\', ':', '!'.
|
||||
/// </summary>
|
||||
public string Name;
|
||||
|
||||
/// <summary>
|
||||
/// This field MUST be 0x00, 0x01, 0x02, or 0x05, depending on the
|
||||
/// actual type of object. All other values are not valid.
|
||||
/// </summary>
|
||||
public ushort NameLength;
|
||||
|
||||
/// <summary>
|
||||
/// This field MUST match the length of the Directory Entry Name Unicode
|
||||
/// string in bytes. The length MUST be a multiple of 2 and include the
|
||||
/// terminating null character in the count. This length MUST NOT exceed 64,
|
||||
/// the maximum size of the Directory Entry Name field.
|
||||
/// </summary>
|
||||
public ObjectType ObjectType;
|
||||
|
||||
/// <summary>
|
||||
/// This field MUST be 0x00 (red) or 0x01 (black). All other values are not valid.
|
||||
/// </summary>
|
||||
public ColorFlag ColorFlag;
|
||||
|
||||
/// <summary>
|
||||
/// This field contains the stream ID of the left sibling. If there
|
||||
/// is no left sibling, the field MUST be set to NOSTREAM (0xFFFFFFFF).
|
||||
/// </summary>
|
||||
public StreamID LeftSiblingID;
|
||||
|
||||
/// <summary>
|
||||
/// This field contains the stream ID of the right sibling. If there
|
||||
/// is no right sibling, the field MUST be set to NOSTREAM (0xFFFFFFFF).
|
||||
/// </summary>
|
||||
public StreamID RightSiblingID;
|
||||
|
||||
/// <summary>
|
||||
/// This field contains the stream ID of a child object. If there is no
|
||||
/// child object, including all entries for stream objects, the field
|
||||
/// MUST be set to NOSTREAM (0xFFFFFFFF).
|
||||
/// </summary>
|
||||
public StreamID ChildID;
|
||||
|
||||
/// <summary>
|
||||
/// This field contains an object class GUID, if this entry is for a
|
||||
/// storage object or root storage object. For a stream object, this field
|
||||
/// MUST be set to all zeroes. A value containing all zeroes in a storage
|
||||
/// or root storage directory entry is valid, and indicates that no object
|
||||
/// class is associated with the storage. If an implementation of the file
|
||||
/// format enables applications to create storage objects without explicitly
|
||||
/// setting an object class GUID, it MUST write all zeroes by default. If
|
||||
/// this value is not all zeroes, the object class GUID can be used as a
|
||||
/// parameter to start applications.
|
||||
/// </summary>
|
||||
public Guid CLSID;
|
||||
|
||||
/// <summary>
|
||||
/// This field contains the user-defined flags if this entry is for a storage
|
||||
/// object or root storage object. For a stream object, this field SHOULD be
|
||||
/// set to all zeroes because many implementations provide no way for
|
||||
/// applications to retrieve state bits from a stream object. If an
|
||||
/// implementation of the file format enables applications to create storage
|
||||
/// objects without explicitly setting state bits, it MUST write all zeroes
|
||||
/// by default.
|
||||
/// </summary>
|
||||
public uint StateBits;
|
||||
|
||||
/// <summary>
|
||||
/// This field contains the creation time for a storage object, or all zeroes
|
||||
/// to indicate that the creation time of the storage object was not recorded.
|
||||
/// The Windows FILETIME structure is used to represent this field in UTC.
|
||||
/// For a stream object, this field MUST be all zeroes. For a root storage
|
||||
/// object, this field MUST be all zeroes, and the creation time is retrieved
|
||||
/// or set on the compound file itself.
|
||||
/// </summary>
|
||||
public ulong CreationTime;
|
||||
|
||||
/// <summary>
|
||||
/// This field contains the modification time for a storage object, or all
|
||||
/// zeroes to indicate that the modified time of the storage object was not
|
||||
/// recorded. The Windows FILETIME structure is used to represent this field
|
||||
/// in UTC. For a stream object, this field MUST be all zeroes. For a root
|
||||
/// storage object, this field MAY<2> be set to all zeroes, and the modified
|
||||
/// time is retrieved or set on the compound file itself.
|
||||
/// </summary>
|
||||
public ulong ModifiedTime;
|
||||
|
||||
/// <summary>
|
||||
/// This field contains the first sector location if this is a stream object.
|
||||
/// For a root storage object, this field MUST contain the first sector of the
|
||||
/// mini stream, if the mini stream exists. For a storage object, this field MUST
|
||||
/// be set to all zeroes.
|
||||
/// </summary>
|
||||
public uint StartingSectorLocation;
|
||||
|
||||
/// <summary>
|
||||
/// This 64-bit integer field contains the size of the user-defined data if this
|
||||
/// is a stream object. For a root storage object, this field contains the size
|
||||
/// of the mini stream. For a storage object, this field MUST be set to all zeroes.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// For a version 3 compound file 512-byte sector size, the value of this field MUST
|
||||
/// be less than or equal to 0x80000000. (Equivalently, this requirement can be stated:
|
||||
/// the size of a stream or of the mini stream in a version 3 compound file MUST be
|
||||
/// less than or equal to 2 gigabytes (GB).) Note that as a consequence of this
|
||||
/// requirement, the most significant 32 bits of this field MUST be zero in a version
|
||||
/// 3 compound file. However, implementers should be aware that some older
|
||||
/// implementations did not initialize the most significant 32 bits of this field,
|
||||
/// and these bits might therefore be nonzero in files that are otherwise valid
|
||||
/// version 3 compound files. Although this document does not normatively specify
|
||||
/// parser behavior, it is recommended that parsers ignore the most significant 32 bits
|
||||
/// of this field in version 3 compound files, treating it as if its value were zero,
|
||||
/// unless there is a specific reason to do otherwise (for example, a parser whose
|
||||
/// purpose is to verify the correctness of a compound file).
|
||||
/// </remarks>
|
||||
public ulong StreamSize;
|
||||
}
|
||||
}
|
||||
72
BurnOutSharp.Models/CFB/Enums.cs
Normal file
72
BurnOutSharp.Models/CFB/Enums.cs
Normal file
@@ -0,0 +1,72 @@
|
||||
namespace BurnOutSharp.Models.CFB
|
||||
{
|
||||
public enum ColorFlag : byte
|
||||
{
|
||||
Red = 0x00,
|
||||
Black = 0x01,
|
||||
}
|
||||
|
||||
public enum ObjectType : byte
|
||||
{
|
||||
Unknown = 0x00,
|
||||
StorageObject = 0x01,
|
||||
StreamObject = 0x02,
|
||||
RootStorageObject = 0x05,
|
||||
}
|
||||
|
||||
public enum SectorNumber : uint
|
||||
{
|
||||
/// <summary>
|
||||
/// Regular sector number.
|
||||
/// </summary>
|
||||
REGSECT = 0x00000000, // 0x00000000 - 0xFFFFFFF9
|
||||
|
||||
/// <summary>
|
||||
/// Maximum regular sector number.
|
||||
/// </summary>
|
||||
MAXREGSECT = 0xFFFFFFFA,
|
||||
|
||||
/// <summary>
|
||||
/// Reserved for future use.
|
||||
/// </summary>
|
||||
NotApplicable = 0xFFFFFFFB,
|
||||
|
||||
/// <summary>
|
||||
/// Specifies a DIFAT sector in the FAT.
|
||||
/// </summary>
|
||||
DIFSECT = 0xFFFFFFFC,
|
||||
|
||||
/// <summary>
|
||||
/// Specifies a FAT sector in the FAT.
|
||||
/// </summary>
|
||||
FATSECT = 0xFFFFFFFD,
|
||||
|
||||
/// <summary>
|
||||
/// End of a linked chain of sectors.
|
||||
/// </summary>
|
||||
ENDOFCHAIN = 0xFFFFFFFE,
|
||||
|
||||
/// <summary>
|
||||
/// Specifies an unallocated sector in the FAT, Mini FAT, or DIFAT.
|
||||
/// </summary>
|
||||
FREESECT = 0xFFFFFFFF,
|
||||
}
|
||||
|
||||
public enum StreamID : uint
|
||||
{
|
||||
/// <summary>
|
||||
/// Regular stream ID to identify the directory entry.
|
||||
/// </summary>
|
||||
REGSID = 0x00000000, // 0x00000000 - 0xFFFFFFF9
|
||||
|
||||
/// <summary>
|
||||
/// Maximum regular stream ID.
|
||||
/// </summary>
|
||||
MAXREGSID = 0xFFFFFFFA,
|
||||
|
||||
/// <summary>
|
||||
/// Terminator or empty pointer.
|
||||
/// </summary>
|
||||
NOSTREAM = 0xFFFFFFFF,
|
||||
}
|
||||
}
|
||||
127
BurnOutSharp.Models/CFB/FileHeader.cs
Normal file
127
BurnOutSharp.Models/CFB/FileHeader.cs
Normal file
@@ -0,0 +1,127 @@
|
||||
using System;
|
||||
|
||||
namespace BurnOutSharp.Models.CFB
|
||||
{
|
||||
/// <see href="https://winprotocoldoc.blob.core.windows.net/productionwindowsarchives/MS-CFB/%5bMS-CFB%5d.pdf"/>
|
||||
public sealed class FileHeader
|
||||
{
|
||||
/// <summary>
|
||||
/// IOdentification signature for the compound file structure, and MUST be
|
||||
/// set to the value 0xD0, 0xCF, 0x11, 0xE0, 0xA1, 0xB1, 0x1A, 0xE1.
|
||||
/// </summary>
|
||||
public byte[] Signature;
|
||||
|
||||
/// <summary>
|
||||
/// Reserved and unused class ID that MUST be set to all zeroes (CLSID_NULL)
|
||||
/// </summary>
|
||||
public Guid CLSID;
|
||||
|
||||
/// <summary>
|
||||
/// Version number for nonbreaking changes. This field SHOULD be set to
|
||||
/// 0x003E if the major version field is either 0x0003 or 0x0004.
|
||||
/// </summary>
|
||||
public ushort MinorVersion;
|
||||
|
||||
/// <summary>
|
||||
/// Version number for breaking changes. This field MUST be set to either
|
||||
/// 0x0003 (version 3) or 0x0004 (version 4).
|
||||
/// </summary>
|
||||
public ushort MajorVersion;
|
||||
|
||||
/// <summary>
|
||||
/// This field MUST be set to 0xFFFE. This field is a byte order mark for
|
||||
/// all integer fields, specifying little-endian byte order.
|
||||
/// </summary>
|
||||
public ushort ByteOrder;
|
||||
|
||||
/// <summary>
|
||||
/// This field MUST be set to 0x0009, or 0x000c, depending on the Major
|
||||
/// Version field. This field specifies the sector size of the compound file
|
||||
/// as a power of 2.
|
||||
///
|
||||
/// If Major Version is 3, the Sector Shift MUST be 0x0009, specifying a
|
||||
/// sector size of 512 bytes.
|
||||
///
|
||||
/// If Major Version is 4, the Sector Shift MUST be 0x000C, specifying a
|
||||
/// sector size of 4096 bytes.
|
||||
/// </summary>
|
||||
public ushort SectorShift;
|
||||
|
||||
/// <summary>
|
||||
/// This field MUST be set to 0x0006. This field specifies the sector size
|
||||
/// of the Mini Stream as a power of 2. The sector size of the Mini Stream
|
||||
/// MUST be 64 bytes.
|
||||
/// </summary>
|
||||
public ushort MiniSectorShift;
|
||||
|
||||
/// <summary>
|
||||
/// This field MUST be set to all zeroes.
|
||||
/// </summary>
|
||||
public byte[] Reserved;
|
||||
|
||||
/// <summary>
|
||||
/// This integer field contains the count of the number of directory sectors
|
||||
/// in the compound file.
|
||||
///
|
||||
/// If Major Version is 3, the Number of Directory Sectors MUST be zero. This
|
||||
/// field is not supported for version 3 compound files.
|
||||
/// </summary>
|
||||
public uint NumberOfDirectorySectors;
|
||||
|
||||
/// <summary>
|
||||
/// This integer field contains the count of the number of FAT sectors in the
|
||||
/// compound file.
|
||||
/// </summary>
|
||||
public uint NumberOfFATSectors;
|
||||
|
||||
/// <summary>
|
||||
/// This integer field contains the starting sector number for the directory stream.
|
||||
/// </summary>
|
||||
public uint FirstDirectorySectorLocation;
|
||||
|
||||
/// <summary>
|
||||
/// This integer field MAY contain a sequence number that is incremented every time
|
||||
/// the compound file is saved by an implementation that supports file transactions.
|
||||
/// This is the field that MUST be set to all zeroes if file transactions are not
|
||||
/// implemented.
|
||||
/// </summary>
|
||||
public uint TransactionSignatureNumber;
|
||||
|
||||
/// <summary>
|
||||
/// This integer field MUST be set to 0x00001000. This field specifies the maximum
|
||||
/// size of a user-defined data stream that is allocated from the mini FAT and mini
|
||||
/// stream, and that cutoff is 4,096 bytes. Any user-defined data stream that is
|
||||
/// greater than or equal to this cutoff size must be allocated as normal sectors from
|
||||
/// the FAT.
|
||||
/// </summary>
|
||||
public uint MiniStreamCutoffSize;
|
||||
|
||||
/// <summary>
|
||||
/// This integer field contains the starting sector number for the mini FAT.
|
||||
/// </summary>
|
||||
public uint FirstMiniFATSectorLocation;
|
||||
|
||||
/// <summary>
|
||||
/// This integer field contains the count of the number of mini FAT sectors in the
|
||||
/// compound file.
|
||||
/// </summary>
|
||||
public uint NumberOfMiniFATSectors;
|
||||
|
||||
/// <summary>
|
||||
/// This integer field contains the starting sector number for the DIFAT.
|
||||
/// </summary>
|
||||
public uint FirstDIFATSectorLocation;
|
||||
|
||||
/// <summary>
|
||||
/// This integer field contains the count of the number of DIFAT sectors in the
|
||||
/// compound file.
|
||||
/// </summary>
|
||||
public uint NumberOfDIFATSectors;
|
||||
|
||||
/// <summary>
|
||||
/// This array of 32-bit integer fields contains the first 109 FAT sector
|
||||
/// locations of the compound file
|
||||
/// </summary>
|
||||
public uint[] DIFAT;
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user