当前位置: 首页 > news >正文

Qt/C++ 了解NTFS文件系统,获取首张MFT表数据,解析文件记录头内容找到第一个属性偏移地址

系列文章目录

一、Qt/C++ 了解NTFS文件系统,了解MFT(Master File Table)主文件表(一)
二、Qt/C++ 了解NTFS文件系统,解析盘符引导扇区数据获取MFT(Master File Table)主文件表偏移地址
三、Qt/C++ 了解NTFS文件系统,获取首张MFT表数据,解析文件记录头内容找到第一个属性偏移地址


目录导读

  • 系列文章目录
  • 前言
  • 解析MFT(Master File Table)主文件表
    • 解析 文件记录头布局($MFT File Record Header Layout)


前言

根据前文获取到的首张MFT(Master File Table)主文件表偏移地址,
获取到首张MFT(Master File Table)主文件表数据,解析文件记录头内容数据,获取到的第一个属性的偏移地址。
用于遍历查找所有属性,直到找到 $DATA(0X80) 属性,获取DataRun数据列表。

NTFS文件系统中每个文件或目录都由一张或多张MFT(Master File Table)主文件表保存数据
DataRun数据列表是指分区盘符的文件目录的所有MFT(Master File Table)主文件表集合所在的偏移地址列表

  • 读取首张MFT(Master File Table)主文件表数据

设置的MFT_LCN偏移地址,读取m_ullRecordSize(1024) 个字节的数据,
参考NTFS-File-Search

//! 设置偏移量读取数据
DWORD ReadBytes(HANDLE m_hVolume,PVOID pBuffer, DWORD cbReadSize, UINT64 ullAbsoluteOffset)
{DWORD	dwNumberOfBytesRead=0;BOOL	bSuccess;if (ullAbsoluteOffset != UINT64_MAX){LARGE_INTEGER liPosition;liPosition.QuadPart = ullAbsoluteOffset;LARGE_INTEGER liUpdatedPosition;if (SetFilePointerEx(m_hVolume, liPosition, &liUpdatedPosition, FILE_BEGIN))m_ullCurrentOffset = liUpdatedPosition.QuadPart;elsereturn 0;}bSuccess = ReadFile(m_hVolume, pBuffer, cbReadSize, &dwNumberOfBytesRead, NULL);if (bSuccess) {m_ullCurrentOffset += cbReadSize;}return dwNumberOfBytesRead;
}//! 开始读取首个MFT表
PBYTE pbMFTBuffer = new BYTE[m_ullRecordSize];
UINT64 MFT_LCN= (UINT64)(m_BootRecord.MFT_LCN * m_BootRecord.BytesPerSector * m_BootRecord.SectorsPerCluster);if (m_ullRecordSize != ReadBytes(m_hVolume,pbMFTBuffer, (INT64)m_ullRecordSize, MFT_LCN))goto out;
qDebug()<<"输出...";
for(int i=0;i<m_ullRecordSize;i++)
{Val+=QString("%1 ").arg(pbMFTBuffer[i],2,16,QLatin1Char('0')).toUpper();if((i+1)%16==0){qDebug()<<Val;Val="";}
}
/*输出...
"46 49 4C 45 30 00 03 00 EC F3 01 ED 15 00 00 00 "
"01 00 01 00 38 00 01 00 B8 01 00 00 00 04 00 00 "
"00 00 00 00 00 00 00 00 17 00 00 00 00 00 00 00 "
"D6 03 00 00 00 00 00 00 10 00 00 00 60 00 00 00 "
"00 00 18 00 00 00 00 00 48 00 00 00 18 00 00 00 "
"A0 73 73 A7 99 E8 D7 01 A0 73 73 A7 99 E8 D7 01 "
"A0 73 73 A7 99 E8 D7 01 A0 73 73 A7 99 E8 D7 01 "
....
....
*/
  • Bootice工具查看数据

在Bootice工具中,第一张MFT(Master File Table)主文件表在引导扇区后第16个扇区。
在这里插入图片描述

解析MFT(Master File Table)主文件表

理解MFT(Master File Table)的结构对于理解NTFS文件系统的运作方式至关重要。以下是MFT结构的详细解释:
MFT记录:
MFT由一系列固定大小的记录组成,每个记录对应一个文件、目录或元数据文件。
MFT记录包含了文件或目录的元数据信息,如文件属性、数据位置、文件名等。
MFT记录号:
每个MFT记录都有一个唯一的标识符,称为MFT记录号。
MFT记录号用于在MFT中定位和识别特定的文件或目录。
摘要出自:MFT(Master File Table,主文件表)是Windows操作系统中NTFS(New Technology File System,新技术文件系统)的关键组成部分,用于存储文件和目录的元数据信息。MFT类似于Unix和Linux系统中的inode,但在实现上有所不同。

