|
| 1 | +from dissect.cstruct import cstruct |
| 2 | + |
| 3 | +vbk_def = """ |
| 4 | +#define PAGE_SIZE 4096 |
| 5 | +
|
| 6 | +/* Storage header */ |
| 7 | +
|
| 8 | +struct StorageHeader { |
| 9 | + uint32 FormatVersion; /* 0x0000 */ |
| 10 | + uint32 Initialized; /* 0x0004 */ |
| 11 | + uint32 DigestTypeLength; /* 0x0008 */ |
| 12 | + char DigestType[251]; /* 0x000C */ |
| 13 | + uint32 SnapshotSlotFormat; /* 0x0107 format > 5 -> crc32c */ |
| 14 | + uint32 StandardBlockSize; /* 0x010B */ |
| 15 | + uint8 ClusterAlign; /* 0x010F */ |
| 16 | + char Unk0[16]; /* 0x0120 */ |
| 17 | + char ExternalStorageId[16]; /* 0x0130 */ |
| 18 | +}; |
| 19 | +
|
| 20 | +/* Snapshot header */ |
| 21 | +
|
| 22 | +struct SnapshotSlotHeader { |
| 23 | + uint32 CRC; |
| 24 | + uint32 ContainsSnapshot; |
| 25 | +}; |
| 26 | +
|
| 27 | +struct DirectoryRootRecord { |
| 28 | + int64 RootPage; /* Root page of the directory */ |
| 29 | + uint64 Count; /* Number of children */ |
| 30 | +}; |
| 31 | +
|
| 32 | +struct BlocksStoreHeader { |
| 33 | + int64 RootPage; /* Root of the blocks store */ |
| 34 | + uint64 Count; /* Number of blocks store entries */ |
| 35 | + int64 FreeRootPage; /* Root of the free blocks tree */ |
| 36 | + int64 DeduplicationRootPage; /* Root of the deduplication tree */ |
| 37 | + int64 Unk0; |
| 38 | + int64 Unk1; |
| 39 | +}; |
| 40 | +
|
| 41 | +struct CryptoStoreRecord { |
| 42 | + int64 RootPage; /* Root of the crypto store */ |
| 43 | +}; |
| 44 | +
|
| 45 | +struct SnapshotDescriptor { |
| 46 | + uint64 Version; /* Acts as a sequence number, highest is active slot */ |
| 47 | + uint64 StorageEOF; /* End of file, aka file size */ |
| 48 | + uint32 BanksCount; /* Number of banks */ |
| 49 | + DirectoryRootRecord DirectoryRoot; /* Directory root record */ |
| 50 | + BlocksStoreHeader BlocksStore; /* Blocks store header */ |
| 51 | + CryptoStoreRecord CryptoStore; /* Crypto store record */ |
| 52 | + uint64 Unk0; |
| 53 | + uint64 Unk1; |
| 54 | +}; |
| 55 | +
|
| 56 | +struct BankDescriptor { |
| 57 | + uint32 CRC; |
| 58 | + uint64 Offset; |
| 59 | + uint32 Size; |
| 60 | +}; |
| 61 | +
|
| 62 | +struct BanksGrain { |
| 63 | + uint32 MaxBanks; |
| 64 | + uint32 StoredBanks; |
| 65 | + // BankDescriptor Banks[StoredBanks]; |
| 66 | +}; |
| 67 | +
|
| 68 | +/* Block headers */ |
| 69 | +
|
| 70 | +struct BankHeader { |
| 71 | + uint16 PageCount; |
| 72 | + uint16 Flags; |
| 73 | + char Unk0[3064]; |
| 74 | + uint64 Unk1; |
| 75 | + char Unk2[1020]; |
| 76 | +}; |
| 77 | +
|
| 78 | +struct BankHeaderV71 { |
| 79 | + uint16 PageCount; |
| 80 | + uint16 Flags; /* 2 == encrypted */ |
| 81 | + char Unk0[3072]; |
| 82 | + char KeySetId[16]; |
| 83 | + char Unk1[16]; |
| 84 | + char Unk2[16]; |
| 85 | + uint32 Unk3; |
| 86 | + char Unk4[968]; |
| 87 | +}; |
| 88 | +
|
| 89 | +struct MetaBlobHeader { |
| 90 | + int64 NextPage; |
| 91 | + int32 Unk0; |
| 92 | +}; |
| 93 | +
|
| 94 | +struct Lz4BlockHeader { |
| 95 | + uint32 Magic; /* 0xF800000F */ |
| 96 | + uint32 CRC; /* CRC32C of the compressed data */ |
| 97 | + uint32 SourceSize; |
| 98 | +}; |
| 99 | +
|
| 100 | +/* DirItem headers */ |
| 101 | +struct BlocksVectorHeader { |
| 102 | + uint64 RootPage; |
| 103 | + uint64 Count; |
| 104 | +}; |
| 105 | +
|
| 106 | +struct SubFolderHeader { |
| 107 | + uint64 RootPage; /* 0x94 */ |
| 108 | + uint32 Count; /* 0x9C */ |
| 109 | + char Data[32]; /* 0xA0 */ |
| 110 | +}; /* 0xC0 */ |
| 111 | +
|
| 112 | +struct ExtFibHeader { |
| 113 | + uint16 UpdateInProgress; /* 0x94 */ |
| 114 | + uint8 Unk3; /* 0x96 */ |
| 115 | + uint8 Format; /* 0x97 Bit 3 == 1 */ |
| 116 | + BlocksVectorHeader BlocksVector; /* 0x98 */ |
| 117 | + uint64 FibSize; /* 0xA8 */ |
| 118 | + uint64 Size; /* 0xB0 */ |
| 119 | + uint8 FsObjAttachState; /* 0xB8 */ |
| 120 | + char Data[7]; /* 0xB9 */ |
| 121 | +}; /* 0xC0 */ |
| 122 | +
|
| 123 | +struct IntFibHeader { |
| 124 | + uint16 UpdateInProgress; /* 0x94 */ |
| 125 | + uint8 Unk3; /* 0x96 */ |
| 126 | + uint8 Format; /* 0x97 Bit 3 == 1 */ |
| 127 | + BlocksVectorHeader BlocksVector; /* 0x98 */ |
| 128 | + uint64 FibSize; /* 0xA8 */ |
| 129 | + uint64 Size; /* 0xB0 */ |
| 130 | + uint8 FsObjAttachState; /* 0xB8 */ |
| 131 | + char Data[7]; /* 0xB9 */ |
| 132 | +}; /* 0xC0 */ |
| 133 | +
|
| 134 | +struct PatchHeader { |
| 135 | + uint32 Unk0; /* 0x94 */ |
| 136 | + BlocksVectorHeader BlocksVector; /* 0x98 */ |
| 137 | + uint64 FibSize; /* 0xA8 Source file size */ |
| 138 | + uint64 Unk4; /* 0xB0 */ |
| 139 | + char Data[8]; /* 0xB8 */ |
| 140 | +}; /* 0xC0 */ |
| 141 | +
|
| 142 | +struct IncrementHeader { |
| 143 | + uint32 Unk0; /* 0x94 */ |
| 144 | + BlocksVectorHeader BlocksVector; /* 0x98 */ |
| 145 | + uint64 FibSize; /* 0xA8 Original FIB size */ |
| 146 | + uint64 Unk4; /* 0xB0 */ |
| 147 | + char Data[8]; /* 0xB8 */ |
| 148 | +}; /* 0xC0 */ |
| 149 | +
|
| 150 | +enum DirItemType : uint32 { |
| 151 | + None = 0, |
| 152 | + SubFolder = 1, |
| 153 | + ExtFib = 2, |
| 154 | + IntFib = 3, |
| 155 | + Patch = 4, |
| 156 | + Increment = 5, |
| 157 | +}; |
| 158 | +
|
| 159 | +struct DirItemRecord { |
| 160 | + DirItemType Type; /* 0x00 */ |
| 161 | + uint32 NameLength; /* 0x04 */ |
| 162 | + char Name[128]; /* 0x08 */ |
| 163 | + int64 PropsRootPage; /* 0x88 */ |
| 164 | + uint32 Unk1; /* 0x90 */ |
| 165 | + union { /* 0x94 */ |
| 166 | + char Data[44]; |
| 167 | + SubFolderHeader SubFolder; |
| 168 | + ExtFibHeader ExtFib; |
| 169 | + IntFibHeader IntFib; |
| 170 | + PatchHeader Patch; |
| 171 | + IncrementHeader Increment; |
| 172 | + }; |
| 173 | +}; |
| 174 | +
|
| 175 | +/* Block descriptors */ |
| 176 | +
|
| 177 | +flag BlockFlags : uint8 { |
| 178 | + None = 0x00, |
| 179 | + Updated = 0x01, |
| 180 | + CommitInProgress = 0x02, |
| 181 | +}; |
| 182 | +
|
| 183 | +enum BlockLocationType : uint8 { |
| 184 | + Normal = 0x00, |
| 185 | + Sparse = 0x01, |
| 186 | + Reserved = 0x02, |
| 187 | + Archived = 0x03, /* CompressedSize | (CompressionType << 32) */ |
| 188 | + BlockInBlob = 0x04, /* BlockId? & 0x3FFFFFF | (BlobId << 26) | ((Offset >> 9) << 42) */ |
| 189 | + BlockInBlobReserved = 0x05, /* BlockId? | 0xFFFFFFFFFC000000 */ |
| 190 | +}; |
| 191 | +
|
| 192 | +enum CompressionType : int8 { |
| 193 | + Plain = -1, |
| 194 | + RL = 2, |
| 195 | + ZLH = 3, |
| 196 | + ZLL = 4, |
| 197 | + LZ4 = 7, |
| 198 | +}; |
| 199 | +
|
| 200 | +struct MetaTableDescriptor { |
| 201 | + int64 RootPage; |
| 202 | + uint64 BlockSize; |
| 203 | + uint64 Count; |
| 204 | +}; |
| 205 | +
|
| 206 | +struct StgBlockDescriptor { |
| 207 | + uint8 Format; /* Format != 4 == legacy */ |
| 208 | + uint32 UsageCounter; |
| 209 | + uint64 Offset; |
| 210 | + uint32 AllocatedSize; |
| 211 | + uint8 Deduplication; |
| 212 | + char Digest[16]; |
| 213 | + CompressionType CompressionType; |
| 214 | + uint8 Unk0; |
| 215 | + uint32 CompressedSize; |
| 216 | + uint32 SourceSize; |
| 217 | +}; |
| 218 | +
|
| 219 | +struct StgBlockDescriptorV7 { |
| 220 | + uint8 Format; /* Format != 4 == legacy */ |
| 221 | + uint32 UsageCounter; |
| 222 | + uint64 Offset; |
| 223 | + uint32 AllocatedSize; |
| 224 | + uint8 Deduplication; |
| 225 | + char Digest[16]; |
| 226 | + CompressionType CompressionType; |
| 227 | + uint8 Unk0; |
| 228 | + uint32 CompressedSize; |
| 229 | + uint32 SourceSize; |
| 230 | + char KeySetId[16]; |
| 231 | +}; |
| 232 | +
|
| 233 | +struct FibBlockDescriptor { |
| 234 | + uint32 BlockSize; |
| 235 | + BlockLocationType Type; |
| 236 | + char Digest[16]; |
| 237 | + // union { |
| 238 | + // struct { |
| 239 | + // uint32 ArchiveUsedSize; |
| 240 | + // uint8 ArchiveCompressionType; |
| 241 | + // uint8 Unk3; |
| 242 | + // uint16 Unk4; |
| 243 | + // } Archived; |
| 244 | + // uint64 Offset; |
| 245 | + // }; |
| 246 | + uint64 BlockId; /* For performance reasons we just put a uint64 here, but this is actually a union */ |
| 247 | + BlockFlags Flags; |
| 248 | +}; |
| 249 | +
|
| 250 | +struct FibBlockDescriptorV7 { |
| 251 | + uint32 BlockSize; |
| 252 | + BlockLocationType Type; |
| 253 | + char Digest[16]; |
| 254 | + // union { |
| 255 | + // struct { |
| 256 | + // uint32 ArchiveUsedSize; |
| 257 | + // uint8 ArchiveCompressionType; |
| 258 | + // uint8 Unk3; |
| 259 | + // uint16 Unk4; |
| 260 | + // } Archived; |
| 261 | + // uint64 Offset; |
| 262 | + // }; |
| 263 | + uint64 BlockId; /* For performance reasons we just put a uint64 here, but this is actually a union */ |
| 264 | + BlockFlags Flags; |
| 265 | + char KeySetId[16]; |
| 266 | +}; |
| 267 | +
|
| 268 | +struct PatchBlockDescriptor { |
| 269 | +}; |
| 270 | +
|
| 271 | +struct PatchBlockDescriptorV7 { |
| 272 | +}; |
| 273 | +
|
| 274 | +/* Property dictionary */ |
| 275 | +
|
| 276 | +enum PropertyType : int32 { |
| 277 | + UInt32 = 1, |
| 278 | + UInt64 = 2, |
| 279 | + AString = 3, |
| 280 | + WString = 4, |
| 281 | + Binary = 5, |
| 282 | + Boolean = 6, |
| 283 | + End = -1, |
| 284 | +}; |
| 285 | +""" # noqa: E501 |
| 286 | +c_vbk = cstruct() |
| 287 | +c_vbk.load(vbk_def) |
0 commit comments