NTFS文件系统全解析:从MFT到数据恢复与跨平台挂载
帮朋友救一块 2TB 移动硬盘那件事到现在我还记得很清楚他一边往硬盘里拷婚礼素材一边手快把线给拔了再插回 Ubuntu 笔记本上终端里跳出一行ls: cannot access usb1: transport endpoint is not connected挂载点目录能进文件却一个也列不出来。更吓人的是插到 Windows 上打开根目录多出来一堆FOUND.000文件夹。那一晚我从引导扇区一路翻到$LogFile才算把 NTFS 这套东西重新梳理了一遍。这篇就把我踩过的坑、查过的资料、验证过的命令按我自己的理解顺序摊开讲。NTFS 是 Windows 家族从 NT 时代沿用至今的默认文件系统它管的不只是文件放在哪个扇区还包括谁能访问、改了怎么记日志、掉了怎么恢复。你在 Linux 上挂载它、在嵌入式设备上避开它、在数据丢失时扫描它面对的其实是同一个东西的不同侧面。下面这些内容写给需要在 Windows、Linux、嵌入式三条线上跟存储打交道的人也写给那些被一块脏硬盘折磨过、想弄明白背后到底发生了什么的读者。1. 从一次热插拔事故说起NTFS把元数据固定放在了哪些位置1.1 引导扇区、簇与MFT三张必须背下来的地图NTFS 卷的第一个扇区是引导扇区也叫 VBR。它的偏移 3 处是 OEM 标识符写着NTFS四个空格补齐八字节。这个位置很关键因为file命令、blkid、分区工具判断这到底是 NTFS 还是 exFAT第一眼看的就是这里。紧接着是每扇区字节数、每簇扇区数、总扇区数以及两个至关重要的字段$MFT 的起始簇号和$MFTMirr 的起始簇号。这两个字段一旦损坏整卷基本就直接判死刑了——因为所有文件的目录信息都藏在那里面。这里必须先说清簇这个概念。格式化的时候你能选的分配单元大小说的就是簇。NTFS 默认在 2TB 以内的卷上用 4KB 簇8 个 512 字节扇区簇越大顺序读写越快、碎片越少但小文件浪费的空间也越多。我用一个小场景说明写一个 100 字节的记事本文件它照样占掉一整个簇也就是 4KB。你在资源管理器里看大小 100 字节、占用空间 4KB差值就是这么来的。簇大小还决定了单文件的理论上限4KB 簇时大约是 16TB64KB 簇时能到 256TB。$MFT 是整个 NTFS 的心脏中文一般叫主文件表。它本身就是一个文件由一连串固定 1KB 大小的文件记录组成每个记录对应卷上的一个文件或目录。第 0 号记录是 $MFT 自己第 1 号是它的镜像 $MFTMirr只镜像前四个记录第 2 号是 $LogFile第 3 号 $Volume第 4 号 $AttrDef第 5 号是根目录.第 6 号 $Bitmap第 7 号 $Boot第 8 号 $BadClus第 9 号 $Secure第 10 号 $UpCase第 11 号 $Extend下面还挂着 $ObjId、$Quota、$Reparse、$UsnJrnl 等。这些以$开头的元数据文件在资源管理器里默认不显示但它们是整套机制的地基。提醒$Bitmap 里每 1 个 bit 对应卷上 1 个簇用来标记该簇是空闲还是已占用。删除文件时这个位被清零数据区本身通常纹丝不动——后面讲恢复时会重点用到这一点。1.2 一切皆属性常驻与非驻留的分界线在哪里NTFS 跟很多文件系统最大的思路差异在于它不认为文件是一个整体而认为文件是一堆属性的集合。每个 MFT 记录里塞的就是这堆属性的列表。属性由类型码、长度、是否常驻标志、名字和内容构成类型码用十六进制标识常见的几个必须记住类型码属性名作用0x10$STANDARD_INFORMATION创建/修改/访问时间、DOS 属性、安全 ID0x30$FILE_NAME文件名、父目录记录号、命名空间0x40$OBJECT_ID对象标识符用于分布式链接追踪0x80$DATA真正的文件内容0x90/0xA0$INDEX_ROOT / $INDEX_ALLOCATION目录索引B 树结构0xB0$BITMAP索引或 MFT 自身的位图0xC0$REPARSE_POINT符号链接、junction 的重解析数据关键在于常驻二字。1KB 的 MFT 记录里头部和属性表头大概要占掉 50 到 60 字节真正能塞内容的空余大约 700 到 900 字节。如果你的文件足够小比如一个 300 字节的配置文件它的 $DATA 属性内容会直接躺在 MFT 记录里这叫常驻属性。一旦超过剩余空间NTFS 就把内容搬到普通的数据簇上$DATA 属性改为非驻留里面只留一段跑列表data runs用 [起始 LCN, 簇数] 的形式描述这块内容到底散落在磁盘的哪几段。这个设计带来的直观后果很值得记住小文件读写不需要寻道到数据区速度极快而删除小文件后只要 MFT 记录没被复用内容其实还在 MFT 里恢复成功率非常高。我在实际做小文本文件恢复测试时常驻数据被完整找回来的概率明显高于几 MB 的大文件。至于目录它本质是一个特殊文件靠 $INDEX_ROOT 和 $INDEX_ALLOCATION 组成一棵 B 树文件名按 UTF-16 排序存放。这就是为什么在几万个文件的目录里按名字查找依然很快。三个时间戳$STANDARD_INFORMATION 和 $FILE_NAME 里各有一套经常被取证工具拿来互相印证因为有一些操作只会更新其中一套。2. $LogFile日志的真实能力边界能保住元数据保不住文件内容2.1 写前日志与检查点chkdsk到底在忙什么NTFS 是一款日志型文件系统但这里的日志和很多人想象的不是一回事。它采用的是经典的写前日志WAL思路修改任何元数据之前先把我打算怎么改记录到 $LogFile 里等日志落盘了再去真正修改 $MFT、$Bitmap 这些结构。每条日志记录带有 LSN日志序列号日志文件里维护着重启区、检查点checkpoint等信息用来界定哪些事务已经确定完成、哪些可能改到一半。断电的瞬间如果某个事务只写了一半重启时系统读 $LogFile把未完成的事务做两种处理之一重做redo那些已经写进日志但还没落到元数据的部分撤销undo那些只改了一部分、无法凑成完整状态的部分。Windows 自己在启动时做这件事相对静默但如果你用过 chkdsk会看到它先做检查文件系统再做检查安全描述符检查索引检查文件记录段这些阶段本质上就是在把日志里的事务对齐顺便校验索引 B 树和 MFT 位图的一致性。这里有个非常容易误解的点chkdsk 不是万能的修复工具它只保证文件系统结构自洽。举个我遇到过的例子一块脏盘上有个目录索引和文件记录对不上chkdsk 把孤儿文件统一扔进FOUND.000文件夹并改名为FILE0000.CHK。文件系统结构是干净了文件本身也没丢但原来的文件名、目录位置、时间戳全都对不上了。很多人跑到这一步就以为修复成功其实只是把烂摊子收拾进了收纳箱。另外一个实操细节$LogFile 的大小是固定的一般是 64MB 左右视卷大小而定。它不会无限增长写满之后靠检查点回收前面的空间。所以日志型文件系统并不是把所有历史操作都记下来它只保证最后一段未完成的操作能被正确收尾这跟审计日志完全是两码事。2.2 数据区的写入为什么不在日志保护范围内这是本篇最想强调的一点NTFS 默认只对元数据做日志普通文件内容不进日志。也就是说你把一个 2GB 的视频拷到硬盘上中途断电$MFT 里这个文件的记录、分配位图、目录索引都能被正确恢复到一致状态但文件内容本身可能只写进去 700MB剩下的部分全是零或者旧数据的残渣。后果分成两类。第一类是文件长度字段已经更新成 2GB但尾部内容没落盘打开时能打开但后半段是垃圾。第二类是长度字段还没更新文件看起来只有 700MB剩下的簇在 $Bitmap 里可能被标成空闲然后被后来的写入占用——这就是文件变短且无法挽回的典型场景。对比一下日志型数据库人家连数据页都记日志所以能做到崩溃后零丢失NTFS 的设计目标是在性能和数据一致性之间取平衡它优先保结构、保可用不保内容完整。所以真实世界里救数据最要紧的动作不是赶紧再拷一次而是立刻停止对该卷的任何写入。哪怕只是让系统自动挂载上卷、生成几个缩略图缓存都可能把那 1.3GB 的缺口填掉。我的习惯是一旦发现拷贝中断先把盘从机器上拔下来或者立刻挂载成只读再用另一块盘做全盘镜像后续所有操作都在镜像上做。注意Windows 的更好的性能磁盘策略启用写缓存延迟写入会在系统内存里排队。热插拔时如果缓存没落盘连 NTFS 的元数据都可能来不及更新。想稳就选快速删除策略代价是写入速度掉一截——这个取舍没有两全法。3. NTFS、FAT32、exFAT与Btrfs跨平台交换盘到底该选谁3.1 单文件4GB与簇大小的硬约束选文件系统时先看你要存什么、要在哪些系统之间搬。文件系统单文件上限卷容量参考跨平台性典型用途FAT324GB − 1 字节Windows 格式化上限 32GB极好几乎所有设备认U 盘、老设备、相机卡exFAT16EB 理论值极大Windows/macOS/Linux 均可老设备可能不认大容量 SD 卡、移动硬盘NTFS16TB4KB 簇256TB 级别Windows 原生Linux 需额外驱动Windows 系统盘、内部数据盘Btrfs16EB 理论值极大主要 LinuxLinux 系统盘、需要快照的场景FAT32 那个 4GB − 1 字节的限制是文件系统结构层面的死结它用 32 位表示文件大小但保留了一位做别的用途所以最大就是 4,294,967,295 字节。我第一次被它坑是拿 16GB U 盘拷一个蓝光原盘切片拷到 99% 报文件过大气得想砸键盘。解决办法要么切分文件要么换 exFAT。NTFS 在这个维度上没短板但它的问题是跨平台性打了折。macOS 只能读不能写原生驱动Linux 要靠 ntfs-3g 或内核 ntfs3安卓手机插上一般只能读。所以如果你要做在 Windows、macOS、Linux 之间来回倒腾的移动硬盘exFAT 往往是更省事的选择如果只是 Windows 内部使用或者需要 NTFS 才有的权限、加密、压缩、硬链接能力那就老老实实用 NTFS。3.2 STM32加FatFs读写SD卡时为什么不该碰NTFS很多人问过我STM32 上是不是可以挂 NTFS我的答案通常是别折腾。FatFs 是 ChaN 写的通用 FAT 实现它支持 FAT12/FAT16/FAT32通过配置FF_FS_EXFAT可以打开 exFAT 支持但它完全不懂 NTFS因为它没有实现 MFT、日志、权限模型这些结构。你拿一张 NTFS 格式化的卡插到板子上f_mount之后返回的就是FR_NO_FILESYSTEM。真正容易踩的是另一件事SD 卡的容量决定了出厂默认格式。SDSC≤2GB多是 FAT16SDHC4~32GB是 FAT32而 SDXC64GB 起按规范出厂就是 exFAT。我见过太多人拿一张 64GB 新卡直接插板子代码里只开了 FAT32结果死活挂不上然后怀疑硬件虚焊、怀疑 SPI 时序折腾一下午。真实原因就是 exFAT 没打开。在ffconf.h里需要关注这几个宏FF_FS_EXFAT打开 exFATFF_USE_LFN打开长文件名FF_LFN_UNICODE决定编码FF_MAX_SS和FF_MIN_SS要覆盖实际扇区大小多数 SD 卡是 512 字节但 exFAT 在某些设备上可能是 4096。另外 exFAT 需要 64 位 LBA 支持FF_FS_EXFAT打开后要确保底层disk_read/disk_write用 64 位地址。做完这些一张 128GB 的 exFAT 卡在 STM32 上读写就不是问题了。顺带说一句音频类 SoC 上常见的文件系统它们大多也是 FAT 精简实现为的是代码体积小、授权干净、扫描目录快播放器要频繁列目录。这类设备不支持 NTFS 是设计选择不是能力缺陷。如果你的项目要做插卡播放最省心的做法就是强制用 FAT32并在产品说明书里写清楚支持最大 32GB、FAT32 格式的卡。3.3 写时复制的Btrfs和原地更新的NTFS思路完全不同把 Btrfs 拉进来对比是因为它代表了另一条技术路线。NTFS 和 ext4 这类属于原地更新要改一个位置的数据就在原地改靠日志保证崩溃一致性。Btrfs 和 ZFS 属于写时复制CoW任何修改都写到新位置写完再更新指针旧数据副本在所有引用都切换完之前一直有效。这带来两个直接差别。第一是校验和Btrfs 对数据块和元数据块都存校验和读到不匹配会报错甚至从镜像副本修复NTFS 对文件内容没有校验和静默损坏bit rot你根本察觉不到直到某天打开一张白图。第二是快照Btrfs 做快照近乎零成本因为只需引用旧的数据块NTFS 没有等价能力VSS 是另一套卷影机制需要空间预分配。我的实际建议是Linux 系统盘用 ext4 或 Btrfs数据中心或需要快照回滚的场景优先 Btrfs跨平台交换盘用 exFATWindows 内部盘乖乖 NTFS。别指望用一种文件系统解决所有问题那通常意味着它在每个维度上都只是能用。4. Linux挂载NTFSntfs-3g和内核ntfs3到底该选哪个4.1 先用/proc/filesystems确认你手上是哪套驱动Linux 世界里挂载 NTFS 有三套实现一定要分清因为它们的参数和行为完全不同。第一套是内核里古老的ntfs驱动只读维护基本停滞第二套是ntfs-3g跑在 FUSE用户态文件系统上成熟、功能全、写支持稳定绝大多数发行版装的就是它第三套是内核ntfs3从 5.15 内核开始合入支持读写性能比 FUSE 方案好代码来自 Paragon。判断方法很简单cat /proc/filesystems | grep -i ntfs # 输出可能包含 ntfs、ntfs3、fuse 等 lsmod | grep -E ntfs|fuse mount | grep ntfs如果mount的输出里出现type fuseblk那走的必然是 ntfs-3g。如果显示type ntfs3就是内核驱动。文件管理器里点一下就挂载的桌面环境GNOME、KDE默认通常调udisks2它的后端又是 ntfs-3g。知道这一点很重要你在文件管理器里点挂载再手动mount -o remount两套挂载方式可能会打架。手动挂载的写法区分如下# ntfs-3g 方式 sudo mount -t ntfs-3g -o uid1000,gid1000,umask022,noatime /dev/sdb1 /mnt/usb # 内核 ntfs3 方式 sudo mount -t ntfs3 -o uid1000,gid1000,umask022 /dev/sdb1 /mnt/usb提示如果两种驱动都可用而你只想临时挂一次显式写-t参数最保险用mount /dev/sdb1 /mnt/usb让内核自己猜结果取决于/proc/filesystems的优先级不同发行版行为不一样。4.2 uid、gid、umask和windows_names权限映射的几个坑NTFS 用的是 ACL 权限模型Linux 用的是 uid/gid 九位权限位两套东西没法一一对应。所以挂载时 NTFS 驱动做的是一刀切映射uid和gid指定挂载后所有文件归谁umask/fmask/dmask指定权限位怎么扣。umask022意味着文件 644、目录 755这是最常用的配置。这里有个新手常掉进去的坑挂载后ls -l看到的权限全都是-rwxrwxrwx或者整齐划一的-rw-r--r--于是有人以为文件权限坏了。并不是坏了而是这套映射本来就是假的真正的权限信息还躺在 $Secure 里。你在 Linux 上chmod 600NTFS 的 ACL 不会同步变化重启挂载后看起来又变回去了。ntfs-3g 支持把 POSIX 权限映射写进卷根的.NTFS-3G/UserMapping文件但那需要额外配置日常用不上。另一个参数是windows_names。加上它之后驱动会拒绝创建 Windows 不允许的文件名比如带:、*、?、\的名字以及CON、PRN这类保留名。不加的话你在 Linux 下能建出a:b这样的文件插到 Windows 上就变成隐藏的备用数据流用户在资源管理器里根本看不到还占空间。我一般建议对要和 Windows 交换数据的盘加上这个选项。还有$DATA之外的一个特性值得提NTFS 的交替数据流ADS。file.txt:hidden这种写法就是往主流之外挂一个小流Windows 的资源管理器不显示dir /r才看得到。Linux 这边的 ntfs-3g 默认不把 ADS 暴露成普通文件所以有些从 Windows 拷过来的文件会少几个字节其实数据在流里。杀毒软件和取证工具对 ADS 特别敏感就是因为这里能藏东西。4.3 脏标志与快速启动Ubuntu不识别NTFS的真实原因Ubuntu 不识别 NTFS这个说法其实不准确真实的报错通常是这两种The disk contains an unclean file system (0, 0). Metadata kept in Windows cache, refused to mount. Please run ntfsfix /dev/sdb1 to fix the dirty bit. NTFS is inconsistent. Run chkdsk /f on Windows then reboot it TWICE! The partition is dirty. Please run chkdsk on Windows.根源是 Windows 的快速启动Fast Startup和休眠。Windows 关机时并没有真正关闭而是把内核会话写进了hiberfil.sys同时 NTFS 卷上留下了脏位和未清空的 $LogFile。Linux 的驱动看到脏标志出于安全考虑会拒绝读写挂载退化成只读。正确的处理顺序是回到 Windows关闭快速启动控制面板里的电源选项或powercfg /h off直接禁用休眠然后彻底关机重启两次让 $LogFile 被正常收尾。这一步做完Linux 就能正常挂载了。次选方案是用ntfsfixsudo umount /dev/sdb1 sudo ntfsfix -d /dev/sdb1 # -d 清除脏标志但必须说清楚ntfsfix 不是 chkdsk。它只会清脏位、重置日志、修一些极简单的引导扇区问题它不会去校验索引树、不会找回丢失的簇、不会修 MFT 里的错误引用。真正有结构性损伤的卷还是得插到 Windows 上跑chkdsk /f必要时加/r扫描坏扇区但那会非常慢。我见过有人用 ntfsfix 修好 之后继续写入最后把索引结构彻底搞乱恢复成本翻了好几倍。5. sync、VFS与页缓存你的数据是什么时候才算真正落盘5.1 从write()到盘片中间隔着四层缓存这个话题值得单独拎出来讲因为我拷贝完了进度条都 100% 了怎么还会丢是所有热插拔事故的共同疑问。答案在于从write()返回到数据真正写进介质中间隔着好几层。第一层是应用自己的缓冲区比如你用的拷贝工具的 buffer。第二层是内核的页缓存page cachewrite()只是把数据拷进内存里的页标成 dirty然后立刻返回。第三层是文件系统层也就是我们说的VFS它是 Linux 里所有文件系统的统一抽象superblock 表示一个已挂载的卷inode 表示一个文件对象dentry 表示目录项缓存file 表示打开的文件句柄。NTFS 挂载到 Linux 上之后也是通过 VFS 暴露给用户的所以你在/mnt/usb上做的操作先落到 VFS 对象上再翻译成 NTFS 驱动能懂的请求。第四层才是块设备层和硬件缓存硬盘自己的 DRAM 缓存收到数据后也可能还没真正写进盘片。脏页什么时候回写由内核参数控制/proc/sys/vm/dirty_expire_centisecs默认 3000也就是 30 秒dirty_writeback_centisecs默认 5005 秒一次唤醒回写线程。所以进度条消失和数据落盘之间最多可能有几十秒的窗口。这个窗口里拔掉 USB前面的写入就全丢了。这也解释了一个现象往 U 盘拷小文件看着很快拔下来插到另一台机器上一看空空如也拷大文件反而稳因为拷贝耗时足够长回写线程一直在后台把脏页刷下去。5.2 什么时候必须sync什么时候sync也救不了sync命令的作用是让内核把所有脏页刷到块设备。经常有人问sync、fsync、fdatasync有什么区别sync是全局的刷所有文件系统fsync(fd)是针对某个文件描述符的刷这个文件的数据和元数据fdatasync(fd)只保证数据落盘元数据里跟读回数据无关的部分比如 mtime可以延后。数据库和日志系统狂热地使用 fsync就是因为它能给出明确的落盘承诺。在 USB 场景下的正确姿势是cp -r /data/photos /mnt/usb/ sync # 等它返回再拔sync会阻塞到写完为止这才算安全。如果你的挂载参数里加了sync选项mount -o sync每次写都会立即落盘代价是写入速度可能下降一个数量级——这也是为什么有些人抱怨加了同步选项后拷文件慢得离谱。还有个常见误区echo 3 /proc/sys/vm/drop_caches被当成清缓存就以为能代替sync。实际上它只丢弃干净的缓存页dirty 页不会被丢必须回写完成才能释放。所以它既不能保数据也不能省事反而会让后续读取变慢。最要命的情况是sync也救不了。如果你在拷贝过程中拔了盘USB 控制器已经断了内核的脏页再也没有目的地可写这些页最终会被丢弃同时在dmesg里留下同一次写入丢失的记录。这种情况下的损失是既定的只能靠恢复工具。6. transport endpoint is not connected挂载点还在、后端已死的排查链路6.1 FUSE挂载的进程模型与断连的产生条件回到开头那个报错。transport endpoint is not connected这个提示不是 NTFS 特有的它是 FUSE 的通用错误出现条件是挂载点还在但背后提供服务的用户态进程已经没了或者连接断了。理解这一点需要知道 FUSE 的架构——内核里有一个 fuse 模块挂载点上的所有文件操作都被转发到一个用户态进程比如mount.ntfs-3g或ntfs-3g由它去干活。内核和这个进程之间靠一个特殊的字符设备/dev/fuse通信。一旦设备被物理拔掉内核会通知各挂载点但 FUSE 挂载点不会自动清理因为内核不知道那个用户态进程是不是还能恢复同时用户态的 ntfs-3g 进程收到 I/O 错误多数情况下会退出。于是挂载点目录还在你cd进去没问题因为目录项在缓存里ls需要向进程要数据拿不到就返回ENOTCONN翻译成人类语言就是 transport endpoint is not connected。同一个错误还有几种触发方式列个对照表方便排查触发原因典型现象判断依据USB 设备物理拔出挂载点仍在操作报 ENOTCONNlsusb里设备消失dmesg有 usb disconnectntfs-3g 进程被 OOM 杀掉突然无法访问进程列表里没了dmesgntfs-3g 崩溃同上可能有 core dumpjournalctl -u或系统日志手动执行过 umount 但失败挂载点残留mount网络文件系统对端断开行为类似适用于 NFS、SSHFS 等值得注意的是安卓上从应用层访问用户存储也有类似的味道应用拿到的/storage/emulated/0/...路径是经过一层模拟层映射过来的视图背后真正的分区不是这个路径。当底层挂载异常或者权限被收回时应用侧的表现也是路径存在但读不到东西。原理上是同一个思路抽象层之上的路径不一定对应真实存在的数据。6.2 从dmesg到umount -l的完整恢复步骤我按实际操作顺序把处理流程写下来这套流程我用了很多次基本能覆盖九成场景。第一步先看内核有没有报错确认是硬件断开还是软件崩溃dmesg | tail -50 # 关注 usb disconnect、reset high-speed USB device、I/O error、EXT4-fs error 之类的关键字第二步看挂载点和进程状态mount | grep usb ps aux | grep -i ntfs lsof /mnt/usb 2/dev/null | head第三步尝试正常卸载。如果报 target is busy说明还有进程在使用这个目录sudo umount /mnt/usb # 如果提示 device is busy sudo fuser -vm /mnt/usb sudo umount -l /mnt/usb # 延迟卸载先把挂载点从命名空间摘掉第四步如果延迟卸载也不行用强制方式。这里要小心-f在某些内核版本上对 FUSE 支持有限所以更稳的顺序是先-l再确认sudo umount -l /mnt/usb mount | grep usb # 应该没有输出了第五步如果挂载点还残留在/proc/mounts里把残留的 ntfs-3g 进程清掉再重试。绝大多数情况下kill掉那个卡死的进程之后挂载点会自动释放。第六步确认设备真的回来了USB 重新枚举成功再重新挂载lsblk -f # 看设备号和文件系统类型 sudo mount -t ntfs-3g -o ro /dev/sdb1 /mnt/usb # 先只读挂载我强烈建议第一次重新挂载时加ro也就是只读。原因很简单设备掉线那一刻很可能正有写入在途NTFS 的元数据可能处于中间状态。先只读挂上把要紧的文件拷出来再决定要不要执行修复。这个习惯救过我不止一次——有位同事就是在重挂载后直接读写把本来还能恢复的目录索引写花了。7. 删除之后数据还在不在MFT残留、USN日志与恢复的正确姿势7.1 删除只是清掉两个位剩下的全靠没被覆盖把前面所有铺垫串起来删除在 NTFS 上到底做了什么简单说就三件事MFT 记录头里的使用中标志被清掉$Bitmap 里对应的簇位被清零父目录的索引项被移除目录索引是 B 树删除节点会走平衡操作。而 $DATA 属性描述的数据簇通常一个字节都不动。所以恢复的第一条铁律是数据还在但只是暂时还在。任何新的写入都可能分配那些被标记为空闲的簇一旦覆盖就真的没了。这也是为什么恢复软件第一步都是要求你把盘挂成只读或者先做镜像。第二条线索是$UsnJrnlUSN 日志。它是 NTFS 的变更日志记录某文件被创建、写入、重命名、删除这类事件带时间戳和原因码。Windows 上可以用fsutil usn readjournal C:查看。对恢复和取证来说它的价值在于能告诉你这个文件在什么时候被删的、删之前叫什么名字配合 MFT 残留记录能把路径和内容对上。默认情况下 USN 日志有大小上限几十 MB 到几百 MB被覆盖后旧记录就没了所以时间拖得越久能查到的历史越少。第三条线索是文件签名。有些文件JPEG、PNG、PDF、ZIP头部有固定字节序列扫描工具可以直接遍历整个数据区找这些魔数这叫文件雕刻。它不需要 MFT 记录代价是恢复出来的文件没有原始名字、没有目录结构、很多碎片化的文件拼不回来。恢复工具一般是两条线都跑先按 MFT 扫找得到就按原名原路径恢复找不到再按签名扫能捞多少算多少。7.2 先做镜像再扫描操作顺序错了神仙也救不回我把一套经过验证的操作顺序写在这里按这个来成功率会明显高一些。第一立刻断电或者把盘从系统里卸载别再让系统自动挂载和索引。Windows 上插上盘弹出的是否扫描并修复一定要点取消——那个自动修复会写盘。第二用只读方式做全盘镜像。Linux 下推荐 ddrescue 而不是 dd因为它能记录坏道、支持断点续做sudo ddrescue -d -r3 /dev/sdb /mnt/backup/disk.img /mnt/backup/disk.map第三如果文件系统结构本身还完好可以在只读挂载下直接拷贝文件如果 MFT 已经损坏、挂载都挂不上就跳过挂载直接在镜像上做结构分析。第四恢复工具选择要看场景。像 GetDataBack for NTFS 这类专门解析 MFT 的工具优势在于它能读原始的 $MFT、重建目录树、处理碎片化文件TestDisk 更偏向分区表和引导扇区级别的修复PhotoRec 则是纯粹的签名雕刻适合文件系统彻底报废的情况。我的经验是先用解析 MFT 的工具跑完再上雕刻工具两者结果合并去重。第五恢复出来的文件不要写回原盘哪怕只是放一下。写到另一块硬盘最好是另一台机器。有几类文件天然难恢复得提前有心理准备被 NTFS 压缩过的文件数据是 LZNT1 压缩块取出来是乱码、加密文件EFS 或 BitLocker 加密过的卷没密钥就没戏、稀疏文件大量空洞恢复出来尺寸对但内容缺、以及碎片极其严重的大文件MFT 记录里的 run list 一旦损坏靠签名也拼不齐顺序。最后一个细节关于时间戳。恢复出来的文件$STANDARD_INFORMATION 里的四个时间创建、修改、MFT 修改、访问经常被取证人员拿来互相比较。如果修改时间早于创建时间或者 MFT 修改时间被改得离谱那基本可以判定有人用工具动过手脚。这个技巧在做数据取证时特别有用普通用户拿它来验证这个文件是不是后来补进去的也很好使。我个人在多年折腾里总结出一条最实用的原则别在出问题的盘上做任何试一试的操作。所有尝试都发生在镜像上成本是几 GB 的磁盘空间收益是保住一次后悔的机会。至于 NTFS 这个文件系统本身它不是完美的——没有数据校验和不保护文件内容权限模型跟 Linux 体系格格不入——但它胜在成熟、工具链齐全、出问题时有足够多的线索可查。把 MFT、$Bitmap、$LogFile、$UsnJrnl 这几个东西的作用记清楚再配上正确的操作顺序绝大多数硬盘事故你都能自己处理掉。
上一篇/下一篇内容由系统自动关联
返回资讯列表 →