Восстановление данных в разделах NTFS
Файловая система NTFS, использование утилит восстановления данных в разделах NTFS, наиболее важные внутренние структуры этой файловой системы.
В статье, посвященной сохранности и восстановлению данных, мы расскажем о файловой системе NTFS, получающей все большее распространение вместе с операционными системами Microsoft Windows NT/2000. Мы расскажем об использовании некоторых утилит восстановления данных в разделах NTFS, а также приведем форматы наиболее важных внутренних структур этой файловой системы.
Файловая система нового поколения для Microsoft Windows NT/2000
Название файловой системы NTFS расшифровывается как New Technology File System, т.е. файловая система, созданная с применением новой технологии. И как Вы увидите далее, это название себя полностью оправдывает. Действительно, файловая система NTFS лишена многих недостатков своих предшественниц - FAT и FAT-32. Она обладает повышенной надежностью, способностью восстановления после сбоев, допускает использование символов национальных алфавитов для имен файлов и каталогов, позволяет упаковывать и шифровать файлы, содержит мощные средства разграничения доступа и т.д. Мы могли бы продолжить этот список еще дальше.
Тем не менее, дисковые разделы NTFS также подвержены разрушениям в результате аппаратных и программных сбоев, вирусного воздействия, ошибок операторов и т.п. Однако благодаря более совершенным принципам, использованным при ее проектировании, вероятность успеха восстановительных работ в разделах NTFS обычно намного выше, чем в разделах FAT и FAT-32.
Объем настоящей статьи не позволяет нам детально рассмотреть все особенности NTFS, поэтому мы ограничимся лишь теми сведениями, которые имеют непосредственное отношение к проведению восстановительных работ.
Заметим также, что все сведения о внутренних недокументированных структурах NTFS, приведенные в этой статье, не претендуют на полноту и точность. Они получены из различных источников, найденных в Интернете, в частности, из документации к драйверу NTFS операционной системы Linux, а также "добыты" в результате собственных исследований дампов системных структур NTFS, проведенных авторами при помощи редактора Microsoft DiskProbe и Microsoft DISKEDIT.
Поиск основных внутренних структур NTFS
Если попытки восстановления данных из разрушенного раздела NTFS при помощи автоматизированных утилит, таких как EraseUndo, CrashUndo или EasyRecovery не привели к успеху, можно попытаться извлечь нужные файлы вручную. В общем случае это довольно нетривиальная работа, однако иногда только этот способ может дать какие-то результаты.
Исследование внутренних структур файловой системы NTFS можно выполнять программой Microsoft DiskProbe из комплекта Windows NT Resource Kit или редактором диска Norton DISKEDIT из комплекта утилит Norton Utilities. Об этих средствах мы уже рассказывали в предыдущей статье нашей серии. Напомним, что Microsoft DiskProbe работает только в среде операционной системы Microsoft Windows NT/2000, а Norton DISKEDIT - в среде MS-DOS.
Определенный интерес в плане изучения внутренних структур NTFS может представлять собой программа Microsoft DISKEDIT, расположенная в пакете обновления операционной системы Microsoft Windows NT Srvice Pack 4, 5 или 6. Не путайте ее с одноименной программой из пакета Norton Utilities - это совершенно разные средства, предназначенные для решения различных задач.
К сожалению, ни один из существующих редакторов диска (кроме, разве лишь, только что упомянутой программы Microsoft DISKEDIT) не окажет Вам существенной помощи при исследовании таких важнейших структур NTFS, как записи главной таблица файлов MFT или записи каталогов. Поэтому при проведении восстановительных работ Вам придется иметь дело главным образом с шестнадцатеричным дампом секторов раздела.
Загрузочный сектор раздела NTFS
В предыдущей статье этой серии мы рассказывали о содержимом главной загрузочной записи MBR, в которой имеется код начальной загрузки и таблица разделов. Там же мы говорили о том, что в начале каждого раздела имеется загрузочная запись Boot Record, содержащая таблицу параметров BIOS Parameter Block (BPB).
Разделы файловой системы NTFS также начинаются с загрузочного сектора. Ниже мы привели формат начальной области загрузочного сектора:
| Смещение, байт | Размер, байт | Описание |
| 0 | 3 | Команда JMP xxxx (переход на программу начальной загрузки) |
| 3 | 8 | Название фирмы-изготовителя операционной системы и версия |
| 0xB | 2 | Размер сектора в байтах |
| 0xD | 1 | Количество секторов в одном кластере |
| 0xE | 7 | Зарезервировано |
| 0x15 | 1 | Тип носителя данных |
| 0x16 | 2 | Зарезервировано |
| 0x18 | 2 | Количество секторов на дорожке |
| 0x1A | 2 | Количество магнитных головок |
| 0x1C | 8 | Зарезервировано |
| 0x24 | 2 | Содержит число 0x80 |
| 0x26 | 2 | Содержит число 0x80 |
| 0x28 | 4 | Младшее слово общего количества секторов в разделе |
| 0x2C | 4 | Старшее слово общего количества секторов в разделе |
| 0x30 | 4 | Младшее слово номера кластера, в котором начинается таблица MFT |
| 0x34 | 4 | Старшее слово номера кластера, в котором начинается таблица MFT |
| 0x38 | 4 | Младшее слово номера кластера, в котором начинается копия таблицы MFT |
| 0x3C | 4 | Старшее слово номера кластера, в котором начинается копия таблицы MFT |
| 0x40 | 4 | Размер записи MFT в кластерах |
| 0x44 | 4 | Размер буфера индексов в кластерах |
| 0x48 | 4 | Младшее слово серийного номера диска |
| 0x4C | 4 | Старшее слово серийного номера диска |
Если Вы создаете собственные программы для работы с разделами NTFS на низком уровне, то Вам пригодится следующее определение типа BOOT_NTFS, составленное с использованием только что приведенного формата загрузочного сектора:
typedef struct _BOOT_NTFS
{
BYTE jump[3];
BYTE name[8];
UINT16 sec_size;
BYTE secs_cluster;
BYTE reserved_0[7];
BYTE media_desc;
UINT16 reserved_2;
UINT16 secs_track;
UINT16 num_heads;
BYTE reserved_3[8];
UINT16 reserved_4;
UINT16 reserved_5;
UINT32 num_secs_lo;
UINT32 num_secs_hi;
UINT32 mft_clus_lo;
UINT32 mft_clus_hi;
UINT32 mft2_clus_lo;
UINT32 mft2_clus_hi;
UINT32 mft_rec_size;
UINT32 buf_size;
UINT32 volume_id_lo;
UINT32 volume_id_hi;
} BOOT_NTFS;
Это определение мы взяли из исходных текстов программы CrashUndo 2000, предназначенной для автоматического восстановления разрушенных томов NTFS.
На рис. 1 мы показали содержимое загрузочного сектора раздела NTFS в виде дампа, полученного с помощью программы Microsoft DiskProbe.
Рис. 1. Дамп загрузочного сектора раздела NTFS
Просматривая дамп визуально, можно зафиксировать признаки, характерные для загрузочной записи NTFS. Это строка "NTFS" в начале сектора, а также текстовые сообщения в его конце. Кроме того, как и всякий служебный сектор, отвечающий за формирование структуры разделов, последние два байта загрузочного сектора NTFS содержат байты 55AA.
Для форматированного просмотра содержимого полей данного сектора выберите из меню View программы Microsoft DiskProbe строку NTFS BootSector. После этого Вы сможете просматривать и редактировать отдельные поля загрузочной записи в диалоговом окне, показанном на рис. 2.
Рис. 2. Просмотр содержимого загрузочного сектора раздела NTFS в форматированном виде
Загрузочный сектор содержит критически важную информацию, при разрушении которой операционная система не сможет смонтировать раздел NTFS. Если это случилось, Вы можете попытаться найти копию загрузочного сектора. В зависимости от размера раздела NTFS и версии операционной системы, в которой он был отформатирован, создается копия загрузочного сектора либо в середине, либо в конце раздела.
Обратите внимание на кнопки Volume End и Volume Middle, расположенные в правой части окна, показанного на рис. 2. С помощью этих кнопок можно перейти к просмотру одной из копий загрузочного сектора.
Если оказалось, что оригинальная загрузочная запись разрушена, можно попытаться записать на ее место копию. Во многих случаях этого оказывается достаточно для того, чтобы смонтировать раздел и скопировать из него необходимые файлы.
Просмотреть содержимое загрузочного сектора раздела NTFS в форматированном виде можно и при помощи программы Microsoft DISKEDIT. Чтобы запустить ее, скопируйте в отдельный каталог из распакованного архива пакета обновления Microsoft Windows NT Service Pack 6 следующие файлы:
- diskedit.exe;
- ifsutil.dll;
- ufat.dll;
- ulib.dll;
- untfs.dll
Далее запустите программу diskedit.exe и выберите из меню File строку Open. Введите в поле Volume Name имя диска, снабдив его двоеточием (рис. 3), а затем щелкните кнопку OK.
Рис. 3. Открытие диска d:
Сразу обращаем Ваше внимание на то, что программа Microsoft DISKEDIT может открыть только такой раздел, который уже был смонтирован операционной системой. Именно поэтому сама по себе программа Microsoft DISKEDIT едва ли может рассматриваться как инструмент восстановления данных. Однако с ее помощью можно многое понять в недокументированных структурах NTFS.
Если раздел поврежден настолько, что смонтировать его не удается, анализ повреждений возможен только при помощи программы Microsoft DiskProbe. Эта программа может открывать не только логические, но и физические диски.
Итак, полагаем, что Вы открыли диск. Теперь, чтобы просмотреть загрузочный сектор, выберите из меню Read строку Sectors. На экране появится диалоговое окно с полями Starting Sector и Run Length. В первом поле нужно ввести номер сектора, который должна прочитать программа (загрузочная запись располагается в секторе с номером 0), а во втором - количество секторов (нам нужен только один сектор, поэтому ведите здесь значение 1). Далее щелкните кнопку OK. В окне программы Microsoft DISKEDIT появится шестнадцатеричный дамп первого сектора, аналогичный дампу, показанному на рис. 1.
Теперь, чтобы перейти в режим форматного просмотра загрузочного сектора, выберите из меню View строку NTFS Boot Sector. Результат этой операции показан на рис. 4.
Рис. 4. Форматный просмотр загрузочной записи NTFS программой Microsoft DISKEDIT
Как видите, все значения здесь отображаются в шестнадцатеричном виде. К сожалению, их нельзя редактировать.
Определение геометрии раздела NTFS
Для успешного проведения восстановительных работ в разделе NTFS необходимо определить его геометрию. Под геометрией раздела мы понимаем набор следующих параметров:
- размер сектора в байтах (поле Bytes per Sector на рис. 2, смещение 0xB от начала сектора);
- размер кластера в секторах (поле Sectors per Cluster, смещение 0xD от начала сектора);
- номер начального кластера главной таблицы файлов MFT и ее копии (поля Clusters to MFT и Clusters to MFT mirr, смещение 0x30 и 0x38 от начала сектора, соответственно);
- размер записи таблицы MFT в кластерах (поле Clusters per FRS, смещение 0x40 от начала сектора)
Строго говоря, геометрию раздела определяют и другие параметры, но для нас сейчас имеют значение только эти.
Размер сектора
Что касается размера сектора Bytes per Sector, то для жестких дисков он обычно равен 512 байт. Другие носители данных (компакт-диски и магнитооптические диски могут использовать иные размеры сектора, такие как 1024 или 2048 байт).
Размер кластера
Важная составляющая геометрии NTFS -размер кластера Sectors per Cluster. Этот размер устанавливается при форматировании раздела и зависит от его объема.
В тех случаях, когда содержимое загрузочного сектора NTFS утеряно, можно воспользоваться следующей таблицей зависимости размера кластера от объема раздела NTFS:
| Объем раздела NTFS, Гбайт | Размер кластера, секторы по 512 байт |
| до 0.5 | 1 |
| от 0.5 до 1 | 2 |
| от 1 до 2 | 4 |
| свыше 2 | 8 |
Эта таблица справедлива для операционной системы Microsoft Windows NT версии 3.51, 4.0 и Microsoft Windows 2000. Что же касается более старых версий Microsoft Windows NT, то в них применялись кластеры и таких размеров:
| Объем раздела NTFS, Гбайт | Размер кластера, секторы по 512 байт |
| от 4 до 8 | 16 |
| от 8 до 16 | 32 |
| от 16 до 32 | 64 |
| свыше 32 | 128 |
Заметим, что при форматировании разделов NTFS можно указать размер кластера явным образом, поэтому приведенные в данной таблице значения следует использовать только в качестве ориентировочных.
Начало таблицы MFT и копии ее первых записей
Теперь о полях Clusters to MFT и Clusters to MFT mirr.
Поле Clusters to MFT содержит номер первого кластера, распределенного главной таблице файлов MFT. Эта таблица содержит ключевую информацию об именах и расположении всех файлов и каталогов, необходимую для проведения восстановительных работ. Заметим, что MFT сама по себе также является файлом с именем $MFT и тоже описана в MFT. Таким образом, файл $MFT ссылается сам на себя.
Обращаем Ваше внимание, что в файловой системе NTFS помимо обычных имеются так называемые системные файлы, имена которых начинаются с символа $. Такие файлы нельзя читать или копировать обычными средствами. Наша утилита восстановления данных CrashUndo for NTFS выполняет эту операцию, читая непосредственно секторы диска, распределенные системным файлам.
При объемах разделов порядка нескольких Гбайт размеры файла $MFT могут достигать десятков Мбайт, особенно если в разделе находится много файлов. По мере того как раздел NTFS живет своей жизнью, на нем появляются и исчезают файлы и каталоги. В результате файл $MFT растет и становится фрагментированным, что замедляет работу файловой системы.
По названию поля Clusters to MFT mirr можно сделать ошибочный вывод о существовании полноценной копии файла $MFT. К сожалению, это не так. Вероятно, из-за больших размеров файла $MFT копируются только его несколько первых записей, в том числе (что важно), запись, описывающая расположение самого файла $MFT.
Размер записи таблицы MFT
Большое значение имеет правильное определение размера записи главной таблицы файлов MFT, записанное в поле Clusters per FRS. Это значение следует рассматривать как целое со знаком. Если содержимое поля положительно, то оно означает количество кластеров, занимаемое одной записью таблицы MFT. Если же оно отрицательное, то для определения размера записи MFT нужно использовать формулу:
MFT_Record_Bytes = 2(-Clusters_Per_FRS)
Здесь Clusters_Per_FRS - значение из поля Clusters per FRS, а MFT_Record_Bytes - количество байт, занимаемых записью MFT.
Поясним эту формулу на примере. В поле Clusters per FRS часто встречается значение 0xF6, которое означает ни что иное, как -10. Если возвести 2 в степень 10, получим значение 1024. Таким образом, размер записи MFT составляет 210=1024 байт. Аналогично, значение 0xF5, равное -11, соответствует размеру записи MFT, равному 211=2048 байт.
Поиск главной таблицы файлов MFT
Что делать, если в результате сбоя полей Clusters to MFT и Clusters to MFT mirr оказалось утерянным?
Вы можете попытаться найти первый сектор кластера, распределенного файлу $MFT при помощи утилиты Microsoft DiskProbe. Для этого откройте восстанавливаемый диск и выберите из меню Tools строку Search Sectors. На экране появится одноименное окно, показанное на рис. 5.
Рис. 5. Поиск записи в таблице MFT для файла $MFT
Установите отметку флажков, как показано на этом рисунке. При этом программа Microsoft DiskProbe будет искать в секторах, интервал номеров которых задан в полях First sector to search и Last sector to search, строку символов "$MFT" в кодировке UNICODE. Именно эта кодировка применяется в NTFS для хранения имен файлов и каталогов.
Флажок Search at offset позволяет выполнять поиск по фиксированному смещению относительно начала сектора. Хотя такой поиск выполняется быстрее, чем поиск по всему сектору (выполняется при отмеченном флажке Exhaustive search), в нашем случае он не приведет к успеху. Дело в том, что расположение имени файла изменяется от одной записи MFT к другой.
Для того чтобы выполнять поиск без учета строчных и прописных букв, мы отметили флажок Ignore case. И, наконец, для поиска строки в кодировке UNICODE мы отметили флажок Unicode characters.
Установив флажки, введите имя файла $MFT в поле Enter characters to search for и щелкните кнопку Search. После этого начнется процесс поиска. Если будет обнаружен подходящий сектор, Вы увидите диалоговое окно, показанное на рис. 6.
Рис. 6. Найден сектор, соответствующий заданным критериям поиска
Щелкните кнопку No, чтобы отказаться от дальнейшего поиска. На экране появится дамп найденного сектора (рис. 7).
Рис. 7. Дамп сектора записи таблицы MFT для файла $MFT
Здесь со смещением 0x00EA располагается имя файла $MFT. Обратите также внимание, что первые 4 байта сектора содержат строку "FILE". Так отмечается начало первого сектора каждой записи MFT.
Структура файла $MFT
Как мы уже говорили, файл $MFT содержит всю информацию о расположении всех файлов раздела, в том числе и самого файла $MFT. Этот файл состоит из записей фиксированной длины, размер которых можно узнать, анализируя загрузочную запись раздела NTFS.
Несколько первых записей файла $MFT описывают системные файлы, перечисленные ниже:
| Номер записи | Имя системного файла | Описание |
| 0x0 | $MFT | Главная таблица файлов MFT |
| 0x1 | $MFTMirr | Копия первых 4 записей таблицы MFT |
| 0x2 | $LogFile | Журнал транзакций. Используется для отката транзакций в случае аварийного завершения операций над файловой системой |
| 0x3 | $Volume | Информация о разделе, например, имя соответствующего логического тома и версия файловой системы NTFS |
| 0x4 | $AttrDef | Список атрибутов, используемых в файловой системе |
| 0x5 | . | Корневой каталог файловой системы |
| 0x6 | $Bitmap | Битовый массив, в котором отмечены все использованные кластеры |
| 0x7 | $Boot | Загрузочный сектор раздела NTFS |
| 0x8 | $BadClus | Список всех плохих кластеров данного раздела. Кластер считается плохим, если в нем есть один плохой сектор |
| 0x9 | $Secure | База данных атрибутов безопасности. Применяется только в NTFS версии 5.0 в среде Microsoft Windows 2000 |
| 0xA | $UpCase | Список всех прописных символов Unicode. Используется для перекодировки строчных символов в прописные и обратно в процессе сравнения имен файлов и каталогов |
| 0xB | $Extend | Файл хранит расширенную информацию файловой системы NTFS версии 5.0, применяемой в среде Microsoft Windows 2000, такую как дисковые квоты, точки монтирования и т.д. |
| 0xC | Зарезервировано | |
| 0xD | Зарезервировано | |
| 0xE | Зарезервировано | |
| 0xF | Зарезервировано |
Далее в файле $MFT следуют записи с информацией обо всех остальных файлах и каталогах. Именно эти записи будут Вам нужны для извлечения файлов из разрушенного раздела NTFS.
Для каждого файла и каталога в файле $MFT создается одна запись, называемая базовой, и, возможно, несколько расширенных записей. Расширенные записи создаются в том случае, если вся информация о файле или каталоге не помещается в базовой записи (напомним, что размер записи файла $MFT ограничен и обычно составляет 1 Кбайт). Обычно такое происходит, если файлы увеличивают свой размер, по мере того как с ними работают пользователи. Это могут быть файлы баз данных, файлы офисных документов и т.д.
На рис. 8 мы показали структуру файла $MFT. В начале файла мы показали область записей, описывающих системные файлы, а в конце - записи остальных файлов и каталогов.
Рис. 8. Структура файла $MFT
Здесь для файлов MyLetter.doc, Readme.txt, game.exe и каталога AllLettersFolder создано по одной базовой записи, а для файла MyDatabase.mdb - одна базовая и две расширенные записи. Базовая запись и расширенные записи связаны в список.
Как найти запись MFT для произвольного файла по его имени?
Это можно сделать при помощи программы Microsoft DiskProbe. Здесь необходимо использовать описанную ранее процедуру поиска файла $MFT, но в поле Enter characters to search for диалогового окна Search Sectors (рис. 5) Вы должны указать имя нужного файла.
Структура записей файла $MFT
Итак, теперь Вы знаете, что ключевая информация о файлах и каталогах, необходимая для извлечения файлов из поврежденных разделов раздела NTFS, находится в файле $MFT в виде базовых и расширенных записей. Начало файла $MFT нетрудно найти, анализируя загрузочный сектор раздела NTFS. Там же хранится и размер отдельных записей таблицы MFT. Теперь нашей задачей будет изучение структуры этих записей.
Если рассматривать запись MFT в целом, то она содержит список областей переменной длины, называемых атрибутами файлов (File Attribut). Размер этого списка и состав хранящихся в нем атрибутов также может изменяться от записи к записи.
Если все атрибуты файла или каталога не помещаются в базовой записи, дополнительно создается одна или несколько расширенных записей. При этом базовая запись содержит атрибут, в котором перечислены все атрибуты данного файла и каталога, а также указано, в каких именно записях (базовой или расширенной) хранятся те или иные атрибуты.
Короче говоря, для каждого файла или каталога в файле $MFT хранится список областей данных (атрибутов файла). Этот список может занимать одну или несколько записей MFT. Базовая запись MFT и все расширенные записи одного и того же файла или каталога связаны в список.
Атрибуты файла
Нам известно о существовании 14 атрибутов файла различного типа. Типы атрибута обозначается числами. Ниже мы перечислили атрибуты известных нам типов с кратким описанием хранящейся в них информации.
| Тип | Имя | Описание |
| 0x10 | $STANDARD_INFORMATION | Стандартный атрибут. Здесь хранится дата и время создания и последнего изменения файла, дата и время последнего доступа к файлу, флаги доступа к файлу, а также дата и время изменения записи MFT, соответствующей данному файлу |
| 0x20 | $ATTRIBUTE_LIST | Список атрибутов. Если помимо базовой записи MFT для файла создаются расширенные записи, в этом атрибуте перечисляются все атрибуты файла. Кроме того, здесь хранится информация о распределении этих атрибутов по записям MFT (по базовой записи и по расширенным записям данного файла). |
| 0x30 | $FILE_NAME | Имя файла или каталога. В этом атрибуте хранится имя файла или каталога, набор флагов доступа, размер файла, а также ссылка на запись MFT каталога, в котором хранится данный файл или каталог. |
| 0x40 | $VOLUME_VERSION | Версия NTFS для данного раздела. |
| 0x50 | $SECURITY_DESCRIPTOR | Дескриптор разграничения доступа. |
| 0x60 | $VOLUME_NAME | Имя тома. Это имя задается при форматировании раздела и может быть изменено пользователем. |
| 0x70 | $VOLUME_INFORMATION | Состояние тома. Здесь хранится версия драйвера, с помощью которого был создан данный раздел, а также флаг программы CHKDSK. Если этот флаг установлен, то при очередной перезагрузке операционной системы программа CHKDSK выполнит проверку данного раздела. |
| 0x80 | $DATA | Атрибут данных. Этот атрибут может содержать либо данные файла (если размеры файла не превышают размеры записи MFT), либо список номеров кластеров, в которых располагается файл (список экстентов файла). |
| 0x90 | $INDEX_ROOT | Корневая вершина дерева типа B+, с применением которого в NTFS реализована система каталогов. |
| 0xA0 | $INDEX_ALLOCATION | Узлы ветвей дерева типа B+, с применением которого в NTFS реализована система каталогов. |
| 0xB0 | $BITMAP | Набор бит, описывающих использование отдельных записей MFT или узлов дерева каталогов. |
| 0xC0 | $SYMBOLIC_LINK | Информация Reparse Point, используется в Microsoft Windows 2000 |
| 0xD0 | $EA_INFORMATION | Информация о расширенных атрибутах файловой системы HPFS. Используется для обеспечения совместимости NTFS с файловой системой HPFS, применяемой в IBM OS/2. |
| 0xE0 | $EA | Данные расширенных атрибутов файловой системы HPFS. |
Для восстановления файлов из разрушенных разделов NTFS наибольший интерес представляют собой атрибуты $STANDARD_INFORMATION, $ATTRIBUTE_LIST, $FILE_NAME и $DATA.
Вначале с помощью Microsoft DiskProbe нужно найти запись MFT файла по имени, которое хранится в атрибуте $FILE_NAME.
Далее, анализируя информацию из атрибута $STANDARD_INFORMATION, можно определить дату создания или изменения файла. На основании этой информации можно сделать вывод о том, нужно ли восстанавливать данный файл или следует поискать другую, более свежую версию этого же файла.
Атрибуты $STANDARD_INFORMATION и $FILE_NAME всегда размещаются в базовой записи MFT, но другие атрибуты этого же файла или каталога могут находиться в расширенных записях. Кроме того, для одного файла может быть создано несколько атрибутов $FILE_NAME, в которых хранится несколько имен одного и того же файла в разных форматах (об этом мы расскажем чуть позже). Поэтому дополнительно может возникнуть необходимость анализа атрибута $ATTRIBUTE_LIST, хранящего полный список атрибутов восстанавливаемого файла.
И, наконец, атрибут $DATA хранит или описывает расположение данных файла, которые, собственно, и требуется восстановить. Там же находится информация о размере файла.
Поиск атрибутов в записях MFT
Прежде чем рассказывать о том, как искать нужные Вам атрибуты в записи MFT, рассмотрим ее структуру в целом.
Как мы уже говорили, размер записи MFT хранится в загрузочном секторе раздела NTFS. Чаще всего записи MFT занимают 2 или 4 сектора, хотя встречаются записи и другого размера.
Каждая запись MFT состоит из заголовка фиксированного формата, вслед за которым идет список атрибутов переменной длины. Приступая к исследованию записи MFT, сначала нужно проанализировать ее заголовок.
Ниже мы представили формат заголовка записи MFT:
| Смещение, байт | Длина, байт | Описание |
| 0x00 | 4 | Текстовая строка "FILE" - признак записи MFT |
| 0x04 | 2 | Смещение массива корректировки записи Update Sequence |
| 0x06 | 2 | Размер массива корректировки записей Update Sequence |
| 0x10 | 2 | Последовательный номер сектора в записи MFT |
| 0x12 | 2 | Счетчик ссылок |
| 0x14 | 2 | Смещение начала списка атрибутов |
| 0x16 | 2 | Флажки, отмечающее состояние записи MFT |
| 0x18 | 4 | Реальный размер записи MFT |
| 0x1C | 4 | Размер памяти, занимаемый записью MFT |
| 0x20 | 8 | Файловый номер (File Reference) базовой записи MFT |
| 0x28 | 2 | Максимальное значение идентификатора атрибута, увеличенное на единицу |
| 0x2A | 2 | Массив корректировки записи MFT размером 2*(N-1) байт, где N - значение размера массива корректировки записи из поля со смещением 0x06 |
Изучать заголовок записи MFT лучше всего на конкретном примере. На рис. 9 мы показали дамп первого сектора записи MFT, созданной для файла DataRecovery3.doc (это файл с текстом статьи, которую Вы сейчас читаете). Область заголовка записи MFT здесь выделена линией красного цвета. Дамп второго сектора записи MFT Вы найдете на рис. 10.
Рис. 9. Заголовок записи MFT
Массив корректировки секторов записи MFT
Прежде всего, обратите внимание на поле со смещением 0x04, в котором находится смещение так называемого массива корректировки записей MFT. На рис. 9 это поле выделено черной рамкой и хранит значение 0x002A (напомним, что в компьютерах с процессорами Intel используется такая система хранения данных, при которой наименее значимые байты слова записываются по младшим адресам).
Размер массива корректировки записи MFT находится в поле со смещением 0x06. В нашем случае его значение равно 3.
Исследуя дамп, показанный на рис 9, мы обнаруживаем, что в массиве корректировки хранятся три числа: 0x0002, 0x700C и 0x0000. Первое из этих чисел служит в качестве шаблона корректировки, а два других - корректировочные значения, соответственно, для первого и второго сектора записи MFT.
В ходе корректировки записи MFT, необходимой для ее дальнейшего анализа, необходимо заменить в первом секторе (рис. 9) значение 0x0002 в слове со смещением 0x01FE на значение 0x700C, а во втором секторе (рис. 10) - значение 0x0002 в слове со смещением 0x01FE на значение 0x0000.
Таким образом, массив корректировки содержит значения, которые необходимо записать в конец каждого сектора записи MFT перед ее использованием.
Рис. 10. Второй сектор записи MFT, показанной на рис. 9
Зачем был придуман такой странный механизм корректировки секторов записи MFT?
Этот механизм предназначен для контроля целостности многосекторных записей MFT. Дело в том, что при возникновении сбоев может случиться так, что не все секторы записи MFT будут успешно сохранены на диске. Обнаружив такую дефектную запись, операционная система, возможно, сумеет отменить связанную с ней транзакцию, не допустив катастрофического разрушения файловой системы.
Конечно, для контроля целостности секторов записи можно было бы применить хорошо проверенный метод подсчета контрольных сумм, однако вычисление таких сумм отнимает немало процессорного времени и может неблагоприятно сказаться на производительности файловой системы.
Вместо этого перед сохранением записи MFT операционная система заменяет последние два байта каждого сектора специальным значением - шаблоном корректировки, которое должно быть одинаковым для всех секторов одной записи MFT, но разным для разных записей MFT. Оригинальное содержимое последних байт секторов записи MFT сохраняется во второй и последующих ячейках массива корректировки. В первую ячейку этого массива при этом записывается значение шаблона корректировки.
В нашем примере оригинальные значения последних двух байт в первом и втором секторе, равные, соответственно, 0x700C и 0x0000, были заменены шаблоном корректировки 0x0002. Перед этим операционная система записала числа 0x700C и 0x0000 во второй и третий элемент массива корректировки, соответственно. В первый элемент массива корректировки было записано значение шаблона корректировки 0x0002.
Прослеживание списка атрибутов
Точное смещение начала списка атрибутов хранится в слове заголовка записи MFT со смещением 0x14. Таким образом, в записи, показанной на рис. 9, список атрибутов начинается со смещением 0x0030.
Каждый атрибут имеет свой заголовок, точный формат которого мы рассмотрим чуть позже. Сейчас для нас главное, что первые четыре байта заголовка атрибута хранят его тип, а вторые - размер в байтах.
Четырехбайтовое слово со смещением 0x0030 в нашем дампе хранит значение 0x00000010. Это стандартный атрибут $STANDARD_INFORMATION. Размер атрибута записан в слове со смещением 0x0034 и равен 0x00000060. Область данных стандартного атрибута выделена на рис. 9 рамкой фиолетового цвета.
Продолжим исследования дампа, представленного на рис. 9.
Прибавив к смещению 0x0030 размер стандартного атрибута $STANDARD_INFORMATION, равный 0x00000060 байт, получим смещение следующего атрибута. Это атрибут имени файла $FILE_NAME с типом 0x00000030 и длиной 0x00000060 байт (выделен на рисунке рамкой синего цвета). Обратите внимание на правую символьную часть дампа, соответствующую этому атрибуту. Нетрудно заметить, что в области данного атрибута хранится строка "DATAREC~1.DOC". Это имя файла DataRecovery3.doc, созданное операционной системой для старых программ DOS, не "умеющих" распознавать длинные имена. Оно хранится здесь в кодировке UNICODE.
Следующий атрибут, расположенный со смещением 0x0108, - это тоже атрибут имени с типом 0x00000030 (выделен рамкой зеленого цвета). Размер памяти, занимаемой данным атрибутом, составляет 0x00000080 байт. Здесь хранится полное имя файла DataRecovery3.doc (также в кодировке UNICODE).
Прослеживая далее список атрибутов, мы можем обнаружить атрибуты $VOLUME_VERSION, не представляющий для нас особого интереса, а также атрибут $DATA.
Атрибут данных $DATA начинается в первом секторе записи MFT со смещением 0x01B0 и заканчивается во втором секторе этой же записи, показанном на рис. 10. Размер атрибута $DATA составляет 0x00000060 байт.
Обратите внимание, что последние два байта первого сектора записи MFT, измененные шаблоном корректировки, приходятся как раз на середину атрибута данных. Если не восстановить в этом месте правильное значение, равное 0x700C, Вы будете неправильно интерпретировать содержимое атрибута данных, что приведет к невозможности восстановления файла.
Формат атрибутов файла
Итак, Вы научились прослеживать списки атрибутов файла в записи MFT. Теперь мы расскажем о внутренней структуре атрибутов.
Атрибуты файлов любого типа состоят из заголовка фиксированного формата и области данных (Data Stream). Заголовок описывает атрибут в целом, а область данных хранит информацию, представленную атрибутом.
Отметим, что атрибуты можно разделить на резидентные и нерезидентные атрибуты.
Если атрибут резидентный, то область данных атрибута находится непосредственно в теле самого атрибута. Если же атрибут нерезидентный, то он содержит только список ссылок на кластеры раздела, в которых находятся данные.
Например, все атрибуты в записи, показанной на рис. 9 и 10, кроме атрибута данных $DATA являются резидентными. Что же касается атрибута данных $DATA, то его размер, составляющий 0x00000060 байт, явно недостаточен для хранения файла DataRecovery3.doc этой статьи (размер файла составляет несколько сотен Кбайт). И в самом деле, как Вы скоро увидите, атрибут $DATA хранит только номера кластеров, выделенных в разделе NTFS для хранения файла.
Заголовок атрибута файла
Как Вы уже знаете, в заголовке атрибута файлов хранится тип атрибута и размер выделенной для его хранения памяти. Вот полный список полей заголовка атрибута:
| Смещение, байт | Размер, байт | Описание |
| 0x00 | 4 | Тип атрибута |
| 0x04 | 4 | Размер области памяти, занимаемой атрибутом |
| 0x08 | 1 | Флаг нерезидентного атрибута |
| 0x09 | 1 | Длина имени атрибута |
| 0x0A | 2 | Смещение области данных атрибута |

