从损坏的驱动器中恢复数据(文件系统:FAT32、NTFS):第 1 部分






4.83/5 (16投票s)
从损坏的驱动器、FAT32、NTFS 中恢复数据。
介绍
一年前,我正在公司做一个重要的项目。突然,我的电脑死机了,我很快意识到我的电脑被病毒严重感染了,所以我重启了电脑。重启后,屏幕上出现一条错误信息:“未找到驱动器”。我发现我的驱动器损坏了,这很糟糕,因为我没有备份我的代码。我问我叔叔该怎么办,他提醒我驱动器恢复软件,但我只找到了它们的演示版,所以我决定自己恢复我宝贵的数据,并开始研究驱动器、文件系统等。现在我谦虚地写这篇文章,以便其他人也能像我一样解决驱动器损坏的问题。
从损坏的硬盘驱动器恢复数据并非易事或短时间的工作。要做到这一点,您需要了解硬盘驱动器、文件系统、它们的结构、它们的特性以及它们的工作原理。此外,您还需要了解损坏的程度。本项目唯一需要您的是全身心的投入、奉献和编程技能。我将尽我最大的努力为您提供您所需的所有信息,以便您在不使用网络上任何商业或荒谬软件的情况下恢复您宝贵的数据。让我们开始我们的冒险吧;任何建议、更正和补充都将受到赞赏。
一些基本概念
- 硬盘驱动器由多个旋转的磁性磁盘组成,就像 CD 盒中的 CD 一样。每个磁盘的两面都可以存储数据,并有两个读写磁头。数据存储在称为柱面的同心环上。柱面可以细分为扇区或块。
- 重要提示:每个扇区(默认)长度为 512 字节。
- 在计算机中,最小的单位是 1 比特。当您使用计算机时,可以访问和处理的最小数据单位是 1 字节。您无法处理比特。当数据在硬盘驱动器上读取或写入时,最小单位是扇区。这意味着如果您想读取或写入 10 或 20 字节,计算机实际上会读取或写入 512 字节。
- 重要提示:要从硬盘驱动器恢复数据,您需要处理扇区而不是字节。例如,您每次需要获取 512 字节(扇区)。如果您不明白,请不要担心,我将在编码部分向您展示。
- 为了在硬盘驱动器上定位任何数据,可以通过柱面、磁头和扇区进行唯一寻址。这种寻址方案称为 CHS 寻址方案。但它正在被弃用,因为它非常复杂。所以不要太担心它,但如果您有兴趣,请自己谷歌搜索。
- 由于 CHS 寻址算法已被弃用,因此出现了一种称为逻辑寻址算法 (LBA) 的新算法。LBA 是一种简单易懂的算法,它将 CHS 寻址方案映射为一系列顺序地址,例如
第一个扇区 = LBA(0)
,第二个扇区 = LBA(1)
,依此类推。 - 注意:如果您想知道您的硬盘大小,那么
- 硬盘(大小) = 块大小 * 总块数。
- 其中块大小 = 512 字节(默认)
- 在开始恢复过程之前,您需要了解三件事
- 主引导记录 (MBR):您从这里开始。它始终存在于驱动器的第一个 LBA 或扇区(512 字节)中。如果存在此项,则该驱动器是可引导的;如果不存在,则该驱动器是不可引导的。可引导驱动器是指其中存在操作系统 的驱动器。我将在后面的教程中解释这一点。
- 卷引导记录 (VBR):卷引导记录 (VBR)(也称为卷引导扇区、分区引导记录或分区引导扇区)是 IBM 个人计算机引入的一种引导扇区,用于创建硬盘驱动器的分区(例如,C:\、D:\、E:\ 等)。每个驱动器(C:\、D:\ 等)都有自己的 VBR。我将在我的第二个教程中解释这一点。
- 文件系统:文件系统基本上是一种算法,它提供有关文件如何存储以及如何减少存储和检索文件时出现的内存(空间)浪费和复杂性的规范。如果您想恢复文件,您将需要知道您的驱动器中存在哪种类型的文件系统(NTFS 或 FAT32)。在这里,我将解释这两种文件系统以及在它们损坏时如何恢复数据。我将在我的第三个教程中解释这一点。
什么是数据损坏?
数据或驱动器损坏是指您的操作系统 (OS) 无法检索文件及其信息或属性的情况。原因有很多。可能是因为您的文件系统损坏了,或者可能是因为您的 MBR 或 VBR 损坏了,或者您的硬盘驱动器或 U 盘物理损坏了等等。如果您的损坏驱动器满足某些要求,您可以轻松恢复数据。
- 驱动器及其扇区可以被您的操作系统 (OS) 识别
- 您的程序可以访问驱动器及其扇区
数据恢复的主要目标是恢复在发生失真和损坏后仍然存在于驱动器中的剩余数据。这意味着您必须遍历每个 LBA 以搜索文件,而您的操作系统已无法做到。
架构
下图为您提供了 MBR、VBR 和文件系统在驱动器中的完整视图。
- 上图提供了可引导驱动器的抽象视图
- 每个驱动器在其分区的第一个扇区中都必须包含 VBR。
- MBR 包含一个分区表,其中包含指向每个 VBR 的地址。
- 每个合适 VBR 都包含一个指向您的数据开始的扇区的地址。
- 您的驱动器中的文件和文件夹以 B+ 树结构的形式存在。我将在我的文件系统教程中解释这种结构。
- 对于像 U 盘这样的不可引导驱动器,没有 MBR,只有 VBR 和其余部分。
损坏级别
为了从损坏的驱动器恢复数据,您首先需要知道您的驱动器或数据损坏到了什么级别。级别决定了您可以恢复多少数据。它们是:
- 级别 1:这是一个简单的级别,只有 MBR 的分区表已损坏。此时,您遍历并搜索每个 LBA 或扇区以查找 VBR,一旦找到 VBR,您就可以找到您的数据。
- 级别 2:在此级别,您的 VBR 的某些字段已损坏,导致您的 OS 无法识别您的文件系统。在这种情况下,您必须分析 VBR 以获取 FAT 32 中根目录的地址字段和 NTFS 中 MFT 的地址字段。如果获取成功,您将可以轻松搜索和恢复损坏和删除的数据,否则您必须逐个扇区进行遍历搜索。
- 级别 3:在上述级别中,我们推断每个节点都包含指向其后续节点的地址,就像一棵树一样。例如,MBR 包含指向相应 VBR 的地址,VBR 包含指向您的文件节点开始的地址,依此类推。因此,如果这些地址或引用已损坏,则恢复所有数据将非常困难。在这种情况下,恢复量直接与知识相关,例如,您对文件系统的了解越深,您就可以恢复更多数据。
- 级别 4:在这种情况下,无法保证您可以恢复数据,因为损坏可能是硬件的物理损坏,例如硬件在火灾中烧毁,或因跌落而变形,或进水等。在这种情况下,您可以在数据恢复实验室进行数据恢复。
现在我们都对数据和驱动器有了基本的了解。由于我之前说过数据恢复过程不是一个简单易行的任务,我们将分部分进行。在我的第一篇教程中,我将讨论主引导记录 (MBR) 以及如何编写读取和分析 MBR 的应用程序。请注意:MBR 是操作系统的重要组成部分。没有 MBR,操作系统就无法运行。请谨慎进行 MBR 实验。本教程及附带的演示项目仅供知识参考。本教程不对您在实验或使用演示项目期间可能造成的任何损坏负责。请自行承担风险。
在我的第二个教程中,我将解释卷引导记录 (VBR) 及其结构。
在我的第三个教程中,我将解释 FAT-32 中的根目录和 NTFS 中的 MFT,以及如何搜索您的文件并允许您的应用程序进行恢复。
背景
主引导记录 (MBR) 始终存在于特定驱动器(HD、PD、MC 等)的第一个扇区 (LBA(0)) 中,前提是该驱动器是可引导的。它完全负责在基于基本输入/输出系统 (BIOS) 的计算机中引导到操作系统。MBR 包含一些有助于系统引导的内容。
- 引导加载程序代码:当您的计算机启动时,它需要执行代码来加载操作系统或您想要的任何软件。这第一组代码驻留在 BIOS 中。此代码检查存在的硬件并进行一些测试以确保一切正常以进行引导。然后,根据您指定的引导顺序(或您的计算机制造商指定的顺序),它开始加载各种磁盘的第一个扇区。当它找到一个标记为 MBR 的磁盘时,它会将执行转移到其中。此代码称为引导加载程序代码(通常只有 440 字节)。引导加载程序代码的任务是查找分区表中的活动分区(例如,操作系统引导文件所在的位置(通常是C:\))。(见下图)查找活动分区的起始扇区。将引导文件副本从分区加载到内存(例如,NTLDR、Boot.ini 等),并将控制权转移给它,这样您的操作系统就可以运行了。您不必深入研究这部分,因为在恢复过程中它没有用处,但如果您有兴趣创建自己的操作系统,您会考虑它。接下来的六个字节是引导代码标识符,就像产品密钥一样。
- 分区表:这是您必须认真考虑的部分,因为分区表包含有关分区(如C:\、E:\、F:\ 等)的信息。分区表的大小为 64 字节。分区是硬盘驱动器的一部分,它已被逻辑上分离,在操作系统看来就像它自己的卷,并且可以拥有独立的文件系统结构。无论哪个分区是活动分区(例如,包含操作系统),包含该分区 VBR 的扇区的起始偏移地址,包括其大小以及该分区是 NTFS 还是 FAT 格式的信息。要恢复您的文件,首先您需要包含您的文件的那些分区(如 C:\ 驱动器),为此您将需要此分区表。(见下图)
- 磁盘签名:MBR 和 VBR 始终包含至少两个字节的磁盘签名(55 AA)。此签名标识该扇区是否包含 MBR 或 VBR,例如,如果驱动器的特定扇区包含磁盘签名,它可能包含 MBR 或 VBR,因此为了在我们的驱动器中查找 MBR 或 VBR,我们将使用此签名。(见下图)
在这里,我们只能处理分区表和磁盘签名(引导签名)。
分区表
存在两种类型的分区表
- 一种是通用的 64 字节主分区表
- 另一种是扩展分区表
64 字节主分区表分析
要检查主分区表,请读取偏移量 1BEh 到 1FDh 之间的内容,并考虑通用分区表的以下结构。
64 字节主分区表 | ||
地址(偏移量) | 长度(字节) | 分区 |
1BE - 1CD | 16 字节 | 分区 1 (C:\) |
1CE - 1DD | 16 字节 | 分区 2 (D:\) |
1DE - 1ED | 16 字节 | 分区 3 (E:\) |
1EE - 1FD | 16 字节 | 分区 4 (F:\) |
在通用的 64 字节主分区表中,所有四个分区都存在于单个分区表中。我将借助下图进行解释。
现在我们来分析 16 字节分区表条目的结构。
让我们以分区 1(C:\ 驱动器)为例,对其进行剖析以查看它包含什么。C:\ 驱动器分区表条目包含的字节在下图中有清晰的说明。
- 引导指示符:这是分区表条目的第一个字节,指示它是否为活动分区。例如,它是否包含操作系统(OS 文件、驱动程序等)。如果此字段包含 80H(十六进制)(十进制=128),则它是活动分区,例如,通常C:\(分区 1)是活动分区(包含 Windows 的引导和系统文件)。如果一个分区是活动分区,那么该分区称为系统分区。对于非活动分区,该字段为 00h。
- 起始 CHS 值:由于 CHS 寻址算法已被弃用。您无需处理此值。忽略它。
- 分区类型描述符:此字段长度为 1 字节,是一个重要字段,因为它提供了有关您的驱动器中实现的文件系统类型的信息。由于每个文件系统都有自己的算法,因此了解您的硬盘驱动器中实现了哪种文件系统非常重要。此字段中可能包含一些十六进制标志,如下所示:
- 00h------------无分区(无文件系统)
- 01h------------DOS FAT-12(文件系统)
- 04h------------DOS FAT-16(无文件系统)
- 05h------------扩展 DOS 3.3(扩展分区文件系统)
- 06h------------DOS 3.31(大文件系统)
- 07h------------Windows NT(NTFS 文件系统)
- 0Bh------------Windows 95(FAT-32 文件系统)
- 有关其他文件系统的更多信息,请单击此处分区类型的十六进制标志。
- 结束 CHS 值:忽略它。
- 包含 VBR 的扇区地址:由于我之前解释过,每个分区在其分区的第一个扇区都有一个卷引导记录 (VBR)。此字段包含指向该 VBR 的地址,因此这是一个重要字段。它包含扇区的十六进制地址,一个扇区长 512 字节,因此先将其转换为十进制,然后乘以 512 以获得 VBR 从开始处的字节偏移量。
- 分区大小:您将在此处获取分区的大小。由于您知道分区的 VBR 地址及其大小,因此您可以推断出分区最后一个扇区的地址,如下所示:
最后一个扇区的地址 = VBR 地址 *(分区大小 / 512)
扩展分区表分析
在主分区表中,我们看到 16 位分区表条目存在于一个 64 位分区表中,但扩展分区表就像一个链表。存在多个分区表,每个分区表包含一个分区条目和指向另一个分区表的引用或地址。我将借助下图向您解释。
扩展分区条目通常具有 05h 或 0Fh 的分区类型;这取决于磁盘的大小。弄清楚扩展分区中有多少个逻辑驱动器的唯一方法是跳转到扩展引导记录中的每个扩展分区表,直到找到最后一个 EBR 表。EBR 可以被描述为由从前一个 EBR 到下一个 EBR 的链接连接在一起。因此,要获得包含扩展分区的任何硬盘驱动器的完整布局,您需要一个摘要或副本,其中包含每个 EBR 的扩展分区表以及主分区表的数据。
Using the Code
要访问可引导驱动器的 MBR,首先您需要访问硬件,为此您需要 Windows API。由于 Windows 的安全策略,没有它您无法访问硬件。因此,要在 C# 代码中导入 Windows DLL 文件,您需要使用[DllImport]
属性。
//
// Windows API Import
//
[DllImport("kernel32.dll", CharSet = CharSet.Auto, SetLastError = true)]
public static extern IntPtr CreateFile(string lpFileName, uint dwDesiredAccess,
uint dwShareMode, IntPtr lpSecurityAttributes,
uint dwCreationDisposition, uint dwFlagsAndAttributes, IntPtr hTemplateFile);
[DllImport("kernel32", SetLastError = true)]
public static extern unsafe bool ReadFile(IntPtr hFile, void* pBuffer, int NumberOfBytesToRead,
int* pNumberOfBytesRead, int Overlapped);
[DllImport("Kernel32.dll", CharSet = CharSet.Auto, SetLastError = true)]
public static extern unsafe ulong SetFilePointer(IntPtr hFile, uint lDistanceToMove, int* lpDistanceToMoveHigh,
uint dwMoveMethod);
[DllImport("kernel32", SetLastError = true)]
public static extern bool CloseHandle(IntPtr hObject);
...
要访问您的驱动器,您可以使用注册表或 WMI 管理器来获取您计算机上的活动驱动器。
//
// WMI MANAGER
//
ManagementObjectSearcher MOSear = new ManagementObjectSearcher("SELECT * FROM Win32_DiskDrive");
foreach (ManagementObject obj2 in MOSear.Get())
{
listBox1.Items.Add(obj2["Model"].ToString());
}
...
首先,您需要通过在 `kernel32.dll` 中的 `CreateFile` 函数创建句柄来访问您的驱动器。然后将扇区读取到缓冲区中。您需要创建一个字段结构,并使用 `marshal.ptrtostructure()` 将字段从扇区输入到内存中。请参阅下面的代码。
//
// partition table
//
...
IntPtr File_Han = WindowAPICLass.CreateFile(@"\\.\PhysicalDrive" + i,
0x80000000, 1, IntPtr.Zero, 3, 0x20000000, IntPtr.Zero);
if (File_Han.ToInt32() != -1)
{
int bytes_read = 0;
byte[] byteArray = new byte[512];
fixed (byte* ref_b = byteArray)
{
WindowAPICLass.ReadFile(File_Han, (void*)ref_b, 0x200, &bytes_read, 0);
....
/////////////////
..........
Marshal.Copy(byteArray, 446, outArray, 64);
PartitionTable PTLB = new PartitionTable();
PTLB = (PartitionTable)Marshal.PtrToStructure(outArray, typeof(PartitionTable));
............
////////////////
............
WindowAPICLass.CloseHandle(File_Han);
}
}
...
关注点
通过这次分析,我了解到 MBR 是操作系统中最精彩、最重要的部分。Windows API 是必须理解的。分析 MBR、VBR、FAT 32 中的根目录等对我来说是一次非常冒险的经历,最终理解 NTFS、FAT32 等最知名的文件系统是一种享受。
历史
- 初始版本:2013 年 12 月 10 日。请稍等我的下一篇文章:“VBR 在数据恢复中的分析和作用。”