237 lines
5.8 KiB
Python
237 lines
5.8 KiB
Python
import os
|
|
import enum
|
|
from destruct import Struct, Switch
|
|
|
|
from .index import IndexNode
|
|
|
|
|
|
Attribute = Switch()
|
|
|
|
def attribute(id):
|
|
def inner(c):
|
|
Attribute.options[id] = c
|
|
return c
|
|
return inner
|
|
|
|
|
|
|
|
class FileFlag(enum.Flag):
|
|
ReadOnly = 1 << 0
|
|
Hidden = 1 << 1
|
|
System = 1 << 2
|
|
Archived = 1 << 5
|
|
Device = 1 << 6
|
|
Normal = 1 << 7
|
|
Temporary = 1 << 8
|
|
Sparse = 1 << 9
|
|
ReparsePoint = 1 << 10
|
|
Compressed = 1 << 11
|
|
Offline = 1 << 12
|
|
NotIndexed = 1 << 13
|
|
Encrypted = 1 << 14
|
|
Directory = 1 << 28
|
|
IndexView = 1 << 29
|
|
Unk31 = 1 << 31
|
|
|
|
@attribute(0x10)
|
|
class StandardInformationAttribute(Struct, partial=True):
|
|
creation_time = UInt(64)
|
|
modification_time = UInt(64)
|
|
meta_modification_time = UInt(64)
|
|
access_time = UInt(64)
|
|
flags = Enum(FileFlag, UInt(32))
|
|
version_max = UInt(32)
|
|
version = UInt(32)
|
|
class_id = UInt(32)
|
|
owner_id = UInt(32)
|
|
security_id = UInt(32)
|
|
quota_amount = UInt(64)
|
|
usn = UInt(64)
|
|
|
|
@attribute(0x20)
|
|
class AttributeListAttribute(Struct):
|
|
type = UInt(32)
|
|
length = UInt(16)
|
|
name_length = UInt(8)
|
|
name_offset = UInt(8)
|
|
vcn_start = UInt(64)
|
|
base_file_reference = UInt(64)
|
|
id = UInt(16)
|
|
name = Ref(Str(kind='raw', exact=True, elem_size=2, encoding='utf-16le'), reference=os.SEEK_CUR)
|
|
|
|
def on_name_length(self, spec, context):
|
|
spec.name.child.length = self.name_length
|
|
|
|
def on_name_offset(self, spec, context):
|
|
spec.name.point = self.name_offset - 0x1A
|
|
|
|
class FilenameNamespace(enum.Enum):
|
|
POSIX = 0
|
|
Win32 = 1
|
|
DOS = 2
|
|
WinDOS = 3
|
|
|
|
@attribute(0x30)
|
|
class FileNameAttribute(Struct):
|
|
parent_file = UInt(64)
|
|
creation_time = UInt(64)
|
|
modification_time = UInt(64)
|
|
meta_modification_time = UInt(64)
|
|
access_time = UInt(64)
|
|
allocated_size = UInt(64)
|
|
real_size = UInt(64)
|
|
flags = Enum(FileFlag, UInt(32))
|
|
unk3c = UInt(32)
|
|
length = UInt(8)
|
|
namespace = Enum(FilenameNamespace, UInt(8))
|
|
name = Str(kind='raw', exact=True, elem_size=2, encoding='utf-16le')
|
|
|
|
def on_length(self, spec, context):
|
|
spec.name.length = self.length
|
|
|
|
class GUID(Struct):
|
|
data = Data(16)
|
|
|
|
def __str__(self):
|
|
return '{{{}-{}-{}-{}-{}}}'.format(
|
|
self.data[0:4].hex(), self.data[4:6].hex(), self.data[6:8].hex(),
|
|
self.data[8:10].hex(), self.data[8:16].hex()
|
|
)
|
|
|
|
@attribute(0x40)
|
|
class ObjectIDAttribute(Struct, partial=True):
|
|
id = GUID
|
|
origin_volume_id = GUID
|
|
origin_id = GUID
|
|
origin_domain_id = GUID
|
|
|
|
class SecurityDescriptorFlag(enum.Flag):
|
|
DefaultOwner = 1 << 0
|
|
DefaultGroup = 1 << 1
|
|
HasDACL = 1 << 2
|
|
DefaultDACL = 1 << 3
|
|
HasSACL = 1 << 4
|
|
DefaultSACL = 1 << 5
|
|
NeedInheritDACL = 1 << 8
|
|
NeedInheritSACL = 1 << 9
|
|
InheritedDACL = 1 << 10
|
|
InheritedSACL = 1 << 11
|
|
ProtectedDACL = 1 << 12
|
|
ProtectedSACL = 1 << 13
|
|
ValidRMControl = 1 << 14
|
|
SelfRelative = 1 << 15
|
|
|
|
class AccessRight(enum.Flag):
|
|
StandardDelete = 1 << 16
|
|
StandardReadControl = 1 << 17
|
|
StandardWriteDAC = 1 << 18
|
|
StandardWriteOwner = 1 << 19
|
|
StandardSynchronize = 1 << 20
|
|
ACL = 1 << 23
|
|
GenericAll = 1 << 28
|
|
GenericExecute = 1 << 29
|
|
GenericWrite = 1 << 30
|
|
GenericRead = 1 << 31
|
|
|
|
class ACEType(enum.Enum):
|
|
# V1, V2
|
|
Allow = 0
|
|
Deny = 1
|
|
Audit = 2
|
|
Alarm = 3
|
|
# V3
|
|
AllowCompound = 4
|
|
# V4
|
|
AllowObject = 5
|
|
DenyObject = 6
|
|
AuditObject = 7
|
|
AlarmObject = 8
|
|
|
|
class ACEFlag(enum.Flag):
|
|
InheritObject = 1 << 0
|
|
InheritContainer = 1 << 1
|
|
InheritNoPropagate = 1 << 2
|
|
InheritOnly = 1 << 3
|
|
Inherited = 1 << 4
|
|
AuditSuccess = 1 << 6
|
|
AuditFail = 1 < 7
|
|
|
|
class ACE(Struct):
|
|
type = Enum(ACEType, UInt(8))
|
|
flags = Enum(ACEFlag, UInt(8))
|
|
size = UInt(16)
|
|
access = UInt(32)
|
|
data = Data()
|
|
|
|
def on_size(self, spec, context):
|
|
spec.data.length = self.size
|
|
|
|
class ACL(Struct):
|
|
revision = UInt(8)
|
|
_pad1 = Pad(1)
|
|
length = UInt(16)
|
|
entry_count = UInt(16)
|
|
_pad6 = Pad(2)
|
|
entries = Arr(ACE)
|
|
|
|
def on_entry_count(self, spec, context):
|
|
spec.count = self.on_entry_count
|
|
|
|
@attribute(0x50)
|
|
class SecurityDescriptorAttribute(Struct):
|
|
revision = UInt(8)
|
|
_pad1 = Pad(1)
|
|
flags = Enum(SecurityDescriptorFlag, UInt(16))
|
|
user_sid_offset = UInt(32)
|
|
group_sid_offset = UInt(32)
|
|
sacl_offset = UInt(32)
|
|
dacl_offset = UInt(32)
|
|
|
|
@attribute(0x60)
|
|
class VolumeNameAttribute(Struct):
|
|
name = Str(kind='raw', exact=True, elem_size=2, encoding='utf-16le')
|
|
|
|
class VolumeInformationFlag(enum.Flag):
|
|
Dirty = 1 << 0
|
|
ResizeLog = 1 << 1
|
|
DoUpgrade = 1 << 2
|
|
MountedByNT4 = 1 << 3
|
|
DeletingUSN = 1 << 4
|
|
RepairIDs = 1 << 5
|
|
ChkDskModified = 1 << 15
|
|
|
|
@attribute(0x70)
|
|
class VolumeInformationAttribute(Struct):
|
|
_pad0 = Pad(8)
|
|
version_major = UInt(8)
|
|
version_minor = UInt(8)
|
|
flags = Enum(VolumeInformationFlag, UInt(16))
|
|
|
|
@attribute(0x80)
|
|
class DataAttribute(Struct):
|
|
data = Data(0)
|
|
|
|
@attribute(0x90)
|
|
class IndexRootAttribute(Struct):
|
|
type = UInt(32)
|
|
collation = UInt(32)
|
|
record_size = UInt(32)
|
|
record_cluster_count = UInt(8)
|
|
_pad3 = Pad(3)
|
|
node = IndexNode[...]
|
|
|
|
def on_type(self, spec, context):
|
|
spec.node = IndexNode[Attribute.options[self.type]]
|
|
|
|
@attribute(0xA0)
|
|
class IndexAllocationAttribute(Struct, generics=['G']):
|
|
nodes = Arr(IndexNode[G])
|
|
|
|
@attribute(0xB0)
|
|
class BitmapAttribute(Struct):
|
|
data = Data(0)
|
|
|
|
@attribute(0x100)
|
|
class LoggedUtilityStreamAttribute(Struct):
|
|
data = Data(0)
|