MFT是一组文件记录。卷中的每个文件都由一个或多个这样的文件记录完整地描述。在Unix术语中,文件记录相当于索引节点。描述给定文件的第一个文件记录称为基本文件记录,其他记录称为扩展文件记录。
文件记录由一个标题、几个可变长度属性和一个结束标记(简单地说就是0xFFFFFFFF)组成。
出自:File - $MFT (0)
Concept - File Record

以第一张MFT(Master File Table)主文件表为例,解析数据结构
MFT(Master File Table)主文件表以FILE0字符串开始。

解析 文件记录头布局($MFT File Record Header Layout)

MFT表中前48字节是文件记录头内容,根据文件记录头数据获取属性开始偏移地址,其数据结构为:

Offset字节大小OSDescription描述
0x004字节(Magic number ‘FILE’ )固定值 一定是"FILE"
0x042字节(Offset to the Update Sequence)更新序列号的偏移
0x062字节(Size in words of Update Sequence) (S)更新序列号与更新数组以字为单位(s)
0x088字节$LogFile Sequence Number (LSN)日志序列号(每次记录被修改,都将导致该序列加1)
0x102字节Sequence number序列号(用于记录本文件记录被重复使用的次数,每次文件删除时加1,跳过0值,如果为0,则保持为0)
0x122字节Hard link count硬链接数 只出现在基本文件记录中,目录所含项数要使用到他
0x142字节Offset to the first Attribute第一个属性流的偏移位置
0x162字节Flags标志字节,1表示记录使用中,2表示该记录为目录
0x184字节Real size of the FILE record文件记录实际大小(填充到8字节,即以8字节为边界)
0x1C4字节Allocated size of the FILE record文件记录分配大小(填充到8字节,即以8字节为边界)
0x208字节File reference to the base FILE record所对应的基本文件记录的文件参考号(扩展文件记录中使用,基本文件记录中为0,在基本文件记录的属性列表0x20属性存储中扩展文件记录的相关信息)
0x282字节Next Attribute Id下一个自由ID号,当增加新的属性时,将该值分配给新属性,然后该值增加,如果IFT记录重新使用,则将它置0,第一个实例总是0
0x2A2字节XPAlign to 4 byte boundary边界, WINDOWS XP 中使用,也就是本记录使用的两个扇区的最后两个字节的值
0x2C4字节XPNumber of this MFT RecordWINDOWS XP中使用,本MFT记录号
  • 其中 Flags 字段:
描述
0x01表示记录正在使用中
0x02记录是一个目录(文件名索引存在)
0x04Record是一个扩展名(为$Extend目录中的记录设置)
0x08存在特殊索引(为包含索引的非目录记录设置: S e c u r e , Secure, SecureObjID, Q u o t a , Quota, QuotaReparse)
  • 实际/分配的大小:

分配的大小是记录在磁盘上占用的空间。这应该是集群大小的倍数,并且可能等于MFT文件记录的大小。实际大小是记录中实际使用的字节数。
注意:实际大小将被填充到一个8字节的边界。

参考:NTFS文件系统详解(三)之NTFS元文件解析
Concept - File Record

  • 实际数据 使用Bootice工具图示

请添加图片描述

  • 定义一个结构体

定义一个48字节的结构体,对齐字节,用于数据结构转换,例如NTFS-File-Search项目中的MFT_FILE_RECORD_HEADER结构:


/*
* $MFT File Record Header Layout - 文件记录头布局 标准属性标题,
* MFT是一组文件记录。卷中的每个文件都由一个或多个这样的文件记录完整地描述。
* 在Unix术语中,文件记录相当于索引节点。描述给定文件的第一个文件记录称为基本文件记录,其他记录称为扩展文件记录。
* 文件记录由一个标题、几个可变长度属性和一个结束标记(简单地说就是0xFFFFFFFF)组成。
* https://flatcap.github.io/linux-ntfs/ntfs/concepts/file_record.html
*/
typedef struct MFT_FILE_RECORD_HEADER
{//!字节4 固定值 一定是"FILE"DWORD		Magic;					// "FILE" (0x454C4946)//!字节2 更新序列号的偏移WORD		UpdateSequenceOffset;	// Update Sequence offset - 偏移到更新序列//!字节2 更新序列号与更新数组以字为单位(s)WORD		SizeOfUpdateSequence;	// Size in words of Update Sequence - 	更新序列的字数//!字节8 日志序列号(每次记录被修改,都将导致该序列加1)ULONGLONG	LogSequenceNumber;		// $LogFile Sequence Number (LSN) - $日志文件序列号(LSN)//!字节2 序列号(用于记录本文件记录被重复使用的次数,每次文件删除时加1,跳过0值,如果为0,则保持为0)WORD		SequenceNumber;			// Sequence number - 序列号//!字节2 硬链接数 只出现在基本文件记录中,目录所含项数要使用到他WORD		HardLinkCount;			// Hard link count - 硬链接计数//!字节2 第一个属性流的偏移位置WORD		FirstAttributeOffset;	// First attribute offset - 到第一个属性的偏移量//!字节2 标志字节,1表示记录使用中,2表示该记录为目录WORD		Flags;//!字节4 文件记录实际大小(填充到8字节,即以8字节为边界)DWORD		RealSize;				// Real size of the FILE record - FILE记录的实际大小//!字节4 文件记录分配大小(填充到8字节,即以8字节为边界)DWORD		AllocatedSize;			// Allocated size of the FILE record - 文件记录的分配大小//!字节8 所对应的基本文件记录的文件参考号(扩展文件记录中使用,基本文件记录中为0,在基本文件记录的属性列表0x20属性存储中扩展文件记录的相关信息)ULONGLONG	FileReference;			// File reference to the base FILE record - 对基本文件记录的文件引用//!字节2 下一个自由ID号,当增加新的属性时,将该值分配给新属性,然后该值增加,如果IFT记录重新使用,则将它置0,第一个实例总是0WORD		NextAttributeId;        // 下一个属性Id//!字节2 边界, WINDOWS XP 中使用,也就是本记录使用的两个扇区的最后两个字节的值WORD		Align;                  // 对齐4字节边界//!字节4 WINDOWS XP中使用,本MFT记录号DWORD		RecordNumber;			// MFT Record Number - MFT记录号
}*PMFT_FILE_RECORD_HEADER;
  • 实际数据转换
PMFT_FILE_RECORD_HEADER header=(PMFT_FILE_RECORD_HEADER)pbMFTBuffer;
qDebug()<<"FirstAttributeOffset: "<<QString::number(header->FirstAttributeOffset,16).toUpper()<<" -> "<<QString::number(header->FirstAttributeOffset,10);
qDebug()<<"LogSequenceNumber: "<<QString::number(header->LogSequenceNumber,16).toUpper()<<" -> "<<QString::number(header->LogSequenceNumber,10);
qDebug()<<"Flags: "<<QString::number(header->Flags,16).toUpper()<<" -> "<<QString::number(header->Flags,10);
qDebug()<<"RealSize: "<<QString::number(header->RealSize,16).toUpper()<<" -> "<<QString::number(header->RealSize,10);
qDebug()<<"AllocatedSize: "<<QString::number(header->AllocatedSize,16).toUpper()<<" -> "<<QString::number(header->AllocatedSize,10);
/*
FirstAttributeOffset:  "38"  ->  "56"
LogSequenceNumber:  "15ED01F3EC"  ->  "94170641388"
Flags:  "1"  ->  "1"
RealSize:  "1B8"  ->  "440"
AllocatedSize:  "400"  ->  "1024"
*/

获取到第一个属性偏移地址(FirstAttributeOffset)是从56字节处开始
如下图示:
在这里插入图片描述


http://www.mrgr.cn/news/26765.html

相关文章:

  • redisController工具类
  • 解决Docker镜像不可下载
  • 一键ai绘图真的可能吗?这些工具让你轻松实现
  • Android 使用scheme唤起app本地打开
  • 第四天旅游线路预览——从贾登峪到喀纳斯景区入口(贾登峪游客服务中心)
  • Django视图:构建动态Web页面的核心技术
  • selenium元素定位:元素点击交互异常解决方法
  • 牛耕分解+形态学分割 全覆盖路径规划(二)Part1. 分割
  • C++——类与对象(三)
  • 负载均衡:从理论到实践 ---day04
  • 【Echarts】使用多横坐标轴展示近十五天天气预报
  • AgentOhana:为智能体学习设计统一的数据和训练流水线
  • 17、电科院FTU检测标准学习笔记-录波性能
  • 现代 Web 开发工具箱:Element-UI 表单组件全攻略(一)
  • AI大模型在知识管理平台上的应用:泛微·采知连实现自动采集.精准搜索.智能问答.主动推荐
  • 常见的站长工具接口有哪些?站长们该如何选择?
  • 在国行iOS设备上启用Apple Intelligence
  • 如何从 Git 克隆项目并推送到新的仓库(包含所有的代码和提交记录)
  • 将数据库系统实践转向AI:使用生成式AI创建高效的开发和维护实践
  • Mysql JSON结果不能IN