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

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;
        else
            return 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,第一个实例总是0
    WORD		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.kler.cn/a/309128.html

相关文章:

  • java操作ES(一)RestHighLevelClient(2)集成与demo
  • 量化交易系统开发-实时行情自动化交易-3.4.2.Okex行情交易数据
  • 【循环神经网络】
  • 【C++】详细介绍模版进阶,细节满满
  • 招聘app开发,人才招聘、求职首要方式
  • 索引【MySQL】
  • 工具类中使用@Value注解引入静态地址
  • uniapp uview扩展u-picker支持日历期间 年期间 月期间 时分期间组件
  • GC垃圾回收机制-Serial GC
  • Uniapp + Vue3 + Vite +Uview + Pinia 分商家实现购物车功能(最新附源码保姆级)
  • Linux下root用户共享conda环境给其他用户
  • 力扣121-买卖股票的最佳时机(Java详细题解)
  • Encountered 31 files that should have been pointers, but weren‘t:(已解决,无废话)
  • System.out源码解读——err 和 out 一起用导致的顺序异常Bug
  • 论文翻译:USENIX-2021 Extracting Training Data from Large Language Models
  • 网络设备登录——《路由与交换技术》实验报告
  • 养宠浮毛严重怎么清理?希喂、范罗士、IAM宠物空气净化器真实测评
  • C++:初始化列表
  • 在线包装盒型生成工具,各种异型包装盒型,PDF导出方便
  • 【蜡笔小新专享】安装虚拟机、PHP、DVWA
  • Linux容器化管理——Docker常见命令总结
  • Apache Pulsar 与 Kafka Streams
  • React实现类似Vue的路由监听Hook
  • 在新电脑上将文件推送到已有的 Git 仓库
  • 【编程基础知识】Java命名规范及最佳实践
  • 孙怡带你深度学习(2)--PyTorch框架认识