Qt/C++ 了解NTFS文件系统,解析盘符引导扇区数据获取MFT(Master File Table)主文件表偏移地址

news2024/12/26 21:49:19

系列文章目录

一、Qt/C++ 了解NTFS文件系统,了解MFT(Master File Table)主文件表(一)
二、Qt/C++ 了解NTFS文件系统,解析盘符引导扇区数据获取MFT(Master File Table)主文件表偏移地址


目录导读

  • 系列文章目录
  • 前言
  • BOOTICE工具介绍
  • 读取分区引导扇区(PBS)


前言

根据NT File System (NTFS) 一文中对引导扇区数据结构的分析,结合前文介绍的GitHub开源项目 NTFS-File-Search中的NTFS_BOOT_SECTOR结构体设计,使用Bootice工具查看分区引导扇区实际数据,计算首张MFT(Master File Table)主文件表在磁盘的偏移地址。

BOOTICE工具介绍

BOOTICE 引导修复工具是款USM的启动相关维护的工具。用于编辑修改磁盘上的引导扇区的信息,也就是MBR,BOOTICE可在磁盘(硬盘、移动硬盘、U盘、SD卡等)上安装磁盘引导程序。BOOTICE引导修复工具此外还具有磁盘扇区编辑、磁盘填充、分区管理等等功能。BOOTICE有着强大的兼容性,在硬盘维护中起来了很大的作用。
BOOTICE支持的引导程序主要有 WEE, GRUB4DOS, SYSLINUX, Plop BootManager, Ms-Dos 及 Windows NT 5/6 等。BOOTICE 还具有分区管理、扇区查看以及对 USB 移动存储设备进行重新格式化的功能。
具体参考 BOOTICE 1.3.4.0最新版

这里注意用于查看磁盘扇区数据,进行数据字节对照,
其中显示的数值都是16进制数据,以C盘目录为例:
在这里插入图片描述


读取分区引导扇区(PBS)

分区引导扇区是从NTFS文件系统格式 分区 的第一个扇区,

只有盘符是NTFS文件系统格式才能通过MFT表获取数据,
其他FAT,FAT32,REFS文件格式有其他的读取方式

如C盘的第一个扇区,以上面显示的C盘数据为例,
引导扇区在第878592个扇区。
读取整段扇区数据,到55 AA结束,一般都是512字节大小,
解析第一个扇区(引导扇区)数据,获取NTFS文件系统中第一个MFT表对应起始地址。

  • NTFS引导扇区内容结构:

表格出自Windows NT文件系统(NT File System)[使用QQ浏览器翻译]

字节偏移量段长度平均数字段名目的
0x003字节0xEB5290x86JMP和nototherwiseprovided(for)除非另有规定说明 导致在该引导扇区中的数据结构之后继续执行。
0x038字节"NTFS    "单词“NTFS”后跟四个尾随空格(0x20)OEM ID这是一个神奇的数字,表明这是一个NTFS文件系统。
0x0B2字节0x0200BPB每扇区字节数磁盘扇区中的字节数。
0x0D1字节0x08BPB每簇扇区簇中的扇区数量。如果该值大于0x80,则扇区数是2的绝对值的幂,认为该字段为负。
0x0E2字节0x0000BPB未使用的保留扇区
0x103字节0x000000BPB不用的该字段始终为0
0x132字节0x0000BPBNTFS未使用该字段始终为0
0x151字节0xF8BPB媒体描述符驱动器的类型。0xF8用于表示硬盘驱动器(与几种大小的软盘不同)。
0x162字节0x0000BPB不用的该字段始终为0
0x182字节0x003FBPB每个磁道的扇区驱动器磁道中的磁盘扇区数量。
0x1A2字节0x00FFBPB头数驱动器上的磁头数。
0x1C4字节0x000D6800BPB隐藏扇区分区前的扇区数量。
0x204字节0x00000000BPB不用的NTFS不使用
0x244字节0x00800080EBPB不用的NTFS不使用
0x288字节0x000000000C8007FFEBPB总部门扇区中的分区大小。
0x308字节0x00000000000C0000EBPB$MFT集群号包含主文件表的群
0x388字节0x0000000000000002EBPB$MFTMirr群集号包含主文件表备份的群集
0x401字节0xF6EBPB每个文件记录段的字节或簇正值表示文件记录段中簇的数量。负值表示文件记录段中的字节数,在这种情况下,大小是绝对值的2次方。(0xF6 = -10 → 210 = 1024).
0x413字节0x000000EBPB不用的NTFS不使用此字段
0x441字节0x01EBPB每个索引缓冲区的字节或簇正值表示索引缓冲区中的簇数量。负值表示字节数,它对负数使用与“每个文件记录段的字节数或簇数”相同的算法
0x453字节0x000000EBPB不用的NTFS不使用此字段
0x488字节0x86EEA7DEEEA7C4B1EBPB卷序列号分配给该分区的唯一随机数,以保持有序。
0x504字节0x00000000校验和,未使用应该是校验和。
0x54426字节引导代码加载操作系统其余部分的代码。这由该扇区的前3个字节指向。
0x01FE2字节0xAA55扇区结束标记 此标志表示这是一个有效的引导扇区。

