Восстановление данных. Практическое руководство — страница 5 из 13

Автоматическое и ручное восстановление данных с жестких дисков

Глава 5Основные концепции ручного восстановления данных

Долгое время главным козырем противников NTFS был следующий аргумент — чем вы будете ее восстанавливать в случае, если она окажется поврежденной? А ведь повреждения файловой системы возникают достаточно часто! При всей своей надежности файловая система NTFS не застрахована от потрясений. Ошибки оператора, вирусы, сбои питания, зависания ОС, дефекты поверхности, отказ электроники — любой из этих факторов может стать причиной повреждения, а то и разрушения файловой системы. С каждым днем человечество все сильнее и сильнее зависит от компьютеров, объемы жестких дисков стремительно растут, а с ними растет и ценность содержащихся на них данных, потеря которых зачастую невосполнима.

Спрос рождает предложение, и на рынке информационных услуг постоянно появляются фирмы, специализирующиеся на восстановлении данных. К сожалению, действительно квалифицированных специалистов можно встретить лишь в некоторых из них. Многие из них лишь создают видимость кипучей деятельности, выставляя астрономические счета при посредственном качестве восстановления. Но время кустарей уже ушло. Рабочая атмосфера изменилась. Хакеры разобрались со строением NTFS и документировали ее ключевые структуры. Начал формироваться достойный инструментарий для ручного восстановления. За минувшее время накопился огромный опыт по борьбе за спасение данных, частью которого я и хочу поделиться с читателями.

Что делать в случае катастрофической потери данных

Прежде всего — не паникуйте! Заниматься восстановлением можно только на трезвую голову. Непродуманные, лихорадочные действия только усугубляют ваше и без того незавидное положение.

Не используйте никаких автоматизированных утилит, если полностью в них не уверены. Последствия такого "лечения" могут быть катастрофическими, а результаты "восстановления" — необратимыми. То же самое относится и к "специалистам", обитающим в фирмах непонятного происхождения и орудующим все теми же автоматизированными утилитами, которыми вы можете воспользоваться и без них. Некоторые пытаются создавать необходимый инструментарий самостоятельно. Чаще всего он оказывается неработоспособным еще с рождения, но зато какая гордость для фирмы! Какое впечатляющее средство демонстрации собственной крутизны! Часто маркетологи этих фирм абсолютно необоснованно заявляют, что разработка их фирмы превосходит все имеющиеся утилиты вместе взятые, как коммерческие, так и условно-бесплатные. Но поверьте, что хорошо известные и давно представленные на рынке утилиты (например, GetDataBack) тоже писали отнюдь не профаны, причем делалось это при непосредственном участии разработчиков оригинального драйвера NTFS, хорошо знающих все его тонкости и особенности поведения. Это лучшее из того, что есть на рынке, и пока еще никому не удалось их превзойти!

Примечание

Разумеется, в данном случае речь идет лишь об автоматизированном восстановлении.

Ничего не записывайте на восстанавливаемый диск и не позволяйте делать это остальным приложениям! Если вы случайно удалили файл с системного диска, ни в коем случае не выходите из Windows официально предписанным способом. Лучше нажмите кнопку RESET. Почему я даю такую "неправильную" рекомендацию? Она "некорректна" только на первый взгляд, а на самом деле это — самый полезный совет, который только можно дать. Дело в том, что при штатном завершении сеанса система сохраняет на диске текущую конфигурацию, существенно увеличивая риск необратимого затирания удаленного файла.

Не пытайтесь "мучить" сбойные сектора многократными попытками чтения, так как это лишь расширяет дефектную область на соседние сектора и может даже привести к повреждению магнитной головки. Если магнитная головка окажется изуродованной, перестанут читаться даже здоровые сектора. Лучше выполните длинное (long) чтение с диска, предварительно отключив контролирующие коды, тогда контроллер возвратит все, что осталось от сектора (ведь зачастую сбой затрагивает только несколько байт).

Если винчестер издает подозрительные звуки вроде постукивания или скрежета, немедленно отключите питание компьютера (опять-таки, не позволяя системе ничего писать на диск), поскольку винчестер может доломаться окончательно в любой момент, и тогда ему уже никакой электронщик не поможет.

Восстанавливайте диски SCSI (и, в особенности, RAID) только на "родном" контроллере, так как различные контроллеры используют различные схемы трансляции адресов. Если же контроллер отказал, его следует либо отремонтировать, либо заменить абсолютно идентичным. С дисками IDE в этом плане возникает гораздо меньше проблем, так как их контроллеры более или менее стандартизованы. Тем не менее, с дисками большого объема (свыше 528 Мбайт) тоже начинается неразбериха и путаница, ставящая их в зависимость от конкретной BIOS и от выбранного режима работы (

NORMAL
,
LBA
или
LARGE
). Если восстанавливаемый диск работает под управлением нестандартных драйверов, например, Rocket, OnDisk, и т.д., то они должны присутствовать и на загрузочной дискете или загрузочном CD, с которых производится восстановление.

Наконец, если данные восстановить так и не удалось — не расстраивайтесь. Во всех жизненных ситуациях надо видеть и хорошие стороны, даже когда ничего хорошего ожидать не приходится.

Основные сведения о структуре диска

Физически жесткий диск представляет собой запечатанный корпус, содержащий одну или несколько одно- или двусторонних пластин, насаженных на шпиндель. Чтение и запись данных осуществляются блоком магнитных головок, каждая из которых обслуживает одну из поверхностей пластины. Информация хранится на дорожках в форме концентрических колец, называемых треками (track). Треки, расположенные на равном расстоянии от центра всех пластин, образуют цилиндр (cylinder). Фрагмент трека, образованный радиальным делением, называется сектором (sector). В современных винчестерах количество секторов на трек не остается постоянным. Напротив, оно дискретно возрастает по мере удаления от центра пластины, таким образом, чтобы линейные размеры сектора оставались более или менее постоянными. Треки и головки нумеруются, начиная с нуля, а нумерация секторов начинается с единицы. Размер сектора для жестких дисков составляет 512 байт.

Первой схемой адресации секторов, доставшейся жестким дискам в наследство от дискет, стала так называемая CHS-адресация, представляющая собой сокращение от Cylinder/Head/Sector (Цилиндр/Головка/Сектор). Данная схема адресации возникла под давлением экономических причин. Когда-то координаты адресуемого сектора непосредственно соответствовали физической действительности, что упрощало и удешевляло дисковый контроллер, не требуя от него никакого интеллектуального поведения. Надо сказать, что дешевизна контроллера является единственным преимуществом данного метода. Эта схема адресации чудовищно неудобна для программистов, так как последовательное чтение диска растягивается на три вложенных цикла. Косность же этой системы граничит с неприличием! Количество секторов в треке должно быть постоянным для всего диска, а в новых винчестерах это не так. Поэтому для сохранения обратной совместимости с существующим программным обеспечением дисковый контроллер виртуализует геометрию винчестера. Это ставит нас в зависимость от выбранной схемы трансляции, которая представляет собой дело сугубо внутреннее и, следовательно, не поддающееся стандартизации. Параметры диска, сообщаемые устройством и напечатанные на этикетке, всегда виртуальны, и узнать реальное положение дел невозможно.

Диски IDE имеют интегрированный контроллер, поэтому они в наименьшей степени зависимы от внешнего мира и могут свободно переноситься с компьютера на компьютер. Разумеется, такой перенос возможен только при условии корректного поведения BIOS (более подробно эта тема будет рассмотрена далее в этой главе). Некоторые винчестеры поддерживают специальную команду ATA —

Initialize device parameters
, устанавливающую текущую виртуальную геометрию диска, а точнее — выбранное количество головок и число секторов на дорожку. Количество цилиндров вычисляется контроллером самостоятельно, на основании общего объема диска, который также можно изменять программными средствами (за это отвечает команда ATA
SET MAX ADDRESS
). Некоторые драйверы и реализации BIOS изменяют геометрию диска, жестко привязывая винчестер к себе. В другом окружении такой диск работать уже не будет, во всяком случае, до установки правильной геометрии.

С устройствами SCSI ситуация обстоит гораздо хуже, и диск соглашается работать только с тем контроллером, под которым он был отформатирован. Различные контроллеры используют различные схемы трансляции. Поэтому подключение диска к несовместимому контроллеру произвольным образом "перемешивает" сектора. Редактор диска с таким винчестером работать еще будет, а вот штатные средства операционной системы и большинство "докторов" — нет.

Продвинутые контроллеры автоматически замещают плохие сектора, либо сохраняя эту информацию в своей энергонезависимой памяти, либо записывая ее в сектора инженерной зоны самого диска. Это еще сильнее привязывает накопитель к его контроллеру, хотя некоторые диски SCSI выполняют переназначение секторов собственными средствами. Выход контроллера SCSI из строя фактически приравнивается к отказу самого диска. Никогда не приобретайте контроллеры SCSI no-name производителей, так как такие фирмы в любой момент могут кануть в лету, и тогда поставки новых контроллеров прекратятся. Контроллеры, интегрированные в материнские платы, вообще никуда не годятся. Они ненадежны и ни с чем не совместимы. Впрочем, разве можно требовать хоть какого-то качества за такие цены? Скупой, как известно, платит дважды!

Сложнее всего обстоят дела с аппаратными реализациями RAID, схема трансляции адресов которых полностью определяется контроллером. Массивы уровня 1, известные как зеркальные наборы (mirror sets), чаще всего используют сквозную (pass-through) трансляцию. Поэтому они без особых проблем могут быть перенесены на любой другой контроллер, или даже подключены в обход него. Массивы остальных уровней, в особенности RAID 3/RAID 5, как правило, оказываются неработоспособными на контроллерах другого типа. Программные реализации RAID, монтируемые Windows NT, хранят информацию о своей геометрии в системном реестре и не могут быть непосредственно перенесены на другие системы. Переустановка Windows NT, как и ее крах, уничтожает программный RAID. К счастью, эта потеря обратима, и впоследствии секреты техники восстановления будут рассмотрены более подробно.

На сегодняшний день схема трансляции CHS признана устаревшей. Так, устройства, придерживающиеся спецификации ATA/ATAPI-6, принятой в июне 2001 года, уже не обязаны ее поддерживать. Тем не менее, она до сих пор встречается во многих служебных структурах операционной системы, в частности, в таблице разделов и загрузочном секторе. Именно поэтому имеет смысл остановиться на этом вопросе поподробнее, тем более что здесь есть о чем поговорить.

