Skip to content

Commit 5dfad11

Browse files
authored
Move VMA, XVA and VBK to dissect.archive (#8)
1 parent 4fe8392 commit 5dfad11

17 files changed

+2280
-3
lines changed

.gitattributes

+1-1
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
tests/data/basic.wim.gz filter=lfs diff=lfs merge=lfs -text
1+
tests/data/* filter=lfs diff=lfs merge=lfs -text

dissect/archive/c_vbk.py

+290
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,290 @@
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+
287+
c_vbk = cstruct().load(vbk_def)
288+
289+
PAGE_SIZE = c_vbk.PAGE_SIZE
290+
"""VBK page size."""

dissect/archive/c_vma.py

+60
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,60 @@
1+
from dissect.cstruct import cstruct
2+
3+
vma_def = """
4+
#define VMA_BLOCK_BITS 12
5+
#define VMA_BLOCK_SIZE (1 << VMA_BLOCK_BITS)
6+
#define VMA_CLUSTER_BITS (VMA_BLOCK_BITS + 4)
7+
#define VMA_CLUSTER_SIZE (1 << VMA_CLUSTER_BITS)
8+
9+
#define VMA_EXTENT_HEADER_SIZE 512
10+
#define VMA_BLOCKS_PER_EXTENT 59
11+
#define VMA_MAX_CONFIGS 256
12+
13+
#define VMA_MAX_EXTENT_SIZE (VMA_EXTENT_HEADER_SIZE + VMA_CLUSTER_SIZE * VMA_BLOCKS_PER_EXTENT)
14+
15+
/* File Format Definitions */
16+
17+
struct VmaDeviceInfoHeader {
18+
uint32 devname_ptr; /* offset into blob_buffer table */
19+
uint32 reserved0;
20+
uint64 size; /* device size in bytes */
21+
uint64 reserved1;
22+
uint64 reserved2;
23+
};
24+
25+
struct VmaHeader {
26+
char magic[4];
27+
uint32 version;
28+
char uuid[16];
29+
int64 ctime;
30+
char md5sum[16];
31+
32+
uint32 blob_buffer_offset;
33+
uint32 blob_buffer_size;
34+
uint32 header_size;
35+
36+
char _reserved1[1984];
37+
38+
uint32 config_names[VMA_MAX_CONFIGS]; /* offset into blob_buffer table */
39+
uint32 config_data[VMA_MAX_CONFIGS]; /* offset into blob_buffer table */
40+
41+
char _reserved2[4];
42+
43+
VmaDeviceInfoHeader dev_info[256];
44+
};
45+
46+
struct VmaExtentHeader {
47+
char magic[4];
48+
uint16 reserved1;
49+
uint16 block_count;
50+
char uuid[16];
51+
char md5sum[16];
52+
uint64 blockinfo[VMA_BLOCKS_PER_EXTENT];
53+
};
54+
"""
55+
56+
c_vma = cstruct(endian=">").load(vma_def)
57+
58+
59+
VMA_MAGIC = b"VMA\x00"
60+
VMA_EXTENT_MAGIC = b"VMAE"

dissect/archive/exceptions.py

+6-2
Original file line numberDiff line numberDiff line change
@@ -6,11 +6,15 @@ class InvalidHeaderError(Error):
66
pass
77

88

9-
class NotADirectoryError(Error):
9+
class FileNotFoundError(Error, FileNotFoundError):
1010
pass
1111

1212

13-
class FileNotFoundError(Error):
13+
class IsADirectoryError(Error, IsADirectoryError):
14+
pass
15+
16+
17+
class NotADirectoryError(Error, NotADirectoryError):
1418
pass
1519

1620

dissect/archive/tools/__init__.py

Whitespace-only changes.

0 commit comments

Comments
 (0)