412 000 произведений, 108 200 авторов.

Электронная библиотека книг » Крис Касперски » Восстановление данных. Практическое руководство » Текст книги (страница 11)
Восстановление данных. Практическое руководство
  • Текст добавлен: 26 июня 2025, 05:19

Текст книги "Восстановление данных. Практическое руководство"


Автор книги: Крис Касперски



сообщить о нарушении

Текущая страница: 11 (всего у книги 26 страниц)

Атрибуты

Структурно всякий атрибут состоит из атрибутного заголовка (attribute header) и тела атрибута (attribute body). Заголовок атрибута всегда хранится в файловой записи, расположенной внутри MFT. Тела резидентных атрибутов хранятся там же. Нерезидентные атрибуты хранят свое тело вне MFT, в одном или нескольких кластерах, перечисленных в заголовке данного атрибута в специальном списке. Если 8-разрядное поле, расположенное по смещению 08h байт от начала атрибутного заголовка, равно нулю, то атрибут считается резидентным, а если единице, то атрибут нерезидентен. Любые другие значения недопустимы.

Первые четыре байта атрибутного заголовка определяют его тип. Тип атрибута, в свою очередь, определяет формат представления тела атрибута. В частности, тело атрибута данных (тип: 80h$DATA) представляет собой "сырую" последовательность байт. Тело атрибута стандартной информации (тип: 10h$STANDARD_INFORMATION) описывает время его создания, права доступа и т.д. Более подробно эта тема будет рассмотрена далее в данной главе.

Следующие четыре байта заголовка содержат длину атрибута, выражаемую в байтах. Длина нерезидентного атрибута равна сумме длин его тела и заголовка, а длина резидентного атрибута равна длине его заголовка. Если к смешению атрибута добавить его длину, мы получим указатель на следующий атрибут (или маркер конца, если текущий атрибут – последний в цепочке).

Длина тела резидентных атрибутов, выраженная в байтах, хранится в 32– разрядном поле, расположенном по смещению 10h байт от начала атрибутного заголовка. 16-разрядное поле, следующее за его концом, хранит смещение резидентного тела, отсчитываемое от начала атрибутного заголовка. С нерезидентными атрибутами в этом плане все намного сложнее, и для хранения длины их тела используется множество полей. Реальный размер тела атрибута (real size of attribute), выраженный в байтах, хранится в 64-разрядном поле, находящемся по смещению 30h байт от начала атрибутного заголовка. Следующее за ним 64-разрядное поле хранит инициализированный размер потока (initialized data size of the stream), выраженный в байтах. Судя по всему, инициализированный размер потока всегда равен реальному размеру тела атрибута. 64-разрядное поле, расположенное по смещению 28h байт от начала атрибутного заголовка, хранит выделенный размер (allocated size of attribute), выраженный в байтах и равный реальному размеру тела атрибута, округленному до размера кластера (в большую сторону).

Два 64-разрядных поля, расположенные по смещениям 10h и 18h байт от начала атрибутного заголовка, задают первый (starting VCN) и последний (last VCN) номера виртуального кластера, принадлежащего телу нерезидентного атрибута. Виртуальные кластеры представляют собой логические номера кластеров, не зависящие от своего физического расположения на диске. В подавляющем большинстве случаев номер первого кластера тела нерезидентного атрибута равен нулю, а последний – количеству кластеров, занятых телом атрибута, уменьшенному на единицу. 16-разрядное поле, расположенное по смещению 20h от начала атрибутного заголовка, содержит указатель на массив Data Runs, расположенный внутри этого заголовка и описывающий логический порядок размещения нерезидентного тела атрибута на диске.

Каждый атрибут имеет свой собственный идентификатор (attribute ID), уникальный для данной файловой записи и хранящийся в 16-разрядном поле, расположенном по смещению 0Eh от начала атрибутного заголовка.

Если атрибут имеет имя (attribute Name), то 16-разрядное поле, расположенное по смещению 0Ah байт от атрибутного заголовка, содержит указатель на него. Для безымянных атрибутов оно равно нулю (большинство атрибутов имен не имеют). Имя атрибута хранится в атрибутном заголовке в формате UNICODE, а его длина определяется 8-разрядным полем, расположенным по смещению 09h байт от начала атрибутного заголовка.

