Краткий FAQ по MBR (Основная Загрузочная Запись). Установка Windows на конвертированный из MBR в GPT диск без потери данных на несистемных разделах Совместимы виндовс mbr с диском gpt

Ситуация следующая. Есть винт на 160Гб. На нем 2 раздела - 40Гб и 120Гб. С целью установки убунты как второй системы была произведена разбивка 120Гб -> 100+10+2+8.
Итоги
1. При загрузке системы выводится сообщение MBR helper not found;
2. fdisk показывает один большой 160Гб диск.

Дураку понятно, что это начало веселой ночи.
Далее, под катом, решения вопроса.

1. Восстановление таблицы разделов

1.1. Parted magic
Данный LiveCD\USB дистрибутив , размером в 100Мб несет в себе огромную кучу софта, для работы с дисками. От разбивки, до восстановления.
Из них всех, нам нужны будут gpart , testdisk , fdisk и ms-sys .
1.2. Gpart
gpart - это утилита, сканирующая по-секторно диск на наличие разделов, которые присутствуют на носителе, но отсутствуют в таблице. В своей работе, она игнорирует уже существующую таблицу (если присутствует). Программа разаботана немецким программистом Michail Brzitwa и больше им не поддерживается. Вялотекущая разработка ведется командами Fedora и Debian. Текущая версия - 0.1h.

Утилита позволяет наиболее быстро и легко восстановить таблицу разделов, но она несет в себе несколько недостатков. Во-первых, разработка была давно заброшена, во-вторых, она иногда не совсем корректно определяет разделы.

Gpart может работать в 2-х режимах. Это быстрый анализ и подробное сканирование. В некоторых случаях, первого режима достаточно. Мы же будем смотреть на второй.

Gpart -if /dev/sda

-i - интерактивный режим. На каждую найденную партицию будет задан вопрос, сохранять ее, либо пропустить.
-f - полный скан диска.

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

Begin scan...
Possible partition(DOS FAT), size(1907mb), offset(0mb)
Possible partition(SGI XFS filesystem), size(5730mb), offset(1907mb)
End scan.
Checking partitions...
Partition(DOS or Windows 95 with 32 bit FAT, LBA): primary
Partition(Linux ext2 filesystem): primary
Ok.
Guessed primary partition table:
Primary partition(1)
type: 012(0x0C)(DOS or Windows 95 with 32 bit FAT, LBA)
size: 1907mb #s(3906544) s(16-3906559)
chs: (0/1/1)-(1023/19/16)d (0/1/1)-(12207/19/16)r
Primary partition(2)
type: 131(0x83)(Linux ext2 filesystem)
size: 5730mb #s(11736000) s(3906560-15642559)
chs: (1023/19/16)-(1023/19/16)d (12208/0/1)-(48882/19/16)r
Primary partition(3)
type: 000(0x00)(unused)
size: 0mb #s(0) s(0-0)

Primary partition(4)
type: 000(0x00)(unused)
size: 0mb #s(0) s(0-0)
chs: (0/0/0)-(0/0/0)d (0/0/0)-(0/0/0)r

Если все ОК, то соглашаемся на запись в таблицу разделов, скрещиваем пальцы и перезагружаемся.
В моем случае, программа определила разделы, которые были до разбивки (40 и 120), что не подходило и заставило искать альтернативные способы восстановления.

1.3. testdisk
Note: подробнее эта утилита описана в этом посте , здесь не буду повторяться.

Эта утилита аналогична предыдущей, но имеет ряд плюсов:
1. более свежая и активно поддерживается;
2. субъективно, работает намного быстрее;
3. функциональнее;
4. есть простой консольный интерфейс на базе ncurses.

Поехали!
1. в первом окне выбираем Create a new log file;
2. выбираем нужный диск (/dev/sda) -> Proceed;
3. отмечаем тип разделов как Intel;
4. выбираем Analyse current partition structure and search for lost partitions;
5. если найденные разделы верны, жмем Backup и переходим к пункту 6, есть возможность быстро пересканировать диск, если где-то ошибка (Quick search);
6. здесь уже виден зеленый список с разделами. Если ок, то записываем, иначе запускаем Deep search.;

В моем случае, результат был аналогичен результату gpart, что есть некорректен.
Запустив Deep search, выждав около 40 минут я получил ответ, от которого на душе так нехило отлегло.
Было найдено несколько партиций, которые накладывались одна на другую (это были изначальная (до манипуляций) 120Гб и новая, на 100Гб). Отметив ненужную, как удаленную, я записал таблицу на диск и перезагрузился. К счастью, все обошлось и компьютер вернулся к состоянию, который был изначально, а я мог с чистой совестью лечь спать.