需要注意的是:磁盘扇区数据中除字符串外的所有值都以小端序(little endian)存储,如
磁盘大小为0x000000000C8007FF字节
但是数据格式是按FF 07 80 0C 00 00 00 00顺序存储

大端模式(Big_endian):字数据的高字节存储在低地址中,而字数据的低字节则存放在高地址中。
小端模式(Little_endian):字数据的高字节存储在高地址中,而字数据的低字节则存放在低地址中。
参考:
Big-endian and Little-endian (大小端)
字节序:Big Endian 和 Little Endian

  • 查看实际扇区数据:

使用BOOTICE工具查看磁盘扇区实际数据,并按上面表格占用字节划分标注;
请添加图片描述
结合引导分区结构表格与盘符数据进行对照,就可以设计一个512字节的C++结构体,来获取引导分区数据:
例如 GitHub开源项目 NTFS-File-Search 设计的NTFS_BOOT_SECTOR 结构

  • NTFS_BOOT_SECTOR结构体

/*
* BIOS Parameter Block (BPB) - BIOS参数块(BPB)
* https://en.wikipedia.org/wiki/NTFS
* https://en.wikipedia.org/wiki/BIOS_parameter_block
* https://www.ntfs.com/ntfs-partition-boot-sector.htm
* NTFS文件系统详解(三)之NTFS元文件解析(https://blog.csdn.net/enjoy5512/article/details/50966009/)
*/
typedef struct NTFS_BOOT_SECTOR
{
    /* Jump instruction */
    /* 跳转指令 EB 52 90*/
    BYTE Jmp[3];

    /* Signature*/
    /* 文件系统的ASSIIC码表示形式 NTFS*/
    BYTE Signature[8];

    //
    // BPB and extended BPB
    //
    //!字节2 每个扇区的字节总数 一般是00 02H  (一般后面描述加H表示十六进制)
    WORD		BytesPerSector;
    //!字节1 簇大小 08 每个簇占8个扇区
    BYTE		SectorsPerCluster;
    //!字节2 保留扇区
    WORD		ReservedSectors;
    //!字节3 总为0
    BYTE		Zeros1[3];
    //!字节2 不使用
    WORD		Unused1;
    //!字节1 介质描述,硬盘为F8
    BYTE		MediaDescriptor;
    //!字节2 总为0
    WORD		Zeros2;
    //!字节2 每磁头扇区数
    WORD		SectorsPerTrack;
    //!字节2 每柱面磁头数
    WORD		NumberOfHeads;
    //!字节4 隐含扇区数 (从MBR到DBR的扇区总数)
    DWORD		HiddenSectors;
    //!字节4 不使用
    DWORD		Unused2;
    //!字节4 不使用 总为80 00 80 00
    DWORD		Unused3;
    //!字节8 扇区总数,即分区大小
    ULONGLONG	TotalSectors;
    //!字节8 $MFT的开始簇号
    ULONGLONG	MFT_LCN;		/* $MFT Logical Cluster Number (LCN) - $MFT逻辑簇数(LCN) */
    //!字节8 $MFTMirr的开始簇号
    ULONGLONG	MFTMirr_LCN;	/* $MFTMirr Logical Cluster Number (LCN) - $MFTMirr 逻辑集群号(LCN) */
    //!字节4 每个MFT记录的簇数
    DWORD		ClustersPerFileRecord;
    //!字节4 每索引的簇数
    DWORD		ClustersPerIndexBlock;
    //! 分区的逻辑序列号
    BYTE		VolumeSN[8];

    /* Boot Code - 引导代码 */
    BYTE BootCode[430];

    //
    // 0xAA55
    //

    BYTE _AA;
    BYTE _55;
};