Если тело атрибута сжато, зашифровано или разрежено, 16-разрядное поле флагов, расположенное по смещению 0Ch байт от начала атрибутного заголовка, не равно нулю.

Основные поля резидентных и нерезидентных атрибутов кратко описаны в табл. 6.4 и 6.5. Остальные поля не играют существенной роли, и потому здесь они не рассматриваются.

Таблица 6.4. Структура резидентного атрибута


00h 4Тип атрибута (например, 0x10, 0x60, 0xB0)
04h 4Длина атрибута, включая этот заголовок
08h 1 00h Флаг нерезидентности (non-resident flag)
09h 1 N Длина имени атрибута (ноль, если атрибут безымянный)
0Ah 2 18h Смещение имени (ноль, если атрибут безымянный)
0Ch 2 00h Флаги
0001h Сжатый атрибут (compressed)
4000h Зашифрованный атрибут (encrypted)
8000h Разреженный атрибут (sparse)
0Eh 2Идентификатор атрибута (attribute ID)
10h 4 L Длина тела атрибута, без заголовка
14h 2 2N+18h Смещение тела атрибута
16h 1Индексный флаг
17h 1 00h Используется для выравнивания
18h 2N UNICODE Имя атрибута (если есть)
2N+18h LТело атрибута

Таблица 6.5. Структура нерезидентного атрибута


00h 4Тип атрибута (например, 0x20, 0x80)
04h 4Длина атрибута, включая этот заголовок
08h 1 01h Флаг нерезидентности (non-resident flag)
09h 1 N Длина имени атрибута (ноль, если атрибут безымянный)
0Ah 2 40h Смещение имени (ноль, если атрибут безымянный)
0Ch 2Флаги
0001h Сжатый атрибут (compressed)
4000h Зашифрованный атрибут (encrypted)
8000h Разреженный атрибут (sparse)
0Eh 2Идентификатор атрибута (attribute ID)
10h 8Начальный виртуальный кластер (starting VCN)
18h 8Конечный виртуальный кластер (last VCN)
20h 2 2N+40h Смещение списка отрезков (data runs)
22h 2Размер блока сжатия (compression unit size), округленный до 4 байт в большую сторону
24h 4 00h Используется для выравнивания
28h 8Выделенный размер (allocated size), округленный до размера кластера
30h 8Реальный размер (real size)
38h 8Инициализированный размер потока (initialized data size of the stream)
40h 2N UNICODE Имя атрибута (если есть)
2N+40h Список отрезков (data runs)

Типы атрибутов

NTFS поддерживает большее количество предопределенных типов атрибутов, перечисленных в табл. 6.6. Тип атрибута определяет его назначение и формат представления тела. Полное описание всех атрибутов заняло бы не одну главу, а целую книгу, поэтому здесь приводятся лишь наиболее "ходовые" из них, а за информацией об остальных обращайтесь к документации Linux-NTFS Project.

Таблица 6.6. Основные типы атрибутов


010h Любая $STANDARD_INFORMATION Стандартная информация о файле (время, права доступа)
020h Любая $ATTRIBUTE_LIST Список атрибутов
030h Любая $FILE_NAME Полное имя файла
040h Windows NT $VOLUME_VERSION Версия тома
040h Windows 2000 $OBJECT_ID Глобально уникальный идентификатор (GUID) и прочие ID
050h Любая $SECURITY_DESCRIPTOR Дескриптор безопасности и списки прав доступа (ACL)
060h Любая $VOLUME_NAME Имя тома
070h Любая $VOLUME_INFORMATION Информация о томе
080h Любая $DATA Основные данные файла
090h Любая $INDEX_ROOT Корень индексов
0A0h Любая $INDEX_ALLOCATION Ветви (sub-nodes) индекса
0B0h Любая $BITMAP Карта свободного пространства
0C0h Windows NT $SYMBOLIC_LINK Символическая ссылка
0C0h Windows 2000 $REPARSE_POINT Для сторонних производителей
0D0h Любая $EA_INFORMATION Расширенные атрибуты для HPFS
0E0h Любая $EA Расширенные атрибуты для HPFS
0F0h Windows NT $PROPERTY_SET Устарело и ныне не используется
100h Windows 2000 $LOGGED_UTILITY_STREAM Используется шифрующей файловой системой (EFS)