3. Восстановление MBR

Для этой задачи, у нас в арсенале есть тулза ms-sys.
Сперва узнаем, что с нашей MBR.

Ms-sys /dev/sda
/dev/sda has an x86 boot sector
it is unknown boot sector

Теперь видно, что на данном диске нет загрузочного сектора.
Утилита может работать с MBR различных операционных систем. Список можно получить, запустив программу без агрументов. В моем случае, необходим был от Windows 7.
Записываем MBR на диск:

Ms-sys -7 /dev/sda
Windows 7 master boot record successfully written to /dev/sda

Проверяем:

Ms-sys /dev/sda
it is Microsof 7 master boot record, like the one this
program creates with the switch -7 on a hard disk device.

Вот и все, нужная MBR установлена и можно перезагружаться.

3. Outro

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

MBR и GPT . Основные вопросы.

MBR и GPT – определение.

Windows предлагает нам 2 опции: Master Boot Record (MBR) – Главная Загрузочная Запись – и Globally Unique Identifier Partition Table (GPT) – Глобально Уникальный Идентификатор Таблицы Разделов. Последняя получила поддержку, начиная с версий Vista/Windows Server 2008 . Однако Windows XP 64-х битная тоже поддерживала этот формат.

MBR – она же Master Boot Record – это основная загрузочная запись на жёстком диске. Находится она в самом начале винчестера, то есть в первых секторах жёсткого диска. Его задача – выбрать раздел диска, в котором будет загружаться операционная система (собственно, главная загрузочная запись для этого и была создана). Это делается с помощью короткого исполняющего кода, который BIOS после самодиагностики, выгружает в . Далее исполняющий код в MBR берёт бразды правления в свои руки и загружает ОС в указанном разделе жёсткого диска (информация о разделах также содержится в загрузочной записи). Кстати, именно поэтому главную загрузочную запись нельзя создать на диске, который нельзя разделить на части и наоборот, её можно создать там, где возможно деление носителя данных на несколько дисковых, пусть и виртуальных, устройств.

Если MBR повреждён, операционная система не запустится никогда. Если повреждена не только запись MBR, но и сектор с главной загрузочной записью – диск можно использовать только как подставку для чашек или разломать на магнитики и дать поиграть ребёнку.

MBR и GPT . Почему уходят от MBR?

В силу давности разработок, MBR не понимает, что такое большое дисковое пространство. Для MBR «большое» начинается с величины объёма в 2,2 терабайта. MBR, повторюсь, такие объёмы не читает и отображать не в состоянии. Далее, MBR воспринимает существование только четырёх первичных разделов (primary partition) или три первичных раздела плюс один расширенный. Таким образом, если разделов необходимо больше, то пользователю необходимо будет создать вторичную структуру на дисковом пространстве. Пользователю ПК она известна как расширенный раздел (extended partition) – то есть специальный тип раздела диска, представляющий собой расширение первичного раздела. Содержит главную загрузочную запись (MBR) с собственной таблицей разделов, а это позволяет не обращать внимания на ограничение этой таблицы и позволяет иметь на диске более четырёх разделов. На жёстком диске может быть, как вы уже догадались, несколько расширенных разделов. И уже после создания расширенного раздела приходится создавать один или несколько разделов логических… Вобщем, правила разбиения на разделы для MBR сложны и ограничены. Поэтому в борьбе таблиц MBR и GPT на смену главной загрузочной записи повсеместно идёт GPT.

MBR и GPT . Что такое GPT?

GPT – GUID (Globally Unique Identifier) Partition Table – таблица разделов глобально (статически) уникального идентификатора. Выражаясь технически, GPT использует более современную систему адресации логических блоков, что позволяет не просто преодолеть планку в 2,2 Тб, но и создавать и успешно обрабатывать диски объёмом чуть более 9 зеттабайт, то есть об ограничении по объёму для создаваемому разделу можно забыть. Кроме того, GPT более надежна, ибо оглавление и таблица разделов диска записаны и в начале, и в конце диска. Если один из них повреждён, второй восстанавливается по образу и подобию уцелевшего. Это отнимает определённое «жизненное» пространство у винчестера, а, следовательно, и у нас с вами, так что небольших объёмов диски вполне жизнеспособны одновременно с MBR и GPT . GPT имеет смысл целенаправленно ставить только на дисках с объёмом от 500 Гбайт (лучше ещё больше).
Далее, благодаря нововведениям, теперь и само количество разделов на винчестере неограниченно. 128 версий операционных систем Windows на одном компьютере не имеют, конечно, смысла, но в некоторых случаях установка сразу нескольких операционных систем разных поколений вполне оправдана. Хотя, говоря про разные поколения, я имею ввиду только последние версии Windows, начиная с Vista. Да, ОС до XP в 32-х битной версии включительно GPT не поддерживаются. И, конечно, не забудьте о проблеме порогового значения в 2 Тбайта, если вы являетесь счастливым обладателем таких объёмов информации. Вот здесь и начинает всплывать вопрос о конвертировании обратно в MBR, который я рассмотрю чуть позже. Единственное, о чём я упомяну сразу – что вопросы о таблице разметки винчестера (MBR и GPT) и установленном базовом программном обеспечении материнской платы (BIOS или UEFI) в процессе установки операционной системы стоят в неразрывной связи.

