close

Вход

Забыли?

вход по аккаунту

?

4 лр

код для вставкиСкачать
Лабораторная работа № 4
Исследование структуры тома NTFS
Цель работы: изучить структуру и особенности NTFS
Теоретическая часть
1. Общая структура тома NTFS
Основой тома NTFS является так называемая $MFT - Master File Table (Главная Файловая Таблица) - своеобразная база данных, хранящая информацию обо всех файлах тома - их именах, атрибутах, способе и порядке размещения на диске. Каталог также является файлом особого типа со списком принадлежащих ему файлов и подкаталогов внутри. Более того, особенность NTFS в том, что сама таблица является файлом и описана внутри себя. Т.к. таблица является файлом, она может располагаться в любом месте диска и фрагментироваться.
В процессе форматирования логического раздела, в его начале создается MTF-зона, по умолчанию занимающая 12.5% от емкости тома. В этой области расположен $MFT-файл, изначально занимающий порядка 64 секторов и растущий от начала MFT-зоны к ее концу по мере создания новых пользовательских файлов/подкаталогов. Таким образом, чем больше файлов содержится на дисковом томе, тем больше размер MFT.
Для предотвращения фрагментации $MFT-файла MFT-зона держится зарезервированной, вплоть до полного исчерпания свободного пространства тома, затем незадействованный "хвост" MFT-зоны усекается в два раза, освобождая место для пользовательских файлов. Этот процесс может повторяться многократно, вплоть до полной отдачи всего зарезервированного пространства.
MFT состоит из записей, размер которых обычно 1024 байта. Каждая запись состоит из заголовка и следующих за ним атрибутов. Поля заголовка строго определены, в атрибутах же хранятся различные сведения о файле и его данные.
Первые 12 записей в MFT всегда занимают служебные метафайлы: $MFT (собственно, сам $MFT), $MFTMirr (зеркало $MFT), $LogFile (файл транзакций), $Volume (сведения о дисковом томе), $AttrDef (определенные атрибуты), '.' (корневой каталог), $Bitmap (карта свободного пространства), $Boot (системный загрузчик), $BadClus (перечень плохих кластеров) и т.д.
Первая запись таблицы называется $MFT и представляет собой описание самой таблицы.
Первые четыре записи настолько важны, что продублированы в специальном $MFTMirr-файле, находящимся приблизительно посередине диска (точное расположение хранится в boot-секторе по смещению 38h байт от его начала. $MFTMirr это всего лишь копия первых четырех элементов.
Записи с 12 по 15 помечены как используемые, но в действительности же они пусты. Записи с 16 по 23 не задействованы и помечены как неиспользуемые. Начиная с 24-й записи, располагаются пользовательские файлы и каталоги. Для ссылки на одну файловую запись из другой используется ее порядковый номер (он же индекс) в $MFT файле, отсчитываемый от нуля. При удалении файла/каталога соответствующая ему файловая последовательность не удаляется физически, а помечается как неиспользуемая. При создании новых файлов записи, помеченные как неиспользуемые, могут задействоваться вновь.
2. Загрузочный сектор NTFS
Начальный адрес MFT (адрес её первой записи), содержится в загрузочном секторе (boot-секторе). Он всегда находится в начале раздела.
Структура загрузочного сектора приведена в таблице:
Смещение Размер в байтах Описание 0x0 3 Команда перехода на загрузочный код. 0x3 8 Сигнатура 'NTFS ' 0xB 2 Количество байт на сектор. Обычно равно 512 0xD 1 Количество секторов в кластере. Обычно равно 8 0xE 2 Должно равняться нулю. 0x10 1 0x11 2 0x13 2 0x15 1 Тип носителя 0x16 2 Должно равняться нулю. 0x18 2 0x1A 2 0x1C 4 Не используется 0x20 4 Должно равняться нулю. 0x24 4 Не используется 0x28 8 Число секторов в томе 0x30 8 Стартовый кластер MFT 0x38 8 Стартовый кластер копии MFT ($MFTMirror) 0x40 1 Кластеров на запись MFT. Представляет собой двоичный логарифм количества кластеров, используемых для хранения одной записи. Обычно равно 10. 0x41 3 Не используется. 0x44 1 Кластеров на индексную запись 0x45 3 Не используется 0x48 8 Серийный номер тома. Уникален. Создается в процессе форматирования. 0x50 4 Не используется. 0x54 426 Загрузочный код 0x1FE 2 Маркер конца. Равен 0xAA55. Описание структуры на языке С++ смотрите в приложении к лабораторной работе!
Среди параметров загрузочного сектора важнейшими являются размер сектора и кластера. Без них идентификация записей и адресация не возможна.
При проверке факта, что том является NTFS, необходимо прежде всего проверить сигнатуру "NTFS ", расположенную по смещению 0x3:
if( NtfsBootSector->oem_id.QuadPart != 0x202020205346544E )
return FALSE;
3.Структура записи MFT
MFT состоит из записей, размер которых обычно 1024 байта. Каждая запись состоит из заголовка и следующих за ним атрибутов. Рисунок 1 - Структура записи MFT
3.1.Заголовок записи
Структура заголовка представлена в таблице
Смещение Размер Описание 0х0 4 Сигнатура 'FILE'. Указывает, что это запись MFT. Позволяет отличить сектора, принадлежащие MFT, от всех остальных секторов. В записях, в которых обнаружены ошибки она равна 'BAAD' 0х4 2 Смещение массива данных, заменённых номером последовательности обновления. 0х6 2 Размер в словах номера последовательности обновления и массива обновления. 0х8 8 Номер последовательности файла транзакций ($LogFile Sequence Number или сокращенно LSN) 0х10 2 Номер последовательности. Увеличивается при каждом выделении и освобождении записи. Например, значение этого поля равное 1 показывает, что запись используется первый раз. 0х12 2 Счетчик жестких ссылок. Определяет число каталогов, содержащих записи для данной структуры. 0х14 2 Смещение первого атрибута 0х16 2 Флаги записи:
Бит 1 устанавливается, если запись используется.
Бит 2 устанавливается, если запись является каталогом
Например, значение этого поля 0х1 означает, что запись используется и является файлом, 0х3 - запись используется и является каталогом. 0х18 4 Реальный размер файловой записи в байтах (совокупный размер заголовка, всех его атрибутов и маркера конца, округленный по 8 байтной границе) 0х1С 4 Выделенный размер файловой записи (действительный размер файловой записи в байтах, округленный по размеру сектора) 0х20 8 Ссылка на базовую файловую запись или ноль, если данная файловая запись базовая. 0х28 2 Идентификатор следующего атрибута 0х2А 2 Для выравнивания 0х2С 4 Индекс данной файловой записи 3.2. Последовательности обновления
Будучи очень важными компонентами файловой системы, $MFT, INDEX и $LogFile нуждаются в механизме контроля целостности своего содержимого. Этой цели служат последовательности обновления.
В последние два слова каждого из секторов, слагающих файловую запись, записывается специальный 2-байтовый номер последовательности обновления, дублируемый в заголовке файловой записи. При каждой операции чтения два последних байта сектора сверяется с соответствующим полем заголовка и если NTFS-драйвер обнаруживает расхождение, данная файловая запись считается недействительной.
Основное назначение последовательностей обновления - защита от "обрыва записи". Если в процессе записи сектора на диск, исчезнет питающее напряжение, может случиться так, что половина файловой записи будет успешно записана, а половина - сохранит прежнее содержимое (файловая запись обычно состоит из двух секторов). После восстановления питания, драйвер файловой системы не может уверенно сказать - была ли файловая запись записана целиком или нет. Вот тут-то последовательности обновления и выручают! При каждой перезаписи сектора update sequence увеличивается на единицу и потому, если произошел обрыв записи, значение последовательности обновления, находящейся в заголовке файловой записи не будет совпадать с последовательностью обновления, расположенной в конце сектора. Ситуация проиллюстрирована на рисунке.
Рисунок 2 - Первый сектор записи MFT
Содержимое занятых последовательностью обновления байт хранится в специальном массиве обновления, расположенном в заголовке файловой записи сразу за номером последовательности обновления. Перед чтением записи таблицы файлов нужно обязательно привести сектора в исходный вид. Алгоритм действий при этом такой:
1. Прочитать первый сектор и расшифровать заголовок записи.
2. Прочитать слова, находящиеся в конце всех секторов записи, и сравнить их с номером последовательности обновления, хранящемся в заголовке. Если они совпали, значит запись не повреждена.
3. Заменить слово, находящееся в конце первого сектора, первым словом, находящемся по смещению, хранящемуся во втором поле заголовка. В конце второго - вторым и т.д.
3.3.Атрибуты
Структурно атрибут стоит из атрибутного заголовка и тела атрибута. Заголовок атрибута всегда хранится в файловой записи, расположенной внутри MFT.
Атрибут, тело которого хранится непосредственно в файловой записи и целиком умещается в ней, называется резидентным. Нерезидентные атрибуты хранят свое тело вне MFT в одном или нескольких кластерах, перечисленных в заголовке данного атрибута в специальном списке (см. "Списки отрезков"). Структура заголовка атрибутов описаны в таблице.
Структура заголовка резидентного атрибута
0х0 4 Тип атрибута 0х4 4 Длина атрибута, включая этот заголовок 0х8 1 Нерезидентный флаг 0х9 1 Длина имени атрибута (ноль, если атрибут безымянный) 0хA 2 Смещение имени(ноль, если атрибут безымянный) 0хC 2 Флаги:
0001h -сжатый атрибут 4000h - зашифрованный атрибут 8000h - разряженный атрибут 0хE 2 Идентификатор атрибута 0х10 4 Длина тела атрибута 0х14 2 Смещение тела атрибута 0х16 1 Индексный флаг 0х17 1 Для выравнивания 0х18 2N Имя атрибута (если есть) Структура заголовка нерезидентного атрибута
0х0 4 Тип атрибута 0х4 4 Длина атрибута, включая этот заголовок 0х8 1 Нерезидентный флаг 0х9 1 Длина имени атрибута (ноль, если атрибут безымянный) 0хA 2 Смещение имени(ноль, если атрибут безымянный) 0хC 2 Флаги:
0001h -сжатый атрибут
4000h - зашифрованный атрибут 8000h - разряженный атрибут 0хE 2 Идентификатор атрибута 0х10 8 Начальный виртуальный кластер (starting VCN) 0х18 8 Конечный виртуальный кластер (last VCN) 0х20 2 Смещение списка отрезков 0х22 2 Размер блока сжатия 0х24 4 Для выравнивания 0х28 8 Выделенный размер, округленный до размера кластера 0х30 8 Реальный размер 0х38 8 Инициализированный размер потока 0х40 2N Имя атрибута, если есть NTFS поддерживает большое количество предопределенных типов атрибутов, перечисленных в таблице. Тип атрибута определяет его назначение и формат представления тела. Полное описание всех атрибутов заняло бы очень много места, поэтому в качестве примера приведём несколько типов:
0х10 - $STANDARD_INFORMATION - стандартная информация о файле (время, права доступа)
0х80 - $DATA - основные данные файла. У каталогов этот атрибут отсутствует.
3.3.1.Списки отрезков
Тела нерезидентных атрибутов хранятся на диске в одной или нескольких кластерных цепочках, называемых отрезками. Отрезком называется последовательность смежных кластеров, характеризующаяся номером начального кластера и длиной. Совокупность отрезков называется списком, run-list'ом или data run'ом.
Смещение списка отрезков указано относительно начала заголовка атрибута.
Для экономии места длина отрезка и номер начального кластера хранятся в полях переменной длины. То есть, если размер отрезка умещается в байт (т.е. его значение не превышает 255), он и хранится в байте. Соответственно, если размер отрезка требует для своего представления двойного слова, он хранится в двойном слове.
Сами же поля размеров хранятся в 4-байтовых ячейках, называемых нибблами или полубайтами.
Список отрезков представляет собой массив структур, каждая из которых описывает характеристики "своего" отрезка, а в конце списка находится завершающий нуль.
Первый байт структуры состоит из двух полубайтов: младший (L) задает длину поля начального кластера отрезка, старший (H) - количество кластеров в отрезке. Далее идёт поле длины отрезка в кластерах. В зависимости от значения L оно может занимать от одного до восьми байт. После расположено поле, содержащее адрес начального кластера отрезка размером H. Если далее идёт ноль, то это был последний отрезок в списке, иначе далее расположен следующий отрезок.
Рисунок 3 - Структура списка отрезков.
Процедура распаковки списка отрезков приведена в приложении к лабораторной работе.
Т.к. сама таблица MFT является файлом, а следовательно фрагментирована, прямая адресация её как массива невозможна, поэтому первоначально необходимо получить список её отрезков.
По итогам вышеизложенного можно составить следующий примерный алгоритм чтения таблицы MFT:
1. Прочитать и проанализировать загрузочный сектор. Для чтения можно воспользоваться процедурой из приложения к лабораторной работе.
2. Прочитать 2 сектора (размер файловой записи) по адресу первой записи MFT (записан в загрузочном секторе). Это будет запись, описывающая саму MFT.
3. Проанализировать заголовок прочитанной записи. На основе полученных данных восстановить искажённую последовательностями обновления информацию в обоих секторах.
4. Найти в записи заголовок атрибута $DATA и прочитать его список отрезков.
5. Распаковать список отрезков. Для распаковки можно воспользоваться процедурой из приложения к лабораторной работе.
6. Полученные отрезки содержат все записи таблицы MFT.
Получив список отрезков таблицы MFT можно аналогично обращаться к её файловым записям.
Практическая часть
Задание.
Используя программные фрагменты приложения, разработать программу, выполняющую следующие действия:
1. Чтение и анализ загрузочного сектора раздела (вывести его содержимое и значения его полей). В случае если анализируемый раздел не является томом NTFS вывести соответствующее сообщение.
2. Получение по номеру записи следующей информации о ней:
* Начальный сектор записи
* Запись описывает файл, каталог или не используется?
* Выделенный и реальный размер записи
* Если это файл, то сообщить, является ли $DATA резидентным или нет.
* Если $DATA нерезидентный, то вывести список фрагментов файла и его размер.
3. Программа должна выводить сообщения об ошибках.
Порядок выполнения работы
1. Выполнить задание.
2. Проверить работоспособность программы и корректность выводимых данных. Например, пятая запись таблицы - каталог, список отрезков первой записи должен начинаться с адреса, равного первому кластеру MFT и т.д.
3. Оформить отчёт и ответить на контрольные вопросы.
Контрольные вопросы
1. Что такое NTFS?
2. Общая структура NTFS
3. Расскажите о назначении основных полей загрузочного сектора
4. Как определить адрес первой записи MFT?
5. Опишите структуру записи MFT
6. Как определить повреждена файловая запись или нет?
7. Что такое нерезидентный атрибут?
8. Для чего нужен список отрезков?
Приложение
//Описание структуры файловой записи
typedef struct _MFT_RECORD
{
/*0x00*/ULONG signature; //сигнатура 'FILE'
/*0x04*/USHORT usa_offs;
/*0x06*/USHORT usa_count;
/*0x08*/ULARGE_INTEGER lsn;
/*0x10*/USHORT sequence_number;
/*0x12*/USHORT link_count;
/*0x14*/USHORT attrs_offset;
/*0x16*/USHORT flags;//флаги, см. MFT_RECORD_FLAGS
/*0x18*/ULONG bytes_in_use;
/*0x1C*/ULONG bytes_allocated;
/*0x20*/ULARGE_INTEGER base_mft_record; //адрес базовой MFT-записи
/*0x28*/USHORT next_attr_instance;
/*0x2A*/USHORT reserved;
/*0x2C*/ULONG mft_record_number;
//size - 48 b
} MFT_RECORD, *PMFT_RECORD;
//список типов основных атрибутов
typedef enum
{
AT_STANDARD_INFORMATION= 0x10,
AT_ATTRIBUTE_LIST= 0x20,
AT_FILE_NAME= 0x30,
AT_OBJECT_ID= 0x40,
AT_SECURITY_DESCRIPTOR= 0x50,
AT_VOLUME_NAME= 0x60,
AT_VOLUME_INFORMATION= 0x70,
AT_DATA= 0x80,
AT_INDEX_ROOT= 0x90,
AT_INDEX_ALLOCATION= 0xa0,
AT_BITMAP= 0xb0,
AT_REPARSE_POINT= 0xc0,
AT_END= 0xffffffff
} ATTR_TYPES;
//Описание структуры атрибута
typedef struct _ATTR_RECORD
{
/*0x00*/ATTR_TYPES type; //тип атрибута
/*0x04*/USHORT length; //длина заголовка; используется для перехода к //следующему атрибуту
/*0x06*/USHORT Reserved;
/*0x08*/UCHAR non_resident; //1 если атрибут нерезидентный, 0 - резидентный
/*0x09*/UCHAR name_length; //длина имени атрибута, в символах
/*0x0A*/USHORT name_offset; //смещение имени атрибута, относительно заголовка
//атрибута
/*0x0C*/USHORT flags; //флаги, перечислены в ATTR_FLAGS
/*0x0E*/USHORT instance;
union
{
//Резидентный атрибут
struct
{
/*0x10*/ULONG value_length; //размер, в байтах, тела атрибута
/*0x14*/USHORT value_offset; //байтовое смещение тела, относительно заголовка //атрибута
/*0x16*/UCHAR resident_flags; //флаги, перечислены в RESIDENT_ATTR_FLAGS
/*0x17*/UCHAR reserved;
} r;
//Нерезидентный атрибут
struct
{
/*0x10*/ULARGE_INTEGER lowest_vcn;
/*0x18*/ULARGE_INTEGER highest_vcn;
/*0x20*/USHORT mapping_pairs_offset;//смещение списка отрезков
/*0x22*/UCHAR compression_unit; /*0x23*/UCHAR reserved1[5];
/*0x28*/ULARGE_INTEGER allocated_size; //размер дискового пространства, //которое было выделено под тело
//атрибута
/*0x30*/ULARGE_INTEGER data_size; //реальный размер атрибута
/*0x38*/ULARGE_INTEGER initialized_size;
} nr;
} u;
} ATTR_RECORD, *PATTR_RECORD;
//---------------------------------------------------------------------------
//Процедура распаковки отрезка
PUCHAR NtfsDecodeRun(
PUCHAR DataRun, //на входе, указатель на отрезок для распаковки
LONGLONG *DataRunOffset, //на выходе, распакованное значение кластерного смещения
ULONGLONG *DataRunLength //на выходе, распакованное значение числа кластеров
)
{
UCHAR DataRunOffsetSize; //размер поля смещения
UCHAR DataRunLengthSize; //размер поля длины
CHAR i;
//из старшего полубайта считаем размер поля смещения
DataRunOffsetSize = (*DataRun >> 4) & 0xF;
//из младшего размер поля смещения
DataRunLengthSize = *DataRun & 0xF;
*DataRunOffset = 0;
*DataRunLength = 0;
//указатель на сами данные
DataRun++;
//цикл распаковки длины отрезка, с каждой итерацией значение сдвигается на i-байт и //прибавляется с длиной
for (i = 0; i < DataRunLengthSize; i++)
{
*DataRunLength += *DataRun << (i << 3);
DataRun++;
}
/* если получен ноль, то это конец списка отрезков*/
if (DataRunOffsetSize == 0)
{
*DataRunOffset = -1;
}
else
{
//цикл распаковки смещения
for (i = 0; i < DataRunOffsetSize - 1; i++)
{
*DataRunOffset += *DataRun << (i << 3);
DataRun++;
}
//последний байт может быть знаковым, поэтому он обрабатывается отдельно
*DataRunOffset = ((CHAR)(*(DataRun++)) << (i << 3)) + *DataRunOffset;
}
//возвращаем указатель на следующий отрезок
return DataRun;
}
Пример вызова функции распаковки отрезка:
PUCHAR DataRun = (PUCHAR)SpisokOtrezkov;//полученный ранее указатель на список отрезков
LONGLONG DataRunOffset;
ULONGLONG DataRunLength;
do
{
DataRun=NtfsDecodeRun(DataRun,&DataRunOffset,&DataRunLength);
}while(DataRunOffset!=-1);
В результате будет распакован весь список отрезков.
Документ
Категория
Рефераты
Просмотров
56
Размер файла
347 Кб
Теги
1/--страниц
Пожаловаться на содержимое документа