На интерфейсном уровне адрес сектора передается, как показано в листинге 5.1.

Листинг 5.1. Интерфейс с диском IDE в режиме CHS

Порт      Значение 

0172/01F2 Количество секторов

0173/01F3 Номер сектора (биты 0-7)

0174/01F4 Номер цилиндра (биты 0-7)

0175/01F5 Номер цилиндра (биты 8-15)

0176/01F6 Номер головки (биты 0-3), привод на шине (бит 4),

          режим CHS/LBA (бит 6)

Сервисные функции BIOS, напротив, адресуют диск несколько иначе, как показано в листинге 5.2.

Листинг 5.2. Интерфейс с прерыванием BIOS INT13h

Регистр Значение

AL      Количество секторов для обработки

CH      Номер цилиндра (биты 0-7)

CL      Номер цилиндра (биты 6-7), номер сектора (биты 0-5)

DH      Номер головки

DL      Привод на шине | 80h

Таким образом, BIOS отводит на адресацию цилиндров всего 10 бит. Потому максимальное количество цилиндров на диске не превышает 1024, что при четырехбитной адресации головок дает предельно достижимый объем диска в

512×210×26×24 == 536870912
байт или всего 512 Мбайт. Это просто смешно, так как производители винчестеров преодолели этот барьер уже много лет назад. С тех пор в мире операционных систем произошло множество изменений. Старушка MS-DOS ушла в небытие, а пришедшая ей на смену Windows работает с диском через собственный драйвер, и ограничения BIOS ее почти не касаются.

Примечание

Почему почти? Вспомните, что первичную загрузку операционной системы осуществляет именно BIOS! При этом, если системные компоненты расположены в секторах, находящихся за пределами 1024 сектора, операционная система не загружается! Причем это относится ко всем операционным системам, а не только к критикуемой Windows!

Для преодоления этого ограничения BIOS вводит дополнительный уровень трансляции (режим

LARGE
), что позволяет увеличить количество головок. К счастью, BIOS выделяет для их адресации не 4 бита, как контроллер диска, а целых 8. Предельно допустимый объем диска теперь составляет
512×210×26×28 = 8589934592
байт или 8 Гбайт. К сожалению, это всего лишь теоретический предел. На практике же большинство реализаций BIOS содержали грубые ошибки, вследствие которых при работе с дисками размером свыше 2 Гбайт они либо банально зависали, либо теряли старшие разряды цилиндра, обращаясь к началу диска и необратимо уничтожая все служебные структуры. До сих пор многие вполне современные реализации BIOS не позволяют адресовать более 64 виртуальных головок, что ограничивает предельно допустимый объем диска все тем же значением, равным 2 Гбайт.

Поэтому при переустановке Windows поверх старой версии на логический диск емкостью свыше 2 Гбайт она может перестать загружаться. Все очень просто! Когда система ставится на только что отформатированный диск, она располагает все свои файлы в самом начале, но по мере заполнения диска область свободного пространства отодвигается все дальше к концу. Отодвинуть файлы первичной загрузки может и дефрагментатор. Тот же результат может быть получен и в результате установки пакета обновления (Service Pack). Иными словами, владельцам больших винчестеров настоятельно рекомендуется разбить его на несколько разделов и установить размер первого (загрузочного) раздела не более, чем в 8 Гбайт, а лучше даже в 2 Гбайт.

Устройства SCSI изначально поддерживают прозрачный механизм логической адресации, или сокращенно LBA (Linear Block Address), последовательно нумерующий все сектора от 0 до последнего сектора диска. В накопителях IDE режим адресации LBA появился, только начиная с ATA-3, но быстро завоевал всеобщее признание. Разрядность адресации определяется устройством. В SCSI она изначально 32-битная, а устройства IDE вплоть до принятия спецификации ATA-6 были ограничены 28 битами, которые распределялись, как показано в листинге 5.3.

Листинг 5.3. Интерфейс с диском IDE в режиме LBA

Порт      Значение

0172/01F2 Количество секторов

0173/01F3 Номер сектора (биты 0-7)

0174/01F4 Номер сектора (биты 8-15)

0175/01F5 Номер сектора (биты 16-24)

0176/01F6 Номер сектора (биты 24-28), привод на шине (бит 4),

          режим CHS/LBA (бит 6)

Как видите, 28-битная адресация обеспечивает поддержку дисков объемом вплоть до 128 Гбайт, однако включение в BIOS поддержки LBA еще не отменяет 8-гигабайтного ограничения, так как номер последнего адресуемого цилиндра по-прежнему остается равным 1024, со всеми вытекающими последствиями. Диски SCSI, за счет их подлинно 32-битной адресации, поддерживают законные 2 Тбайт, так как они управляются собственной BIOS, на которую не наложено никаких унаследованных ограничений.

Утвержденная ATA-6 48-битная адресация расширяет предельно допустимые размеры дисков IDE до астрономических величин (а именно, до 131,072 Тбайт), по крайней мере, в теории. На практике в Windows 2000 с пакетом обновления SP2 или более ранним отсутствует поддержка 48-битного режима LBA. Поэтому для работы с большими дисками необходимо обновить драйвер Atapi.sys и добавить в состав ключа реестра

HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\atapi\Parameters
параметр
EnableBigLba
с типом данных
DWORD
и значением, равным 1 (более подробную информацию можно найти в статье Microsoft Knowledge Base: 260910).

Один физический диск может быть разбит на несколько логических, каждый из которых последовательно нумеруется от первого до последнего сектора либо "сквозной" адресацией, либо по схеме CHS. В некоторых случаях Windows требует задания абсолютного номера сектора (который на самом деле отнюдь не абсолютный, а относительный, отсчитывающийся от стартового сектора раздела), в других — ожидает увидеть "святую троицу" (цилиндр, головку, сектор), опять-таки, отсчитывающихся от стартового сектора. Так, если раздел начинается с адреса

123/15/62
, то первой его головкой все равно будет головка 0!

На уровне файловой системы операционная система адресует диск кластерами (cluster). Каждый кластер образован непрерывной последовательностью секторов, количество которых равно степени двойки (1, 2, 4, 8, …). Размер кластера задается на этапе форматирования диска и в дальнейшем уже не меняется. Основное назначение кластеров — уменьшение фрагментации файлов и уменьшение разрядности служебных файловых структур. В частности, FAT 16 нумерует кластеры двойными словами, и потому может адресовать не более

10000h*sizeof(cluster)
дискового пространства. Легко видеть, что уже на 80-гигабайтном диске размер кластера составляет 1 Мбайт, и десяток файлов, каждый из которых имеет размер 1 байт, займут 10 Мбайт! Это впечатляет, не правда ли? Файловая система NTFS, оперирующая 64-битными величинами, не страдает подобными ограничениями, и типичная величина кластера, выбираемая по умолчанию, составляет всего 4 сектора. В отличие от секторов, кластеры нумеруются, начиная с нуля.

Главная загрузочная запись

Первые жесткие диски имели небольшой размер и форматировались практически так же, как и дискеты. Однако их объемы стремительно росли, и MS- DOS была уже не в состоянии полностью их адресовать. Для преодоления этого ограничения был введен механизм разделов (partitions), позволяющий разбивать один физический диск на несколько логических. Каждый из логических дисков имеет собственную файловую систему и форматируется независимо от других. За счет чего это достигается?

В первом секторе физического диска (цилиндр 0/головка 0/сектор 1) хранится специальная структура данных — главная загрузочная запись (Master Boot Record, MBR). Она состоит из двух основных частей — первичного загрузчика (master boot code) и таблицы разделов (partition table), описывающей схему разбиения и геометрию каждого из логических дисков. Схематичное изображение жесткого диска, разбитого на разделы, представлено на рис. 5.1. В конце сектора по смещению

1FE
находится сигнатура
55h AAh
, по которой BIOS определяет признак "загрузочности" сектора. Даже если вы не хотите дробить свой винчестер на части и форматируете его как один диск, присутствие MBR обязательно.

Рис. 5.1. Схематичное представление жесткого диска, разбитого на разделы

При старте компьютера BIOS выбирает загрузочный диск. Как правило, это Primary Master, но порядок загрузки в большинстве современных реализаций BIOS можно изменять. Наиболее продвинутые реализации даже выводят интерактивное меню при нажатии и удержании клавиши во время прохождения процесса первоначального тестирования при включении (Power- On Self-Test, POST). Затем BIOS считывает первый сектор (цилиндр 0/головка 0/сектор 1) в память по адресу

0000h:7C00h
, проверяет наличие сигнатуры
55h AAh
в его конце, и, если такая сигнатура действительно обнаруживается, передает управление по адресу
0000h:7C00h
. В противном случае анализируется следующее загрузочное устройство, а в случае его отсутствия выдается сообщение об ошибке.

Первичный загрузчик, получив управление, сканирует уже загруженную в память таблицу разделов, находит активный раздел (

Boot indicator == 80h
), извлекает номер стартового сектора раздела, так же называемого загрузочным сектором (boot-sector). Затем загрузчик перемещает свое тело по другому адресу, чтобы избежать затирания, загружает boot-сектор в память по адресу
0000h:7C00h
, убеждается в наличии сигнатуры
55h AAh
и передает управление на
0000h:7C00h
, в противном случае выдается сообщение об ошибке, и после нажатия на любую клавишу компьютер перезагружается. Ряд нестандартных загрузчиков, выходящих за стандартные спецификации Microsoft, поддерживают несколько активных разделов, последовательно перебирая их один за другим.

Если первичный загрузчик поврежден, то BIOS не сможет запустить операционную систему с такого диска, однако при подключении его "вторым" (или при загрузке с дискеты) все логические диски будут доступны. Как минимум, они должны быть "видимы", то есть команды

C:
,
D:
,
E:
должны выполняться нормально, хотя работоспособность команды
dir
уже не гарантируется. Для того чтобы это было именно так, необходимо соблюдение следующих двух условий:

1. Во-первых, файловая система соответствующего раздела должна быть известна загруженной операционной системе и не повреждена.

2. Во-вторых, загрузочный сектор должен быть в целости и сохранности (данный вопрос будет обсуждаться далее в этой главе).

Таблица разделов, которую анализирует первичный загрузчик (master boot code), а чуть позже — драйвер логических дисков операционной системы, состоит из четырех записей размером по

10h
каждая, расположенных по смещениям
1BEh
,
1CEh
,
1DEh
, и
1EEh
байт от начала диска соответственно. Каждая из них описывает свой логический раздел, задавая его стартовый и конечный сектора, записанные в формате CHS.