MBR и GPT . Сравнение.

А какая мне-то разница?

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

  • GPT – более современная
  • GPT будет требовать от Windows, чтобы та загружалась только в режиме (про прежние загрузчики придётся забыть)
  • MBR требует от прежних поколений Windows загрузки в режиме BIOS (впрочем, 64-битные версии могут загружаться и режиме UEFI)

На этом теоретическую часть про MBR и GPT я предлагаю закончить и перейти к практическим вопросам установки операционных систем и конвертирования таблиц дисков:

Как узнать, какая версия таблицы у меня?

Проверить, как всегда, легко. Зажимаем клавиши Windows + R , вводим команду diskmgmt.msc . В окне консоли выберем слева Управление дисками . Выберите любой из разделов, щёлкните правой кнопкой мыши и нажмите Свойства (это же окно можно обнаружить прямо из Проводника системы со списком локальных дисков):

В окне из присутствующих дисков (там все) выберите интересующий жёсткий и снова дважды по нему щёлкните. Появится окно свойств для конкретного диска, где вы найдёте вкладку Тома . В ней найдём кнопку Заполнить :

Можно зайти с другой стороны. Утилита от Windows

В консоли набираем последовательно команды:

Diskpart list disk

И что видим? Под идентификатором GPT ничего нет, значит этот стиль раздела отношения к данному диска никакого не имеет:

Успехов нам всем

Прочитано: 283

Привет друзья! В последней версии Windows 10 появилась (GPT в MBR утилита не конвертирует), но конвертировать можно только жёсткие диски с установленной операционной системой. Если установлена Windows 10 , то можно конвертировать в онлайне и offline. Windows 7 и Win 8 только в offline, Висту конвертировать не пробовал. Но если есть нужда конвертировать жёсткий диск без операционной системы, то это можно сделать так.

В Управлении дисками видно, что у меня 3 физических диска. Два имеют разметку GPT. Один разметку MBR.

На диск c разметкой MBR я решил установить операционную систему Windows 8.1 и для этого освободил на нём место.

У меня есть три варианта установки. Установить OS со своим загрузчиком на диске MBR , но тогда установленная OS будет загружаться в режиме Legacy. Мне это не совсем удобно, так как у меня уже установлены OS на диски GPT и загружаются они в режиме UEFI.

Второй вариант, установить OS на диск MBR , а загрузчик создать на разделе EFI. В этом случае у меня не будет независимого (отдельного) загрузчика. Я Выбрал третий вариант установки. В Windows 10 (в которой я сейчас работаю) в версии 1703 появилась утилита MBR2GPT, которая умеет конвертировать диски MBR в GPT. Конвертировать можно только жёсткие диски с установленной OS и загрузчиком на этом диске. Windows 10 можно конвертировать в режиме online и offline. Windows 7 и Win 8 можно конвертировать только в режиме offline. Windows 8.1, которую я собираюсь установить, будет в offline, что без проблем позволит мне конвертировать диск MBR в GPT.

Начнём с того, что создадим раздел, присвоим букву и создадим метку.

Щёлкаем правой мышью на нераспределённом пространстве и выбираем "Создать простой том".

Назначаем букву диска (S:).

Присваиваем метку тома - OS.

Теперь нам нужно сделать раздел активным, но в Управлении дисками сделать это не получилось.

Сделаем это в командной строке с помощью diskpart.

Теперь нужно распаковать (развернуть) архив операционной системы, находящийся в дистрибутиве windows в файле install.wim(esd), на созданный раздел и создать загрузчик. Обычно я использую для этого средства windows утилиты dism и bcdboot, но эти утилиты не имеют графического интерфейса и для того, чтобы лучше показать последовательность действий использую утилиту WinNTSetup, которая имеет графический интерфейс. Сначала монтирую в виртуальный привод (F:) ISO c дистрибутивом Windows 8.1.

