我需要有人对我迄今为止的手动 NTFS 恢复过程进行健全性检查,因为它让我陷入了困境。
背景:
- 我有一个 1TB NTFS 外置硬盘(WD Elements),里面主要存放的是照片。
- 不知何故,它已损坏并在 Windows 上显示为原始磁盘。
- 它出现在 Linux 系统的
/dev/disk/by-path
(和by-id
等by-uuid
)目录中,并显示为/dev/sdb
。 - EaseUS 能够通过快速扫描(而不是繁重的深度扫描)找到(几乎?)其中的所有照片
- EaseUS 找到了大约 70GB 的文件(大部分是照片)。
- 我认为 NTFS 记录已损坏,也就是说这不是机械故障。
- 我想亲自尝试恢复,以获得乐趣和利益。
- 我没有其他足够大的驱动器来制作损坏驱动器的完整映像。
我需要解析 NTFS MFT $File 记录,因为:
- 我想恢复原始文件名和目录结构。
- 如果图像不是写在连续的簇中,那么仅通过查找图像文件签名我就无法成功恢复它。
计划如下:
- 对损坏的磁盘的一部分进行成像。
- 对其进行解析以识别并读取 MFT $File 记录。
- 使用 $File 记录(特别是其 $Data 属性)来确定每个文件的数据运行。
- 知道数据为文件运行后,我可以从使用创建的图像中挑选出文件的字节
ddrescue
。 - 冲洗并重复,直到完成。
首先——这听起来像是一个合理的计划吗?
我做了什么:
- 找到一堆$File记录
- 解析一个以获取数据运行
- 在数据运行指定的位置读取原始字节。
具体来说:
- 用于
ddrescue
对 100GB(从 0 开始)的损坏磁盘进行映像处理。- 我猜想我需要的几乎所有实际数据都写入了前 100GB,因为感兴趣的数据总量为 70GB。如果需要,我可以在后续的 100GB 部分中重复整个过程。
- 我用来映像第一个 100GB 的命令是
ddrescue /dev/sdb ~/mydisk.img ~/mydisk.map --size=100G
。 ddrescue
确实遇到了 I/O 错误并报告仅恢复了约 99.57%。- 图像的开头(前 20MB 左右)似乎是空的,所以这可能是驱动器故障的原因。我暂时忽略了这一点。
- 读取 100GB 图像并找到 ASCII 字符串“FILE”的所有实例,它表示 MFT 中 $File 记录的开始。
- 这也会引发误报,例如任意文件中间出现单词“PROFILE”。
- 因此,我只考虑“FILE”的一次出现与下一次出现之间的距离小于等于 1024 字节的结果,因为这是最大 MFT 记录大小。如果“FILE”的一次出现与下一次出现之间的距离为 3MB,那么它不太可能是 $File 记录。
- 迭代假定的 $File 记录(大小 <= 1024 字节)并提取 $Data 属性。
- 对其进行数据运行解析(忽略关于常驻属性与非常驻属性的讨论,我认为我理解这些讨论,但不是我的问题的一部分)。
因此,我完成了上述过程,选择了一条 $File 记录并确定了其数据运行。以下是 $Data 属性(标题和内容):
80 00 00 00 48 00 00 00 01 00 00 00 00 00 01 00
00 00 00 00 00 00 00 00 FA 03 00 00 00 00 00 00
40 00 00 00 00 00 00 00 00 B0 3F 00 00 00 00 00
F4 AC 3F 00 00 00 00 00 F4 AC 3F 00 00 00 00 00
32 FB 03 ED C8 11 00 00 FF FF FF FF 82 79 47 11
数据运行详细信息是最后一行的前半部分,就在FF FF FF FF
属性标记结束之前:
- 长度字节:
32
- 簇运行数:(
FB 03
小端)= 运行中有 1019 个簇 - 簇起始号:
ED C8 11
= 1165549 是运行的第一个簇 - 下一个
00
表示不再有运行。
现在,考虑到每个扇区有 512 个字节,每个簇有 128 个扇区,我从 100GB 图像中读取(1019 * 128 * 512)个字节,从(1165549 * 128 * 512)开始。
不幸的是,这给我留下了一个 66.8MB 的文件,其中大部分都是 0x00,尽管最后有一些数据。我很确定我弄错了,我只是偶然发现了一些数据(尽管我确实碰巧以 JPG 文件结束标记(DD F9)结束)。
我完成整个任务的方法是否合理,而我只是在某个地方犯了一个小错误?
或者我误解了 NTFS 的一些基本知识,而这完全是错误的想法?
答案1
首先——这听起来像是一个合理的计划吗?
不。我的意思是我没有深入研究你的解码运行方法,但是,起始簇是相对于文件系统的起始(=当我们谈论 NTFS 时,卷/分区的起始)。因此,任何指向簇号的 MFT 条目都指向相对于分区起始的簇号,而不是相对于卷的任意 100 MB 部分。
此外,MFT 是“自引用”,因此首先要尝试找到 MFT 的起点,然后从中导出全部MFT 条目。如果您找不到 MFT 的开头,请尝试查找 MFT 的镜像。
因此,为了正确解码 MFT 条目并获取其引用的数据,我们需要:
- 分区开始的偏移量。
- 正确的簇大小
因此,如果我们解码起始簇,我们可以执行以下操作:(簇号 * 扇区 / 簇)+ 偏移分区
您如何确定每个簇有 128 个扇区?这似乎完全不对!请参见此处的默认值:https://www.disktuna.com/default-cluster-sizes-for-fat-exfat-and-ntfs/。
答案2
将损坏的光盘暴露于您描述的读取负载是不专业的。第一个要求是将该驱动器复制到稳定健康的驱动器,以避免丢失额外的扇区,并且不再有不可读的扇区。无法复制不可读扇区的事实令人难过,但关键是避免您或恢复程序处理读取错误。
您的恢复尝试很可能已经对该驱动器造成了额外的损坏。
由于元数据结构和数据不一定以线性方式排列,因此您无法通过随后将 100GB 切片读入其他可用驱动器存储来弥补至少拥有一个足够大的驱动器的不足。您需要随机访问。不幸的是,在您的情况下,一旦结构指向下一个 100GB 切片,您就必须清空 100GB 存储区域。
如果您已经在使用您喜欢的编程语言解析结构,则无需为复制作业运行 dd 等 unix 命令。在您开始恢复尝试时,只需要运行一次 ddrescue。
如果您只是想学习 NTFS 内部结构,那也很好,而且很酷,但您可以在 USB 等存储设备上学习。无需大驱动器。
请思考一下 Easeus 未能恢复您想要的元数据(如文件名和文件夹结构)的原因。
答案3
我认为驱动器是线性的,从簇 0 扇区 0 字节 0 开始一直到物理驱动器的末尾。
是也不是。存储地址是线性的,从字节 0 开始。扇区地址也是线性的。
簇地址是线性的,从簇号零开始,但仅相对于其各自的分区。没有磁盘范围的簇标签,只有从零开始的分区范围的簇标签。
您是说,如果我使用像 ddrescue 这样的工具来读取字节 0 - 1000000,我不应该期望读取描述布局的 NTFS 元数据?
NTFS 元数据不仅涉及引导扇区,还涉及主文件表和其他文件。当从驱动器的开头读取 1 MB 时,您只会读取主文件表的一小部分(前提是它位于那里)。它的位置不固定,并且可能会在碎片整理时发生变化。
使用此策略来试验并了解您的文件系统: https://forum.cgsecurity.org/phpBB3/viewtopic.php?p=31304#p31304
尝试解密 NTFS 时,最好先了解预期结果。这是一种解密过程,类似于“已知明文攻击”,您知道整个明文。
有人刚刚对我的答案投了反对票。如果是你,请解释原因。是不是哪里出了错?我想知道!谢谢。