Внимание!

Даже если диск работает в режиме LBA, разделы все равно адресуются через CHS!

Поле относительного смещения раздела, отсчитываемое от начала таблицы разделов, является вспомогательным, и его избыточность очевидна. То же самое относится и полю, содержащему значение общего количества секторов на диске, так как очевидно, что это значение может быть вычислено на основе стартового и конечного секторов. Одни операционные системы и загрузчики игнорируют вспомогательные поля, другие же их активно используют. Именно поэтому содержимое этих полей должно соответствовать действительности.

Поле идентификатора диска содержит уникальную 32-разрядную последовательность, помогающую операционной системе отличить один смонтированный диск от другого, и автоматически копируемую в следующий ключ реестра:

HKLM\SYSTEM\MountedDevices
. На самом деле Windows свободно обходится и без него, поэтому содержимое данного поля некритично.

Поле Boot ID содержит идентификатор файловой системы, установленной на разделе. В случае NTFS этот идентификатор равен

07h
. За динамическими дисками, согласно фирменной спецификации, закреплен идентификатор
42h
.

На практике это справедливо лишь для тех из них, которые были получены путем обновления (update) обычного (basic) раздела до динамического (dynamic) тома. Сведения об остальных динамических дисках в таблице разделов не хранятся, а содержатся в последнем мегабайте физического диска в базе данных менеджера логических дисков (Logical Disk Manager, LDM). Для стандартных дисковых менеджеров эта информация недоступна. При установке операционной системы семейства Windows 9x или одного из клонов UNIX на винчестер, содержащий динамические диски, они могут быть необратимо утеряны, так как, согласно таблице разделов, занятое ими пространство помечено как свободное. Тем не менее, загрузочный логический диск (независимо от того, динамический он или нет) в обязательном порядке должен присутствовать в таблице разделов, иначе BIOS не сможет его загрузить.

Четыре записи таблицы разделов позволяют иметь всего четыре логических диска (см. рис. 5.1). Этого явно недостаточно, но расширение таблицы разделов оказалось невозможным, так как последняя запись упирается в конец сектора. Разработчики сочли нежелательным использовать следующий сектор, поскольку он активно используется многими вирусами и нестандартными драйверами. К тому же, это все равно не позволяет решить проблему радикально, а лишь оттягивает неизбежный конец. Тогда инженеры нашли другое решение, предложив концепцию расширенных разделов (Extended partition). Если значение индикатора загрузки (

boot ID
) некоторого раздела равно
05h
или
0Fh
, то такой раздел трактуется как "виртуальный физический диск", с собственной таблицей разделов, расположенной в его начале, на которую и указывает стартовый сектор расширенного раздела (рис. 5.2). Иначе говоря, таблица разделов получается вложенной, и уровень вложения ограничен разве что свободным дисковым пространством и объемом стековой памяти загрузчика (при условии, что он использует рекурсивный алгоритм сканирования). Таким образом, таблица разделов как бы "размазывается" вдоль винчестера (рис. 5.3). Большинство утилит резервирования сохраняют лишь первый сектор, чего явно недостаточно (впрочем, первый сектор гибнет намного чаще других, так что даже плохая политика резервирования лучше, чем совсем ничего).

Рис. 5.2. Структурная схема типичного жесткого диска, содержащая главные (primary) и расширенные (extended) разделы

Рис. 5.3. Расширенная таблица разделов

Штатные утилиты для разбиения диска на разделы (FDISK.EXE, Disk Manager) при создании логических дисков на расширенном разделе создают расширенную таблицу разделов с четырьмя записями: одна используется для описания логического раздела, вторая описывает еще один (следующий) логический раздел, а две не используются. Таким образом, получается "цепочка" таблиц разделов, в которой первая таблица разделов описывает от одного до трех основных (primary) разделов, а каждая следующая — соответствующий ей логический диск и положение следующей таблицы разделов (рис. 5.3).

Таким образом, при разбиении винчестера на четыре логических диска на нем образуются четыре таблицы разделов (см. листинг 5.4), хотя в данном случае можно было бы обойтись и одной. Штатный загрузчик требует, чтобы активный раздел описывался первой записью первой таблицы разделов, вследствие чего операционная система может грузиться только с диска С:. Нестандартные менеджеры загрузки, анализирующие всю цепочку разделов, позволяют загружаться с любого из разделов. Самые честные из них создают в первой таблице разделов еще один раздел (благо, если диск был разбит с помощью программы FDISK, то свободное место там всегда есть), назначают его активным и помещают в него свое тело. Другие же внедряются непосредственно в MBR и замещают собой первичный загрузчик, что создает очевидные проблемы совместимости.

Листинг 5.4. Пример таблицы разделов, сформированной программой FDISK

Sector Inspector Copyright Microsoft Corporation 2003

==================================================================

Target - \\.\PHYSICALDRIVE0

         1867 Cylinders

          255 Heads

           63 Sectors Per Track

          512 BytesPerSector

           12 MediaType


LBN 0 [С 0, H 0, S 1]

==================================================================

                     Master Boot Record

==================================================================

| B | FS TYPE |     START    |      END     |          |         |

| F | (hex)   |   C    H    S|   C    H    S| RELATIVE |  TOTAL  |

==================================================================

| * |   07    |   0    1    1| 764  254   63|        63| 12289662|

|   |   0f    | 765    0    1|1023  254   63|  12289725| 17687565|

|   |   00    |   0    0    0|   0    0    0|         0|        0|

|   |   00    |   0    0    0|   0    0    0|         0|        0|

==================================================================


LBN 12289725 [C 765, H 0, S 1]

==================================================================

                  Extended Boot Record

==================================================================

| B | FS TYPE |    START     |     END      |          |         |

| F | (hex)   |   C    H    S|   C    H    S| RELATIVE |  TOTAL  |

==================================================================

|   |   07    | 765    1    1|1023  254   63|        63|  8193087|

|   |   05    |1023    0    1|1023  254   63|   8193150|  4096575|

|   |   00    |   0    0    0|   0   0     0|         0|        0|

|   |   00    |   0    0    0|   0   0     0|         0|        0|

==================================================================


LBN 20482875 [C 1275, H 0, S 1]

==================================================================

                  Extended Boot Record

==================================================================

| B | FS TYPE |    START     |     END      |          |         |

| F | (hex)   |   C    H    S|   C    H    S| RELATIVE |  TOTAL  |

==================================================================

|   |   07    |1023    1    1|1023  254   63|        63|  4096512|

|   |   05    |1023    0    1|1023  254   63|  12289725|  5397840|

|   |   00    |   0    0    0|   0    0    0|         0|        0|

|   |   00    |   0    0    0|   0    0    0|         0|        0|

==================================================================


LBN 24579450 [С 1530, H 0, S 1]

==================================================================

                  Extended Boot Record

==================================================================

| B | FS TYPE |    START     |     END      |          |         |

| F | (hex)   |   C    H    S|   C    H    S| RELATIVE |  TOTAL  |

==================================================================

|   |   07    |1023    1    1|1023  254   63|        63|  5397777|

|   |   00    |   0    0    0|   0    0    0|         0|        0|

|   |   00    |   0    0    0|   0    0    0|         0|        0|

|   |   00    |   0    0    0|   0    0    0|         0|        0|

==================================================================

Если таблица разделов повреждена, логические диски, скорее всего, будут полностью недоступны — они не будут отображаться ни Проводником Windows (Windows Explorer), ни файловым менеджером FAR, а команда

C:
вызовет ошибку. Искажение таблицы разделов не приводит к немедленному изменению объема уже отформатированных томов, так как эта информация хранится в загрузочном секторе (boot sector). Однако при последующим переформатировании произойдет затирание данных из соседнего раздела, или же текущий раздел окажется усеченным. Кстати говоря, если расширенный раздел указывает сам на себя или на один из предшествующих разделов в цепочке, то все известные мне операционные системы наглухо зависнут еще на этапе загрузки, даже если диск подключен "вторым". Чтобы исправить ситуацию, необходимо запустить редактор диска или другую утилиту, а для этого необходимо загрузить операционную систему! Существует несколько путей выхода из этой, казалось бы, неразрешимой ситуации. Самый простой вариант — горячее подключение диска "на лету" с последующей работой с ним через BIOS или порты ввода/вывода. Если и диск, и материнская плата переживут это (а для устройств IDE подключение "на лету" представляется довольно жестким испытанием), то вы сможете запустить доктора и работать с диском на физическом уровне. Другой, чисто хакерский, путь — пропатчить MS-DOS, изменив сигнатуру
55h AAh
на какое-нибудь другое значение, тогда она не сможет распознать таблицу разделов и, соответственно, не станет ее анализировать. Как вариант, можно записать в boot-сектор дискеты специально подготовленную программу, которая обнуляет MBR или искажает сигнатуру, расположенную в его конце. Просто загрузитесь с нее и все!

Воспользовавшись любым редактором диска (например, Microsoft Disk Probe из комплекта Resource Kit), считаем первый сектор физического диска. Он должен выглядеть приблизительно так, как показано на рис. 5.4.

Рис. 5.4. Внешний вид MBR

Не правда ли, MBR выглядит как знаменитая Матрица? Ее формат кратко описан в таблице 5.1.


Таблица 5.1. Формат MBR

СмещениеРазмерОписание
0x000
перемен.Код загрузчика
0x1BB
4h
Идентификатор диска
0x1BE
10h
Partition 1
0x1CE
10h
Partition 2
0x1DE
10h
Partition 3
0x1EE
10h
Partition 4
0x1FE
0x2
"Магическое число" — сигнатура
55h AAh
, которое указывает, что данный сектор представляет собой MBR

Первые

1BBh
байт занимают код и данные загрузчика, среди которых отчетливо выделяются текстовые строки.

Примечание

Кстати говоря, локализовав сообщения загрузчика в национальных версиях Windows, например, в русской, Microsoft допустила грубейшую стратегическую ошибку. Ведь в BIOS нет никаких кириллических шрифтов, поэтому русские символы выглядят бессмысленной абракадаброй.

По смещению

1BBh
расположен четырехбайтовый идентификатор диска, принудительно назначаемый Windows при запуске Disk Manager. Коварство Microsoft не знает границ! Еще со времен первых IBM PC (тогда они назывались XT) загрузчик владел первыми
1BEh
байтами MBR, и достаточно многие загрузчики (и вирусы!) использовали эти байты на полную катушку. Нетрудно сообразить, что произойдет, если внутрь загрузчика вдруг запишется идентификатор. Это убьет его! Поэтому байты
1BBh
1BEh
лучше не трогать.