После этого запускаю утилиту WinNTSetup.

В появившемся окне выбираю путь к установочным файлам Windows 8.1. Установочные файлы, это архив OS Install.wim. В моём случае install.wim находится в виртуальном приводе (F:) в папке sources.

По умолчанию WinNTSetup для загрузчика выбирает локальный диск (том, раздел) с загрузчиком работающей системы, но мне нужен загрузчик на другом жёстком диске. На MBR дисках загрузчик можно создать только на активном разделе. Активным я сделал раздел (S:) метка OS. Выбираю этот раздел.

Почему WinNTSetup не понравился активный раздел не понял.

Теперь нужно указать раздел, в который будет установлена OS. В моём случае это раздел (S:).

Нажимаем "Установка" и выбираем загрузчик MBR (пункт BIOS).

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

затем предложение перезагрузить компьютер для продолжения установки. Продолжать установку в режиме Legacy я не хочу и нажимаю "Отмена".

Продолжить установку я решил в режиме UEFI. С помощью утилиты MBR2GPT проверяю всё ли я сделал правильно. Команда

mbr2gpt /disk:1 /validate /allowFullOS

Перезапись основной загрузочной записи (Master Boot Record ) позволяет не только восстановить её (при необходимости), но и расправиться с .

Восстановление (перезапись) основной загрузочной записи (Master Boot Record ) в автоматическом режиме

– установите в лоток привода загрузочный диск (или );

– нажмите Ctrl+Alt+Del ;

Delete для входа в CMOS Setup Utility ;

– установите загрузку с CD /DVD-ROM , нажмите F10 , санкционируйте сделанные изменения, начнется перезагрузка;

, нажмите любую клавишу;

– в окне Windows Boot Manager выберите Windows Setup /Установка Windows –> нажмите Enter ;

US ), нажмите Next ;

их установлено 2 или более);

– установите переключатель Use recovery tools that can help fix problems starting Windows –> Next ;

– в следующем окне – System Recovery Options (Параметры восстановления системы ) – доступны опции:

· Startup Repair (Automatically fix problems that are preventing Windows from starting );

· System Restore (Restore Windows to an earlier point in time );

· System Image Recovery (Recover your computer using a system image you created earlier );

· Windows Memory Diagnostic (Check your computer for memory hardware errors );

· Command Prompt (Open a command prompt window );

– выберите Startup Repair ;

– средство восстановления запуска Startup Repair проведёт диагностику и устранение неполадок;

– (если проблемы не будут выявлены, появится сообщение «Startup Repair could not detect a problem» );

– нажмите Finish –> Restart ;

– во время перезагрузки нажмите Delete для входа в CMOS Setup Utility ;

– установите загрузку с жёсткого диска, нажмите F10 ;

Восстановление (перезапись) основной загрузочной записи (Master Boot Record ) с помощью

установите в лоток привода загрузочный диск (или );

– нажмите Ctrl+Alt+Del ;

– во время перезагрузки нажмите Delete для входа в CMOS Setup Utility ;

– установите загрузку с CD /DVD-ROM , нажмите F10 , санкционируйте сделанные изменения, начнётся перезагрузка;

– после перезагрузки, если появится сообщение «Press any key to boot from CD or DVD…» , нажмите любую клавишу;

– в окне Windows Boot Manager выберите Windows Setup /Установка Windows –> нажмите Enter ;

– когда программа установки загрузит установочные файлы в оперативную память, появится окно выбора раскладки клавиатуры (можете выбрать русскую, а можете оставить US ), нажмите Next ;

– в следующем окне выберите операционную систему (если на вашем их установлено 2 или более);

– установите переключатель Use recovery tools that can help fix problems starting Windows –> Next ;

– в окне System Recovery Options (Параметры восстановления системы ) выберите Command Prompt ;

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

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

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

Номер функции заносится в регистр 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 DH, ; Стартовый номер головки
MOV CX, ; Стартовый сектор с цилиндром INT 13h
JC error ; Ошибка чтения
;Обрабатываем считанный boot-сектор или расширенную таблицу разделов
;===================================================================
;
CMP byte , 80h
JZ LOAD_BOOT ; Это загрузочный сектор
; Передаем на него управление
CMP byte , 05h
JZ LOAD_CHS_EXT ; Это расширенная таблица разделов
; в формате CHS
CMP byte , 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, ; Смещение partition относительно
; начала раздела
ADD EAX, EDI ; EDI должен содержать номер сектора
; текущего MBR
MOV ;
...
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 .