$STANDARD_INFORMATION

Атрибут стандартной информации описывает время создания/изменения/последнего доступа к файлу и права доступа, а также некоторую другую вспомогательную информацию (например, квоты). Структура атрибута стандартной информации кратко описана в табл. 6.7.

Таблица 6.7. Структура атрибута $STANDARD_INFORMATION


– -ЛюбаяСтандартный атрибутный заголовок (standard attribute header)
00h 8ЛюбаяC – время создания (creation) файла
08h 8ЛюбаяA – время изменения (altered) файла
10h 8ЛюбаяM – время изменения файловой записи (MFT changed)
18h 8ЛюбаяR – время последнего чтения (read) файла
20h 4ЛюбаяПрава доступа MS-DOS (MS-DOS file permissions)
0001h Только на чтение (read-only)
0002h Скрытый (hidden)
0004h Системный (system)
0020h Архивный (archive)
0040h Устройство (device)
0080h Обычный (normal)
0100h Временный (temporary)
0200h Разреженный (sparse) файл
0400h Точка передачи (reparse point)
0800h Сжатый (compressed)
1000h Оффлайновый (offline)
2000h Неиндексируемый (not content indexed)
4000h Зашифрованный (encrypted)
24h 4ЛюбаяСтаршее двойное слово номера версии (maximum number of versions)
28h 4ЛюбаяМладшее двойное слово номера версии (version number)
2Ch 4ЛюбаяИдентификатор класса (class ID)
30h 4Windows 2000Идентификатор владельца (owner ID)
34h 4Windows 2000Идентификатор безопасности (security ID)
38h 8Windows 2000Количество квотируемых байт (quota charged)
40h 8Windows 2000Номер последней последовательности обновления (update sequence number USN)

$ATTRIBUTE_LIST

Атрибут списка атрибутов (прямо каламбур) используется в тех случаях, когда все атрибуты файла не умещаются в базовой файловой записи, и файловая система вынуждена располагать их в расширенных файловых записях. Индексы расширенных файловых записей содержатся в атрибуте списка атрибутов, помещаемом в базовую файловую запись.

При каких обстоятельствах атрибуты не умещаются в одной файловой записи? Это может произойти в следующих случаях:

□ файл содержит много альтернативных имен или жестких ссылок;

□ файл сильно фрагментирован;

□ файл содержит очень сложный дескриптор безопасности;

□ файл имеет очень много потоков данных (т.е. атрибутов типа $DATA).

Структура атрибута списка атрибутов приведена в табл. 6.8.

Таблица 6.8. Структура атрибута $ATTRIBUTE_LIST


– -Стандартный атрибутный заголовок (standard attribute header)
00h 4Тип (type) атрибута (см. табл. 6.6)
04h 2Длина записи (record length)
06h 1Длина имени (name length), или ноль, если нет, условно – N
07h 1Смещение имени (offset to name), или ноль если нет
08h 8Начальный виртуальный кластер (starting VCN)
10h 8Ссылка на базовую/расширенную файловую запись
18h 2Идентификатор атрибута (attribute ID)
1Ah 2NЕсли N>0, то имя в формате UNICODE

$FILE_NAME

Атрибут полного имени файла хранит имя файла в соответствующем пространстве имен. Таких атрибутов у файла может быть и несколько (например, имя Win32 и имя MS-DOS). Здесь же хранятся и жесткие ссылки (hard link), если они есть.

Структура атрибута полного имени приведена в табл. 6.9.

Таблица 6.9. Структура атрибута $FILE_NAME


