Издательский дом ООО "Гейм Лэнд"ЖУРНАЛ ХАКЕР #79, ИЮЛЬ 2005 г.

Стряпаем 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

Назад на стр. 079-114-4  Содержание  Вперед на стр. 079-114-6