This commit is contained in:
Burgess Leo
2025-05-19 17:33:30 +08:00
parent 07a4ae7a74
commit 697b449bff
4 changed files with 252 additions and 86 deletions

View File

@@ -60,7 +60,7 @@ def GetFileMftEntry(file_path):
drive_letter = os.path.splitdrive(file_path)[0][0]
device = f"\\\\.\\{drive_letter}:"
print(f"Opening device: {device}")
# print(f"Opening device: {device}")
try:
img = pytsk3.Img_Info(device)
@@ -73,10 +73,10 @@ def GetFileMftEntry(file_path):
root_path = f"{drive_letter}:\\"
rel_path = os.path.relpath(abs_path, root_path).replace("/", "\\")
print(f"Looking up MFT entry for: {rel_path}")
# print(f"Looking up MFT entry for: {rel_path}")
mft_entry = find_file_mft_entry(fs, rel_path)
print(f"MFT Entry: {mft_entry}")
# print(f"MFT Entry: {mft_entry}")
if mft_entry is None:
raise RuntimeError("Could not find MFT entry for the specified file.")
@@ -105,7 +105,7 @@ def CalculateFileMftStartSector(mft_entry, volume_letter="Z"):
start_sector = config_data["MftPosition"] * 8 + mft_entry * 2
if start_sector < 0:
raise ValueError("起始扇区号不能为负数")
print(f"文件 MFT Entry 的起始扇区号: {start_sector}")
# print(f"文件 MFT Entry 的起始扇区号: {start_sector}")
return start_sector
@@ -217,11 +217,106 @@ def GetFile80hPattern(file_path):
try:
mft_entry_value = GetFileMftEntry(file_path)
StartSector = CalculateFileMftStartSector(mft_entry_value, volume_letter)
print(f"\n文件的相关信息以及80属性内容")
print(Get80hPattern(StartSector, volume_letter))
# print(f"文件的相关信息以及80属性内容")
# print(Get80hPattern(StartSector, volume_letter))
file80h_pattern = Get80hPattern(StartSector, volume_letter)
return file80h_pattern
except Exception as e:
print(f"❌ Error: {e}")
return None
if __name__ == '__main__':
GetFile80hPattern(r"Z:\hello.txt")
# if __name__ == '__main__':
# GetFile80hPattern(r"Z:\demo.jpg")
def analyze_ntfs_data_attribute(data):
"""
分析 NTFS 数据结构中的80属性($DATA),返回文件分片数量
参数:
data (list): 包含字典的列表,每个字典需有'sequence'
(示例结构见问题描述)
返回:
int: 分片数量(常驻属性返回1非常驻属性返回数据运行的分片数)
异常:
ValueError: 当输入数据无效时抛出
"""
# 第一步提取并转换sequence数据
hex_bytes = []
for entry in data:
if 'sequence' in entry:
for hex_str in entry['sequence']:
hex_bytes.extend(hex_str.split())
# 将十六进制字符串转换为整数列表
try:
attribute_data = [int(x, 16) for x in hex_bytes]
except ValueError:
raise ValueError("无效的十六进制数据")
# 第二步:分析属性结构
if len(attribute_data) < 24:
raise ValueError("属性数据过短,无法解析头部信息")
# 检查属性类型(0x80)
if attribute_data[0] != 0x80:
raise ValueError("不是80属性($DATA属性)")
# 检查是否常驻(偏移0x08)
is_resident = attribute_data[8] == 0
if is_resident:
return 1
else:
# 解析非常驻属性的数据运行列表
data_run_offset = attribute_data[0x20] | (attribute_data[0x21] << 8)
if data_run_offset >= len(attribute_data):
raise ValueError("数据运行偏移超出属性长度")
data_runs = attribute_data[data_run_offset:]
fragment_count = 0
pos = 0
while pos < len(data_runs):
header_byte = data_runs[pos]
if header_byte == 0x00:
break
len_len = (header_byte >> 4) & 0x0F
offset_len = header_byte & 0x0F
if len_len == 0 or offset_len == 0:
break
pos += 1 + len_len + offset_len
fragment_count += 1
return fragment_count
input_data = [
{
'start_byte': 3221267456,
'offset': 264,
'sequence': [
'80 00 00 00 48 00 00 00',
'01 00 00 00 00 00 01 00',
'00 00 00 00 00 00 00 00',
'79 00 00 00 00 00 00 00',
'40 00 00 00 00 00 00 00',
'00 a0 07 00 00 00 00 00',
'0b 93 07 00 00 00 00 00',
'0b 93 07 00 00 00 00 00',
'31 7a 00 ee 0b 00 00 00'
],
'is_resident': False,
'total_groups': 9,
'attribute_length': 72
}
]
print(analyze_ntfs_data_attribute(input_data)) # 输出分片数量