Стряпаем MBR Крис Касперски ака мыщъх Хакер, номер #079, стр. 079-114-5 Обнаружив загрузочный раздел (а сделать это можно с помощью флага 80h в partition’е), загрузчик должен считать его первый сектор и разместить в памяти по адресу 0000:7C000h, то есть аккурат поверх своего тела. А вот это уже нехорошо! И чтобы не нарваться на крах системы, загрузчик должен заблаговременно перенести свою тушу в другое место, что обычно осуществляется командой MOVSB. Копироваться можно в любое место памяти — от 0080:0067h до 9E00h. Память, расположенную ниже 0080:0067h, лучше не трогать, так как здесь находятся векторы прерываний и системные переменные BIOS'а, а от A000h и выше начинается область отображения ПЗУ, так что предельно доступный адрес равен A000h минус 200h (размер сектора), то есть 9E00h. Что еще? Ах да! Трогать DL-регистр ни в коем случае нельзя, поскольку в нем передается номер загрузочного привода. Писать загрузчик я рекомендую на FASM, кстати говоря, на единственном известном мне ассемблере, «переваривающем» команду дальнего вызова JMP 0000:7C00h напрямую. Все остальные ассемблеры заставляют извращаться приблизительно так: PUSH offset_of_target PUSH segment_of_target RETF Здесь мы заталкиваем в стек сегмент и смещение целевого адреса и выполняем дальний RET, переносящий нас на нужное место. Еще можно воспользоваться самомодифицирующимся кодом, собрав команду JMP FAR «вручную», или просто расположить целевой адрес в одном сегменте с исходным адресом (например 0000:7C00h --> 0000:7E00h), но это все муторно и некрасиво. В общем, скелет нашего загрузчика на FASM будет выглядеть так: use16 ORG 7С00h CLD ; копируем слева направо (в сторону увеличения адресов) MOV SI,7C00h ; откуда копировать MOV DI,7E00h ; куда копировать MOV CX,200h ; длина сектора REP MOVSB ; копируем ; // выбираем раздел, который мы хотим загрузить, ; // считываем его в память по адресу 0000:7C000h JMP 0000:7C000h ; передаем управление на boot-сектор [инсталляция нашего загрузчика в MBR] Под старушкой MS-DOS записать свой загрузчик в MBR было просто: дергали прерывание INT 13h с функцией 03h (запись сектора) и все. Но под Windows NT этот прием уже не работает и приходится прибегать к услугам функции CreateFile. Если вместо имени открываемого файла ей указать название устройства, например "\\.\PHYSICALDRIVE0" (первый физический диск), мы сможем свободно читать и записывать его секторы вызовами ReadFile и WriteFile соответственно. При этом флаг dwCreationDisposition должен быть установлен в значение OPEN_EXISTING, а dwShareMode — в значение FILE_SHARE_WRITE. Еще потребуют права root'а или, в терминологии Windows, администратора, иначе ничего не получится. Законченный пример вызова CreateFile выглядит так: [открытие непосредственного доступа к жесткому диску под 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 |