注意使用
#pragma pack( push, 1 )
#pragma pack( pop )
进行字节对齐。

学习C/C++源码案例的时候,pragma pack是经常会遇到
参考#pragma pack 详解

  • 读取引导分区数据

读取引导分区数据转换成指定结构体,获取首个MFT表地址

    qDebug()<<" Start ---->";
    //!磁盘第一个512字节结构 BIOS参数
    NTFS_BOOT_SECTOR	m_BootRecord;
    const WCHAR lpszVolumeName[7] = { L'\\', L'\\', L'.', L'\\', L'C', L':' };
    HANDLE m_hVolume= CreateFile(lpszVolumeName,
                                 GENERIC_READ,
                                 FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE,
                                 NULL,
                                 OPEN_EXISTING,
                                 FILE_ATTRIBUTE_NORMAL | FILE_FLAG_BACKUP_SEMANTICS,
                                 NULL
                             );
       if (m_hVolume == INVALID_HANDLE_VALUE)
           goto out ;
       DWORD dwNumberOfBytesRead;
       if (ReadFile(m_hVolume, &m_BootRecord, NTFS_BOOTSECTOR_SIZE, &dwNumberOfBytesRead, NULL))
       {
           if (dwNumberOfBytesRead == NTFS_BOOTSECTOR_SIZE)
           {
              qDebug()<<"[磁盘扇区中的字节数] :  "<<QString::number(m_BootRecord.BytesPerSector,16).toUpper()<<" -> "<<QString::number(m_BootRecord.BytesPerSector,10);
              qDebug()<<"[簇中的扇区数量] :     "<<QString::number(m_BootRecord.SectorsPerCluster,16).toUpper()<<" -> "<<QString::number(m_BootRecord.SectorsPerCluster,10);
              qDebug()<<"[每磁头扇区数] :       "<<QString::number(m_BootRecord.SectorsPerTrack,16).toUpper()<<" -> "<<QString::number(m_BootRecord.SectorsPerTrack,10);
              qDebug()<<"[每柱面磁头数] :       "<<QString::number(m_BootRecord.NumberOfHeads,16).toUpper()<<" -> "<<QString::number(m_BootRecord.NumberOfHeads,10);
              qDebug()<<"[分区大小] :          "<<QString::number(m_BootRecord.TotalSectors,16).toUpper()<<" -> "<<QString::number(m_BootRecord.TotalSectors,10);
              qDebug()<<"[$MFT的开始簇号] :     "<<QString::number(m_BootRecord.MFT_LCN,16).toUpper()<<" -> "<<QString::number(m_BootRecord.MFT_LCN,10);
              qDebug()<<"[$MFTMirr的开始簇号] : "<<QString::number(m_BootRecord.MFTMirr_LCN,16).toUpper()<<" -> "<<QString::number(m_BootRecord.MFTMirr_LCN,10);
           }
       }
       CloseHandle(m_hVolume);
out:
    qDebug()<<" End ---->";
/*
QCoreApplication Start ---->
[磁盘扇区中的字节数] :   "200"  ->  "512"
[簇中的扇区数量] :      "8"  ->  "8"
[每磁头扇区数] :        "3F"  ->  "63"
[每柱面磁头数] :        "FF"  ->  "255"
[分区大小] :           "C8007FF"  ->  "209717247"
[$MFT的开始簇号] :      "C0000"  ->  "786432"
[$MFTMirr的开始簇号] :  "2"  ->  "2"
QCoreApplication End ---->
*/

由此得到首个MFT在簇号 786432 位置,
计算首张MFT表磁盘地址字节偏移量MFT_LCN:
UINT64 MFT_LCN= (UINT64)(m_BootRecord.MFT_LCN * m_BootRecord.BytesPerSector * m_BootRecord.SectorsPerCluster);
MFT偏移簇号786432
7864328512= “3221225472” =“0XC0000000”

计算出的地址通过ReadFile设置偏移量读取出来确实是MFT结构表数据,
但是这在其他文章中计算方式又不一样:

  • 【1】.MFT偏移簇号786432
    (786432∗4096(偏移)+63∗512(C盘偏移地址)=3221257728=0xC0007E00)

出自 NTFS文件系统详解

  • 【2】.文件记录由两部分构成,一部分是文件记录头,另一部分是属性列表,最后结尾是四个“FF”。然后我们根据上面BPB中的偏移簇号偏移盘偏移地址找到系统MFT所在地址 (789632 * 8 +63 = 6291519),

