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

BIOS на блюдечке

Крис Касперски ака мыщъх

Хакер, номер #078, стр. 078-108-7


; перехватываем INT 01h

MOV ax, CS

XOR bx,bx

MOV DS,bx

; смещение нашего обработчика относительно сегмента 0000h

MOV [bx], offset our_vx_code

MOV [bx+2], bx

MOV DS, ax

; устанавливаем точку останова на исполнение

MOV eax,302h

; линейный физический адрес точки останова

MOV ebx,7С00h

; заносим значения в отладочные регистры

MOV dr7,eax

mov dr0,ebx

[модификация boot-блока]

Вышеописанный способ внедрения кода работает только на Award и отчасти Phoenix, что не есть хорошо. Существует универсальный способ, совместимый со всеми BIOS'ами, однако он далеко не так прост. Ведь единственное место, куда мы можем внедриться везде, — это boot-блок, а точнее, безусловный переход, лежащий по адресу F000h:FFF0h.

Давай возьмем какой-нибудь BIOS и дизассемблируем его (пусть для определенности это будет AMI 6728 ver. 52 от материнской платы MSI 865PE Neo3-F, имя файла прошивки — A6728IMS.520).

[внешний вид типичного boot-блока (фрагмент)]

0007FD20: 80 00 00 00-00 31 49 38-36 35 78 78-78 00 00 00

0007FD30: 00 00 00 00-00 00 00 00-00 00 00 00-00 00 00 00

…

0007FF30: 00 00 00 00-00 00 00 00-00 00 00 00-00 00 00 00

0007FFE0: 31 49 38 36-35 58 58 58-00 00 00 00-00 00 00 00

0007FFF0: !!!EA CD FF 00-F0!!! 31 31 2F-31 36 2F 30-34 00 FC 00

В хвосте boot-блока находится ~200h нулей, чего вполне достаточно для размещения нашего кода. Исправляем EA CD FF 00-F0 (jmp 0F000:0FFCD) на EA 30 7F 00 F0 (jmp 0F000:7F30), копируем свой код поверх нулей и радуемся жизни. Естественно, в других прошивках эти цифры могут несколько отличаться, поэтому перед внедрением в BIOS наш код должен автоматически находить длинную последовательность нулей в его хвосте. Это легко. Сложнее пересчитать контрольную сумму. Разные BIOS'ы хранят ее в разных местах. Что делать? Матчасть учить, вот что! Контрольная сумма boot-блока равна нулю. Это закон. Поэтому нам достаточно рассчитать контрольную сумму нашего кода и добавить к его концу два байта (у boot-блоков, в отличие от ISA, подсчет контрольной суммы ведется не по байтам, а по словам), добившись, чтобы его контрольная сумма равнялась нулю, тогда и контрольная сумма всего boot-блока будет равна нулю! Искать местоположение оригинальной контрольной суммы не нужно!

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

В нашем случае код, отвечающий за это, находится по смещению 7078Dh от начала файла.

[волшебная последовательность 55 AA 7x]

0007078D: 26813F55AA cmp es:[bx],0AA55

00070792: 7410 je 0000707A4

Назад на стр. 078-108-6  Содержание  Вперед на стр. 078-108-8