Со смещения

1BEh
начинается таблица разделов, представляющая собой массив из четырех записей типа
partition
. Каждая из этих записей описывает свой логический диск, что позволяет нам создавать до четырех разделов на каждом HDD. Формат записи таблицы разделов представлен в табл. 5.2. Динамические диски, впервые появившиеся в Windows 2000, хранятся в базе данных Менеджера Логических Дисков (Logical Disk Manager Database), и в таблице разделов присутствовать не обязаны.


Таблица 5.2. Формат записи таблицы разделов

СмещениеРазмерОписание
000
1ВЕ
1CE
1DE
1EE
byte
Флаг активного загрузочного раздела (Boot Indicator).
80h
— загрузочный раздел,
00h
— незагрузочный раздел
001
1BF
1CF
1DF
1EF
Стартовая головка раздела
002
1C0
1D0
1E0
1F0
byte
Стартовый сектор раздела (биты 0–5). Старшие биты стартового цилиндра (биты 6–7)
003
1C1
1D1
1E1
1F1
byte
Младшие биты стартового цилиндра (биты 0–7)
004
1C2
1D2
1E2
1F2
byte
Идентификатор системы (Boot ID), см. табл. 5.3
005
1C3
1D3
1E3
1F3
byte
Конечная головка раздела
006
1С4
1D4
1E4
1F4
byte
Конечный сектор раздела (биты 0–5). Старшие биты конечного цилиндра (биты 6–7)
007
1C5
1D5
1E5
1F5
Младшие биты конечного цилиндра (биты 0–7)
008
1C6
1D6
1E6
1F6
dword
Смещение раздела относительно начала таблицы разделов в секторах
00C
1CA
1DA
1EA
1FA
dword
Количество секторов раздела

Таблица 5.3. Возможные значения Boot ID

Boot IDТип раздела
00h
Раздел свободен
0x01
Раздел FAT12 (менее чем 32 680 секторов в томе или 16 Мбайт)
0x04
Раздел FAT16 (32 680–65 535 секторов или 16–33 Мбайт)
0x05
Расширенный раздел (extended partition)
0x06
Раздел BIGDOS FAT16 (33 Мбайт–4 Гбайт)
0x07
Раздел NTFS
0x0B
Раздел FAT32
0x0C
Раздел FAT32 с поддержкой расширенной BIOS
INT 13h
0x0E
Раздел BIGDOS FAT16 с поддержкой расширенной BIOS
INT 13h
0x0F
Расширенный раздел с поддержкой расширенной BIOS
INT 13h
0x12
Раздел EISA
0x42
Динамический диск
0x86
Раздел legacy FT FAT16
0x87
Раздел legacy FT NTFS
0x8B
Наследуемый отказоустойчивый том, отформатированный для FAT32 (Legacy FT volume formatted with FAT32)
0x8C
Наследуемый отказоустойчивый том с поддержкой BIOS
INT 13h
, отформатированный для FAT32 (Legacy FT volume using BIOS
INT 13h
extensions formatted with FAT32)

Техника восстановления главной загрузочной записи

Существует множество утилит для автоматического восстановления первичного загрузчика и таблицы разделов, к числу которых относятся, например, GetDataBack, Easy Recovery, Active@Data Recovery Software и др. До поры до времени они вполне успешно справлялись со своей задачей, восстанавливая даже полностью уничтоженные таблицы разделов, однако с появлением емких дисков, преодолевших барьер в 2 Гбайт с помощью всевозможных расширений, они стали часто путаться. Поэтому и доверять им больше нельзя. Если не хотите потерять свои данные — восстанавливайте MBR самостоятельно (тем более что это достаточно простая операция, не требующая особой квалификации). Восстановление значительно упрощается, если в вашем распоряжении имеется копия таблицы разделов, снятая с помощью Sector Inspector или любой другой подобной утилиты. К сожалению, чаще всего ее под рукой не оказывается…

Если операционная система отказывается загружаться, а на экране появляется сообщение BIOS, выглядящее примерно следующим образом:

Disk Boot failure, Non-System disk or disk error...

Press  to restart
то это указывает на разрушение сигнатуры
55h AAh
, обычно сопровождаемое смертью первичного загрузчика.

Примечание

Очень важно отличать сообщение BIOS от сообщений первичного загрузчика и загрузочного сектора. Зайдите в BIOS Setup и отключите все загрузочные устройства, оставив активным только диск

A:
(и не забудьте извлечь из него дискету). А теперь перезагрузитесь и запомните, какое сообщение появится на экране. Это и будет "ругательством" BIOS.

Восстановить сигнатуру

55h AAh
можно в любом дисковом редакторе. Когда будете это делать, убедитесь, что в начале диска присутствует осмысленный код первичного загрузчика (master boot code).

Рекомендация

Если вы испытываете затруднение с дизассемблированием в уме, воспользуйтесь IDA PRO или HIEW. Вы не умеете дезассемблировать? Тогда попробуйте оценить степень "нормальности" первичного загрузчика визуально (однако для этого опять-таки требуется опыт работы с кодом). В начале более или менее стандартного загрузчика расположено приблизительно

100h
байт машинного кода, в котором обнаруживаются последовательности:
00 7C
,
1B 7C
,
BE 07
,
CD 13
,
CD 18
,
CD 10
,
55 AA
, а затем идут характерные текстовые сообщения:
Invalid partition table
,
Error loading operating system
,
Missing operating system
(см. рис. 5.4). Если загрузчик поврежден, но сигнатура
55 AA
цела, то попытка загрузки с такого диска обернется неизменным зависанием.

Восстановить искореженный первичный загрузчик можно с помощью утилиты FDISK.EXE, запущенной с ключом

/MBR
, записывающей в главную загрузочную запись первого диска стандартный код первичного загрузчика (master boot code). Недокументированный ключ
/CMBR
, появившийся в MS-DOS 7.0, позволяет выбирать любой из подключенных дисков. В Windows 2000 и более новых версиях этого же результата можно добиться, загрузив консоль восстановления и дав команду
FIXMBR
.

Внимание!

Если вы использовали нестандартный загрузчик (например, LILO), то после перезаписи MBR сможете загружаться только с основного раздела, а для запуска операционных систем из других разделов вам придется переустановить свой мультизагрузочный менеджер. Кстати говоря, такой менеджер можно написать и самостоятельно. При наличии HIEW, а еще лучше — транслятора ассемблера — работа не займет и получаса.

Как уже говорилось, некоторые загрузчики изменяют схему трансляции адресов жесткого диска, поэтому со штатным загрузчиком такой диск окажется неработоспособен. Попробуйте переустановить загрузчик с дистрибутивных дисков — быть может, это поможет. В противном случае ничего не остается, как писать свой собственный загрузчик, определять текущую геометрию диска и соответствующим образом транслировать секторные адреса. Это — довольно сложная задача, требующая серьезной подготовки, и здесь ее лучше не обсуждать.

Если загрузчик выводит сообщение

Invalid partition table
, то это еще не значит, что таблица разделов действительно повреждена. Вполне возможно, что на самом деле таблица разделов цела, но просто ни один из основных разделов не назначен активным. Такое случается при использовании нестандартных загрузчиков, загружающих операционную систему из расширенного раздела. После выполнения команды
FDISK /MBR
или при установке операционной системы, автоматически заменяющий первичный загрузчик своим собственным, этот новый загрузчик не обнаружит в пределах досягаемости ни одного активного раздела, и, что вполне естественно, сигнализирует вам об этом. Такое поведение, в частности, характерно для Windows 98. Для решения проблемы либо восстановите прежний загрузчик, либо установите операционную систему на первичный раздел и, запустив FDISK, сделайте его активным.

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

Восстановление основного раздела, созданного с помощью FDISK или Disk Manager, в большинстве случаев осуществляется элементарно, а остальные, как правило, восстанавливать и не требуется, поскольку именно MBR гибнет чаще всего, а расширенные разделы, рассредоточенные по всему диску, погибают разве что при явном удалении разделов средствами FDISK или Disk Manager.

Адрес стартового сектора первого логического диска всегда равен 0/1/1 (Cylinder/Head/Sector), относительный (Relative) сектор — количеству головок жесткого диска, уменьшенному на единицу.

Рекомендация

Сведения о геометрии диска можно почерпнуть из любого дискового редактора — например, Sector Inspector.

Конечный сектор определить несколько сложнее. Если загрузочный сектор цел (более подробно этот вопрос будет обсуждаться далее в этой главе), то узнать количество секторов в разделе (total sectors) можно на основании значения поля

BootRecord.NumberSectors
, увеличив его значение на единицу. Тогда номер конечного цилиндра будет равен
LastCyl := Total Sectors/(Heads*SecPerTrack)
, где
Heads
— количество головок на физическом диске, a
SecPerTrack
— количество секторов на трек. Номер конечной головки равен
LastHead := (Total Sector - (LastCyl*Heads SecPerTrack))/SecPerTrack
, а номер конечного сектора равен
LastSec := (Total Sector - (LastCyl*Heads SecPerTrack)) % SecPerTrack
. Пропишите полученные значения в MBR и проверьте, не находится ли за вычисленным концом раздела следующий раздел? Это должна быть либо расширенная таблица разделов, либо загрузочный сектор. Если это так, создайте еще одну запись в таблице разделов, заполнив ее соответствующим образом.

А теперь зададимся вопросом; возможно ли восстановить таблицу разделов, если загрузочный сектор отсутствует, и восстановить его не представляется возможным? Это — вполне реалистичная задача. Необходимо лишь найти загрузочные сектора или расширенные таблицы разделов, принадлежащие последующим разделам. В этом вам поможет контекстный поиск. Ищите сектора, содержащие сигнатуру

55h AAh
в конце. Отличить загрузочный сектор от расширенной таблицы разделов очень просто. В загрузочном секторе по смещению три байта от его начала расположен идентификатор производителя (
OEM ID
), например,
NTFS
,
MSWIN4.1
и т.д. Размер текущего раздела будет на один сектор меньше. Теперь, зная размер и геометрию диска, можно рассчитать и конечный цилиндр/головку/сектор.