– -Стандартный атрибутный заголовок (standard attribute header)
00h 8Ссылка (file reference) на материнский каталог
08h 8C – время создания (creation) файла
10h 8A – время последнего изменения (altered) файла
18h 8M – время последнего изменения файловой записи (MFT changed)
20h 8R – время последнего чтения (read) файла
28h 8Выделенный размер (allocated size) файла
30h 8Реальный размер (real size) файла
38h 4Флаг (см. табл. 6.7)
3Ch 4Используется HPFS
40h 1Длина имени в символах – L
41h 1Пространство имен файла (filename namespace)
42h 2LИмя файла в формате UNICODE без завершающего нуля

Списки отрезков

Тела нерезидентных атрибутов хранятся на диске в одной или нескольких кластерных цепочках, называемых отрезками (runs). Отрезком называется последовательность смежных кластеров, характеризующаяся номером начального кластера и длиной. Совокупность отрезков называется списком (run-list или data run).

Внутренний формат представления списков не то, чтобы сложен, но простым его тоже на назовешь. Для экономии места длина отрезка и номер начального кластера хранятся в полях переменной длины. Если размер отрезка умещается в байт (т.е. его значение не превышает 255), то он займет один байт. По аналогии, если размер отрезка требует для своего представления двойного слова, то он займет двойное слово.

Сами же поля размеров хранятся в 4-битных ячейках, называемых нибблами (nibble) или полубайтами. Шестнадцатеричная система счисления позволяет легко переводить байты в нибблы и наоборот. Младший ниббл равен (X & 15), а старший – (X / 16). Иначе говоря, младший ниббл соответствует младшему шестнадцатеричному разряду байта, а старший – старшему. Например, 69h состоит из двух нибблов, причем младший равен 9h, а старший – 6h.

Список отрезков представляет собой массив структур, каждая из которых описывает характеристики "своего" отрезка. Структура элемента списка отрезков показана в табл. 6.10. В конце списка находится завершающий ноль. Первый байт структуры состоит из двух нибблов: младший задает длину поля начального кластера отрезка (условно обозначаемого буквой F), а старший – количество кластеров в отрезке (L). Затем идет поле длины отрезка. В зависимости от значения L оно может занимать от одного до восьми байт (поля большей длины недопустимы). Первый байт поля стартового кластера файла расположен по смещению 1+L байт от начала структуры (что соответствует 2+2*L нибблам). Кстати говоря, в документации Linux-NTFS Project (версия 0.4) поля размеров начального кластера и количества кластеров в отрезке перепутаны местами.

Таблица 6.10. Структура одного элемента списка отрезков


01Размер поля длины (L)
11Размер поля начального кластера (S)
22*LКоличество кластеров в отрезке
2+2*L2*SНомер начального кластера отрезка

Покажем, как с этим работать на практике. Предположим, что мы имеем следующий список отрезков, соответствующий нормальному не фрагментированному файлу (что может быть проще!): 21 18 34 56 00. Попробуем его декодировать?

Начнем с первого байта – 21h. Младший полубайт (01h) описывает размер поля длины отрезка, старший (02h) – размер поля начального кластера. Следующие несколько байт представляют поле длины отрезка, размер которого в данном случае равен одному байту – 18h. Два других байта (34h 56h) задают номер начального кластера отрезка. Нулевой байт на конце сигнализирует о том, что это последний отрезок в файле. Таким образом, наш файл состоит из одного-единственного отрезка, начинающегося с кластера 5634h и заканчивающегося кластером 5634h + 18h == 564Ch.

