不知道这是不是复制品,反正我的Google-fu很弱,如果我输入超过五个单词,Google几乎找不到任何相关的东西.
我正在try 解析位于"//?/X:/$MFT"
的主文件表,我知道try 直接打开它将提高PermissionDenied
.当然,我已经想出了一种绕过它的方法.通过打开"//?/X:"
,这创建了一个句柄,允许我读取 bootstrap 扇区,然后我可以从那里读取MFT…
我已经编写了代码,或者至少其中的绝大多数,我已经可以将所有的MFT读取到主内存中,但在这个阶段,内存使用率很高,信息组织得不好.但在this documentation的帮助下,我已经解析了所有我想要的信息.
你可以看到我的代码here.
正如您从我的代码中看到的,我使用大量偏移量将字节分割成块,并调用相应的函数迭代地解码这些块,我将向您展示我的意思:
from typing import NamedTuple
class Record_Header_Flags(NamedTuple):
In_Use: bool
Directory: bool
Extension: bool
Special_Index: bool
class Record_Header(NamedTuple):
LogFile_Serial: int
Written: int
Hardlinks: int
Flags: Record_Header_Flags
Record_Size: int
Base_Record: int
Base_Writes: int
Record_ID: int
HEADER_FLAGS = (1, 2, 4, 8)
def parse_signed_little_endian(data: bytes) -> int:
return (
-1 * (1 + sum((b ^ 0xFF) * (1 << i * 8) for i, b in enumerate(data)))
if data[-1] & 128
else int.from_bytes(data, "little")
)
def parse_little_endian(data: bytes) -> int:
return int.from_bytes(data, "little")
def parse_header_flags(data: bytes) -> Record_Header_Flags:
flag = data[0]
return Record_Header_Flags(*(bool(flag & bit) for bit in HEADER_FLAGS))
FILE_RECORD_HEADER = (
(8, 16, parse_little_endian),
(16, 18, parse_little_endian),
(18, 20, parse_little_endian),
(22, 24, parse_header_flags),
(24, 28, parse_little_endian),
(32, 38, parse_little_endian),
(38, 40, parse_little_endian),
(44, 48, parse_little_endian),
)
def parse_record_header(data: bytes) -> Record_Header:
return Record_Header(
*(func(data[start:end]) for start, end, func in FILE_RECORD_HEADER)
)
data = b"FILE0\x00\x03\x00\x9dt \x13\x0c\x00\x00\x00\x08\x00\x02\x008\x00\x01\x00\xd8\x01\x00\x00\x00\x04\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x05\x00\x00\x00\xff\xff\x00\x00"
print(parse_record_header(data))
Record_Header(LogFile_Serial=51860501661, Written=8, Hardlinks=2, Flags=Record_Header_Flags(In_Use=True, Directory=False, Extension=False, Special_Index=False), Record_Size=472, Base_Record=0, Base_Writes=0, Record_ID=65535)
有人告诉我,这是低效和不毕达式的,正确的方法是使用struct
和ctypes
的组合.
我知道我可以使用struct.unpack("<i", data)[0]
解析4字节的小端序列,格式为:"<I"
的4字节无符号LE,"<q"
的8字节LE和"<Q"
的8字节ULE.但有些值是6字节的序列.
我不知道如何使用ctypes
种 struct .
此外,MFT使用非标准格式,如Windows文件时间:
from datetime import datetime, timedelta
from typing import NamedTuple
EPOCH = datetime(1601, 1, 1, 0, 0, 0)
def parse_NTFS_timestamp(data: bytes) -> datetime:
return EPOCH + timedelta(seconds=int.from_bytes(data, "little") * 1e-7)
如何使用ctypes
和struct
来解析我给出的示例,并解析包含非标准编码的字节序列,例如0x10$STANDARD_INFORMATION中的时间戳字段?