Имейте в виду, что Windows хранит копию загрузочного сектора, которая, в зависимости от версии, может быть расположена либо в середине раздела, либо в его конце. Другие копии могут находиться в архивных файлах и файле подкачки. Как отличить копию сектора от оригинала? Элементарно, Ватсон! Если это подлинник, то вслед за ним пойдут служебные структуры файловой системы (в частности, для NTFS это будет MFT, каждая запись которой начинается с легко узнаваемой строки

FILE*
). К счастью, служебные структуры файловой системы обычно располагаются на более или менее предсказуемом смещении относительно начала раздела, и, отталкиваясь от их "географического" расположения, мы можем установить размеры каждого из логических дисков, даже если все-все-все загрузочные сектора и расширенные таблицы разделов уничтожены.

Что произойдет, если границы разделов окажутся определенными неверно? Если мы переборщим, увеличив размер раздела сверх необходимого, все будет нормально работать, поскольку карта свободного пространства хранится в специальной структуре (у NTFS это файл

$bitmap
, а у FAT 12/32 — непосредственно сама FAT) и "запредельные" сектора будут добавлены только после переформатирования раздела. Если все что нам нужно — это скопировать данные с восстанавливаемого диска на другой носитель, то возиться с подгонкой параметров таблицы разделов не нужно! Распахните ее на весь физический диск и дело с концом!

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

$mft/$mftmirr
содержат номер своего первого кластера. Стоит нам найти первую запись
FILE*
, как мы узнаем, на каком именно секторе мы сейчас находимся (конечно, при условии, что сумеем определить количество секторов на кластер, но это уже другая тема, которая более подробно будет обсуждаться далее в этой главе).

Проблема нулевой дорожки

Главная загрузочная запись жестко держит за собой первый сектор, и если он вдруг окажется разрушенным, работа с таким диском станет невозможной. Внешний вид типичного сектора MBR приведен в листинге 5.5. До недавнего времени проблема решалась посекторным копированием винчестера, переносом данных на здоровый жесткий диск с идентичной геометрией и последующим восстановлением MBR.

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

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

Листинг 5.5. Внешний вид типичного сектора MBR

0x0000 eb 2e 49 50 41 52 54 20-63 6f 64 65 20 30 30 39 ы.IPART code 009

0x0010 20 2d 20 49 6f 6d 65 67-61 20 43 6f 12 70 6f 72  - Iomega Corpor

0x0020 61 74 69 6f 6e 20 2d 20-31 31 2f 32 33 2f 39 30 ation - 11/23/90

0x0030 fa fc 8c c8 8e d0 be 00-7c 8e d8 8e c0 b9 00 02 ·№М╚О╨╝.|О╪О└╣..

0x0040 bf 00 7e be 00 7c f3 a4-e9 00 02 fb bd 00 7e 8b ┐.~╛.|єдщ..√╜.~Л

0x0050 fd be be 01 b9 04 00 80-3a 80 74 0b 83 c6 10 e2 ¤╛╛.╣..А:Аt.Г╞.т

0x0060 f6 8b b5 b2 01 eb 51 56-83 c6 10 49 e3 0b 80 3a ЎЛ╡▓.ыQVГ╞.Iу.А:

0x0070 80 75 f5 8b b5 b0 01 eb-3f 5e 56 8a 12 8a 72 01 АuїЛ╡░.ы?^VК.Кr.

0x0080 8a 4a 02 8a 6a 03 bb 00-7c be 05 00 56 b8 01 02 КJ.Кj.╗.|╛..V╕..

0x0090 cd 13 73 0e 33 c0 cd 13-5e 4e 75 f0 8b b5 b4 01 ═.s.3└═.^NuЁЛ╡┤.

0x00a0 eb 16 5e be fe 7d 81 3c-55 aa 74 06 8b b5 b6 01 ы.^╛■}Б

0x00b0 eb 06 5e 03 f5 e9 48 fd-e8 1b 00 8b b5 b8 01 e8 ы.^.їщH¤ш..Л╡╕.ш

0x00c0 14 00 b4 00 cd 16 33 c0-8е c0 26 c7 06 72 04 34 ..┤.═.3└О└&╟.r.4

0x00d0 12 ea f0 ff 00 f0 03 f5-ac 3c 00 74 0b 56 b4 0e .ъЁ .Ё.їм<.t.V┤.

0x00e0 bb 07 00 cd 10 5e eb f0-c3 49 6e 76 61 6c 69 64 ╗..═.^ыЁ├Invalid

0x00f0 20 70 61 72 74 69 74 69-6f 6e 20 74 61 62 6c 65  partition table

0x0100 00 44 69 73 6b 20 69 73-20 6e 6f 74 20 62 6f 6f .Disk is not boo

0x0110 74 61 62 6c 65 00 45 72-72 6f 72 20 6c 6f 61 64 table.Error load

0x0120 69 6e 67 20 6f 70 65 72-61 74 69 6e 67 20 73 79 ing operating sy

0x0130 73 74 65 6d 00 4d 69 73-73 69 6e 67 20 6f 70 65 stem.Missing ope

0x0140 72 61 74 69 6e 67 20 73-79 73 74 65 6d 00 0d 0a rating system...

0x0150 52 65 70 6c 61 63 65 20-61 6e 64 20 73 74 72 69 Replace and stri

0x0160 6b 65 20 61 6e 79 20 6b-65 79 20 77 68 65 6e 20 ke any key when 

0x0170 72 65 61 64 79 0d 0a 00-00 00 00 00 00 00 00 00 ready...........

0x0180 00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00 ................

0x0190 00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00 ................

0x01a0 00 00 00 00 00 00 00 00-00 00 00 00 00 00 45 06 ..............E.

0x01b0 e9 00 01 01 16 01 35 01-4e 01 6a 72 a5 d5 00 00 щ.....5.N.jrе╒..

0x01c0 00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00 ................

0x01d0 00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00 ................

0x01e0 00 00 00 00 00 00 00 00-00 00 00 00 00 00 80 01 ..............A.

0x01f0 01 00 06 3f 20 5f 20 00-00 00 e0 ff 02 00 55 aa ...? _ ...p ..Uk

Создаем MBR и пишем свой менеджер мультизагрузки

В этом разделе я расскажу, как написать собственный менеджер мультизагрузки. Менеджер мультизагрузки представляет собой код, находящийся в загрузочном секторе, и по выбору пользователя загружающий любую из нескольких операционных систем, установленных на компьютере. В процессе обсуждения вы познакомитесь с прерыванием

INT 13h
, таблицей разделов и т.д. Стандартный загрузчик, устанавливаемый большинством операционных систем по умолчанию, слишком примитивен, чтобы его воспринимать всерьез, а нестандартные загрузчики от независимых разработчиков обычно слишком неповоротливы и ненадежны. Вот и давайте напишем свой! Пока мы будем его писать, мы познаем дао и дзен ассемблера, научимся отлаживать программы без отладчика и поближе познакомимся с низкоуровневыми интерфейсами винчестера.

Интерфейс INT 13h

Управлять дисками можно как через порты ввода/вывода, так и через BIOS. Порты намного более могущественны и интересны, однако BIOS программируется намного проще, к тому же она поддерживает большое количество разнокалиберных накопителей, абстрагируясь от конструктивных особенностей каждой конкретной модели. Поэтому будем действовать через нее, а точнее, через интерфейс прерывания

INT 13h
.

Попробуем прочитать сектор с диска в режиме CHS. Действовать нужно из самой MBR или из "голой" MS-DOS, иначе у нас ничего не получится, ведь Windows NT блокирует прямой доступ к диску даже из режима эмуляции MS-DOS.

Номер функции заносится в регистр

AH
. В случае чтения он равен двум. Регистр
AL
отвечает за количество обрабатываемых секторов. Так как мы собираемся читать по одному сектору за операцию, занесем сюда единицу. Регистр
DH
хранит номер головки, a
DL
— номер привода (
80h
 — первый жесткий диск,
81h
— второй и т.д.). Пять младших битов регистра
CL
задают номер сектора, оставшиеся биты регистра
CL
и восемь битов регистра
CH
определяют номер цилиндра, который мы хотим прочитать. Регистровая пара
ES:BX
указывает на адрес буфера-приемника. Вот, собственно говоря, и все. После выполнения команды
INT 13h
считываемые данные окажутся в буфере, а если произойдет ошибка (например, головка "споткнется" о BAD-сектор), то BIOS установит флаг переноса (carry flag), и мы будем вынуждены либо повторить попытку, либо вывести грустное сообщение на экран.

Код этой программы на языке ассемблера представлен в листинге 5.6.

Листинг 5.6. Код, считывающий загрузочный сектор или расширенную таблицу разделов

MOV SI, 1BEh ; Перейти к первому разделу

MOV AX, CS   ; Настраиваем ES

MOV ES, AX

MOV BX, buf  ; Смещение буфера

...

read_all_partitions:

 MOV AX, bud            ; Читать 1 сектор с диска

 MOV DL, 80h            ; Читать с первого диска

 MOV DH, [SI+1]         ; Стартовый номер головки

 MOV CX, [SI+2]         ; Стартовый сектор с цилиндром INT 13h

 JC error               ; Ошибка чтения


 ;Обрабатываем считанный boot-сектор или расширенную таблицу разделов

 ;===================================================================

 ;

 CMP byte [SI], 80h

 JZ LOAD_BOOT            ; Это загрузочный сектор

                         ; Передаем на него управление


 CMP byte [SI+4], 05h

 JZ LOAD_CHS_EXT         ; Это расширенная таблица разделов

                         ; в формате CHS


 CMP byte [SI+4], 0Fh

 JZ LOAD_LBA_EXT         ; Это расширенная таблица разделов

                         ; в формате LBA


 ADD SI, 10h             ; Переходим на следующий раздел

 CMP SI, 1EEh

 JNA read_all_partitions ; Читаем все разделы один за другим

...
buf rb 512               ; Буфер на 512 байт

Запись сектора в режиме CHS происходит практически точно так же, только регистр

AH
равен не
02h
, a
03h
. С режимом LBA разобраться намного сложнее, но мы, как настоящие хакеры, его обязательно осилим.

Чтение сектора осуществляется функцией

42h
(
AH = 42h
). В регистр
DL
, как и прежде, заносится номер привода, а вот регистровая пара
DS:SI
указывает на адресный пакет (disk address packet), представляющий собой продвинутую структуру формата, описанного в табл. 5.4.


Таблица 5.4. Формат адресного пакета, используемый для чтения и записи секторов в режиме LBA

СмещениеТипОписание
00h
BYTE
Размер пакета —
10h
или
18h
01h
BYTE
Поле зарезервировано и должно быть равно нулю
02h
WORD
Сколько секторов читать
04h
DWORD
32-разрядный адрес буфера-приемника в формате
seg:offs
08h
QWORD
Стартовый номер сектора для чтения
10h
QWORD
64-разрядный плоский адрес буфера-приемника. Используется только в случае, если 32-разрядный адрес равен
FFFF:FFFF