出自 NTFS文件系统详解(三)之NTFS元文件解析

  • 【3】.在NTFS文件系统中,每个文件记录都有一个唯一的标识符,称为文件记录号(File Record Number,简称FRN)。要访问某个文件记录,需要先找到该文件记录在$MFT元文件中的偏移地址。计算偏移地址的公式如下:
    $MFTOffset = MFTStartCluster * ClusterSize + FRN * RecordSize
    其中,MFTStartCluster是$MFT元文件的起始簇号ClusterSize是簇的大小FRN是文件记录号RecordSize是文件记录的大小

出自 「NTFS:让你的硬盘更安全、更高效!」NTFS文件系统详解

带入上面【1】,【2】的公式,我读取的数据反而是错误的,而C://盘符的文件记录号一般为5固定值,带入计算也错误,带入0计算正常,不知道是不是NTFS版本的问题,后面还是以NTFS-File-Search 示例中的计算方式为准。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2132103.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

防止文件外发泄密有什么方法?这7防外发方式可以看下!

防止文件外发泄密有什么方法&#xff1f; 一、使用防泄密软件外发&#xff1a;可对发送的文件进行权限设定。接收&#xff1a;可查看次数、可查看时间复制、修改、打印、外发受到限制。文件外发控制&#xff1a;以对外发的文件进行权限设定&#xff0c;如可打开的次数、可打开时…

基于JavaWeb开发的java ssm springboot+VUE疫情防疫系统系统前后端分离设计和实现

基于JavaWeb开发的java ssm springbootVUE疫情防疫系统系统前后端分离设计和实现 &#x1f345; 作者主页 网顺技术团队 &#x1f345; 欢迎点赞 &#x1f44d; 收藏 ⭐留言 &#x1f4dd; &#x1f345; 文末获取源码联系方式 &#x1f4dd; &#x1f345; 查看下方微信号获取…

【深度学习】【OnnxRuntime】【Python】模型转化、环境搭建以及模型部署的详细教程

【深度学习】【OnnxRuntime】【Python】模型转化、环境搭建以及模型部署的详细教程 提示:博主取舍了很多大佬的博文并亲测有效,分享笔记邀大家共同学习讨论 文章目录 【深度学习】【OnnxRuntime】【Python】模型转化、环境搭建以及模型部署的详细教程前言模型转换--pytorch转on…

文件系统(磁盘 磁盘文件 inode)

文章目录 磁盘看看物理磁盘磁盘的存储结构 对磁盘的储存进行逻辑抽象inode号文件名 -> inode判断文件在哪个分区 磁盘 电脑中存在非常多的文件&#xff0c;被打开的文件只是少量的。 没有被打开的文件&#xff0c;在磁盘中放着&#xff0c;那么文件是如何存取&#xff1f; …

Unity 之 【Android Unity FBO渲染】之 [Unity 渲染 Android 端播放的视频] 的一种方法简单整理

Unity 之 【Android Unity FBO渲染】之 [Unity 渲染 Android 端播放的视频] 的一种方法简单整理 目录 Unity 之 【Android Unity FBO渲染】之 [Unity 渲染 Android 端播放的视频] 的一种方法简单整理 一、简单介绍 二、FBO 简单介绍 三、案例实现原理 四、注意事项 五、简…

深度盘点PLM 项目管理系统哪家强?优缺点一目了然!

本文将盘点10款知名的PLM 项目管理系统&#xff0c;为企业选型提供参考&#xff01; 想象一下&#xff0c;在一个企业的产品研发过程中&#xff0c;各种数据、文档四处散落&#xff0c;不同部门之间沟通不畅&#xff0c;项目进度难以把控。这时&#xff0c;PLM 项目管理系统就如…

在线压缩图片地址

https://squoosh.app/editor这个是免费的&#xff0c;并且不限制图片数量 https://tinypng.com/ 这个限制图片的大小&#xff0c;如果单张图片超过5M需要收费 https://www.jpeg-optimizer.com/ https://imagecompressor.com/

再次进阶 舞台王者 第八季完美童模全球赛形象大使【于洪森】赛场秀场超燃合集!

7月20-23日&#xff0c;2024第八季完美童模全球总决赛在青岛圆满落幕。在盛大的颁奖典礼上&#xff0c;一位才能出众的少年——于洪森&#xff0c;迎来了他舞台生涯的璀璨时刻。 形象大使——于洪森&#xff0c;以璀璨童星之姿&#xff0c;优雅地踏上完美童模盛宴的绚丽舞台&am…