Рассмотрим более сложный пример фрагментированного файла со следующим списком отрезков: 31 38 73 25 34 32 14 01 E5 11 02 31 42 AA 00 03 00. Извлекаем первый байт – 31h. Один байт приходится на поле длины, и три байта – на поле начального кластера. Таким образом, первый отрезок (run 1) начинается с кластера 342573h и продолжается вплоть до кластера 342573h + 38 == 3425ABh. Чтобы найти смещение следующего отрезка в списке, мы складываем размер обоих полей с их начальным смещением: 3 + 1 == 4. Отсчитываем четыре байта от начала списка отрезков и переходим к декодированию следующего отрезка: 32h – два байта на поле длины отрезка (равное в данном случае 0114h) и три байта – на поле номера начального кластера (0211E5h). Следовательно, второй отрезок (run 2) начинается с кластера 0211E5h и продолжается вплоть до кластера 0211E5h + 114h == 212F9h. Третий отрезок (run 3): 31h – один байт на поле длины и три байта – на поле начального кластера, равные 42h и 0300AAh соответственно. Поэтому третий отрезок (run 3) начинается с кластера 0300AAh и продолжается вплоть до кластера 0300AAh + 42h == 300ECh. Завершающий ноль на конце списка отрезков сигнализирует о том, что это последний отрезок в файле.

Таким образом, подопытный файл состоит из трех отрезков, разбросанных по диску в следующем живописном порядке: 342573h3425ABh; 0211E5h212F9h; 0300AAh300ECh. Остается только прочитать его с диска! Нет ничего проще!

Начиная с версии 3.0, NTFS поддерживает разреженные (sparse) атрибуты, т.е. такие атрибуты, которые не записывают на диск кластеры, содержащие одни нули. При этом поле номера начального кластера отрезка может быть равным нулю, что означает, что данному отрезку не выделен никакой кластер. Поле длины содержит количество кластеров, заполненных нулями. Их не нужно считывать с диска. Вы должны самостоятельно изготовить их в памяти. Между прочим, далеко не все дисковые доктора знают о существовании разреженных атрибутов (если атрибут разрежен, его флаг равен 8000h), и интерпретируют нулевую длину поля номера начального кластера весьма странным образом. Последствия такого "лечения" обычно оказываются весьма печальными.

Пространства имен

NTFS изначально проектировалась как файловая система, не зависящая от платформы, способная работать с большим количеством различных подсистем, в том числе: Win32, MS-DOS, POSIX. Так как каждая из перечисленных подсистем налагает собственные ограничения на набор символов, допустимых для использования в имени файла, NTFS вынуждена поддерживать несколько независимых пространств имен (name spaces).

POSIX

Допустимы все символы UNICODE (с учетом регистра), за исключением символа нуля (NULL), обратной косой черты () и знака двоеточия (:). Последнее из перечисленных ограничений, кстати говоря, не есть ограничение POSIX. Напротив, это – внутреннее ограничение файловой системы NTFS, использующей этот символ для доступа к именованным атрибутам. Максимально допустимая длина имени составляет 255 символов.

Win32