Код, читающий сектор в режиме LBA, в общем случае выглядит так, как показано в листинге 5.7.

Листинг 5.7. Код, осуществляющий чтение сектора с диска в режиме LBA

MOV DI, 1BEh      ; Перейти к первому разделу

MOV AX, CS        ; Настраиваем...

MOV buf_seg       ; ...сегмент

MOV EAX, [DI+08h] ; Смещение partition относительно

                  ; начала раздела

ADD EAX, EDI      ; EDI должен содержать номер сектора

                  ; текущего MBR

MOV [X_SEC]       ;

...

read_all_partitions:

 MOV АН, 42h      ; Читать сектор в режиме LBA

 MOV DL, 80h      ; Читать с первого диска

 MOV SI, dap      ; Смещение адресного пакета INT 13h

 JC error         ; Ошибка чтения


...

dap:

packet_size db 10h ; размер пакета 10h байт

reserved    db 00h ; "Заначка" для будущих расширений

N_SEC       dw 01h ; Читаем один сектор

buf_seg     dw 00h ; Сюда будет занесен сегмент буфера-приемника

buf_off     dw buf ; Смещение буфера-приемника

X_SEC       dd 0   ; Сюда будет занесен номер сектора для чтения

dd 0               ; Реально не используемый хвост

                   ; 64-битного адреса

buf rb 512         ; Буфер на 512 байт

Запись осуществляется аналогично чтению, только регистр

AH
содержит не
42h
, a
43h
. Регистр
AL
определяет режим: если бит 0 равен 1, BIOS выполняет не запись, а ее эмуляцию. Бит 2, будучи взведенным, задействует запись с проверкой. Если регистр
AL
равен 0, выполняется обыкновенная запись по умолчанию.

Теперь, освоившись с дисковыми прерываниями, перейдем к обсуждению остальных аспектов программирования.

Создаем код загрузчика

Лучше всего загрузчики программируются на FASM. С точки зрения ассемблера загрузчик представляет собой обыкновенный двоичный файл, предельно допустимый объем которого составляет

1BBh
(443) байт. Немного? Но не будем спешить с выводами. Всякий раздел всегда начинается с начала цилиндра, а это значит, что между концом MBR и началом раздела имеется, по меньшей мере, n свободных секторов, где
n == sectors per track
. Практически все современные винчестеры имеют по 64 сектора на дорожку, что дает нам:
443 + 63*512 == 32 699
байт или приблизительно 32 Кбайт. Да в этот объем даже графический интерфейс с мышью уместить можно! Однако делать этого мы не будем. Настоящие хакеры работают в текстовом режиме с командной строкой.

Как уже говорилось, BIOS загружает MBR по адресу

7C00h
, поэтому в начале ассемблерного кода должна стоять директива
ORG 7C00h
, а еще —
USE16
, ведь загрузчик выполняется в 16-разрядном реальном режиме. Позже, при желании, он может перейти в защищенный режим, но это будет уже потом. Не будем лезть в такие дебри.

Обнаружив загрузочный раздел (а обнаружить это можно по флагу

80h
, находящемуся по нулевому смещению от начала раздела), загрузчик должен считать первый сектор этого раздела, поместив его в памяти по адресу
0000:7C00h
, то есть в точности поверх своего собственного тела. А вот это уже нехорошо! И чтобы не вызвать крах системы, загрузчик должен заблаговременно перенести свое тело по другому адресу, что обычно осуществляется командой
MOVSB
. Копироваться можно по любому из адресов памяти — от
0080:0067h
до
9FE00h
. Память, расположенную ниже
0080:0067h
, лучше не трогать, так как здесь находятся вектора прерываний и системные переменные BIOS, а от
A000h
и выше начинается область отображения ПЗУ, так что предельно доступный адрес равен
A000h - 200h (размер сектора) == 9FE00h
.

Не забывайте, что трогать регистр

DL
ни в коем случае нельзя, поскольку в нем передается номер загрузочного привода. Некоторые загрузчики содержат ошибку, всегда загружаясь с первого жесткого диска, и это в то время, как BIOS уже больше 10 лет как позволяют менять порядок загрузки, и потому загрузочным может быть любой привод.

По правде говоря, FASM — это единственный известный мне ассемблер, "переваривающий" команду дальнего вызова

JMP 0000:7C00h
напрямую. Все остальные ассемблеры заставляют извращаться приблизительно так:
PUSH offset_of_target/PUSH segment_of_target/RETF
. Здесь мы заталкиваем в стек сегмент и смещение целевого адреса и выполняем дальний
RETF
, переносящий нас на нужное место. Еще можно воспользоваться самомодифицирующимся кодом, собрав команду
JMP FAR
"вручную", или просто расположить целевой адрес в одном сегменте с исходным адресом (например,
0000:7C00h
0000:7E00h
). Однако эти подходы муторны и утомительны.

В общем, скелет нашего загрузчика будет выглядеть так, как показано в листинге 5.8.

Листинг 5.8. Скелет простейшего загрузчика, написанный на FASM

use16

ORG 7C00h

CLD            ; Копируем слева направо

               ; (в сторону увеличения адресов)

MOV SI,7C00h   ; Откуда копировать

MOV DI,7E00h   ; Куда копировать

MOV CX,200h    ; Длина сектора

REP MOVSB      ; Копируем


; // Выбираем раздел, который мы хотим загрузить,

; // считываем его в память по адресу 0000:7C00h

; // (см. листинги 5.7 и 5.6)


JMP 0000:7C00h ; Передаём управление на загрузочный сектор

Записываем загрузчик в главную загрузочную запись

Под старушкой MS-DOS записать свой загрузчик в MBR было просто. Для этого достаточно дернуть прерывание

INT 13h
, функция
03h
(запись сектора). Но под Windows NT этот прием уже не работает, и приходится прибегать к услугам функции
CreateFile
. Если вместо имени открываемого файла указать название устройства, например,
\\.\PHYSICALDRIVE0
(первый физический диск), мы сможем свободно читать и записывать его сектора вызовами
ReadFile
и
WriteFile
соответственно. При этом флаг
dwCreationDisposition
должен быть установлен на значение
OPEN_EXISTING
, а флаг
dwShareMode
— на значение
FILE_SHARE_WRITE
. Еще потребуются права системного администратора, иначе ничего не получится.

Законченный пример вызова

CreateFile
выглядит, как показано в листинге 5.9.

Листинг 5.9. Открытие непосредственного доступа к жесткому диску под Windows NT

XOR EAX,EAX

PUSH EAX                                   ; hTemplateFile

PUSH dword FILE_ATTRIBUTE_NORMAL           ; dwFlagsAndAttributes

PUSH dword OPEN_EXISTING                   ; dwCreationDisposition

PUSH EAX                                   ; lpSecurityAttributes

PUSH dword FILE_SHARE_WRITE                ; dwShareMode

PUSH dword (GENERIC_WRITE OR GENERIC_READ) ; dwDesiredAccess

PUSH DEVICE_NAME                           ; Имя устройства

CALL CreateFile                            ; Открываем устройство

INC EAX

TEST EAX,EAX

JZ error

DEC EAX

...

DEVICE_NAME db "\\.\PHYSICALDRIVE0",0

BUF RB 512 ; Буфер

Открыв физический диск и убедившись в успешности этой операции, мы должны прочитать оригинальный MBR-сектор в буфер, перезаписать первые

1BBh
байт, ни в коем случае не трогая таблицу разделов и сигнатуру
55h AAh
(мы ведь не хотим, чтобы диск перестал загружаться, верно?). Теперь остается записать обновленный код MBR на место и закрыть дескриптор устройства. После перезагрузки все изменения вступят в силу.

Примечание

Правда, вполне возможно, что внесенные вами изменения и не подумают вступать в силу. Загрузчик жестоко мстит за малейшие ошибки проектирования. Поэтому, чтобы не потерять содержимое своих разделов, для начала лучше попрактиковаться на VMWare или любом другом эмуляторе PC.

Под Windows 9x, разумеется, трюк с

CreateFile
не работает. Но там можно воспользоваться симуляцией прерываний из DMPI или обратиться к драйверу ASPI. Оба способа были подробно описаны в моей книге "Техника защиты компакт-дисков от копирования". Однако, хотя в ней речь идет о CD, а не о HDD, жесткие диски программируются аналогично.

Прежде чем писать собственный загрузчик, рекомендуется изучить существующие нестандартные загрузчики. Все перечисленные ниже загрузчики распространяются по лицензии GPL или BSD, то есть без ограничений.

□ Ge2000.asm — тщательно прокомментированный Stealth-вирус, подменяющий системный загрузчик своим собственным. Хоть это и вирус, но он не опасен и может быть использован в учебных целях.

□ Mbr.asm — предельно простой, но полнофункциональный загрузчик с поддержкой разделов свыше 8 Гбайт.

□ Bootasm — отличный менеджер мультизагрузки с подробными комментариями, переходит в защищенный режим, может грузиться с дискеты, компакт-диска, zip-дискеты, винчестера и т.д. Поддерживает разделы свыше 8 Гбайт, показывает индикатор загрузки и делает множество других полезных вещей, которые не помешает изучить.

Отладка кода загрузчика

Отлаживать код загрузчика невероятно трудно. Загрузчик получает управление задолго до запуска операционной системы, когда никакие отладчики еще не работают. Несколько лет назад это представляло огромную проблему, и при разработке "навороченных" загрузчиков приходилось либо встраивать в них интегрированный мини-отладчик, либо выискивать ошибки вручную, изучая листинги с карандашом в руке. С появлением эмуляторов все изменилось. Достаточно запустить такой эмулятор, как BOCHS (рис. 5.5), и вы сможете отлаживать загрузчик как и любую другую программу!

Рис. 5.5. Внешний вид эмулятора BOCHS в процессе отладки загрузочного сектора

Программирование загрузчиков — одна из тех немногих областей, в которых применение ассемблера действительно обоснованно. Языки высокого уровня для этого слишком абстрагированы от оборудования. Кроме того, они недостаточно гибки. Вот почему хакеры так любят возиться с загрузчиками, добавляя сюда множество новых возможностей, включая автоматическую загрузку с CD-ROM или дисков SCSI, противодействие вирусам, парольную защиту с шифрованием данных и т.д. Здесь действительно есть, где развернуться, и есть на чем показать все свои возможности. В качестве дополнительного чтения я рекомендовал бы вам несколько весьма интересных источников. Вот они:

MBR and OS Boot Records — масса интересного материала по MBR (на английском языке): http://thestarman.narod.ru/asm/mbr/MBR_in_detail.htm;

BOCHS — отличный эмулятор со встроенным отладчиком, значительно облегчающий процесс "пуско-наладки" загрузочных секторов. Бесплатен, распространяется с исходными текстами: http://bochs.sourceforge.net;

http://www.koders.com (рис. 5.6) — отличный поисковик, нацеленный на поиск исходных кодов, по ключевому слову MBR выдает огромное количество загрузчиков на любой вкус;

Рис. 5.6. Поиск исходных текстов загрузчиков MBR на сайте Koders

Ralf Brown Interrupt List (рис. 5.7) — знаменитый "Список прерываний" (Interrupt List) Ральфа Брауна (Ralf Brown), описывающий все прерывания, включая недокументированные (на английском языке): http://www.pobox.com/~ralf;

Рис. 5.7. Просмотр легендарного "Списка прерываний" Ральфа Брауна

□ OpenBIOS — проект "Открытого BIOS", распространяемого в исходных текстах. Помогает понять некоторые неочевидные моменты обработки системного загрузчика: http://www.openbios.info/docs/index.html.

Динамические диски

Динамические диски, впервые появившиеся в Windows 2000, представляют собой все тот же программный RAID, призванный преодолеть ограничения стандартных механизмов разбиения диска на разделы. Он учитывает ошибки своего прямого предшественника — программных реализаций RAID в Windows NT, хранящих конфигурационную информацию в системном реестре. Этот недостаток препятствовал переносу RAID с компьютера на компьютер, и делало эти массивы чрезвычайно чувствительными к повреждениями реестра.

Типы динамических дисков, поддерживаемые Windows 2000

Начиная с Windows 2000, операционные системы этого семейства поддерживают следующие типы динамических дисков:

Простые (simple) — практически ничем не отличаются от обычных разделов, за исключением того, при переразбиении диска отпадает необходимость в перезагрузке. Данный тип является базовым для всех остальных динамических дисков.

 • Избыточность данных — отсутствует

 • Эффективность — низкая

Составные (spanned) — состоят из одного или нескольких простых дисков, находящихся в различных разделах или даже на физически различных устройствах, но представленные как один логический диск. Запись данных на простые диски осуществляется последовательно (то есть составной диск представляет собой классический линейный RAID).

 • Избыточность данных — отсутствует

 • Эффективность — низкая

Чередующиеся (striped) — чередующиеся динамические диски аналогичны составным, но данные записываются параллельно на все простые диски. При условии, что простые диски расположены на различных каналах контроллера IDE, это значительно увеличивает скорость обмена данными. Иными словами, чередующиеся динамические диски представляют собой классическую реализацию RAID уровня 0.

 • Избыточность данных — отсутствует

 • Эффективность — средняя

Зеркальные (mirrored) — зеркальные динамические тома представляют собой два простых диска, расположенных на разных устройствах. Данные дублируются на оба носителя (RAID уровня 1).

 • Избыточность данных — средняя

 • Эффективность — средняя

Чередующиеся с контролем четности (striped with parity) — соответствуют RAID уровня 5. Такие тома состоят из трех или большего количества дисков. Фактически такие тома представляют собой чередующиеся тома, на которых реализован контроль ошибок. Запись данных ведется на два диска, в два блока, а на третий диск и в третий блок записывается код коррекции ошибок (error correction code, ECC), с помощью которого содержимое отказавшего блока можно восстановить по информации любого из блоков.

 • Избыточность данных — высокая

 • Эффективность — высокая

Зеркальные с чередованием (mirrored striped) — эти тома соответствуют RAID 1+0.

 • Избыточность данных — средняя

 • Эффективность — высокая

По умолчанию Windows создает базовые диски (basic volumes). Однако любой базовый диск в любой момент времени может быть обновлен до динамического, и это не потребует даже перезагрузки системы.

Примечание

Терминологические соответствия для обычных (basic) и динамических (dynamic) дисков приведены в табл. 5.5.


Таблица 5.5. Терминологические соответствия динамических и обычных дисков

Базовые разделы (Basic disks)Динамические разделы (Dynamic disks)
Основный раздел (Primary partition)Простой том (Simple volume)
Системный и загрузочный разделы (System and boot partitions)Системный и загрузочный тома (System and boot volumes)
Активный раздел (Active partition)Активный том (Active volume)
Расширенный раздел (Extended partition)Том и свободное пространство (Volume and unallocated space)
Логический диск (Logical drive)Простой том (Simple volume)
Набор томов (Volume set)Составной том (Spanned volume)
Чередующийся набор (Stripe set)Чередующийся том (Stripe set)

Динамические диски не пользуются таблицей разделов, а потому и не имеют проблем, связанных с ограничением разрядности адресации CHS, и позволяют создавать тома практически неограниченного размера. Однако динамические диски, созданные путем обновления основных разделов, все-таки остаются в таблице разделов, при этом для них значение поля

Boot ID
меняется на
42h
. Если эта информация будет удалена, система откажется подключать такой динамический диск. Между прочим, операционная система Windows может быть установлена только на такой динамический диск, который был получен путем обновления базового, так как BIOS может загружать систем) лишь с тех разделов, которые перечислены в таблице разделов. При этом динамические диски, созданные "на лету", в таблицу разделов как раз и не попадают.

Схема разбиения динамических дисков содержится в базе данных менеджера логических дисков (Logical Disk Manager Database, LDM). Это — протоколируемая (journalled) база данных, поддерживающая транзакции и устойчивая к сбоям. Если в процессе манипуляции с томами вдруг происходит сбой питания, то при последующем включении компьютера будет выполнен откат (rollback) в предыдущее состояние. При переносе винчестера, содержащего один или несколько динамических дисков, на другой компьютер они автоматически распознаются и монтируются, как обыкновенные диски.

База данных LDM хранится в последнем мегабайте жесткого диска, а для дисков, полученных путем обновления базового раздела до динамического, — в последнем мегабайте этого раздела. Как уже говорилось, идентификатор загрузки

Boot ID
соответствующей записи таблицы разделов принимает значение
42h
. Так происходит потому, что при стандартном разбиении винчестера в его конце просто не остается свободного места, и операционной системе приходится сохранять эту информацию непосредственно на самом обновляемом диске (естественно, для этого на нем необходимо иметь по меньшей мере 1 Мбайт свободного пространства).

Сразу же за таблицей разделов по адресу