WPF实现Hammer 3D入门学习

代码下载&#xff1a;https://download.csdn.net/download/bjhtgy/89748674

springboot Web基础开发

Spring Boot 是一个用于简化 Spring 应用开发的框架&#xff0c;它通过自动配置和开箱即用的功能&#xff0c;使得创建和部署 Spring 应用变得更为高效。以下是 Spring Boot 基础 Web 开发的一些关键点和实操总结&#xff1a; 1. 项目搭建 使用 Spring Initializr: 访问 Spring…

代码随想录刷题day31丨56. 合并区间,738.单调递增的数字,总结

代码随想录刷题day31丨56. 合并区间&#xff0c;738.单调递增的数字&#xff0c;总结 1.题目 1.1合并区间 题目链接&#xff1a;56. 合并区间 - 力扣&#xff08;LeetCode&#xff09; 视频讲解&#xff1a;贪心算法&#xff0c;合并区间有细节&#xff01;LeetCode&#x…

源代码加密软件有哪些?2024常用的10款好用的企业源代码加密软件分享!

源代码作为企业的核心资产&#xff0c;一旦泄露&#xff0c;将可能导致技术被窃取、产品被复制&#xff0c;甚至引发法律纠纷。 一、企业源代码泄密的危害详情描述 企业源代码泄密事件频发&#xff0c;其危害不容小觑。 一方面&#xff0c;源代码的泄露可能导致企业的核心技术…

国内领先线上运动平台:如何借助AI技术实现业务腾飞与用户体验升级

“ 从智能训练到身体分析&#xff0c;再到辅助判决&#xff0c;AI技术正以惊人的速度渗透进体育和健身领域&#xff0c;为运动员和健身爱好者提供了前所未有的个性化体验。 ” AI&#xff0c;运动的智能伴侣 在巴黎奥运会上&#xff0c;AI技术的运用成为了焦点。它不仅为运动…

人脸关键点数据集WFLW

数据集&#xff1a;Look at Boundary: A Boundary-Aware Face Alignment Algorithm 论文&#xff1a;Look at Boundary: A Boundary-Aware Face Alignment Algorithm 发表&#xff1a;CVPR2018 1. 标注点位 官方说有98个点&#xff0c;但是配图只有0-95&#xff0c;咋回事&…

java设计模式(持续更新中)

1 设计模式介绍 设计模式代表了代码的最佳实践&#xff0c;被有经验的开发人员使用。设计模式是很多被反复使用并知晓的&#xff0c;主要是对代码和经验的总结。使用设计模式是为了重用代码&#xff0c;并让代码更容易被人理解&#xff0c;保证代码的可靠性。对接口编程而不是…

单考一个OCP认证?还是OCP和OCM认证都要考?

​ Oracle的OCP认证是数据库行业非常经典的一个认证&#xff0c;从事数据库行业的人都建考一个 Oracle OCP 认证。 OCP认证内容包括&#xff1a; OCA部分&#xff1a;数据库基础知识、SQL 语言使用、基本的数据库管理技能等&#xff0c;如数据库安装与配置、理解数据库架构、…

Web APIs - DOM节点操作

Web APIs - DOM节点操作 第9天 目标: 了解DOM节点的增删改查&#xff0c;掌握利用数据操作页面&#xff0c;完成移动端通讯录案例 日期对象节点操作M端事件JS插件综合案例 1、日期对象 日期对象&#xff1a;用来表示日期和时间的对象 作用&#xff1a;可以得到当前系统日期和…

力扣139-单词拆分(Java详细题解)

题目链接&#xff1a;139. 单词拆分 - 力扣&#xff08;LeetCode&#xff09; 前情提要&#xff1a; 因为本人最近都来刷dp类的题目所以该题就默认用dp方法来做。 最近刚学完背包&#xff0c;所以现在的题解都是以背包问题为基础再来写的。 如果大家不懂背包问题的话&#…

深度盘点:2024年企业最喜欢用的WMS仓库管理系统有哪些?

本文将列举国内外知名的仓库管理系统&#xff0c;从每个系统的适用范围、核心功能、特点来为大家解读。为企业选型提供参考&#xff01; WMS系统是Warehouse Management System&#xff08;仓库管理系统&#xff09;的简称&#xff0c;它是一个帮助企业和仓库管理者高效管理仓库…

NMOS与PMOS原理图

重点关注续流二极管方向和电流流向&#xff1a; NMOS应用&#xff1a; PMOS 应用&#xff1a;