Доступны все символы UNICODE (без учета регистра), за исключением следующего набора: кавычки ("), звездочка (*), косая черта (/), двоеточие (:), знак "меньше" (<), знак "больше" (>), вопросительный знак (?), обратная косая черта (), а также символ конвейера (|). Кроме того, имя файла не может заканчиваться точкой или пробелом. Максимально допустимая длина имени составляет 255 символов.

MS-DOS

Доступны все символы пространства имен Win32 (без учета регистра), за исключением следующих: знак плюса (+), запятая (,), точка (.), точка с запятой (;), знак равенства (=). Длина имени файла не должна превышать восьми символов, за которыми следует необязательное расширение имени файла, имеющее длину от одного до трех символов.

Назначение служебных файлов

NTFS содержит большое количество служебных файлов (метафайлов) строго определенного формата. Важнейший из метафайлов, $MFT, мы только что рассмотрели. Остальные метафайлы играют вспомогательную роль. Для восстановления данных детально знать их структуру необязательно. Тем не менее, если они окажутся искажены, то штатный драйвер файловой системы не сможет работать с таким томом, поэтому иметь некоторые представления о назначении каждого из них все же необходимо.

Краткие сведения о назначении важнейших метафайлов приведены в табл. 6.11. К сожалению, в пределах одной главы нет возможности подробно рассмотреть структуру всех существующих метафайлов, поэтому заинтересованным читателям рекомендуется искать эту информацию в документации к Linux-NTFS Project.

Таблица 6.11. Назначение основных метафайлов NTFS


0 $MFT ЛюбаяГлавная файловая таблица (Master File Table, MFT)
1 $MFTMirr ЛюбаяРезервная копия первых четырех элементов MFT
2 $LogFile ЛюбаяЖурнал транзакций (transactional logging file)
3 $Volume ЛюбаяСерийный номер, время создания, флаг не сброшенного кэша (dirty flag) тома
4 $AttrDef ЛюбаяОпределение атрибутов
5. (точка)ЛюбаяКорневой каталог (root directory) тома
6 $Bitmap ЛюбаяКарта свободного/занятого пространства
7 $Boot ЛюбаяЗагрузочная запись (boot record) тома
8 $BadClus ЛюбаяСписок плохих кластеров (bad clusters) тома
9 $Quota Windows NTИнформация о квотах (quota information)
9 $Secure Windows 2000Использованные дескрипторы безопасности (security descriptors)
10 $UpCase ЛюбаяТаблица заглавных символов (uppercase characters) для трансляции имен
11 $Extend Windows 2000Каталоги: $ObjId, $Quota, $Reparse, $UsnJrnl
12-15не используетсяЛюбаяПомечены как использованные, но в действительности пустые
16-23не используетсяЛюбаяПомечены как неиспользуемые
Любой $ObjId Windows 2000Уникальные идентификаторы каждого файла
Любой $Quota Windows 2000Информация о квотах (quota information)
Любой $Reparse Windows 2000Информация о точке передачи (reparse point)
Любой $UsnJrnl Windows 2000Журнал шифрованной файловой системы (journaling of encryption)
>24Пользовательский файлЛюбаяОбычные файлы
>24Пользовательский каталогЛюбаяОбычные каталоги


Практический пример

Рассказ о файловой системе NTFS был бы неполным без практической иллюстрации техники разбора файловой записи вручную. До сих пор мы витали в облаках теоретической абстракции. Пора спускаться на грешную землю.

Воспользовавшись любым дисковым редактором, например, Disk Probe, попробуем декодировать одну файловую запись вручную. Найдем сектор, содержащий сигнатуру FILE в его начале (не обязательно брать первый встретившийся сектор). Он может выглядеть, например, как в листинге 6.4.

Листинг 6.4. Ручное декодирование файловой записи (разные атрибуты выделены разным цветом)

        : 00 01 02 03 04 05 06 07 | 08 09 0A 0B 0C 0D 0E 0F

00000000: 46 49 4C 45 2A 00 03 00 | 60 79 1A 04 02 00 00 00 FILE*...`y......

00000010: 01 00 01 00 30 00 01 00 | 50 01 00 00 00 04 00 00 ....0...P.......

00000020: 00 00 00 00 00 00 00 00 | 04 00 03 00 00 00 00 00 ................

00000030: 10 00 00 00 60 00 00 00 | 00 00 00 00 00 00 00 00 ................

00000040: 48 00 00 00 18 00 00 00 | B0 D5 C9 2F C6 0B C4 01 H.......░╒╔/╞.─.

00000050: E0 5A B3 7B A9 FA C3 01 | 90 90 F1 2F C6 0B C4 01 рZ│{й·├.PPё/╞.─.

00000060: 50 7F BC FE C8 0B C4 01 | 20 00 00 00 00 00 00 00 P⌂╝■╚.─. .......

00000070: 00 00 00 00 00 00 00 00 | 00 00 00 00 05 01 00 00 ................

00000080: 00 00 00 00 00 00 00 00 | 00 00 00 00 00 00 00 00 ................

00000090: 30 00 00 00 70 00 00 00 | 00 00 00 00 00 00 02 00 0...p...........

000000A0: 54 00 00 00 18 00 01 00 | DB 1A 01 00 00 00 01 00 T.......█.......

000000B0: B0 D5 C9 2F C6 0B C4 01 | B0 D5 C9 2F C6 0B C4 01 ░╒╔/╞.─.░╒╔/╞.─.

000000C0: B0 D5 C9 2F C6 0B C4 01 | B0 D5 C9 2F C6 CB C4 01 ░╒╔/╞.─.░╒╔/╞.─.

000000D0: 00 00 00 00 00 00 00 00 | 00 00 00 00 00 00 00 00 ................

000000E0: 20 00 00 00 00 00 00 00 | 09 03 49 00 6C 00 66 00 ..........I.l.f.

000000F0: 61 00 6B 00 2E 00 64 00 | 62 00 78 00 00 00 00 00 a.k...d.b.x.....

00000100: 80 00 00 00 48 00 00 00 | 01 00 00 00 00 00 03 00 А...H...........

00000110: 00 00 00 00 00 00 00 00 | ED 04 00 00 00 00 00 00 ........э.......

00000120: 40 00 00 00 00 00 00 00 | 00 E0 4E 00 00 00 00 00 @........рN.....

00000130: F0 D1 4E 00 00 00 00 00 | F0 D1 4E 00 00 00 00 00 Ё╤N.....Ё╤N.....

00000140: 32 EE 04 D9 91 00 00 81 | FF FF FF FF 82 79 47 11 2ю.┘С..Б    ВyG.

000001F0: 00 00 00 00 00 00 00 00 | 00 00 00 00 00 00 03 00 ................

        : 00 01 02 03 04 05 06 07 | 08 09 0A 0B 0C 0D 0F 0F

Первым делом необходимо восстановить оригинальное содержимое последовательности обновления. По смещению 04h от начала сектора лежит 16-разрядный указатель на нее, равный в данном случае 2Ah (значит, это NTFS 3.0 или более ранняя версия). А что у нас лежит по смещению 2Ah? Это – пара байт 03 00. Данная последовательность представляет собой номер последовательности обновления. Сверяем его с содержимым двух последних байт этого и следующего секторов (смещения 1FEh и 3FEh соответственно). Они равны! Следовательно, данная файловая запись цела (по крайней мере, на первый взгляд), и можно переходить к операции ее восстановления. По смещению 2Ch расположен массив, содержащий оригинальные значения последовательности обновления. Количество элементов в нем равно содержимому 16-разрядного поля, расположенному по смещению 06h от начала сектора и уменьшенного на единицу (в данном случае имеем 03h – 01h == 02h). Извлекаем два слова, начиная со смещения 2Ch (в данном случае они равны 00 00 и 00 00) и записываем их в конец первого и последнего секторов.

Теперь нам необходимо выяснить, используется ли данная файловая запись, или же ассоциированный с ней файл или каталог был удален. 16-разрядное поле, расположенное по смещению 16h, содержит значение 01h. Следовательно, перед нами файл, а не каталог, и этот файл еще не удален. Но является ли эта файловая запись базовой для данного файла или мы имеем дело с ее продолжением? 64-разрядное поле, расположенное по смещению 20h, равно нулю, следовательно, данная файловая запись – базовая.

Очень хорошо, теперь переходим к исследованию атрибутов. 16-разрядное поле, находящееся по смещению 14h, равно 30h, следовательно, заголовок первого атрибута начинается со смещения 30h от начала сектора.

Первое двойное слово атрибута равно 10h, значит, перед нами атрибут типа $STANDARD_INFORMATION. 32-разрядное поле длины атрибута, находящееся по смещению 04h и равное в нашем случае 60h байт, позволяет нам вычислить смещение следующего атрибута в списке: 30h (смещение нашего атрибута) + 60h (его длина) == 90h (смещение следующего атрибута). Первое двойное слово следующего атрибута равно 30h, значит, это атрибут типа $NAME, и следующее 32-разрядное поле хранит его длину, равную в данном случае 70h. Сложив длину атрибута с его смещением, мы получим смещение следующего атрибута – 90h + 70h == 100h. Первое двойное слово третьего атрибута равно 80h, следовательно, это атрибут типа $DATA, хранящий основные данные файла. Складываем его смещение с длиной – 100h + 32h == 132h. И вот здесь мы наткнулись на частокол FFFFFFh, сигнализирующий о том, что атрибут $DATA последний в списке.

Теперь, разбив файловую запись на атрибуты, можно приступить к исследованию каждого из атрибутов в отдельности. Начнем с разбора имени. 8-разрядное поле, находящееся по смещению 08h от начала атрибутного заголовка (и по смещению 98h от начала сектора), содержит флаг нерезидентности. В данном случае этот флаг равен нулю. Это значит, атрибут резидентный, и его тело хранится непосредственно в самой файловой записи, что уже хорошо. 16-разрядное поле, расположенное по смещению 0Сh от начала атрибутного заголовка (и по смещению 9Ch от начала сектора) равно нулю, следовательно, тело атрибута не сжато и не зашифровано. Таким образом, можно приступать к разбору тела атрибута. 32-разрядное поле, расположенное по смещению 10h от начала атрибутного заголовка (и по смещению A0h от начала сектора), содержит длину атрибутного тела, равную в данном случае 54h байт. 16-разрядное поле, расположенное по смещению 14h от начала атрибутного заголовка и по смещению A4h от начала сектора, хранит смещение атрибутного тела, равное в данном случае 18h. Следовательно, тело атрибута $FILE_NAME располагается по смещению A8h от начала сектора.

Формат атрибута типа $FILE_NAME описан в табл. 6.9. Первые восемь байт содержат ссылку на родительский каталог этого файла, равную в данном случае 11ADBh:01 (индекс – 11ADBh, номер последовательности – 01h). Следующие 32 байта содержат данные о времени создания, изменения и времени последнего доступа к файлу. По смещению 28h от начала тела атрибута и D0h от начала сектора лежит 64-разрядное поле выделенного размера, а за ним – 64-разрядное поле реального размера. Оба равны нулю, что означает, что за размером файла следует обращаться к атрибутам типа $DATA.

Длина имени файла содержится в 8-разрядном поле, находящемся по смещению 40h байт от начала тела атрибута и по смещению E8h от начала сектора. В данном случае оно равно 09h. Само же имя начинается со смещения 42h от начала тела атрибута и со смещения EAh от начала сектора. И здесь находится имя файла llfak.dbx.

Переходим к атрибуту основных данных файла, пропустив атрибут стандартной информации, который не содержит решительно ничего интересного. 8-разрядный флаг нерезидентности, расположенный по смещению 08h от начала атрибутного заголовка и по смещению 108h от начала сектора, равен 01h, следовательно, атрибут нерезидентный. 16-разрядный флаг, расположенный по смещению 0Ch от начала атрибутного заголовка и по смещению 10Ch от начала сектора, равен нулю, значит, атрибут не сжат и не зашифрован. 8-разрядное поле, расположенное по смещению 09h от начала атрибутного заголовка и по смещению 109h от начала сектора, равно нулю – атрибут безымянный. Реальная длина тела атрибута (в байтах) содержится в 64-разрядном поле, расположенном по смещению 30h от начала атрибутного заголовка и по смещению 130h от начала сектора. В данном случае она равна 4ED1F0h (5.165.552). Два 64-разрядных поля, расположенных по смещениям 10h/110h и 18h/118h байт от начала атрибутного заголовка/сектора соответственно, содержат начальный и конечный номер виртуального кластера нерезидентного тела. В данном случае они равны: 0000h и 4EDh соответственно.

Остается лишь декодировать список отрезков, адрес которого хранится в 16-разрядном поле, находящемся по смещению 20h от начала атрибутного заголовка и 120h от начала сектора. В данном случае поле равно 40h, что соответствует смещению от начала сектора в 140h. Сам же список отрезков выглядит так: 32 EE 04 D9 91 00 00. Ага! Два байта занимает поле длины (равное в данном случае 04EEh кластерам) и три – поле начального кластера (0091h). Завершающий ноль на конце говорит о том, что этот отрезок последний в списке отрезков.

Подытожим полученную информацию. Файл называется llfak.dbx, он начинается с кластера 0091h и продолжается вплоть до кластера 57Fh, при реальной длине файла в 5.165.552 байт. Это все, что надо! Теперь остается только скопировать файл на резервный носитель (например, ZIP или стример).


    Ваша оценка произведения:

Популярные книги за неделю