0/0/2
расположен приватный заголовок
PRIVHEAD
, содержащий в себе ссылки на основные структуры LDM (рис. 5.8). Если
PRIVHEAD
погибнет, Windows не сможет обнаружить и смонтировать динамические диски. К сожалению, гибнет он удручающе часто. Подавляющее большинство загрузочных вирусов и дисковых менеджеров считают сектор
0/0/2
свободным и используют его для хранения своего тела, необратимо затирая прежнее содержимое. Осознавая значимость заголовка
PRIVHEAD
, разработчики из Microsoft сохранили его в двух копиях, одна из которых хранится в конце LDM, а другая — в последнем секторе физического диска. Благодаря такой избыточности
PRIVHEAD
практически никогда не приходится восстанавливать вручную. Однако если такая необходимость все же возникнет, обратитесь к проекту LINUX-NTFS за подобным описанием его структуры (http://www.linux-ntfs.org/), здесь же оно по соображениям экономии места не приводится.

Рис. 5.8. База данных LDM и ее дислокация

Внутреннее устройство базы данных LDM не документировано. При этом даже поверхностный взгляд на ее структуру сразу же дает понятие о ее мощи и сложности (рис. 5.9). На самом верху иерархии расположено оглавление базы — структура

TOCBLOCK
(Table Of Content Block), состоящая из двух секций,
config
и
log
(причем, вероятно, в будущем их список будет расширен). Секция
config
содержит информацию о текущем разбиении диска на динамические тома, a
log
хранит журнал изменений схемы разбиения. Это — очень мощное средство в борьбе с энтропией! Если удалить один или несколько динамических разделов, информация о старом разбиении сохранится в журнале, что позволит с легкостью восстановить утерянные тома! Будучи очень важной структурой, оглавление диска защищено от случайного разрушения тремя резервными копиями, одна из которых вплотную примыкает к оригинальной версии
TOCBLOCK
,
расположенной
в начале базы LDM, а две других находятся в конце диска, между копиями PRIVHEAD.

Рис. 5.9. Внутренняя структура LDM

Внутренне секция

config
состоит из заголовка (
VMDB
) и одного или нескольких 128-байтных структур, называемых
VBLKs
, каждая из которых описывает соответствующий ей том, контейнер, раздел, диск или группу дисков. Заголовок
VMDB
не имеет копии и нигде не дублируется. Однако все его изменения протоколируются в журнале (
KLOG
) и потому могут быть восстановлены.

Примечание

Строение

VMDB
и
VBLKs
подробно описано в разделе "LDM Documentation" на сайте проекта LINUX-NTFS. Поэтому здесь оно не приводится в целях экономии места. Оно действительно очень громоздко, к тому же, крайне маловероятно, что кому-то потребуется восстанавливать секцию
config
вручную.

Для просмотра базы данных LDM и архивирования ее содержимого можно воспользоваться утилитой LDM-dump Марка Руссиновича, бесплатную копию которой можно скачать с его сайта (http://www.sysinternals.com/files/ldmdump.zip). Как вариант можно зарезервировать последний мегабайт физического диска, а также последние мегабайты всех разделов, для которых значение поля

Boot ID
равно
42h
. Сделать это можно с помощью любого дискового редактора (например, Sector Inspector). Эту информацию рекомендуется хранить на надежном носителе (Zip-дискете, CD-R/RW). Помимо этого, не забудьте также создать и резервную копию структуры
TOCBLOCK
.

При восстановлении удаленных динамических дисков необходимо учитывать следующие факторы:

1. Во-первых, журнал изменений на интерфейсном уровне недоступен, и выполнить откат штатными средствами операционной системы невозможно.

2. Во-вторых, загрузочные сектора удаляемых дисков автоматически очищаются, и восстанавливать их приходится вручную. Более подробно эта тема будет раскрыта в следующем разделе.

Если размер и тип удаленного динамического диска вам известны (на дисках NTFS его можно извлечь из копии загрузочного сектора), просто зайдите в Менеджер Управления Дисками (Disk Manager) и воссоздайте его заново, от предложения отформатировать раздел любезно откажитесь и восстановите очищенный загрузочный сектор по методике, описанной в следующем разделе.

Как видно, Microsoft тщательно позаботилась о своих пользователях и тщательно проработала структуру динамических дисков, что для нее, вообще говоря, нехарактерно.

Основные сведения о загрузочном секторе

Первый сектор логического диска носит название загрузочного (boot). Он содержит код самозагрузки (bootstrap code) и важнейшие сведения о геометрии диска, без которых раздел просто не будет смонтирован. Структура загрузочного сектора определяется архитектурными особенностями конкретной файловой системы. В частности, структура загрузочного сектора NTFS описана в табл. 5.6.


Таблица 5.6. Строение загрузочного сектора NTFS

СмещениеРазмерОписание
0x00
3 bytesИнструкция перехода
0x03
8 байт
OEM ID
— идентификатор
0x0B
25 bytesBPB
0x24
48 bytesExtended BPB
0x54
426 bytesBootstrap Code
0x01FE
WORD
55 AA

В начале всякого сектора расположена трехбайтная машинная команда перехода на код самозагрузки (обычно она имеет вид

EB 52 90
, хотя возможны и различные вариации). Так происходит потому, что при загрузке boot-сектора в память управление передается на его первый байт, а код самозагрузки по туманным историческим соображениям был отодвинут в конец сектора (для NTFS верхняя граница составляет
54h
байт), вот и приходится прыгать блохой!

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

MSDOS5.0
для FAT16,
MSWIN4.0
/
MSWIN4.1
для FAT32 и
NTFS
— для NTFS). Если это поле окажется искаженным, то драйвер не сможет смонтировать диск. В ряде случаев драйвер может даже счесть такой диск не отформатированным.

Примечание

С дисками, отформатированными для использования FAT, Windows 2000 будет работать даже в том случае, если поле

OEM ID
запорчено. В отношении NTFS это не так.

Следом за идентификатором расположен 25-байтовый блок параметров BIOS (BIOS Parameter Block, BPB), хранящий сведения о геометрии диска (количество цилиндров, головок, секторов, размер сектора, количество секторов в кластере и т.д.). Если эта информация окажется утерянной или искаженной, то нормальное функционирование драйвера файловой системы станет невозможным. Причем, в отличие от информации о числе цилиндров/головок/секторов, которая дублирует информацию, содержащуюся в MBR, а при ее утере элементарно восстанавливается описанным выше способом, размер кластера определить не так-то просто! Позже мы обсудим этот вопрос более подробно, пока же вполне достаточно сослаться на табл. 5.7, в которой указаны размеры кластера томов NTFS, по умолчанию выбираемые штатной утилитой форматирования.


Таблица 5.7. Размеры кластеров, по умолчанию выбираемые штатной утилитой форматирования в Windows 2000

Размер дискаРазмер кластера
<512 Мбайт1 сектор
< 1 Гбайт2 сектора
< 2 Гбайт4 сектора
> 2 Гбайт8 секторов

При выборе размера кластера вручную Windows 2000 поддерживает следующий размерный ряд: 1 сектор, 2 сектора, 4 сектора, 8 секторов, 16 секторов, 32 сектора, 64 сектора и 128 секторов. Чем больше размер кластера, тем слабее фрагментация и выше предельно адресуемый объем дискового пространства. Однако потери от грануляции с увеличением размера кластера тоже растут. Впрочем, размеры кластеров редко задаются вручную.

К блоку параметров BIOS вплотную примыкает его продолжение — расширенный блок параметров BIOS (extended BPB), хранящий номер первого кластера MFT, ее размер в кластерах, номер кластера с зеркалом MFT, а также некоторую другую служебную информацию. В отличие от FAT16/FAT32, MFT может располагаться в любом месте диска (для борьбы с BAD-секторами это актуально). При нормальном развитии событий MFT располагается практически в самом начале диска (где-то в районе четвертого кластера) и, если только она не была перемещена, то ее легко найти глобальным поиском (искать следует строку

FILE*
по смещению о от начала сектора). При разрушении или некорректном заполнении расширенного блока параметров BIOS драйвер файловой системы отказывается монтировать раздел, объявляя его не отформатированным.

Следом за расширенным блоком параметров BIOS идет код самозагрузки (Bootstrap Code), который ищет на диске загрузчик операционной системы (у операционных систем из семейства Windows NT это — файл ntldr), загружает его в память и передает ему управление. Если код самозагрузки отсутствует, загрузка операционной системы становится невозможной, однако при подключении восстанавливаемого диска вторым раздел должен быть прекрасно виден. Повреждение кода самозагрузки вызывает перезагрузку компьютера или его зависание.

Наконец, завершает загрузочный сектор уже известная нам сигнатура

55h AAh
, без которой он ни за что не будет признан загрузочным. Подробная информация обо всех полях загрузочного сектора NTFS приведена в табл. 5.8.


Таблица 5.8. Значения полей загрузочного сектора NTFS

СмещениеРазмерОписание
0x00
3 байтаИнструкция перехода
0x03
8 байт
OEM ID
0x0B
WORD
Количество байт на сектор (для жестких дисков всегда 512)
0x0D
BYTE
Количество секторов на кластер
0x0E
WORD
Количество зарезервированных секторов, всегда равно 0
0x10
3 байтаHe используется NTFS и всегда должно быть равно 0
0x13
WORD
Не используется NTFS и всегда должно быть равно 0
0x15
BYTE
Дескриптор носителя (media descriptor) — для жестких дисков всегда равен
0xF8
0x16
WORD
Не используется NTFS и всегда должно быть равно 0
0x18
WORD
Количество секторов на дорожку
0x1A
WORD
Количество головок
0x1C
DWORD
Количество скрытых секторов
0x20
DWORD
Не используется NTFS и всегда должно быть равно 0
0x24
DWORD
Не используется NTFS и всегда должно быть равно 0
0x28
8 байтОбщее количество секторов (total sector)
0x30
8 байтЛогический номер кластера, с которого начинается MFT
0x38
8 байтлогический номер кластера, с которого начинается зеркало MTF
0x40
DWORD
Количество кластеров на сегмент (File Record Segment)
0x44
DWORD
Количество кластеров на блок индексов (index block)
0x48
8 байтСерийный номер тома
0x50
DWORD
Контрольная сумма (0 — не подсчитывать).
0x54
426 байтКод самозагрузки (Bootstrap Code)
0x01FE
WORD
Сигнатура
55 AA

Техника восстановления загрузочного сектора

Осознавая значимость загрузочного сектора, операционная система Windows NT при форматировании диска создает его зеркальную копию (однако делает она это только на разделах NTFS). Для различных версий Windows расположение резервной копии загрузочного сектора различно. Так, Windows NT 4.0 располагает ее в середине логического диска, a Windows 2000 — в последнем секторе раздела. Если таблица разделов уцелела, то для восстановления загрузочного сектора достаточно просто перейти в начало следующего раздела и отступить на сектор назад (Windows 2000) или поделить количество секторов логического диска пополам (с округлением в нижнюю сторону) и перейти к сектору с полученным номером, дав редактору диска команду GO (Windows NT 4.0).

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

NTFS
по смещению 3 от начала сектора). Поскольку положение копии фиксировано и отсчитывается от начала логического диска, мы можем с абсолютной уверенностью определить границы раздела. Предположим, что копия загрузочного сектора найдена в секторе
1289724
, а поле
NumberSectors
содержит значение
12289661
. Тогда номер конечного сектора раздела равен
1289724
, а номер стартового сектора можно вычислить следующим образом:
1289724 - 12289661 == 63
. Поскольку загрузочный сектор расположен на расстоянии одной головки от таблицы разделов, что соответствует значению
SectorPerTrack
, мы сможем восстановить и ее.

Если резервных копий загрузочного сектора нет, его придется реконструировать вручную. К счастью, это совсем не так сложно, как может показаться на первый взгляд. В поле идентификатора производителя заносится строка

NTFS
(обратите внимание, что на конце этой строки должны быть четыре пробела). Поля, задающие количество секторов на дорожке и количество головок, заполняются, исходя из текущей геометрии диска. Количество скрытых секторов (то есть количество секторов, расположенных между началом раздела и загрузочным разделом) равно количеству головок. Общее количество секторов в разделе вычисляется на основании его размера (если точный размер не известен, берите значение с запасом).

Количество секторов в кластере определить сложнее. Это особенно справедливо, если при форматировании диска было задано количество секторов на кластер, отличное от значения по умолчанию. Но ситуация вовсе не безнадежна. Последовательно сканируя файловые записи в MFT, найдите файл с предопределенной и заранее известной сигнатурой. Пусть, для определенности, это будет файл NTOSKRNL.EXE. Откройте его аутентичную копию в HEX-редакторе, найдите уникальную последовательность, гарантированно не встречающуюся ни в каких других файлах и расположенную в пределах первых 512 байт от его начала, после чего найдите эту сигнатуру глобальным поиском по всему диску. Начальный номер кластера вам известен (он содержится в MFT), логический номер сектора известен тоже (его нашел дисковый редактор). Теперь остается лишь соотнести эти две величины между собой. Естественно, если дисковый редактор найдет удаленную копию NTOSKRNL.EXE (или на диске будут присутствовать несколько файлов NTOSKRNL.EXE), данный метод даст осечку, поэтому полученный результат необходимо уточнить, проведя аналогичные исследования с использованием других файлов.

Логический номер первого кластера MFT равен первому кластеру, в начале которого встретилась строка

FILE*
(конечно, при том условии, что MFT не была перемещена). По умолчанию Windows выделяет под MFT 12,5% от емкости раздела, помещая ее зеркальную копию в середину. Кроме того, ссылка на "зеркало" присутствует и в самой MFT. Если же MFT разрушена, переместитесь в середину диска, немного отступите назад и повторите глобальный поиск строки
FILE*
(только, смотрите, не вылетите в соседний раздел!). Первое же найденное вхождение с высокой степенью вероятности и будет зеркальной копией MFT.

Количество кластеров на сегмент обычно равно

F6h
, а количество кластеров на блок индексов —
01h
. Других значений мне встречать не доводилось. Серийный номер тома может быть любым — он ни на что не влияет.

Для восстановления отсутствующего (искаженного) кода самозагрузки загрузите консоль восстановления Windows 2000 или Windows XP и дайте команду

FIXBOOT
.

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

Глава 6