diff --git a/db_manage/clear_table_record.py b/db_manage/clear_table_record.py index c9d4b64..5e585cd 100644 --- a/db_manage/clear_table_record.py +++ b/db_manage/clear_table_record.py @@ -25,5 +25,5 @@ def ClearTableRecordsWithReset(db_path, table_name): if __name__ == '__main__': # ClearTableRecordsWithReset(db_path='../src/db_ntfs_info.db', table_name='db_path') # ClearTableRecordsWithReset(db_path='../src/db_ntfs_info.db', table_name='db_device') - # ClearTableRecordsWithReset(db_path='../src/db_ntfs_info.db', table_name='db_config') - ClearTableRecordsWithReset(db_path='../src/db_ntfs_info.db', table_name='db_node') + ClearTableRecordsWithReset(db_path='../src/db_ntfs_info.db', table_name='db_config') + # ClearTableRecordsWithReset(db_path='../src/db_ntfs_info.db', table_name='db_node') diff --git a/ntfs_utils/db_config.py b/ntfs_utils/db_config.py index 251607d..edb3040 100644 --- a/ntfs_utils/db_config.py +++ b/ntfs_utils/db_config.py @@ -8,9 +8,10 @@ def GetNTFSBootInfo(volume_letter): - Bytes per sector - Sectors per cluster - Cluster size (bytes) + - $MFT 起始簇号 参数: - volume_letter: 卷标字符串,例如 'C' + volume_letter: str,卷标字符串,例如 'C' 返回: dict 包含上述信息 @@ -62,10 +63,15 @@ def GetNTFSBootInfo(volume_letter): # 计算簇大小 cluster_size = bytes_per_sector * sectors_per_cluster + # 解析 $MFT 起始簇号(LCN),偏移 0x30,QWORD(8 字节) + mft_lcn_bytes = buffer[0x30:0x38] + mft_lcn = int.from_bytes(mft_lcn_bytes, byteorder='little', signed=False) + return { "BytesPerSector": bytes_per_sector, "SectorsPerCluster": sectors_per_cluster, - "ClusterSize": cluster_size + "ClusterSize": cluster_size, + "MftPosition": mft_lcn } diff --git a/ntfs_utils/db_node.py b/ntfs_utils/db_node.py index 9797d16..b6ef005 100644 --- a/ntfs_utils/db_node.py +++ b/ntfs_utils/db_node.py @@ -2,6 +2,8 @@ import hashlib import random import sqlite3 +from mft_analyze import GetFile80hPattern + # 工具函数:获取文件扩展名 def GetFileExtension(name: str) -> str: @@ -64,7 +66,23 @@ def GetFileHash(full_path: str) -> str: # 获取分片数(1~4) def GetExtentCount(full_path: str) -> int: - return random.randint(1, 4) + try: + pattern = GetFile80hPattern(full_path) + if not pattern: + return 1 # 默认值 + + # 取第一个80h属性(通常文件只有一个80h属性) + attr = pattern[0] + + if attr['is_resident']: + return 1 # 常驻属性只有一个分片 + else: + # 非常驻属性需要解析实际分片数 + # 这里简化为从sequence中解析,实际可能需要更复杂的解析 + return 1 # 简化处理,实际应根据数据结构解析 + except Exception as e: + print(f"❌ 获取ExtentCount出错: {e}, 使用默认值1") + return 1 # 出错时返回默认值 # 获取随机位置 @@ -77,6 +95,53 @@ def GetRandomLength() -> int: return random.randint(1000, 9999) +def GetFileLocation(full_path: str) -> int: + try: + pattern = GetFile80hPattern(full_path) + if not pattern: + return GetRandomLocation() # 回退到随机值 + + attr = pattern[0] + if attr['is_resident']: + # 常驻属性: start_byte + offset + content_offset + # 解析content_offset (sequence第三个元素的后4字节) + content_offset_bytes = attr['sequence'][2].split()[4:8] + content_offset = int.from_bytes( + bytes.fromhex(''.join(content_offset_bytes)), + byteorder='little' + ) + return attr['start_byte'] + attr['offset'] + content_offset + else: + # 非常驻属性需要解析runlist + # 这里简化为返回start_byte + return attr['start_byte'] + except Exception as e: + print(f"❌ 获取Location出错: {e}, 使用随机值") + return GetRandomLocation() # 出错时返回随机值 + + +def GetFileLength(full_path: str) -> int: + try: + pattern = GetFile80hPattern(full_path) + if not pattern: + return GetRandomLength() # 回退到随机值 + + attr = pattern[0] + if attr['is_resident']: + # 常驻属性: 解析sequence第三个元素的前4字节 + content_length_bytes = attr['sequence'][2].split()[0:4] + return int.from_bytes( + bytes.fromhex(''.join(content_length_bytes)), + byteorder='little' + ) + else: + # 非常驻属性: 从属性头中解析实际大小 + return attr['attribute_length'] # 简化处理 + except Exception as e: + print(f"❌ 获取Length出错: {e}, 使用随机值") + return GetRandomLength() # 出错时返回随机值 + + # 主函数:将 db_path 数据导入 db_node def InsertNodeDataToDB(db_path='../src/db_ntfs_info.db', table_name='db_node'): conn = sqlite3.connect(db_path) @@ -166,4 +231,4 @@ def InsertNodeDataToDB(db_path='../src/db_ntfs_info.db', table_name='db_node'): if __name__ == '__main__': - InsertNodeDataToDB() \ No newline at end of file + InsertNodeDataToDB() diff --git a/ntfs_utils/mft_analyze.py b/ntfs_utils/mft_analyze.py index 95899e5..eb0a819 100644 --- a/ntfs_utils/mft_analyze.py +++ b/ntfs_utils/mft_analyze.py @@ -76,6 +76,7 @@ def GetFileMftEntry(file_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}") if mft_entry is None: raise RuntimeError("Could not find MFT entry for the specified file.") @@ -102,7 +103,9 @@ def CalculateFileMftStartSector(mft_entry, volume_letter="Z"): config_data = GetNTFSBootInfo(volume_letter) # 计算文件 MFT Entry 的起始扇区号 start_sector = config_data["MftPosition"] * 8 + mft_entry * 2 - + if start_sector < 0: + raise ValueError("起始扇区号不能为负数") + print(f"文件 MFT Entry 的起始扇区号: {start_sector}") return start_sector @@ -214,10 +217,11 @@ 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)) except Exception as e: print(f"❌ Error: {e}") if __name__ == '__main__': - GetFile80hPattern(r"Z:\demo.jpg") + GetFile80hPattern(r"Z:\hello.txt") diff --git a/src/db_ntfs_info.db b/src/db_ntfs_info.db index 2740b3d..d013de6 100644 Binary files a/src/db_ntfs_info.db and b/src/db_ntfs_info.db differ